diff options
author | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
---|---|---|
committer | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
commit | c6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch) | |
tree | 1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/utils/asymptote/application.cc | |
parent | 07ee7222e389b0777456b427a55c22d0e6ffd267 (diff) |
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/application.cc')
-rw-r--r-- | Build/source/utils/asymptote/application.cc | 713 |
1 files changed, 0 insertions, 713 deletions
diff --git a/Build/source/utils/asymptote/application.cc b/Build/source/utils/asymptote/application.cc deleted file mode 100644 index 0a3c0f10353..00000000000 --- a/Build/source/utils/asymptote/application.cc +++ /dev/null @@ -1,713 +0,0 @@ -/***** - * application.cc - * Andy Hammerlindl 2005/05/20 - * - * An application is a matching of arguments in a call expression to formal - * parameters of a function. Since the language allows default arguments, - * keyword arguments, rest arguments, and anything else we think of, this - * is not a simple mapping. - *****/ - -#include "application.h" -#include "exp.h" -#include "coenv.h" -#include "runtime.h" -#include "runarray.h" - -using namespace types; -using absyntax::varinit; -using absyntax::arrayinit; -using absyntax::arglist; - -namespace trans { - -// Lower scores are better. Packed is added onto the other qualifiers so -// we may score both exact and casted packed arguments. -const score FAIL=0, EXACT=1, CAST=2; -const score PACKED=2; - -bool castable(env &e, formal& target, formal& source) { - return target.Explicit ? equivalent(target.t,source.t) - : e.castable(target.t,source.t, symbol::castsym); -} - -score castScore(env &e, formal& target, formal& source) { - return equivalent(target.t,source.t) ? EXACT : - (!target.Explicit && - e.fastCastable(target.t,source.t)) ? CAST : FAIL; -} - - -void restArg::transMaker(coenv &e, Int size, bool rest) { - // Push the number of cells and call the array maker. - e.c.encode(inst::intpush, size); - e.c.encode(inst::builtin, rest ? run::newAppendedArray : - run::newInitializedArray); -} - -void restArg::trans(coenv &e, temp_vector &temps) -{ - // Push the values on the stack. - for (mem::list<arg *>::iterator p = inits.begin(); p != inits.end(); ++p) - (*p)->trans(e, temps); - - if (rest) - rest->trans(e, temps); - - transMaker(e, (Int)inits.size(), (bool)rest); -} - -class maximizer { - app_list l; - - // Tests if x is as good (or better) an application as y. - bool asgood(application *x, application *y) { - // Matches to open signatures are always worse than matches to normal - // signatures. - if (x->sig->isOpen) - return y->sig->isOpen; - else if (y->sig->isOpen) - return true; - - assert (x->scores.size() == y->scores.size()); - - // Test if each score in x is no higher than the corresponding score in - // y. - return std::equal(x->scores.begin(), x->scores.end(), y->scores.begin(), - std::less_equal<score>()); - } - - bool better(application *x, application *y) { - return asgood(x,y) && !asgood(y,x); - } - - // Add an application that has already been determined to be maximal. - // Remove any other applications that are now not maximal because of its - // addition. - void addMaximal(application *x) { - app_list::iterator y=l.begin(); - while (y!=l.end()) - if (better(x,*y)) - y=l.erase(y); - else - ++y; - l.push_front(x); - } - - // Tests if x is maximal. - bool maximal(application *x) { - for (app_list::iterator y=l.begin(); y!=l.end(); ++y) - if (better(*y,x)) - return false; - return true; - } - -public: - maximizer() {} - - void add(application *x) { - if (maximal(x)) - addMaximal(x); - } - - app_list result() { - return l; - } -}; - -ty *restCellType(signature *sig) { - formal& f=sig->getRest(); - if (f.t) { - array *a=dynamic_cast<array *>(f.t); - if (a) - return a->celltype; - } - - return 0; -} - -void application::initRest() { - formal& f=sig->getRest(); - if (f.t) { - ty *ct = restCellType(sig); - if (!ct) - vm::error("formal rest argument must be an array"); - - rf=formal(ct, symbol::nullsym, false, f.Explicit); - } - if (f.t || sig->isOpen) { - rest=new restArg(); - } -} - -//const Int REST=-1; -const Int NOMATCH=-2; - -Int application::find(symbol name) { - formal_vector &f=sig->formals; - for (size_t i=index; i<f.size(); ++i) - if (f[i].name==name && args[i]==0) - return (Int)i; - return NOMATCH; -} - -bool application::matchDefault() { - if (index==args.size()) - return false; - else { - formal &target=getTarget(); - if (target.defval) { - args[index]=new defaultArg(target.t); - advanceIndex(); - return true; - } - else - return false; - } -} - -bool application::matchArgumentToRest(env &e, formal &source, - varinit *a, size_t evalIndex) -{ - if (rest) { - score s=castScore(e, rf, source); - if (s!=FAIL) { - rest->add(seq.addArg(a, rf.t, evalIndex)); - scores.push_back(s+PACKED); - return true; - } - } - return false; -} - -bool application::matchAtSpot(size_t spot, env &e, formal &source, - varinit *a, size_t evalIndex) -{ - formal &target=sig->getFormal(spot); - if(target.t->kind == types::ty_error) return false; - - score s=castScore(e, target, source); - - if (s == FAIL) - return false; - else if (sig->formalIsKeywordOnly(spot) && source.name == symbol::nullsym) - return false; - else { - // The argument matches. - args[spot]=seq.addArg(a, target.t, evalIndex); - if (spot==index) - advanceIndex(); - scores.push_back(s); - return true; - } -} - -bool application::matchArgument(env &e, formal &source, - varinit *a, size_t evalIndex) -{ - assert(!source.name); - - if (index==args.size()) - // Try to pack into the rest array. - return matchArgumentToRest(e, source, a, evalIndex); - else - // Match here, or failing that use a default and try to match at the next - // spot. - return matchAtSpot(index, e, source, a, evalIndex) || - (matchDefault() && matchArgument(e, source, a, evalIndex)); -} - -bool application::matchNamedArgument(env &e, formal &source, - varinit *a, size_t evalIndex) -{ - assert(source.name); - - Int spot=find(source.name); - return spot!=NOMATCH && matchAtSpot(spot, e, source, a, evalIndex); -} - -bool application::complete() { - if (index==args.size()) - return true; - else if (matchDefault()) - return complete(); - else - return false; -} - -bool application::matchRest(env &e, formal &source, varinit *a, - size_t evalIndex) { - // First make sure all non-rest arguments are matched (matching to defaults - // if necessary). - if (complete()) - // Match rest to rest. - if (rest) { - formal &target=sig->getRest(); - score s=castScore(e, target, source); - if (s!=FAIL) { - rest->addRest(seq.addArg(a, target.t, evalIndex)); - scores.push_back(s); - return true; - } - } - return false; -} - -// When the argument should be evaluated, possibly adjusting for a rest -// argument which occurs before named arguments. -size_t adjustIndex(size_t i, size_t ri) -{ - return i < ri ? i : i+1; -} - -bool application::matchSignature(env &e, types::signature *source, - arglist &al) { - formal_vector &f=source->formals; - -#if 0 - cout << "num args: " << f.size() << endl; - cout << "num keyword-only: " << sig->numKeywordOnly << endl; -#endif - - size_t ri = al.rest.val ? al.restPosition : f.size(); - - // First, match all of the named (non-rest) arguments. - for (size_t i=0; i<f.size(); ++i) - if (f[i].name) - if (!matchNamedArgument(e, f[i], al[i].val, adjustIndex(i,ri))) - return false; - - // Then, the unnamed. - for (size_t i=0; i<f.size(); ++i) - if (!f[i].name) - if (!matchArgument(e, f[i], al[i].val, adjustIndex(i,ri))) - return false; - - // Then, the rest argument. - if (source->hasRest()) - if (!matchRest(e, source->getRest(), al.rest.val, ri)) - return false; - - // Fill in any remaining arguments with their defaults. - return complete(); -} - -bool application::matchOpen(env &e, signature *source, arglist &al) { - assert(rest); - - // Pack all given parameters into the rest argument. - formal_vector &f=source->formals; - for (size_t i = 0; i < f.size(); ++i) - if (al[i].name) - // Named arguments are not handled by open signatures. - return false; - else - rest->add(seq.addArg(al[i].val, f[i].t, i)); - - if (source->hasRest()) - rest->addRest(new varinitArg(al.rest.val, source->getRest().t)); - - return true; -} - -application *application::match(env &e, function *t, signature *source, - arglist &al) { - assert(t->kind==ty_function); - application *app=new application(t); - - bool success = t->getSignature()->isOpen ? - app->matchOpen(e, source, al) : - app->matchSignature(e, source, al); - - //cout << "MATCH " << success << endl; - - return success ? app : 0; -} - -void application::transArgs(coenv &e) { - temp_vector temps; - - for(arg_vector::iterator a=args.begin(); a != args.end(); ++a) - (*a)->trans(e,temps); - - if (rest) - rest->trans(e,temps); -} - -bool application::exact() { - if (sig->isOpen) - return false; - for (score_vector::iterator p = scores.begin(); p != scores.end(); ++p) - if (*p != EXACT) - return false; - return true; -} - -bool application::halfExact() { - if (sig->isOpen) - return false; - if (scores.size() != 2) - return false; - if (scores[0] == EXACT && scores[1] == CAST) - return true; - if (scores[0] == CAST && scores[1] == EXACT) - return true; - return false; -} - -// True if any of the formals have names. -bool namedFormals(signature *sig) -{ - formal_vector& formals = sig->formals; - size_t n = formals.size(); - for (size_t i = 0; i < n; ++i) { - if (formals[i].name) - return true; - } - return false; -} - -// Tests if arguments in the source signature can be matched to the formals -// in the target signature with no casting or packing. -// This allows overloaded args, but not named args. -bool exactMightMatch(signature *target, signature *source) -{ - // Open signatures never exactly match. - if (target->isOpen) - return false; - -#if 0 - assert(!namedFormals(source)); -#endif - - formal_vector& formals = target->formals; - formal_vector& args = source->formals; - - // Sizes of the two lists. - size_t fn = formals.size(), an = args.size(); - - // Indices for the two lists. - size_t fi = 0, ai = 0; - - while (fi < fn && ai < an) { - if (equivalent(formals[fi].t, args[ai].t)) { - // Arguments match, move to the next. - ++fi; ++ai; - } else if (formals[fi].defval) { - // Match formal to default value. - ++fi; - } else { - // Failed to match formal. - return false; - } - } - - assert(fi == fn || ai == an); - - // Packing array arguments into the rest formal is inexact. Do not allow it - // here. - if (ai < an) - return false; - - assert(ai == an); - - // Match any remaining formal to defaults. - while (fi < fn) - if (formals[fi].defval) { - // Match formal to default value. - ++fi; - } else { - // Failed to match formal. - return false; - } - - // Non-rest arguments have matched. - assert(fi == fn && ai == an); - - // Try to match the rest argument if given. - if (source->hasRest()) { - if (!target->hasRest()) - return false; - - if (!equivalent(source->getRest().t, target->getRest().t)) - return false; - } - - // All arguments have matched. - return true; -} - -// Tries to match applications without casting. If an application matches -// here, we need not attempt to match others with the slower, more general -// techniques. -app_list exactMultimatch(env &e, - types::overloaded *o, - types::signature *source, - arglist &al) -{ - assert(source); - - app_list l; - - // This can't handle named arguments. - if (namedFormals(source)) - return l; /* empty */ - - for (ty_vector::iterator t=o->sub.begin(); t!=o->sub.end(); ++t) - { - if ((*t)->kind != ty_function) - continue; - - function *ft = (function *)*t; - - // First we run a test to see if all arguments could be exactly matched. - // If this returns false, no such match is possible. - // If it returns true, an exact match may or may not be possible. - if (!exactMightMatch(ft->getSignature(), source)) - continue; - - application *a=application::match(e, ft, source, al); - - // Consider calling - // void f(A a=new A, int y) - // with - // f(3) - // This matches exactly if there is no implicit cast from int to A. - // Otherwise, it does not match. - // Thus, there is no way to know if the - // match truly is exact without looking at the environment. - // In such a case, exactMightMatch() must return true, but there is no - // exact match. Such false positives are eliminated here. - // - // Consider calling - // void f(int x, real y=0.0, int z=0) - // with - // f(1,2) - // exactMightMatch() will return true, matching 1 to x and 2 to z, but the - // application::match will give an inexact match of 1 to x to 2 to y, due - // to the cast from int to real. Therefore, we must test for exactness - // even after matching. - if (a && a->exact()) - l.push_back(a); - } - - //cout << "EXACTMATCH " << (!l.empty()) << endl; - return l; -} - -bool halfExactMightMatch(env &e, - signature *target, types::ty *t1, types::ty *t2) -{ - formal_vector& formals = target->formals; - if (formals.size() < 2) - return false; - if (formals.size() > 2) { - // We should probably abort the whole matching in this case. For now, - // return true and let the usual matching handle it. - return true; - } - - assert(formals[0].t); - assert(formals[1].t); - - // These casting tests if successful will be repeated again by - // application::match. It would be nice to avoid this somehow, but the - // additional complexity is probably not worth the minor speed improvement. - if (equivalent(formals[0].t, t1)) - return e.fastCastable(formals[1].t, t2); - else - return equivalent(formals[1].t, t2) && e.fastCastable(formals[0].t, t1); -} - -// Most common after exact matches are cases such as -// 2 + 3.4 (int, real) --> (real, real) -// that is, binary operations where one of the operands matches exactly and the -// other does not. This function searches for these so-called "half-exact" -// matches. This should only be called after exactMultimatch has failed. -app_list halfExactMultimatch(env &e, - types::overloaded *o, - types::signature *source, - arglist &al) -{ - assert(source); - - app_list l; - - - // Half exact is only in the case of two arguments. - formal_vector& formals = source->formals; - if (formals.size() != 2 || source->hasRest()) - return l; /* empty */ - - // This can't handle named arguments. - if (namedFormals(source)) - return l; /* empty */ - - // Alias the two argument types. - types::ty *t1 = formals[0].t; - types::ty *t2 = formals[1].t; - - assert(t1); assert(t2); - - for (ty_vector::iterator t=o->sub.begin(); t!=o->sub.end(); ++t) - { - if ((*t)->kind != ty_function) - continue; - - function *ft = (function *)*t; - -#if 1 - if (!halfExactMightMatch(e, ft->getSignature(), t1, t2)) - continue; -#endif - - application *a=application::match(e, ft, source, al); - -#if 1 - if (a && a->halfExact()) - l.push_back(a); -#endif - } - - return l; -} - -// Simple check if there are too many arguments to match the candidate -// function. -// A "tooFewArgs" variant was also implemented at some point, but did -// not give any speed-up. -bool tooManyArgs(types::signature *target, types::signature *source) { - return source->getNumFormals() > target->getNumFormals() && - !target->hasRest(); -} - -// The full overloading resolution system, which handles casting of arguments, -// packing into rest arguments, named arguments, etc. -app_list inexactMultimatch(env &e, - types::overloaded *o, - types::signature *source, - arglist &al) -{ - assert(source); - - app_list l; - - -#define DEBUG_GETAPP 0 -#if DEBUG_GETAPP - //cout << "source: " << *source << endl; - //cout << "ARGS: " << source->getNumFormals() << endl; - bool perfect=false; - bool exact=false; - bool halfExact=false; -#endif - - for(ty_vector::iterator t=o->sub.begin(); t!=o->sub.end(); ++t) { - if ((*t)->kind==ty_function) { -#if DEBUG_GETAPP - function *ft = dynamic_cast<function *>(*t); - signature *target = ft->getSignature(); - if (equivalent(target, source)) - perfect = true; -#endif - - // Check if there are two many arguments to match. - if (tooManyArgs((*t)->getSignature(), source)) - continue; - - application *a=application::match(e, (function *)(*t), source, al); - if (a) - l.push_back(a); - -#if DEBUG_GETAPP - if (a && !namedFormals(source)) { - assert(a->exact() == exactlyMatchable(ft->getSignature(), source)); - if (a->halfExact() && !namedFormals(source)) { - assert(halfExactMightMatch(e, target, source->getFormal(0).t, - source->getFormal(1).t)); - } - - } - if (a && a->exact()) - exact = true; - if (a && a->halfExact()) - halfExact = true; -#endif - } - } - -#if DEBUG_GETAPP - cout << (perfect ? "PERFECT" : - exact ? "EXACT" : - halfExact ? "HALFEXACT" : - "IMPERFECT") - << endl; -#endif - - if (l.size() > 1) { - // Return the most specific candidates. - maximizer m; - for (app_list::iterator x=l.begin(); x!=l.end(); ++x) { - assert(*x); - m.add(*x); - } - return m.result(); - } - else - return l; -} - -enum testExactType { - TEST_EXACT, - DONT_TEST_EXACT, -}; - -// Sanity check for multimatch optimizations. -void sameApplications(app_list a, app_list b, testExactType te) { - assert(a.size() == b.size()); - - if (te == TEST_EXACT) { - for (app_list::iterator i = a.begin(); i != a.end(); ++i) { - if (!(*i)->exact()) { - cout << *(*i)->getType() << endl; - } - assert((*i)->exact()); - } - for (app_list::iterator i = b.begin(); i != b.end(); ++i) - assert((*i)->exact()); - } - - if (a.size() == 1) - assert(equivalent(a.front()->getType(), b.front()->getType())); -} - -app_list multimatch(env &e, - types::overloaded *o, - types::signature *source, - arglist &al) -{ - app_list a = exactMultimatch(e, o, source, al); - if (!a.empty()) { -#if DEBUG_CACHE - // Make sure that exactMultimatch and the fallback return the same - // application(s). - sameApplications(a, inexactMultimatch(e, o, source, al), TEST_EXACT); -#endif - - return a; - } - - a = halfExactMultimatch(e, o, source, al); - if (!a.empty()) { -#if DEBUG_CACHE - sameApplications(a, inexactMultimatch(e, o, source, al), DONT_TEST_EXACT); -#endif - - return a; - } - - // Slow but most general method. - return inexactMultimatch(e, o, source, al); -} - -} // namespace trans |