示例#1
0
  protected void checkReturn(Stmt.Return ret) {
    JavaMethod method = (JavaMethod) getEnclosingScope(JavaMethod.class);

    if (method instanceof JavaConstructor) {
      return; // could do better than this.
    }

    Type retType = method.returnType().attribute(Type.class);

    if (ret.expr() != null) {
      checkExpression(ret.expr());

      Type ret_t = ret.expr().attribute(Type.class);
      try {
        if (ret_t.equals(new Type.Void())) {
          syntax_error("cannot return a value from method whose result type is void", ret);
        } else if (!types.subtype(retType, ret_t, loader)) {
          syntax_error("required return type " + retType + ",  found type " + ret_t, ret);
        }

      } catch (ClassNotFoundException ex) {
        syntax_error(ex.getMessage(), ret);
      }
    } else if (!(retType instanceof Type.Void)) {
      syntax_error("missing return value", ret);
    }
  }
示例#2
0
  protected void checkInstanceOf(Expr.InstanceOf e) throws ClassNotFoundException {
    checkExpression(e.lhs());

    Type lhs_t = e.lhs().attribute(Type.class);
    final Type rhs_t = e.rhs().attribute(Type.class);

    if (lhs_t instanceof Type.Primitive) {

      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(
              e.lhs(), new Type.Wildcard(JAVA_LANG_OBJECT, null), loader, types),
          e.lhs().attribute(SourceLocation.class));

    } else if (!(rhs_t instanceof Type.Reference)) {

      // This is an unusual case - the error is in the source code, so we can't
      // make a suggestion by reflection. We just make a generic suggestion

      syntax_error(
          "Syntax Error: Can only check if object is instance of an array or class type", e.rhs());

    } else if ((lhs_t instanceof Type.Array || rhs_t instanceof Type.Array)
        && !(types.subtype(lhs_t, rhs_t, loader))) {
      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(e.lhs(), rhs_t, loader, types),
          e.lhs().attribute(SourceLocation.class));
    }
  }
示例#3
0
  protected void checkVarDef(Stmt.VarDef def) {
    // Observe that we cannot use the declared type here, rather we have to
    // use the resolved type!
    Type t = def.type().attribute(Type.class);

    for (Triple<String, Integer, Expr> d : def.definitions()) {
      if (d.third() != null) {
        checkExpression(d.third());

        Type nt = t;
        for (int i = 0; i != d.second(); ++i) {
          nt = new Type.Array(nt);
        }

        Type i_t = d.third().attribute(Type.class);
        try {
          if (!types.subtype(nt, i_t, loader)) {
            ErrorHandler.handleTypeMismatch(
                new TypeMismatchException(d.third(), nt, loader, types),
                d.third().attribute(SourceLocation.class));
          }
        } catch (ClassNotFoundException ex) {
          syntax_error(ex.getMessage(), def);
        }
      }
    }
  }
示例#4
0
  protected void checkCast(Expr.Cast e) {
    Type e_t = e.expr().attribute(Type.class);
    Type c_t = e.type().attribute(Type.class);
    try {
      if (e_t instanceof Type.Clazz && c_t instanceof Type.Clazz) {
        Clazz c_c = loader.loadClass((Type.Clazz) c_t);
        Clazz e_c = loader.loadClass((Type.Clazz) e_t);

        // the trick here, is that javac will never reject a cast
        // between an interface and a class or interface. However, if we
        // have a cast from one class to another class, then it will
        // reject this if neither is a subclass of the other.
        if (c_c.isInterface() || e_c.isInterface()) {
          // cast cannot fail here.
          return;
        }
      } else if ((e_t instanceof Type.Variable || e_t instanceof Type.Wildcard)
          && c_t instanceof Type.Reference) {
        // javac always lets this pass, no matter what
        return;
      }

      if (types.boxSubtype(c_t, e_t, loader) || types.boxSubtype(e_t, c_t, loader)) {
        // this is OK
        return;
      } else if (c_t instanceof Type.Primitive && e_t instanceof Type.Primitive) {
        if (e_t instanceof Type.Char && (c_t instanceof Type.Byte || c_t instanceof Type.Short)) {
          return;
        } else if (c_t instanceof Type.Char
            && (e_t instanceof Type.Byte || e_t instanceof Type.Short)) {
          return;
        }
      }

      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(e.expr(), c_t, loader, types),
          e.attribute(SourceLocation.class));
    } catch (ClassNotFoundException ex) {
      syntax_error(ex.getMessage(), e);
    }
  }
