Beispiel #1
0
  /**
   * During the join process, there might be cycle. It means the ECR <code>
   * root</code> might be set to <code>freshType</code>. The type-union should take care of it --
   * union <code>freshType</code> to <code>unionType</code>. In particular, <code>freshType</code>
   * is an object type, while <code>
   * unionType</code> is a struct type, then <code>unionType</code> should be collapsed before union
   * with <code>freshType</code>.
   *
   * @param root
   * @param unionType
   * @param freshType
   * @return unified type
   */
  private ValueType resolveType(ECR root, ValueType unionType, ValueType freshType) {
    Preconditions.checkArgument(!unionType.isLambda());
    Preconditions.checkArgument(!freshType.isLambda());

    Pair<ValueType, ValueType> pair = swap(unionType, freshType);
    ValueType t1 = pair.fst(), t2 = pair.snd();

    if (t1.isSimple() && t2.isStruct()) {
      Collection<ECR> elems = t2.asStruct().getFieldMap().asMapOfRanges().values();
      ValueType resType = t1;
      for (ECR elem : elems) {
        ECR elemLoc = getLoc(elem);
        ValueType elemLocType = getType(elemLoc);
        Parent parent = elemLocType.getParent().removeECR(root);
        elemLocType.setParent(parent);
        if (elemLocType.isStruct()) {
          elemLocType = collapseStruct(elemLoc, elemLocType.asStruct());
        }

        union(root, elemLoc);
        resType = unify(resType, elemLocType);
      }
      return resType;
    }

    return unify(t1, t2);
  }
Beispiel #2
0
  /**
   * Swap <code>t1</code> and <code>t2</code> if <code> kind(t1) > kind(t2)
   * </code>
   *
   * @param t1
   * @param t2
   * @return the pair of value types <code>(t1', t2')</code> that <code>kind(t1') <= kind(t2')
   *     </code>
   */
  private Pair<ValueType, ValueType> swap(ValueType t1, ValueType t2) {

    if (t1.isBottom()) return Pair.of(t1, t2);
    if (t2.isBottom()) return Pair.of(t2, t1);

    if (t1.isLambda()) {
      assert t2.isLambda();
      return Pair.of(t1, t2);
    }

    if (t2.isLambda()) {
      assert t1.isLambda();
      return Pair.of(t1, t2);
    }

    ValueTypeKind kind1 = t1.getKind();
    ValueTypeKind kind2 = t2.getKind();

    switch (kind1) {
      case BOTTOM:
        return Pair.of(t1, t2);
      case BLANK:
        switch (kind2) {
          case BOTTOM:
          case BLANK:
            return Pair.of(t2, t1);
          default:
            return Pair.of(t1, t2);
        }
      case SIMPLE:
        switch (kind2) {
          case BLANK:
          case BOTTOM:
          case SIMPLE:
            return Pair.of(t2, t1);
          default:
            return Pair.of(t1, t2);
        }
      default: // case STRUCT:
        switch (kind2) {
          case BLANK:
          case BOTTOM:
          case SIMPLE:
          case STRUCT:
            return Pair.of(t2, t1);
          default:
            return Pair.of(t1, t2);
        }
    }
  }
Beispiel #3
0
  /**
   * Unify value types <code>t1</code> and <code>t2</code>
   *
   * @param t1
   * @param t2
   * @return a unified value type
   */
  ValueType unify(ValueType t1, ValueType t2) {
    Pair<ValueType, ValueType> pair = swap(t1, t2);
    t1 = pair.fst();
    t2 = pair.snd();
    if (t1.equals(t2)) return t1;
    if (t1.isBottom()) {
      if (t1.hasOpTag()) t2.enableOpTag();
      return t2;
    }

    Parent parent = Parent.getLUB(t1.getParent(), t2.getParent());
    Size size = Size.getLUB(t1.getSize(), t2.getSize());
    boolean hasOpTag = t1.hasOpTag() || t2.hasOpTag();

    switch (t1.getKind()) {
      case BLANK:
        {
          switch (t2.getKind()) {
            case BLANK:
              return ValueType.blank(size, parent, hasOpTag);
            case SIMPLE:
              {
                return ValueType.simple(
                    t2.asSimple().getLoc(), t2.asSimple().getFunc(), size, parent, hasOpTag);
              }
            default:
              { // case STRUCT:
                return ValueType.struct(t2.asStruct().getFieldMap(), size, parent, hasOpTag);
              }
          }
        }
      case SIMPLE:
        {
          switch (t2.getKind()) {
            case SIMPLE:
              {
                ECR loc1 = t1.asSimple().getLoc();
                ECR loc2 = t2.asSimple().getLoc();
                ECR func1 = t1.asSimple().getFunc();
                ECR func2 = t2.asSimple().getFunc();

                ECR loc = join(loc1, loc2);
                ECR func = join(func1, func2);

                return ValueType.simple(loc, func, size, parent, hasOpTag);
              }
            default: // case STRUCT:
              throw new IllegalArgumentException();
          }
        }
      case STRUCT:
        {
          if (ValueTypeKind.STRUCT.equals(t2.getKind())) {
            RangeMap<Long, ECR> map = getCompatibleMap(t1.asStruct(), t2.asStruct());
            return ValueType.struct(map, size, parent, hasOpTag);
          } else {
            throw new IllegalArgumentException();
          }
        }
      default:
        { // Lambda
          assert (t2.isLambda());

          List<ECR> params = Lists.newArrayList();
          Iterator<ECR> paramItr1 = t1.asLambda().getParams().iterator();
          Iterator<ECR> paramItr2 = t2.asLambda().getParams().iterator();
          while (paramItr1.hasNext() && paramItr2.hasNext()) {
            ECR param1 = paramItr1.next();
            ECR param2 = paramItr2.next();
            ECR param = join(param1, param2);
            params.add(param);
          }

          while (paramItr1.hasNext()) params.add(paramItr1.next());
          while (paramItr2.hasNext()) params.add(paramItr2.next());

          ECR ret1 = t1.asLambda().getRet();
          ECR ret2 = t2.asLambda().getRet();
          ECR ret = join(ret1, ret2);

          return ValueType.lam(ret, params, parent);
        }
    }
  }