예제 #1
0
  /**
   * Returns <code>true</code> if type src can be converted to type dst.
   *
   * @param src a type
   * @param dst the type src should be converted to
   * @return <code>true</code> if type src can be converted to type dst
   */
  public static boolean isConvertibleTo(Type src, Type dst) {
    if (src == null || dst == null) {
      return false;
    }

    if (src.isFloat() && dst.isFloat()) {
      return dst.getSizeInBits() >= src.getSizeInBits();
    }

    if (src.isBool() && dst.isBool()
        || src.isString() && dst.isString()
        || (src.isInt() || src.isUint()) && (dst.isInt() || dst.isUint())
        || (src.isInt() || src.isUint()) && dst.isFloat()) {
      return true;
    }

    if (src.isList() && dst.isList()) {
      TypeList typeSrc = (TypeList) src;
      TypeList typeDst = (TypeList) dst;
      // Recursively check type convertibility
      if (isConvertibleTo(typeSrc.getType(), typeDst.getType())) {
        if (typeSrc.getSizeExpr() != null && typeDst.getSizeExpr() != null) {
          return typeSrc.getSize() <= typeDst.getSize();
        }
        return true;
      }
    }

    return false;
  }
예제 #2
0
  /**
   * Returns the Greatest Lower Bound of the given types. The GLB is the smallest type of (t1, t2).
   * When t1 and t2 have different types (e.g. one is a int and the other is a uint), an int is
   * returned.
   *
   * @param t1 a type
   * @param t2 another type
   * @return the Greatest Lower Bound of the given types
   */
  public static Type getGlb(Type t1, Type t2) {
    if (t1.isBool() && t2.isBool()) {
      return IrFactory.eINSTANCE.createTypeBool();
    } else if (t1.isInt() && t2.isInt()) {
      return IrFactory.eINSTANCE.createTypeInt(
          Math.min(((TypeInt) t1).getSize(), ((TypeInt) t2).getSize()));
    } else if (t1.isUint() && t2.isUint()) {
      return IrFactory.eINSTANCE.createTypeUint(
          Math.min(((TypeUint) t1).getSize(), ((TypeUint) t2).getSize()));
    } else if (t1.isInt() && t2.isUint()) {
      int si = ((TypeInt) t1).getSize();
      int su = ((TypeUint) t2).getSize();
      if (si > su) {
        return IrFactory.eINSTANCE.createTypeInt(su + 1);
      } else {
        return IrFactory.eINSTANCE.createTypeInt(si);
      }
    } else if (t1.isUint() && t2.isInt()) {
      int su = ((TypeUint) t1).getSize();
      int si = ((TypeInt) t2).getSize();
      if (si > su) {
        return IrFactory.eINSTANCE.createTypeInt(su + 1);
      } else {
        return IrFactory.eINSTANCE.createTypeInt(si);
      }
    }

    return null;
  }
예제 #3
0
  /**
   * Returns the Least Upper Bound of the given types, which is the smallest type that can contain
   * both types. If no such type exists (e.g. when types are not compatible with each other), <code>
   * null</code> is returned.
   *
   * @param t1 a type
   * @param t2 another type
   * @return the Least Upper Bound of the given types
   */
  public static Type getLub(Type t1, Type t2) {
    if (t1 == null || t2 == null) {
      return null;
    }

    if (t1.isBool() && t2.isBool()) {
      return IrFactory.eINSTANCE.createTypeBool();
    } else if (t1.isFloat() && t2.isFloat()) {
      return IrFactory.eINSTANCE.createTypeFloat(
          Math.max(((TypeFloat) t1).getSize(), ((TypeFloat) t2).getSize()));
    } else if (t1.isString() && t2.isString()) {
      return IrFactory.eINSTANCE.createTypeString();
    } else if (t1.isInt() && t2.isInt()) {
      return IrFactory.eINSTANCE.createTypeInt(
          Math.max(((TypeInt) t1).getSize(), ((TypeInt) t2).getSize()));
    } else if (t1.isList() && t2.isList()) {
      TypeList listType1 = (TypeList) t1;
      TypeList listType2 = (TypeList) t2;
      Type type = getLub(listType1.getType(), listType2.getType());
      if (type != null) {
        // only return a list when the underlying type is valid
        int size = Math.max(listType1.getSize(), listType2.getSize());
        return IrFactory.eINSTANCE.createTypeList(size, type);
      }
    } else if (t1.isUint() && t2.isUint()) {
      return IrFactory.eINSTANCE.createTypeUint(
          Math.max(((TypeUint) t1).getSize(), ((TypeUint) t2).getSize()));
    } else if (t1.isInt() && t2.isUint()) {
      int si = ((TypeInt) t1).getSize();
      int su = ((TypeUint) t2).getSize();
      if (si > su) {
        return IrFactory.eINSTANCE.createTypeInt(si);
      } else {
        return IrFactory.eINSTANCE.createTypeInt(su + 1);
      }
    } else if (t1.isUint() && t2.isInt()) {
      int su = ((TypeUint) t1).getSize();
      int si = ((TypeInt) t2).getSize();
      if (si > su) {
        return IrFactory.eINSTANCE.createTypeInt(si);
      } else {
        return IrFactory.eINSTANCE.createTypeInt(su + 1);
      }
    }

    return null;
  }