示例#5
0
 protected void checkConvert(Expr.Convert e) {
   Type rhs_t = e.expr().attribute(Type.class);
   Type c_t = (Type) e.type().attribute(Type.class);
   try {
     if (!types.subtype(c_t, rhs_t, loader)) {
       ErrorHandler.handleTypeMismatch(
           new TypeMismatchException(e.expr(), c_t, loader, types),
           e.expr().attribute(SourceLocation.class));
     }
   } catch (ClassNotFoundException ex) {
     syntax_error(ex.getMessage(), e);
   }
 }
示例#6
0
  protected void checkAssignment(Stmt.Assignment def) {
    checkExpression(def.lhs());
    checkExpression(def.rhs());

    Type lhs_t = def.lhs().attribute(Type.class);
    Type rhs_t = def.rhs().attribute(Type.class);

    try {
      if (!types.subtype(lhs_t, rhs_t, loader)) {
        ErrorHandler.handleTypeMismatch(
            new TypeMismatchException(def.rhs(), lhs_t, loader, types),
            def.rhs().attribute(SourceLocation.class));
      }
    } catch (ClassNotFoundException ex) {
      syntax_error(ex.getMessage(), def);
    }
  }
示例#7
0
  protected void checkTryCatchBlock(Stmt.TryCatchBlock block) {
    checkBlock(block);
    checkBlock(block.finaly());

    for (final Stmt.CatchBlock cb : block.handlers()) {
      checkBlock(cb);
      try {
        if (!types.subtype(JAVA_LANG_THROWABLE, cb.type().attribute(Type.class), loader)) {

          // This is a unique case - no substitution can be found by reflection
          // (as the error is within the actual source code text), so we make a generic
          // suggestion
          syntax_error("Syntax Error: Exception type must extend java.lang.Throwable", cb.type());
        }
      } catch (ClassNotFoundException ex) {
        syntax_error(ex.getMessage(), block);
      }
    }
  }
示例#8
0
  protected void checkField(JavaField d) {
    checkExpression(d.initialiser());

    Type lhs_t = d.type().attribute(Type.class);

    if (d.initialiser() != null) {
      Type rhs_t = d.initialiser().attribute(Type.class);

      try {
        if (!types.subtype(lhs_t, rhs_t, loader)) {

          ErrorHandler.handleTypeMismatch(
              new TypeMismatchException(d.initialiser(), lhs_t, loader, types),
              d.initialiser().attribute(SourceLocation.class));
        }
      } catch (ClassNotFoundException ex) {
        syntax_error(ex.getMessage(), d);
      }
    }
  }
示例#9
0
  protected void checkForEach(Stmt.ForEach stmt) {
    checkExpression(stmt.source());
    checkStatement(stmt.body());

    // need to check that the static type of the source expression
    // implements java.lang.iterable
    Type s_t = stmt.source().attribute(Type.class);
    try {
      if (!(s_t instanceof Type.Array)
          && !types.subtype(new Type.Clazz("java.lang", "Iterable"), s_t, loader)) {

        ErrorHandler.handleTypeMismatch(
            new TypeMismatchException(
                stmt.source(),
                new Type.Wildcard(new Type.Clazz("java.lang", "Iterable"), null),
                loader,
                types),
            stmt.source().attribute(SourceLocation.class));
      }
    } catch (ClassNotFoundException ex) {
      syntax_error(ex.getMessage(), stmt);
    }
  }