Beispiel #1
0
 /** {@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;
 }
Beispiel #2
0
 /**
  * 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);
 }