Example #1
0
  protected Node typeCheckNullTarget(
      TypeChecker tc, List<Type> paramTypes, List<Type> explicitTypeArgs) throws SemanticException {
    JL5TypeSystem ts = (JL5TypeSystem) tc.typeSystem();
    JL5NodeFactory nf = (JL5NodeFactory) tc.nodeFactory();
    JL5Context c = (JL5Context) tc.context();

    // the target is null, and thus implicit
    // let's find the target, using the context, and
    // set the target appropriately, and then type check
    // the result
    JL5MethodInstance mi = c.findJL5Method(this.name(), paramTypes, explicitTypeArgs);

    Receiver r;
    if (mi.flags().isStatic()) {
      r = nf.CanonicalTypeNode(position(), mi.container()).type(mi.container());
    } else {
      // The method is non-static, so we must prepend with "this", but we
      // need to determine if the "this" should be qualified. Get the
      // enclosing class which brought the method into scope. This is
      // different from mi.container(). mi.container() returns a super
      // type
      // of the class we want.
      ClassType scope = c.findMethodScope(name);

      if (!ts.equals(scope, c.currentClass())) {
        r = nf.This(position(), nf.CanonicalTypeNode(position(), scope)).type(scope);
      } else {
        r = nf.This(position()).type(scope);
      }
    }

    // we call typeCheck on the reciever too.
    r = (Receiver) r.del().typeCheck(tc);
    return this.targetImplicit(true).target(r).del().typeCheck(tc);
  }
Example #2
0
  public Node typeCheck(TypeChecker tc) throws SemanticException {
    JL5Call_c n = null;
    JL5TypeSystem ts = (JL5TypeSystem) tc.typeSystem();
    JL5Context c = (JL5Context) tc.context();
    ReferenceType targetType = null;
    List<Type> explicitTypeArgs = null;
    List<Type> paramTypes = new ArrayList<Type>();

    if (typeArguments != null && !typeArguments.isEmpty()) {
      explicitTypeArgs = new ArrayList<Type>();
      if (target() == null) {
        // should not actually happen. grammar doesn't allow it
        throw new SemanticException(
            "Explicit target required when using explicit type arguments", position());
      }
      for (Iterator it = typeArguments().iterator(); it.hasNext(); ) {
        explicitTypeArgs.add(((TypeNode) it.next()).type());
      }
    }

    for (Iterator i = this.arguments().iterator(); i.hasNext(); ) {
      Expr e = (Expr) i.next();
      paramTypes.add(e.type());
    }

    JL5MethodInstance mi;
    // JLS 15.12.1
    if (target == null) {
      return typeCheckNullTarget(tc, paramTypes, explicitTypeArgs);
    } else {
      targetType = this.findTargetType();
      mi = ts.findJL5Method(targetType, name, paramTypes, explicitTypeArgs, c);
    }

    boolean staticContext = (this.target instanceof TypeNode);

    if (staticContext && !mi.flags().isStatic()) {
      throw new SemanticException(
          "Cannot call non-static method "
              + this.name
              + " of "
              + targetType
              + " in static "
              + "context.",
          this.position());
    }

    if (this.target instanceof Special
        && ((Special) this.target).kind() == Special.SUPER
        && mi.flags().isAbstract()) {
      throw new SemanticException(
          "Cannot call an abstract method " + "of the super class", this.position());
    }

    n = (JL5Call_c) this.methodInstance(mi).type(mi.returnType());
    // n.checkConsistency(c);
    return n;
  }
  public List<Type> solve() {
    List<Constraint> constraints = getInitialConstraints();
    List<EqualConstraint> equals = new ArrayList<EqualConstraint>();
    List<SubTypeConstraint> subs = new ArrayList<SubTypeConstraint>();
    List<SuperTypeConstraint> supers = new ArrayList<SuperTypeConstraint>();

    while (!constraints.isEmpty()) {
      Constraint head = constraints.remove(0);
      if (head.canSimplify()) {
        constraints.addAll(0, head.simplify());
      } else {
        if (head instanceof EqualConstraint) {
          EqualConstraint eq = (EqualConstraint) head;
          equals.add(eq);
        } else if (head instanceof SubTypeConstraint) {
          SubTypeConstraint sub = (SubTypeConstraint) head;
          subs.add(sub);
        } else if (head instanceof SuperTypeConstraint) {
          SuperTypeConstraint sup = (SuperTypeConstraint) head;
          supers.add(sup);
        }
      }
    }
    Comparator<Constraint> comp =
        new Comparator<Constraint>() {
          public int compare(Constraint o1, Constraint o2) {
            return typeVariables().indexOf(o1) - typeVariables().indexOf(o2);
          }
        };
    Collections.sort(equals, comp);
    Collections.sort(subs, comp);

    Type[] solution = new Type[typeVariables().size()];
    for (EqualConstraint eq : equals) {
      int i = typeVariables().indexOf(eq.formal);
      if ((solution[i] != null) && (!ts.equals(eq.actual, solution[i]))) {
        solution[i] = ts.Object();
      } else {
        solution[i] = eq.actual;
      }
    }
    for (int i = 0; i < solution.length; i++) {
      if (solution[i] == null) {
        TypeVariable toSolve = typeVariables().get(i);
        Set<ClassType> uset = new HashSet<ClassType>();
        for (Constraint c : subs) {
          if (c.formal.equals(toSolve)) uset.add((ClassType) c.actual);
        }
        List<ClassType> u = new ArrayList<ClassType>(uset);
        if (u.size() == 1) {
          solution[i] = u.get(0);
        } else if (u.size() > 1) {
          solution[i] = ts.lubType(u);
        }
      }
    }
    for (int i = 0; i < solution.length; i++) if (solution[i] == null) solution[i] = ts.Object();
    List<Type> r = new ArrayList<Type>();
    Collections.addAll(r, solution);
    return r;
  }