summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/entry.cc
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2010-06-18 23:24:00 +0000
committerKarl Berry <karl@freefriends.org>2010-06-18 23:24:00 +0000
commit47fea6d4aa5c9cfb2e71c51f769dac3023630035 (patch)
tree6a4b15f0b85d8bb5602146e20241b49e938f409b /Build/source/utils/asymptote/entry.cc
parent0dfdf5c49b160d464b74a9cae8882ea81cc47878 (diff)
asy 1.99
git-svn-id: svn://tug.org/texlive/trunk@19047 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/entry.cc')
-rw-r--r--Build/source/utils/asymptote/entry.cc579
1 files changed, 373 insertions, 206 deletions
diff --git a/Build/source/utils/asymptote/entry.cc b/Build/source/utils/asymptote/entry.cc
index 93fb9997054..4cf0059b340 100644
--- a/Build/source/utils/asymptote/entry.cc
+++ b/Build/source/utils/asymptote/entry.cc
@@ -14,7 +14,11 @@
#include "entry.h"
#include "coder.h"
+using types::ty;
using types::signature;
+using types::overloaded;
+using types::ty_vector;
+using types::ty_iterator;
namespace trans {
@@ -118,89 +122,97 @@ bool tenv::add(symbol src, symbol dest,
}
#ifdef NOHASH //{{{
-void venv::add(venv& source, varEntry *qualifier, coder &c)
-{
- // Enter each distinct (unshadowed) name,type pair.
- for(names_t::iterator p = source.names.begin();
- p != source.names.end();
- ++p)
- add(p->first, p->first, source, qualifier, c);
-}
-
-bool venv::add(symbol src, symbol dest,
- venv& source, varEntry *qualifier, coder &c)
-{
- bool added=false;
- name_t &list=source.names[src];
- types::overloaded set; // To keep track of what is shadowed.
-
- for(name_iterator p = list.begin();
- p != list.end();
- ++p) {
- varEntry *v=*p;
- if (!equivalent(v->getType(), &set)) {
- set.addDistinct(v->getType(), src->special());
- if (v->checkPerm(READ, c)) {
- enter(dest, qualifyVarEntry(qualifier, v));
- added=true;
- }
- }
- }
-
- return added;
-}
-
-varEntry *venv::lookByType(symbol name, ty *t)
-{
- // Find first applicable function.
- name_t &list = names[name];
- for(name_iterator p = list.begin();
- p != list.end();
- ++p) {
- if (equivalent((*p)->getType(), t))
- return *p;
- }
- return 0;
-}
-
-void venv::list(record *module)
-{
- bool where=settings::getSetting<bool>("where");
- // List all functions and variables.
- for(names_t::iterator N = names.begin(); N != names.end(); ++N) {
- symbol s=N->first;
- name_t &list=names[s];
- for(name_iterator p = list.begin(); p != list.end(); ++p) {
- if(!module || (*p)->whereDefined() == module) {
- if(where) cout << (*p)->getPos();
- (*p)->getType()->printVar(cout, s);
- cout << ";\n";
- }
- }
- }
- flush(cout);
-}
-
-ty *venv::getType(symbol name)
-{
- types::overloaded set;
-
- // Find all applicable functions in scope.
- name_t &list = names[name];
-
- for(name_iterator p = list.begin();
- p != list.end();
- ++p) {
- set.addDistinct((*p)->getType(), name->special());
- }
-
- return set.simplify();
-}
+/*NOHASH*/ void venv::add(venv& source, varEntry *qualifier, coder &c)
+/*NOHASH*/ {
+/*NOHASH*/ // Enter each distinct (unshadowed) name,type pair.
+/*NOHASH*/ for(names_t::iterator p = source.names.begin();
+/*NOHASH*/ p != source.names.end();
+/*NOHASH*/ ++p)
+/*NOHASH*/ add(p->first, p->first, source, qualifier, c);
+/*NOHASH*/ }
+/*NOHASH*/
+/*NOHASH*/ bool venv::add(symbol src, symbol dest,
+/*NOHASH*/ venv& source, varEntry *qualifier, coder &c)
+/*NOHASH*/ {
+/*NOHASH*/ bool added=false;
+/*NOHASH*/ name_t &list=source.names[src];
+/*NOHASH*/ types::overloaded set; // To keep track of what is shadowed.
+/*NOHASH*/ bool special = src.special();
+/*NOHASH*/
+/*NOHASH*/ for(name_iterator p = list.begin();
+/*NOHASH*/ p != list.end();
+/*NOHASH*/ ++p) {
+/*NOHASH*/ varEntry *v=*p;
+/*NOHASH*/ if (!equivalent(v->getType(), &set)) {
+/*NOHASH*/ set.addDistinct(v->getType(), special);
+/*NOHASH*/ if (v->checkPerm(READ, c)) {
+/*NOHASH*/ enter(dest, qualifyVarEntry(qualifier, v));
+/*NOHASH*/ added=true;
+/*NOHASH*/ }
+/*NOHASH*/ }
+/*NOHASH*/ }
+/*NOHASH*/
+/*NOHASH*/ return added;
+/*NOHASH*/ }
+/*NOHASH*/
+/*NOHASH*/ varEntry *venv::lookByType(symbol name, ty *t)
+/*NOHASH*/ {
+/*NOHASH*/ // Find first applicable function.
+/*NOHASH*/ name_t &list = names[name];
+/*NOHASH*/ for(name_iterator p = list.begin();
+/*NOHASH*/ p != list.end();
+/*NOHASH*/ ++p) {
+/*NOHASH*/ if (equivalent((*p)->getType(), t))
+/*NOHASH*/ return *p;
+/*NOHASH*/ }
+/*NOHASH*/ return 0;
+/*NOHASH*/ }
+/*NOHASH*/
+/*NOHASH*/ void venv::list(record *module)
+/*NOHASH*/ {
+/*NOHASH*/ bool where=settings::getSetting<bool>("where");
+/*NOHASH*/ // List all functions and variables.
+/*NOHASH*/ for(names_t::iterator N = names.begin(); N != names.end(); ++N) {
+/*NOHASH*/ symbol s=N->first;
+/*NOHASH*/ name_t &list=names[s];
+/*NOHASH*/ for(name_iterator p = list.begin(); p != list.end(); ++p) {
+/*NOHASH*/ if(!module || (*p)->whereDefined() == module) {
+/*NOHASH*/ if(where) cout << (*p)->getPos();
+/*NOHASH*/ (*p)->getType()->printVar(cout, s);
+/*NOHASH*/ cout << ";\n";
+/*NOHASH*/ }
+/*NOHASH*/ }
+/*NOHASH*/ }
+/*NOHASH*/ flush(cout);
+/*NOHASH*/ }
+/*NOHASH*/
+/*NOHASH*/ ty *venv::getType(symbol name)
+/*NOHASH*/ {
+/*NOHASH*/ types::overloaded set;
+/*NOHASH*/
+/*NOHASH*/ // Find all applicable functions in scope.
+/*NOHASH*/ name_t &list = names[name];
+/*NOHASH*/ bool special = name.special();
+/*NOHASH*/
+/*NOHASH*/ for(name_iterator p = list.begin();
+/*NOHASH*/ p != list.end();
+/*NOHASH*/ ++p) {
+/*NOHASH*/ set.addDistinct((*p)->getType(), special);
+/*NOHASH*/ }
+/*NOHASH*/
+/*NOHASH*/ return set.simplify();
+/*NOHASH*/ }
// }}}
-#else // {{{
+#else
ostream& operator<< (ostream& out, const venv::key &k) {
- k.t->printVar(out, k.name);
+ if(k.special)
+ k.u.t->printVar(out, k.name);
+ else {
+ out << k.name;
+ if (k.u.sig)
+ out << *k.u.sig;
+ }
return out;
}
@@ -220,117 +232,270 @@ bool venv::keyeq::operator()(const key k, const key l) const {
}
#else
bool venv::keyeq::operator()(const key k, const key l) const {
-#if 0
- cerr << "k.t = " << k.t << " " << k << endl;
- cerr << "l.t = " << l.t << " " << l << endl;
-#endif
return k.name==l.name &&
- (k.name.special() ? equivalent(k.t, l.t) :
- equivalent(k.t->getSignature(),
- l.t->getSignature()));
+ (k.special ? equivalent(k.u.t, l.u.t) :
+ equivalent(k.u.sig, l.u.sig));
}
#endif
-void venv::remove(key k) {
- //cerr << "removing: " << k << endl;
- value *&val=all[k];
- assert(val);
- if (val->next) {
- val->next->shadowed=false;
- value *temp=val->next;
- val->next=0;
- val=temp;
- }
- else
- all.erase(k);
-
- // Don't erase it from scopes.top() as that will be popped of the stack at
- // the end of endScope anyway.
-
- names[k.name].pop_front();
-}
-
#ifdef CALLEE_SEARCH
-size_t numArgs(ty *t) {
+size_t numFormals(ty *t) {
signature *sig = t->getSignature();
return sig ? sig->getNumFormals() : 0;
}
+#endif
-void checkMaxArgs(venv *ve, symbol name, size_t expected) {
- size_t maxFormals = 0;
- ty *t = ve->getType(name);
- if (types::overloaded *o=dynamic_cast<types::overloaded *>(t)) {
- for (types::ty_vector::iterator i=o->sub.begin(); i != o->sub.end(); ++i)
- {
- size_t n = numArgs(*i);
- if (n > maxFormals)
- maxFormals = n;
- }
- } else {
- maxFormals = numArgs(t);
+void venv::checkName(symbol name)
+{
+ // TODO: test maxFormals
+
+ // Get the type, and make it overloaded if it is not (for uniformity).
+ overloaded o;
+ ty *t = getType(name);
+ if (!t)
+ t = &o;
+ if (!t->isOverloaded()) {
+ o.add(t);
+ t = &o;
}
- if (expected != maxFormals) {
- cout << "expected: " << expected << " computed: " << maxFormals << endl;
- cout << "types: " << endl;
- if (types::overloaded *o=dynamic_cast<types::overloaded *>(t)) {
- cout << " overloaded" << endl;
- for (types::ty_vector::iterator i=o->sub.begin(); i != o->sub.end();
- ++i)
- {
- cout << " " << **i << endl;
- }
- } else {
- cout << " non-overloaded" << endl;
- cout << " " << *t << endl;
+ assert(t->isOverloaded());
+
+ size_t size = 0;
+ for (ty_iterator i = t->begin(); i != t->end(); ++i) {
+ varEntry *v = lookByType(name, *i);
+ assert(v);
+ assert(equivalent(v->getType(), *i));
+ ++size;
+ }
+
+ size_t matches = 0;
+ for (keymap::iterator p = all.begin(); p != all.end(); ++p) {
+ if (p->first.name == name) {
+ ++matches;
+
+ varEntry *v=p->second.v;
+ assert(v);
+ assert(equivalent(t, v->getType()));
}
- cout.flush();
}
- assert(expected == maxFormals);
+ assert(matches == size);
+}
+
+void rightKind(ty *t) {
+ if (t && t->isOverloaded()) {
+ ty_vector& set=((overloaded *)t)->sub;
+ assert(set.size() > 1);
+ }
}
+
+#ifdef DEBUG_CACHE
+#define RIGHTKIND(t) (rightKind(t))
+#define CHECKNAME(name) (checkName(name))
+#else
+#define RIGHTKIND(t) (void)(t)
+#define CHECKNAME(name) (void)(name)
#endif
-void venv::enter(symbol name, varEntry *v) {
- assert(!scopes.empty());
- key k(name, v);
-#ifdef DEBUG_ENTRY
- cout << "entering: " << k << " (t=" << k.t << ")" << endl;
+void venv::namevalue::addType(ty *s) {
+ RIGHTKIND(t);
+
+#ifdef DEBUG_CACHE
+ assert(!s->isOverloaded());
+#endif
+
+ if (t == 0) {
+#if CALLEE_SEARCH
+ maxFormals = numFormals(s);
#endif
- value *val=new value(v);
+ t = s;
+ } else {
+ if (!t->isOverloaded())
+ t = new overloaded(t);
-#ifdef DEBUG_ENTRY
- keymap::iterator p=all.find(k);
- if (p!=all.end()) {
- cout << " over: " << p->first << endl;
+#ifdef DEBUG_CACHE
+ assert(t->isOverloaded());
+ assert(!equivalent(t, s));
+#endif
+
+ ((overloaded *)t)->add(s);
+
+#if CALLEE_SEARCH
+ size_t n = numFormals(s);
+ if (n > maxFormals)
+ maxFormals = n;
+#endif
}
+
+ RIGHTKIND(t);
+}
+
+void venv::namevalue::replaceType(ty *new_t, ty *old_t) {
+#ifdef DEBUG_CACHE
+ assert(t != 0);
+ RIGHTKIND(t);
#endif
- val->next=all[k];
- if (val->next)
- val->next->shadowed=true;
+ if (t->isOverloaded()) {
+ for (ty_iterator i = t->begin(); i != t->end(); ++i) {
+ if (equivalent(old_t, *i)) {
+ *i = new_t;
+ return;
+ }
+ }
- all[k]=val;
- scopes.top().insert(keymultimap::value_type(k,val));
+ // An error, the type was not found.
+ assert("unreachable code" == 0);
-#ifdef CALLEE_SEARCH
- // I'm not sure if this works properly with rest arguments.
- signature *sig = v->getSignature();
- size_t newmax = sig ? sig->getNumFormals() : 0;
- mem::list<value *>& namelist = names[k.name];
- if (!namelist.empty()) {
- size_t oldmax = namelist.front()->maxFormals;
- if (oldmax > newmax)
- newmax = oldmax;
+ } else {
+#ifdef DEBUG_CACHE
+ assert(equivalent(old_t, t));
+#endif
+ t = new_t;
}
- val->maxFormals = newmax;
- namelist.push_front(val);
- // A sanity check, disabled for speed reasons.
#ifdef DEBUG_CACHE
- checkMaxArgs(this, k.name, val->maxFormals);
+ assert(t != 0);
+ RIGHTKIND(t);
#endif
+}
+
+#ifdef DEBUG_CACHE
+void venv::namevalue::popType(ty *s)
+#else
+void venv::namevalue::popType()
+#endif
+{
+#ifdef DEBUG_CACHE
+ assert(t);
+ RIGHTKIND(t);
+ assert(!s->isOverloaded());
+#endif
+
+ if (t->isOverloaded()) {
+ ty_vector& set=((overloaded *)t)->sub;
+
+#ifdef DEBUG_CACHE
+ assert(set.size() > 0);
+ assert(equivalent(set.back(), s));
+#endif
+
+ // We are relying on the fact that this was the last type added to t, and
+ // that type are added by pushing them on the end of the vector.
+ set.pop_back();
+
+ if (set.size() == 1)
+ t = set.front();
+ } else {
+#ifdef DEBUG_CACHE
+ assert(equivalent(t, s));
+#endif
+ t = 0;
+ }
+
+ RIGHTKIND(t);
+
+ // Don't try to reduce numFormals as I doubt it is worth the cost of
+ // recalculating.
+}
+
+void venv::remove(const addition& a) {
+ CHECKNAME(a.k.name);
+
+ value &val=all[a.k];
+
+#ifdef DEBUG_CACHE
+ assert(val);
+#endif
+
+ if (a.shadowed) {
+ // Unshadow the previously shadowed varEntry.
+ names[a.k.name].replaceType(a.shadowed->getType(), val.v->getType());
+ val.v = a.shadowed;
+ } else {
+ // Remove the (name,sig) key completely.
+#if DEBUG_CACHE
+ names[a.k.name].popType(val.v->getType());
#else
- names[k.name].push_front(val);
+ names[a.k.name].popType();
#endif
+ all.erase(a.k);
+ }
+
+ CHECKNAME(a.k.name);
+}
+
+void venv::beginScope() {
+ if (all.empty()) {
+ assert(scopesizes.empty());
+ ++empty_scopes;
+ } else {
+ scopesizes.push(additions.size());
+ }
+}
+
+void venv::endScope() {
+ if (scopesizes.empty()) {
+ // The corresponding beginScope happened when the venv was empty, so
+ // clear the hash tables to return to that state.
+ all.clear();
+ names.clear();
+
+ assert(empty_scopes > 0);
+ --empty_scopes;
+ } else {
+ size_t scopesize = scopesizes.top();
+ assert(additions.size() >= scopesize);
+ while (additions.size() > scopesize) {
+ remove(additions.top());
+ additions.pop();
+ }
+ scopesizes.pop();
+ }
+}
+
+// Adds the definitions of the top-level scope to the level underneath,
+// and then removes the top scope.
+void venv::collapseScope() {
+ if (scopesizes.empty()) {
+ // Collapsing an empty scope.
+ assert(empty_scopes > 0);
+ --empty_scopes;
+ } else {
+ scopesizes.pop();
+ }
+}
+
+
+void venv::enter(symbol name, varEntry *v)
+{
+ CHECKNAME(name);
+
+ key k(name, v);
+
+ value &slot=all[k];
+ if (slot.v) {
+ // The new value shadows an old value. They have the same signature, but
+ // possibly different return types. If necessary, update the type stored
+ // by name.
+ names[name].replaceType(v->getType(), slot.v->getType());
+
+ // Replace the old value, but store its now-shadowed varEntry.
+ if (!scopesizes.empty())
+ additions.push(addition(k, slot.v));
+
+ slot.v = v;
+
+ } else {
+ // Add to the names hash table.
+ names[name].addType(v->getType());
+
+ if (!scopesizes.empty())
+ additions.push(addition(k, 0));
+
+ slot.v=v;
+ }
+
+ CHECKNAME(name);
}
@@ -353,15 +518,10 @@ varEntry *venv::lookBySignature(symbol name, signature *sig) {
return 0;
}
- mem::list<value *>& namelist = names[name];
- if (namelist.empty()) {
- // No variables of this name.
- //cout << "FAIL BY EMPTY" << endl;
- return 0;
- }
+ namevalue& nv = names[name];
// Avoid ambiguities with default parameters.
- if (namelist.front()->maxFormals != sig->getNumFormals()) {
+ if (nv.maxFormals != sig->getNumFormals()) {
#if 0
if (lookByType(key(name, sig)))
cout << "FAIL BY NUMARGS" << endl;
@@ -390,7 +550,7 @@ void venv::add(venv& source, varEntry *qualifier, coder &c)
{
// Enter each distinct (unshadowed) name,type pair.
for(keymap::iterator p = source.all.begin(); p != source.all.end(); ++p) {
- varEntry *v=p->second->v;
+ varEntry *v=p->second.v;
if (v->checkPerm(READ, c))
enter(p->first.name, qualifyVarEntry(qualifier, v));
}
@@ -399,68 +559,75 @@ void venv::add(venv& source, varEntry *qualifier, coder &c)
bool venv::add(symbol src, symbol dest,
venv& source, varEntry *qualifier, coder &c)
{
- bool added=false;
- values &list=source.names[src];
-
- for (values::iterator p=list.begin(); p!=list.end(); ++p)
- if (!(*p)->shadowed) {
- varEntry *v=(*p)->v;
+ ty *t=source.getType(src);
+ if (!t)
+ return false;
+ else if (t->isOverloaded()) {
+ bool added=false;
+ for (ty_iterator i = t->begin(); i != t->end(); ++i) {
+ varEntry *v=source.lookByType(src, *i);
if (v->checkPerm(READ, c)) {
enter(dest, qualifyVarEntry(qualifier, v));
added=true;
}
}
-
- return added;
+ return added;
+ } else {
+ varEntry *v=source.lookByType(src, t);
+ if (v->checkPerm(READ, c)) {
+ enter(dest, qualifyVarEntry(qualifier, v));
+ return true;
+ }
+ return false;
+ }
}
ty *venv::getType(symbol name)
{
-#if 0
- cout << "getType: " << name << endl;
-#endif
- types::overloaded set;
- values &list=names[name];
+ return names[name].t;
+}
+
+void listValue(symbol name, varEntry *v, record *module)
+{
+ if (!module || v->whereDefined() == module)
+ {
+ if (settings::getSetting<bool>("where"))
+ cout << v->getPos();
- for (values::iterator p=list.begin(); p!=list.end(); ++p)
- if (!(*p)->shadowed)
- set.add((*p)->v->getType());
+ v->getType()->printVar(cout, name);
- return set.simplify();
+ cout << ";\n";
+ }
}
-void venv::listValues(symbol name, values &vals, record *module)
+void venv::listValues(symbol name, record *module)
{
- ostream& out=cout;
-
- bool where=settings::getSetting<bool>("where");
- for(values::iterator p = vals.begin(); p != vals.end(); ++p) {
- if(!module || (*p)->v->whereDefined() == module) {
- if(where) out << (*p)->v->getPos();
- if ((*p)->shadowed)
- out << " <shadowed> ";
- (*p)->v->getType()->printVar(out, name);
- out << ";\n";
- }
- }
- flush(out);
+ ty *t=getType(name);
+
+ if (t->isOverloaded())
+ for (ty_iterator i = t->begin(); i != t->end(); ++i)
+ listValue(name, lookByType(name, *i), module);
+ else
+ listValue(name, lookByType(name, t), module);
+
+ flush(cout);
}
void venv::list(record *module)
{
// List all functions and variables.
- for(namemap::iterator N = names.begin(); N != names.end(); ++N)
- listValues(N->first, N->second,module);
+ for (namemap::iterator N = names.begin(); N != names.end(); ++N)
+ listValues(N->first, module);
}
void venv::completions(mem::list<symbol >& l, string start)
{
for(namemap::iterator N = names.begin(); N != names.end(); ++N)
- if (prefix(start, N->first) && !N->second.empty())
+ if (prefix(start, N->first) && N->second.t)
l.push_back(N->first);
}
-#endif // }}}
+#endif
} // namespace trans