Пример #1
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));
    }
  }
Пример #2
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);
        }
      }
    }
  }
Пример #3
0
  protected void checkUnOp(Expr.UnOp uop) {
    checkExpression(uop.expr());

    Type e_t = uop.expr().attribute(Type.class);

    switch (uop.op()) {
      case UnOp.NEG:
        if (!(e_t instanceof Type.Byte
            || e_t instanceof Type.Char
            || e_t instanceof Type.Short
            || e_t instanceof Type.Int
            || e_t instanceof Type.Long
            || e_t instanceof Type.Float
            || e_t instanceof Type.Double)) {
          ErrorHandler.handleOperatorTypeMismatch(
              new OperatorTypeMismatchException(
                  uop.expr(), T_INT, loader, types, uop.operator(), AllowedType.PRIMITIVE),
              uop.expr().attribute(SourceLocation.class));
        }
        break;
      case UnOp.NOT:
        if (!(e_t instanceof Type.Bool)) {
          ErrorHandler.handleOperatorTypeMismatch(
              new OperatorTypeMismatchException(
                  uop.expr(), T_BOOL, loader, types, uop.operator(), AllowedType.BOOL),
              uop.expr().attribute(SourceLocation.class));
        }
        break;
      case UnOp.INV:
        if (!(e_t instanceof Type.Byte
            || e_t instanceof Type.Char
            || e_t instanceof Type.Short
            || e_t instanceof Type.Int
            || e_t instanceof Type.Long)) {
          ErrorHandler.handleOperatorTypeMismatch(
              new OperatorTypeMismatchException(
                  uop.expr(), T_INT, loader, types, uop.operator(), AllowedType.NUMBER),
              uop.expr().attribute(SourceLocation.class));
        }
        break;
    }
  }
Пример #4
0
  protected void checkArrayIndex(Expr.ArrayIndex e) {
    checkExpression(e.index());
    checkExpression(e.target());

    Type i_t = e.index().attribute(Type.class);

    if (!(i_t instanceof Type.Int)) {
      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(e.index(), T_INT, loader, types),
          e.index().attribute(SourceLocation.class));
    }

    Type t_t = e.target().attribute(Type.class);
    if (!(t_t instanceof Type.Array)) {

      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(
              e.target(), new Type.Array(new Type.Wildcard(JAVA_LANG_OBJECT, null)), loader, types),
          e.attribute(SourceLocation.class));
    }
  }
Пример #5
0
  protected void checkTernOp(Expr.TernOp e) {
    checkExpression(e.condition());
    checkExpression(e.trueBranch());
    checkExpression(e.falseBranch());

    Type c_t = e.condition().attribute(Type.class);

    if (!(c_t instanceof Type.Bool)) {
      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(e.condition(), T_BOOL, loader, types),
          e.condition().attribute(SourceLocation.class));
    }
  }
Пример #6
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);
   }
 }
Пример #7
0
  protected void checkDoWhile(Stmt.DoWhile stmt) {
    checkExpression(stmt.condition());
    checkStatement(stmt.body());

    if (stmt.condition() != null) {
      Type c_t = stmt.condition().attribute(Type.class);

      if (!(c_t instanceof Type.Bool)) {
        ErrorHandler.handleTypeMismatch(
            new TypeMismatchException(stmt.condition(), T_BOOL, loader, types),
            stmt.condition().attribute(SourceLocation.class));
      }
    }
  }
Пример #8
0
  protected void checkSynchronisedBlock(Stmt.SynchronisedBlock block) {
    checkExpression(block.expr());
    checkBlock(block);

    Type e_t = block.expr().attribute(Type.class);

    if (!(e_t instanceof Type.Reference)) {
      // The most generic reference type possible - use Object as lower bound to help get the point
      // across
      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(
              block.expr(), new Type.Wildcard(JAVA_LANG_OBJECT, null), loader, types),
          block.expr().attribute(SourceLocation.class));
    }
  }
Пример #9
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);
    }
  }
Пример #10
0
  protected void checkSwitch(Stmt.Switch sw) {
    checkExpression(sw.condition());

    Type condT = sw.condition().attribute(Type.class);

    if (!(condT instanceof Type.Int)) {
      ErrorHandler.handleTypeMismatch(
          new TypeMismatchException(sw.condition(), T_INT, loader, types),
          sw.condition().attribute(SourceLocation.class));
    }

    for (Case c : sw.cases()) {
      checkExpression(c.condition());
      for (Stmt s : c.statements()) {
        checkStatement(s);
      }
    }
  }
Пример #11
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);
      }
    }
  }
Пример #12
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);
    }
  }
Пример #13
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);
    }
  }
