예제 #1
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);
        }
    }
  }
예제 #2
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);
        }
    }
  }
예제 #3
0
  void ccjoin(Size rangeSize, ECR e1, ECR e2) {
    ValueType type1 = getType(e1);
    if (type1.isBottom()) {
      addCCjoin(rangeSize, e1, e2);
      return;
    }

    Size size1 = type1.getSize();
    if (!Size.isLessThan(rangeSize, size1)) {
      addCCjoin(rangeSize, e1, e2);
      expand(e1, rangeSize); // expand(e1) would call setType(e1, ...) and thus ccjoin(e1, e2)
      return;
    }

    if (e1.equals(e2)) return;

    switch (type1.getKind()) {
      case BLANK:
        {
          addCCjoin(rangeSize, e1, e2);
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              setType(e2, ValueType.blank(rangeSize, Parent.getBottom()));
              return;
            default:
              Size size2 = type2.getSize();
              if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
              return;
          }
        }
      case SIMPLE:
        {
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              setType(
                  e2,
                  ValueType.simple(
                      type1.asSimple().getLoc(),
                      type1.asSimple().getFunc(),
                      rangeSize,
                      Parent.getBottom(),
                      type2.hasOpTag()));
              return;
            case BLANK:
              {
                setType(
                    e2,
                    ValueType.simple(
                        type1.asSimple().getLoc(),
                        type1.asSimple().getFunc(),
                        type2.getSize(),
                        type2.getParent(),
                        type2.hasOpTag()));
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case SIMPLE:
              {
                cjoin(type1.asSimple().getLoc(), type2.asSimple().getLoc());
                cjoin(type1.asSimple().getFunc(), type2.asSimple().getFunc());
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case STRUCT:
              {
                addCCjoin(rangeSize, e1, e2);
                collapseStruct(e2, type2.asStruct());
                return;
              }
            default: // lambda
              return;
          }
        }
      case STRUCT:
        {
          ValueType type2 = getType(e2);
          switch (type2.getKind()) {
            case BOTTOM:
              {
                RangeMap<Long, ECR> fieldMapCopy = FieldRangeMap.create();
                fieldMapCopy.putAll(type1.asStruct().getFieldMap());
                setType(
                    e2,
                    ValueType.struct(
                        fieldMapCopy, rangeSize, Parent.getBottom(), type2.hasOpTag()));
                return;
              }
            case BLANK:
              {
                RangeMap<Long, ECR> fieldMapCopy = FieldRangeMap.create();
                fieldMapCopy.putAll(type1.asStruct().getFieldMap());
                Size size2 = type2.getSize();
                setType(
                    e2, ValueType.struct(fieldMapCopy, size2, type2.getParent(), type2.hasOpTag()));
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                return;
              }
            case SIMPLE:
              {
                addCCjoin(rangeSize, e1, e2);
                Size size2 = type2.getSize();
                if (!Size.isLessThan(rangeSize, size2)) expand(e2, rangeSize);
                for (ECR elemECR : type1.asStruct().getFieldMap().asMapOfRanges().values()) {
                  ValueType elemType = getType(elemECR);
                  Size elemSize = elemType.getSize();
                  ccjoin(elemSize, elemECR, e2);
                }
                return;
              }
            case STRUCT:
              {
                throw new IllegalArgumentException();
                //				Size size2 = type2.getSize();
                //				if(!Size.isLessThan(rangeSize, size2)) {
                //					addCCjoin(rangeSize, e1, e2);
                //					expand(e2, rangeSize); return;
                //				}
                //
                //				ValueType unifyStructType = unify(type1, type2); // unify structure type
                // eagerly
                //				setType(e1, unifyStructType);
                //				setType(e2, unifyStructType);
                //				return;
              }
            default:
              return; // lambda
          }
        }
      default:
        return; // lambda
    }
  }