예제 #4
0
  /**
   * Creates a new type based on the unification of t1 and t2, and clips its size to {@link
   * #maxSize}.
   *
   * @param t1 a type
   * @param t2 a type
   * @param unification how to unify t1 and t2
   */
  public static Type createType(Type t1, Type t2, Unification unification) {
    Type type = unification.getType(t1, t2);
    int size = unification.getSize(t1, t2);

    // only set the size if it is different than 0
    if (size != 0) {
      if (type.isInt()) {
        ((TypeInt) type).setSize(size);
      } else if (type.isUint()) {
        ((TypeUint) type).setSize(size);
      }
    }

    return type;
  }
예제 #5
0
  /**
   * Returns the type of a binary expression whose left operand has type t1 and right operand has
   * type t2, and whose operator is given.
   *
   * <p>TODO replace automatic int/uint to float casting with explicit casts
   *
   * @param op operator
   * @param t1 type of the first operand
   * @param t2 type of the second operand
   * @param source source object
   * @param feature feature
   * @return the type of the binary expression, or <code>null</code>
   */
  public static Type getTypeBinary(OpBinary op, Type t1, Type t2) {
    if (t1 == null || t2 == null) {
      return null;
    }

    switch (op) {
      case BITAND:
        return createType(t1, t2, Glb.instance);

      case BITOR:
      case BITXOR:
        return createType(t1, t2, Lub.instance);

      case TIMES:
        if ((t1.isInt() || t1.isUint()) && t2.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t2.getSizeInBits());
        } else if ((t2.isInt() || t2.isUint()) && t1.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t1.getSizeInBits());
        } else if (t1.isFloat() && t2.isFloat()) {
          return createType(t1, t2, Lub.instance);
        }
        return createType(t1, t2, LubSum.instance);

      case MINUS:
        if ((t1.isInt() || t1.isUint()) && t2.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t2.getSizeInBits());
        } else if ((t2.isInt() || t2.isUint()) && t1.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t1.getSizeInBits());
        } else if (t1.isFloat() && t2.isFloat()) {
          return createType(t1, t2, Lub.instance);
        }
        return createType(t1, t2, SignedLub.instance);

      case PLUS:
        if (t1.isString() && !t2.isList() || t2.isString() && !t1.isList()) {
          return IrFactory.eINSTANCE.createTypeString();
        }

        if ((t1.isInt() || t1.isUint()) && t2.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t2.getSizeInBits());
        } else if ((t2.isInt() || t2.isUint()) && t1.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t1.getSizeInBits());
        } else if (t1.isFloat() && t2.isFloat()) {
          return createType(t1, t2, Lub.instance);
        }
        return createType(t1, t2, LubPlus1.instance);

      case DIV:
      case DIV_INT:
        if ((t1.isInt() || t1.isUint()) && t2.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t2.getSizeInBits());
        } else if ((t2.isInt() || t2.isUint()) && t1.isFloat()) {
          return IrFactory.eINSTANCE.createTypeFloat(t1.getSizeInBits());
        } else if (t1.isFloat() && t2.isFloat()) {
          return createType(t1, t2, Lub.instance);
        }
      case SHIFT_RIGHT:
        return EcoreUtil.copy(t1);

      case MOD:
        return EcoreUtil.copy(t2);

      case SHIFT_LEFT:
        return createType(t1, t2, LubSumPow.instance);

      case EQ:
      case GE:
      case GT:
      case LE:
      case LT:
      case NE:
        return IrFactory.eINSTANCE.createTypeBool();

      case EXP:
        return null;

      case LOGIC_AND:
      case LOGIC_OR:
        return IrFactory.eINSTANCE.createTypeBool();

      default:
        return null;
    }
  }