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); }
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; }