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