1 /*****
2  * application.cc
3  * Andy Hammerlindl 2005/05/20
4  *
5  * An application is a matching of arguments in a call expression to formal
6  * parameters of a function.  Since the language allows default arguments,
7  * keyword arguments, rest arguments, and anything else we think of, this
8  * is not a simple mapping.
9  *****/
10 
11 #include "application.h"
12 #include "exp.h"
13 #include "coenv.h"
14 #include "runtime.h"
15 #include "runarray.h"
16 
17 using namespace types;
18 using absyntax::varinit;
19 using absyntax::arrayinit;
20 using absyntax::arglist;
21 
22 namespace trans {
23 
24 // Lower scores are better.  Packed is added onto the other qualifiers so
25 // we may score both exact and casted packed arguments.
26 const score FAIL=0, EXACT=1, CAST=2;
27 const score PACKED=2;
28 
castable(env & e,formal & target,formal & source)29 bool castable(env &e, formal& target, formal& source) {
30   return target.Explicit ? equivalent(target.t,source.t)
31     : e.castable(target.t,source.t, symbol::castsym);
32 }
33 
castScore(env & e,formal & target,formal & source)34 score castScore(env &e, formal& target, formal& source) {
35   return equivalent(target.t,source.t) ? EXACT :
36     (!target.Explicit &&
37      e.fastCastable(target.t,source.t)) ? CAST : FAIL;
38 }
39 
40 
transMaker(coenv & e,Int size,bool rest)41 void restArg::transMaker(coenv &e, Int size, bool rest) {
42   // Push the number of cells and call the array maker.
43   e.c.encode(inst::intpush, size);
44   e.c.encode(inst::builtin, rest ? run::newAppendedArray :
45              run::newInitializedArray);
46 }
47 
trans(coenv & e,temp_vector & temps)48 void restArg::trans(coenv &e, temp_vector &temps)
49 {
50   // Push the values on the stack.
51   for (mem::list<arg *>::iterator p = inits.begin(); p != inits.end(); ++p)
52     (*p)->trans(e, temps);
53 
54   if (rest)
55     rest->trans(e, temps);
56 
57   transMaker(e, (Int)inits.size(), (bool)rest);
58 }
59 
60 class maximizer {
61   app_list l;
62 
63   // Tests if x is as good (or better) an application as y.
asgood(application * x,application * y)64   bool asgood(application *x, application *y) {
65     // Matches to open signatures are always worse than matches to normal
66     // signatures.
67     if (x->sig->isOpen)
68       return y->sig->isOpen;
69     else if (y->sig->isOpen)
70       return true;
71 
72     assert (x->scores.size() == y->scores.size());
73 
74     // Test if each score in x is no higher than the corresponding score in
75     // y.
76     return std::equal(x->scores.begin(), x->scores.end(), y->scores.begin(),
77                       std::less_equal<score>());
78   }
79 
better(application * x,application * y)80   bool better(application *x, application *y) {
81     return asgood(x,y) && !asgood(y,x);
82   }
83 
84   // Add an application that has already been determined to be maximal.
85   // Remove any other applications that are now not maximal because of its
86   // addition.
addMaximal(application * x)87   void addMaximal(application *x) {
88     app_list::iterator y=l.begin();
89     while (y!=l.end())
90       if (better(x,*y))
91         y=l.erase(y);
92       else
93         ++y;
94     l.push_front(x);
95   }
96 
97   // Tests if x is maximal.
maximal(application * x)98   bool maximal(application *x) {
99     for (app_list::iterator y=l.begin(); y!=l.end(); ++y)
100       if (better(*y,x))
101         return false;
102     return true;
103   }
104 
105 public:
maximizer()106   maximizer() {}
107 
add(application * x)108   void add(application *x) {
109     if (maximal(x))
110       addMaximal(x);
111   }
112 
result()113   app_list result() {
114     return l;
115   }
116 };
117 
restCellType(signature * sig)118 ty *restCellType(signature *sig) {
119   formal& f=sig->getRest();
120   if (f.t) {
121     array *a=dynamic_cast<array *>(f.t);
122     if (a)
123       return a->celltype;
124   }
125 
126   return 0;
127 }
128 
initRest()129 void application::initRest() {
130   formal& f=sig->getRest();
131   if (f.t) {
132     ty *ct = restCellType(sig);
133     if (!ct)
134       vm::error("formal rest argument must be an array");
135 
136     rf=formal(ct, symbol::nullsym, false, f.Explicit);
137   }
138   if (f.t || sig->isOpen) {
139     rest=new restArg();
140   }
141 }
142 
143 //const Int REST=-1;
144 const Int NOMATCH=-2;
145 
find(symbol name)146 Int application::find(symbol name) {
147   formal_vector &f=sig->formals;
148   for (size_t i=index; i<f.size(); ++i)
149     if (f[i].name==name && args[i]==0)
150       return (Int)i;
151   return NOMATCH;
152 }
153 
matchDefault()154 bool application::matchDefault() {
155   if (index==args.size())
156     return false;
157   else {
158     formal &target=getTarget();
159     if (target.defval) {
160       args[index]=new defaultArg(target.t);
161       advanceIndex();
162       return true;
163     }
164     else
165       return false;
166   }
167 }
168 
matchArgumentToRest(env & e,formal & source,varinit * a,size_t evalIndex)169 bool application::matchArgumentToRest(env &e, formal &source,
170                                       varinit *a, size_t evalIndex)
171 {
172   if (rest) {
173     score s=castScore(e, rf, source);
174     if (s!=FAIL) {
175       rest->add(seq.addArg(a, rf.t, evalIndex));
176       scores.push_back(s+PACKED);
177       return true;
178     }
179   }
180   return false;
181 }
182 
matchAtSpot(size_t spot,env & e,formal & source,varinit * a,size_t evalIndex)183 bool application::matchAtSpot(size_t spot, env &e, formal &source,
184                               varinit *a, size_t evalIndex)
185 {
186   formal &target=sig->getFormal(spot);
187   if(target.t->kind == types::ty_error) return false;
188 
189   score s=castScore(e, target, source);
190 
191   if (s == FAIL)
192     return false;
193   else if (sig->formalIsKeywordOnly(spot) && source.name == symbol::nullsym)
194     return false;
195   else {
196     // The argument matches.
197     args[spot]=seq.addArg(a, target.t, evalIndex);
198     if (spot==index)
199       advanceIndex();
200     scores.push_back(s);
201     return true;
202   }
203 }
204 
matchArgument(env & e,formal & source,varinit * a,size_t evalIndex)205 bool application::matchArgument(env &e, formal &source,
206                                 varinit *a, size_t evalIndex)
207 {
208   assert(!source.name);
209 
210   if (index==args.size())
211     // Try to pack into the rest array.
212     return matchArgumentToRest(e, source, a, evalIndex);
213   else
214     // Match here, or failing that use a default and try to match at the next
215     // spot.
216     return matchAtSpot(index, e, source, a, evalIndex) ||
217       (matchDefault() && matchArgument(e, source, a, evalIndex));
218 }
219 
matchNamedArgument(env & e,formal & source,varinit * a,size_t evalIndex)220 bool application::matchNamedArgument(env &e, formal &source,
221                                      varinit *a, size_t evalIndex)
222 {
223   assert(source.name);
224 
225   Int spot=find(source.name);
226   return spot!=NOMATCH && matchAtSpot(spot, e, source, a, evalIndex);
227 }
228 
complete()229 bool application::complete() {
230   if (index==args.size())
231     return true;
232   else if (matchDefault())
233     return complete();
234   else
235     return false;
236 }
237 
matchRest(env & e,formal & source,varinit * a,size_t evalIndex)238 bool application::matchRest(env &e, formal &source, varinit *a,
239                             size_t evalIndex) {
240   // First make sure all non-rest arguments are matched (matching to defaults
241   // if necessary).
242   if (complete())
243     // Match rest to rest.
244     if (rest) {
245       formal &target=sig->getRest();
246       score s=castScore(e, target, source);
247       if (s!=FAIL) {
248         rest->addRest(seq.addArg(a, target.t, evalIndex));
249         scores.push_back(s);
250         return true;
251       }
252     }
253   return false;
254 }
255 
256 // When the argument should be evaluated, possibly adjusting for a rest
257 // argument which occurs before named arguments.
adjustIndex(size_t i,size_t ri)258 size_t adjustIndex(size_t i, size_t ri)
259 {
260   return i < ri ? i : i+1;
261 }
262 
matchSignature(env & e,types::signature * source,arglist & al)263 bool application::matchSignature(env &e, types::signature *source,
264                                  arglist &al) {
265   formal_vector &f=source->formals;
266 
267 #if 0
268   cout << "num args: " << f.size() << endl;
269   cout << "num keyword-only: " << sig->numKeywordOnly << endl;
270 #endif
271 
272   size_t ri = al.rest.val ? al.restPosition : f.size();
273 
274   // First, match all of the named (non-rest) arguments.
275   for (size_t i=0; i<f.size(); ++i)
276     if (f[i].name)
277       if (!matchNamedArgument(e, f[i], al[i].val, adjustIndex(i,ri)))
278         return false;
279 
280   // Then, the unnamed.
281   for (size_t i=0; i<f.size(); ++i)
282     if (!f[i].name)
283       if (!matchArgument(e, f[i], al[i].val, adjustIndex(i,ri)))
284         return false;
285 
286   // Then, the rest argument.
287   if (source->hasRest())
288     if (!matchRest(e, source->getRest(), al.rest.val, ri))
289       return false;
290 
291   // Fill in any remaining arguments with their defaults.
292   return complete();
293 }
294 
matchOpen(env & e,signature * source,arglist & al)295 bool application::matchOpen(env &e, signature *source, arglist &al) {
296   assert(rest);
297 
298   // Pack all given parameters into the rest argument.
299   formal_vector &f=source->formals;
300   for (size_t i = 0; i < f.size(); ++i)
301     if (al[i].name)
302       // Named arguments are not handled by open signatures.
303       return false;
304     else
305       rest->add(seq.addArg(al[i].val, f[i].t, i));
306 
307   if (source->hasRest())
308     rest->addRest(new varinitArg(al.rest.val, source->getRest().t));
309 
310   return true;
311 }
312 
match(env & e,function * t,signature * source,arglist & al)313 application *application::match(env &e, function *t, signature *source,
314                                 arglist &al) {
315   assert(t->kind==ty_function);
316   application *app=new application(t);
317 
318   bool success = t->getSignature()->isOpen ?
319     app->matchOpen(e, source, al) :
320     app->matchSignature(e, source, al);
321 
322   //cout << "MATCH " << success << endl;
323 
324   return success ? app : 0;
325 }
326 
transArgs(coenv & e)327 void application::transArgs(coenv &e) {
328   temp_vector temps;
329 
330   for(arg_vector::iterator a=args.begin(); a != args.end(); ++a)
331     (*a)->trans(e,temps);
332 
333   if (rest)
334     rest->trans(e,temps);
335 }
336 
exact()337 bool application::exact() {
338   if (sig->isOpen)
339     return false;
340   for (score_vector::iterator p = scores.begin(); p != scores.end(); ++p)
341     if (*p != EXACT)
342       return false;
343   return true;
344 }
345 
halfExact()346 bool application::halfExact() {
347   if (sig->isOpen)
348     return false;
349   if (scores.size() != 2)
350     return false;
351   if (scores[0] == EXACT && scores[1] == CAST)
352     return true;
353   if (scores[0] == CAST && scores[1] == EXACT)
354     return true;
355   return false;
356 }
357 
358 // True if any of the formals have names.
namedFormals(signature * sig)359 bool namedFormals(signature *sig)
360 {
361   formal_vector& formals = sig->formals;
362   size_t n = formals.size();
363   for (size_t i = 0; i < n; ++i) {
364     if (formals[i].name)
365       return true;
366   }
367   return false;
368 }
369 
370 // Tests if arguments in the source signature can be matched to the formals
371 // in the target signature with no casting or packing.
372 // This allows overloaded args, but not named args.
exactMightMatch(signature * target,signature * source)373 bool exactMightMatch(signature *target, signature *source)
374 {
375   // Open signatures never exactly match.
376   if (target->isOpen)
377     return false;
378 
379 #if 0
380   assert(!namedFormals(source));
381 #endif
382 
383   formal_vector& formals = target->formals;
384   formal_vector& args = source->formals;
385 
386   // Sizes of the two lists.
387   size_t fn = formals.size(), an = args.size();
388 
389   // Indices for the two lists.
390   size_t fi = 0, ai = 0;
391 
392   while (fi < fn && ai < an) {
393     if (equivalent(formals[fi].t, args[ai].t)) {
394       // Arguments match, move to the next.
395       ++fi; ++ai;
396     } else if (formals[fi].defval) {
397       // Match formal to default value.
398       ++fi;
399     } else {
400       // Failed to match formal.
401       return false;
402     }
403   }
404 
405   assert(fi == fn || ai == an);
406 
407   // Packing array arguments into the rest formal is inexact.  Do not allow it
408   // here.
409   if (ai < an)
410     return false;
411 
412   assert(ai == an);
413 
414   // Match any remaining formal to defaults.
415   while (fi < fn)
416     if (formals[fi].defval) {
417       // Match formal to default value.
418       ++fi;
419     } else {
420       // Failed to match formal.
421       return false;
422     }
423 
424   // Non-rest arguments have matched.
425   assert(fi == fn && ai == an);
426 
427   // Try to match the rest argument if given.
428   if (source->hasRest()) {
429     if (!target->hasRest())
430       return false;
431 
432     if (!equivalent(source->getRest().t, target->getRest().t))
433       return false;
434   }
435 
436   // All arguments have matched.
437   return true;
438 }
439 
440 // Tries to match applications without casting.  If an application matches
441 // here, we need not attempt to match others with the slower, more general
442 // techniques.
exactMultimatch(env & e,types::overloaded * o,types::signature * source,arglist & al)443 app_list exactMultimatch(env &e,
444                          types::overloaded *o,
445                          types::signature *source,
446                          arglist &al)
447 {
448   assert(source);
449 
450   app_list l;
451 
452   // This can't handle named arguments.
453   if (namedFormals(source))
454     return l; /* empty */
455 
456   for (ty_vector::iterator t=o->sub.begin(); t!=o->sub.end(); ++t)
457     {
458       if ((*t)->kind != ty_function)
459         continue;
460 
461       function *ft = (function *)*t;
462 
463       // First we run a test to see if all arguments could be exactly matched.
464       // If this returns false, no such match is possible.
465       // If it returns true, an exact match may or may not be possible.
466       if (!exactMightMatch(ft->getSignature(), source))
467         continue;
468 
469       application *a=application::match(e, ft, source, al);
470 
471       // Consider calling
472       //   void f(A a=new A, int y)
473       // with
474       //   f(3)
475       // This matches exactly if there is no implicit cast from int to A.
476       // Otherwise, it does not match.
477       // Thus, there is no way to know if the
478       // match truly is exact without looking at the environment.
479       // In such a case, exactMightMatch() must return true, but there is no
480       // exact match.  Such false positives are eliminated here.
481       //
482       // Consider calling
483       //   void f(int x, real y=0.0, int z=0)
484       // with
485       //   f(1,2)
486       // exactMightMatch() will return true, matching 1 to x and 2 to z, but the
487       // application::match will give an inexact match of 1 to x to 2 to y, due
488       // to the cast from int to real.  Therefore, we must test for exactness
489       // even after matching.
490       if (a && a->exact())
491         l.push_back(a);
492     }
493 
494   //cout << "EXACTMATCH " << (!l.empty()) << endl;
495   return l;
496 }
497 
halfExactMightMatch(env & e,signature * target,types::ty * t1,types::ty * t2)498 bool halfExactMightMatch(env &e,
499                          signature *target, types::ty *t1, types::ty *t2)
500 {
501   formal_vector& formals = target->formals;
502   if (formals.size() < 2)
503     return false;
504   if (formals.size() > 2) {
505     // We should probably abort the whole matching in this case.  For now,
506     // return true and let the usual matching handle it.
507     return true;
508   }
509 
510   assert(formals[0].t);
511   assert(formals[1].t);
512 
513   // These casting tests if successful will be repeated again by
514   // application::match.  It would be nice to avoid this somehow, but the
515   // additional complexity is probably not worth the minor speed improvement.
516   if (equivalent(formals[0].t, t1))
517     return e.fastCastable(formals[1].t, t2);
518   else
519     return equivalent(formals[1].t, t2) && e.fastCastable(formals[0].t, t1);
520 }
521 
522 // Most common after exact matches are cases such as
523 //   2 + 3.4   (int, real) --> (real, real)
524 // that is, binary operations where one of the operands matches exactly and the
525 // other does not.  This function searches for these so-called "half-exact"
526 // matches.  This should only be called after exactMultimatch has failed.
halfExactMultimatch(env & e,types::overloaded * o,types::signature * source,arglist & al)527 app_list halfExactMultimatch(env &e,
528                              types::overloaded *o,
529                              types::signature *source,
530                              arglist &al)
531 {
532   assert(source);
533 
534   app_list l;
535 
536 
537   // Half exact is only in the case of two arguments.
538   formal_vector& formals = source->formals;
539   if (formals.size() != 2 || source->hasRest())
540     return l; /* empty */
541 
542   // This can't handle named arguments.
543   if (namedFormals(source))
544     return l; /* empty */
545 
546   // Alias the two argument types.
547   types::ty *t1 = formals[0].t;
548   types::ty *t2 = formals[1].t;
549 
550   assert(t1); assert(t2);
551 
552   for (ty_vector::iterator t=o->sub.begin(); t!=o->sub.end(); ++t)
553     {
554       if ((*t)->kind != ty_function)
555         continue;
556 
557       function *ft = (function *)*t;
558 
559 #if 1
560       if (!halfExactMightMatch(e, ft->getSignature(), t1, t2))
561         continue;
562 #endif
563 
564       application *a=application::match(e, ft, source, al);
565 
566 #if 1
567       if (a && a->halfExact())
568         l.push_back(a);
569 #endif
570     }
571 
572   return l;
573 }
574 
575 // Simple check if there are too many arguments to match the candidate
576 // function.
577 // A "tooFewArgs" variant was also implemented at some point, but did
578 // not give any speed-up.
tooManyArgs(types::signature * target,types::signature * source)579 bool tooManyArgs(types::signature *target, types::signature *source) {
580   return source->getNumFormals() > target->getNumFormals() &&
581     !target->hasRest();
582 }
583 
584 // The full overloading resolution system, which handles casting of arguments,
585 // packing into rest arguments, named arguments, etc.
inexactMultimatch(env & e,types::overloaded * o,types::signature * source,arglist & al)586 app_list inexactMultimatch(env &e,
587                            types::overloaded *o,
588                            types::signature *source,
589                            arglist &al)
590 {
591   assert(source);
592 
593   app_list l;
594 
595 
596 #define DEBUG_GETAPP 0
597 #if DEBUG_GETAPP
598   //cout << "source: " << *source << endl;
599   //cout << "ARGS: " << source->getNumFormals() << endl;
600   bool perfect=false;
601   bool exact=false;
602   bool halfExact=false;
603 #endif
604 
605   for(ty_vector::iterator t=o->sub.begin(); t!=o->sub.end(); ++t) {
606     if ((*t)->kind==ty_function) {
607 #if DEBUG_GETAPP
608       function *ft = dynamic_cast<function *>(*t);
609       signature *target = ft->getSignature();
610       if (equivalent(target, source))
611         perfect = true;
612 #endif
613 
614       // Check if there are two many arguments to match.
615       if (tooManyArgs((*t)->getSignature(), source))
616         continue;
617 
618       application *a=application::match(e, (function *)(*t), source, al);
619       if (a)
620         l.push_back(a);
621 
622 #if DEBUG_GETAPP
623       if (a && !namedFormals(source)) {
624         assert(a->exact() == exactlyMatchable(ft->getSignature(), source));
625         if (a->halfExact() && !namedFormals(source)) {
626           assert(halfExactMightMatch(e, target, source->getFormal(0).t,
627                                      source->getFormal(1).t));
628         }
629 
630       }
631       if (a && a->exact())
632         exact = true;
633       if (a && a->halfExact())
634         halfExact = true;
635 #endif
636     }
637   }
638 
639 #if DEBUG_GETAPP
640   cout << (perfect     ? "PERFECT" :
641            exact       ? "EXACT" :
642            halfExact   ? "HALFEXACT" :
643            "IMPERFECT")
644        << endl;
645 #endif
646 
647   if (l.size() > 1) {
648     // Return the most specific candidates.
649     maximizer m;
650     for (app_list::iterator x=l.begin(); x!=l.end(); ++x) {
651       assert(*x);
652       m.add(*x);
653     }
654     return m.result();
655   }
656   else
657     return l;
658 }
659 
660 enum testExactType {
661   TEST_EXACT,
662   DONT_TEST_EXACT,
663 };
664 
665 // Sanity check for multimatch optimizations.
sameApplications(app_list a,app_list b,testExactType te)666 void sameApplications(app_list a, app_list b, testExactType te) {
667   assert(a.size() == b.size());
668 
669   if (te == TEST_EXACT) {
670     for (app_list::iterator i = a.begin(); i != a.end(); ++i) {
671       if (!(*i)->exact()) {
672         cout << *(*i)->getType() << endl;
673       }
674       assert((*i)->exact());
675     }
676     for (app_list::iterator i = b.begin(); i != b.end(); ++i)
677       assert((*i)->exact());
678   }
679 
680   if (a.size() == 1)
681     assert(equivalent(a.front()->getType(), b.front()->getType()));
682 }
683 
multimatch(env & e,types::overloaded * o,types::signature * source,arglist & al)684 app_list multimatch(env &e,
685                     types::overloaded *o,
686                     types::signature *source,
687                     arglist &al)
688 {
689   app_list a = exactMultimatch(e, o, source, al);
690   if (!a.empty()) {
691 #if DEBUG_CACHE
692     // Make sure that exactMultimatch and the fallback return the same
693     // application(s).
694     sameApplications(a, inexactMultimatch(e, o, source, al), TEST_EXACT);
695 #endif
696 
697     return a;
698   }
699 
700   a = halfExactMultimatch(e, o, source, al);
701   if (!a.empty()) {
702 #if DEBUG_CACHE
703     sameApplications(a, inexactMultimatch(e, o, source, al), DONT_TEST_EXACT);
704 #endif
705 
706     return a;
707   }
708 
709   // Slow but most general method.
710   return inexactMultimatch(e, o, source, al);
711 }
712 
713 } // namespace trans
714