Пример #14
0
  protected void checkBinOp(Expr.BinOp e) {
    checkExpression(e.lhs());
    checkExpression(e.rhs());

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

    if ((lhs_t instanceof Type.Primitive || rhs_t instanceof Type.Primitive)
        && !lhs_t.equals(rhs_t)) {
      if ((lhs_t instanceof Type.Long
              || lhs_t instanceof Type.Int
              || lhs_t instanceof Type.Short
              || lhs_t instanceof Type.Char
              || lhs_t instanceof Type.Byte)
          && rhs_t instanceof Type.Int
          && (e.op() == BinOp.SHL || e.op() == BinOp.SHR || e.op() == BinOp.USHR)) {
        return; // Ok!
      } else if ((isJavaLangString(lhs_t) || isJavaLangString(rhs_t)) && e.op() == BinOp.CONCAT) {
        return; // OK
      }
    } else if ((lhs_t instanceof Type.Char
            || lhs_t instanceof Type.Byte
            || lhs_t instanceof Type.Int
            || lhs_t instanceof Type.Long
            || lhs_t instanceof Type.Short
            || lhs_t instanceof Type.Float
            || lhs_t instanceof Type.Double)
        && (rhs_t instanceof Type.Char
            || rhs_t instanceof Type.Byte
            || rhs_t instanceof Type.Int
            || rhs_t instanceof Type.Long
            || rhs_t instanceof Type.Short
            || rhs_t instanceof Type.Float
            || rhs_t instanceof Type.Double)) {

      switch (e.op()) {
          // easy cases first
        case BinOp.EQ:
        case BinOp.NEQ:
        case BinOp.LT:
        case BinOp.LTEQ:
        case BinOp.GT:
        case BinOp.GTEQ:
          // need more checks here
          if (!(e_t instanceof Type.Bool)) {
            ErrorHandler.handleTypeMismatch(
                new TypeMismatchException(e, T_BOOL, loader, types),
                e.attribute(SourceLocation.class));
          }
          return;
        case BinOp.ADD:
        case BinOp.SUB:
        case BinOp.MUL:
        case BinOp.DIV:
        case BinOp.MOD:
          {
            // hmmmm ?
            return;
          }
        case BinOp.SHL:
        case BinOp.SHR:
        case BinOp.USHR:
          {
            // bit-shift operations always take an int as their rhs, so
            // make sure we have an int type
            if (lhs_t instanceof Type.Float || lhs_t instanceof Type.Double) {

              ErrorHandler.handleOperatorTypeMismatch(
                  new OperatorTypeMismatchException(
                      e.lhs(), T_INT, loader, types, e.operator(), AllowedType.INTEGER),
                  e.lhs().attribute(SourceLocation.class));

            } else if (!(rhs_t instanceof Type.Int)) {
              ErrorHandler.handleOperatorTypeMismatch(
                  new OperatorTypeMismatchException(
                      e.rhs(), T_INT, loader, types, e.operator(), AllowedType.INT),
                  e.rhs().attribute(SourceLocation.class));
            }
            return;
          }
        case BinOp.AND:
        case BinOp.OR:
        case BinOp.XOR:
          {
            if (rhs_t instanceof Type.Float || rhs_t instanceof Type.Double) {
              ErrorHandler.handleOperatorTypeMismatch(
                  new OperatorTypeMismatchException(
                      e.rhs(), T_INT, loader, types, e.operator(), AllowedType.INTEGER),
                  e.rhs().attribute(SourceLocation.class));
            }
            return;
          }
      }
    } else if (lhs_t instanceof Type.Bool && rhs_t instanceof Type.Bool) {
      switch (e.op()) {
        case BinOp.LOR:
        case BinOp.LAND:
        case BinOp.AND:
        case BinOp.OR:
        case BinOp.XOR:
        case BinOp.EQ:
        case BinOp.NEQ:
          return; // OK
      }
    } else if ((isJavaLangString(lhs_t) || isJavaLangString(rhs_t))
        && e.op() == Expr.BinOp.CONCAT) {
      return; // OK
    } else if (lhs_t instanceof Type.Reference
        && rhs_t instanceof Type.Reference
        && (e.op() == Expr.BinOp.EQ || e.op() == Expr.BinOp.NEQ)) {
      return;
    }

    if (checkTypeAllowed(lhs_t, e.getAllowed(true)))
      ErrorHandler.handleOperatorTypeMismatch(
          new OperatorTypeMismatchException(
              e.rhs(),
              (checkTypeAllowed(T_INT, e.getAllowed(false))) ? T_INT : T_BOOL,
              loader,
              types,
              e.operator(),
              e.getAllowed(false)),
          e.rhs().attribute(SourceLocation.class));

    ErrorHandler.handleOperatorTypeMismatch(
        new OperatorTypeMismatchException(
            e.lhs(),
            (checkTypeAllowed(T_INT, e.getAllowed(true))) ? T_INT : T_BOOL,
            loader,
            types,
            e.operator(),
            e.getAllowed(true)),
        e.lhs().attribute(SourceLocation.class));
  }