/** {@inheritDoc} */ @Override public Expr resolve(Type t, Collection<ErrorWarning> warns) { if (errors.size() > 0) return this; TempList<Expr> args = new TempList<Expr>(this.args.size()); boolean changed = false; for (int i = 0; i < this.args.size(); i++) { Type p = fun.get(i).type; Expr x = this.args.get(i); Expr y = x.resolve(p, warns) .typecheck_as_set(); // Use the function's param type to narrow down the choices if (x != y) changed = true; args.add(y); // if (warns!=null && Version.experimental && !y.type.isSubtypeOf(p)) // warns.add(new ErrorWarning(x.span(), "This argument may contain a tuple not in the // parameter's type.\n" // +"The Alloy Analyzer's analysis may be unsound\n" // +"if the argument has a tuple outside the parameter's type.\n" // +"The argument has type "+y.type+"\nbut the parameter has type "+p)); } return changed ? make(pos, closingBracket, fun, args.makeConst(), extraWeight) : this; }
/** * Constructs an ExprCall node with the given predicate/function "fun" and the list of arguments * "args". */ public static Expr make( Pos pos, Pos closingBracket, Func fun, List<Expr> args, long extraPenalty) { if (extraPenalty < 0) extraPenalty = 0; if (args == null) args = ConstList.make(); long weight = extraPenalty; boolean ambiguous = false; JoinableList<Err> errs = emptyListOfErrors; TempList<Expr> newargs = new TempList<Expr>(args.size()); if (args.size() != fun.count()) { errs = errs.make( new ErrorSyntax( pos, "" + fun + " has " + fun.count() + " parameters but is called with " + args.size() + " arguments.")); } for (int i = 0; i < args.size(); i++) { final int a = (i < fun.count()) ? fun.get(i).type.arity() : 0; final Expr x = args.get(i).typecheck_as_set(); ambiguous = ambiguous || x.ambiguous; errs = errs.make(x.errors); weight = weight + x.weight; if (x.mult != 0) errs = errs.make(new ErrorSyntax(x.span(), "Multiplicity expression not allowed here.")); if (a > 0 && x.errors.isEmpty() && !x.type.hasArity(a)) errs = errs.make( new ErrorType( x.span(), "This should have arity " + a + " but instead its possible type(s) are " + x.type)); newargs.add(x); } Type t = Type.FORMULA; if (!fun.isPred && errs.size() == 0) { final Type tt = fun.returnDecl.type; try { // This provides a limited form of polymorphic function, // by using actual arguments at each call site to derive a tighter bound on the return // value. DeduceType d = new DeduceType(); for (int i = 0; i < args.size(); i++) { ExprVar param = fun.get(i); d.env.put(param, newargs.get(i).type.extract(param.type.arity())); } t = fun.returnDecl.accept(d); if (t == null || t.is_int() || t.is_bool || t.arity() != tt.arity()) t = tt; // Just in case an error occurred... } catch (Throwable ex) { t = tt; // Just in case an error occurred... } } return new ExprCall( pos, closingBracket, ambiguous, t, fun, newargs.makeConst(), extraPenalty, weight, errs); }