1 /*****
2  * entry.cc
3  * Andy Hammerlindl 2002/08/29
4  *
5  * All variables, built-in functions and user-defined functions reside
6  * within the same namespace.  To keep track of all these, table of
7  * "entries" is used.
8  *****/
9 
10 #include <iostream>
11 
12 #include <cmath>
13 #include <cstring>
14 #include <utility>
15 #include "entry.h"
16 #include "coder.h"
17 
18 using std::memset;
19 using types::ty;
20 using types::signature;
21 using types::overloaded;
22 using types::ty_vector;
23 using types::ty_iterator;
24 
25 namespace trans {
26 
check(action act,coder & c)27 bool entry::pr::check(action act, coder &c) {
28   // We assume PUBLIC permissions and one's without an associated record are not
29   // stored.
30   assert(perm!=PUBLIC && r!=0);
31   return c.inTranslation(r->getLevel()) ||
32     (perm == RESTRICTED && act != WRITE);
33 }
34 
report(action act,position pos,coder & c)35 void entry::pr::report(action act, position pos, coder &c) {
36   if (!c.inTranslation(r->getLevel())) {
37     if (perm == PRIVATE) {
38       em.error(pos);
39       em << "accessing private field outside of structure";
40     }
41     else if (perm == RESTRICTED && act == WRITE) {
42       em.error(pos);
43       em << "modifying non-public field outside of structure";
44     }
45   }
46 }
47 
entry(entry & e1,entry & e2)48 entry::entry(entry &e1, entry &e2) : where(e2.where), pos(e2.pos) {
49   perms.insert(perms.end(), e1.perms.begin(), e1.perms.end());
50   perms.insert(perms.end(), e2.perms.begin(), e2.perms.end());
51 }
52 
entry(entry & base,permission perm,record * r)53 entry::entry(entry &base, permission perm, record *r)
54   : where(base.where), pos(base.pos) {
55   perms.insert(perms.end(), base.perms.begin(), base.perms.end());
56   addPerm(perm, r);
57 }
58 
checkPerm(action act,coder & c)59 bool entry::checkPerm(action act, coder &c) {
60   for (mem::list<pr>::iterator p=perms.begin(); p != perms.end(); ++p)
61     if (!p->check(act, c))
62       return false;
63   return true;
64 }
65 
reportPerm(action act,position pos,coder & c)66 void entry::reportPerm(action act, position pos, coder &c) {
67   for (mem::list<pr>::iterator p=perms.begin(); p != perms.end(); ++p)
68     p->report(act, pos, c);
69 }
70 
71 
varEntry(varEntry & qv,varEntry & v)72 varEntry::varEntry(varEntry &qv, varEntry &v)
73   : entry(qv,v), t(v.t),
74     location(new qualifiedAccess(qv.location, qv.getLevel(), v.location)) {}
75 
getLevel()76 frame *varEntry::getLevel() {
77   record *r=dynamic_cast<record *>(t);
78   assert(r);
79   return r->getLevel();
80 }
81 
encode(action act,position pos,coder & c)82 void varEntry::encode(action act, position pos, coder &c) {
83   reportPerm(act, pos, c);
84   getLocation()->encode(act, pos, c);
85 }
86 
encode(action act,position pos,coder & c,frame * top)87 void varEntry::encode(action act, position pos, coder &c, frame *top) {
88   reportPerm(act, pos, c);
89   getLocation()->encode(act, pos, c, top);
90 }
91 
qualifyVarEntry(varEntry * qv,varEntry * v)92 varEntry *qualifyVarEntry(varEntry *qv, varEntry *v)
93 {
94   return qv ? (v ? new varEntry(*qv,*v) : qv) : v;
95 }
96 
97 
add(symbol dest,names_t::value_type & x,varEntry * qualifier,coder & c)98 bool tenv::add(symbol dest,
99                names_t::value_type &x, varEntry *qualifier, coder &c)
100 {
101   if (!x.second.empty()) {
102     tyEntry *ent=x.second.front();
103     if (ent->checkPerm(READ, c)) {
104       enter(dest, qualifyTyEntry(qualifier, ent));
105       return true;
106     }
107   }
108   return false;
109 }
110 
add(tenv & source,varEntry * qualifier,coder & c)111 void tenv::add(tenv& source, varEntry *qualifier, coder &c) {
112   // Enter each distinct (unshadowed) name,type pair.
113   for(names_t::iterator p = source.names.begin(); p != source.names.end(); ++p)
114     add(p->first, *p, qualifier, c);
115 }
116 
add(symbol src,symbol dest,tenv & source,varEntry * qualifier,coder & c)117 bool tenv::add(symbol src, symbol dest,
118                tenv& source, varEntry *qualifier, coder &c) {
119   names_t::iterator p = source.names.find(src);
120   if (p != source.names.end())
121     return add(dest, *p, qualifier, c);
122   else
123     return false;
124 }
125 
126 // To avoid writing qualifiers everywhere.
127 typedef core_venv::cell cell;
128 
initTable(size_t capacity)129 void core_venv::initTable(size_t capacity) {
130   // Assert that capacity is a power of two.
131   assert((capacity & (capacity-1)) == 0);
132 
133   this->capacity = capacity;
134   size = 0;
135   mask = capacity - 1;
136   table = new (UseGC) cell[capacity];
137   memset(table, 0, sizeof(cell) * capacity);
138 }
139 
clear()140 void core_venv::clear() {
141   if (size != 0) {
142     memset(table, 0, sizeof(cell) * capacity);
143     size = 0;
144   }
145 }
146 
resize()147 void core_venv::resize() {
148   size_t oldCapacity = capacity;
149   size_t oldSize = size;
150   cell *oldTable = table;
151 
152   initTable(capacity * 4);
153 
154   for (size_t i = 0; i < oldCapacity; ++i) {
155     cell& b = oldTable[i];
156     if (!b.empty() && !b.isATomb()) {
157       varEntry *old = store(b.name, b.ent);
158 
159       // We should not be shadowing anything when reconstructing the table.
160       DEBUG_CACHE_ASSERT(old == 0);
161     }
162   }
163 
164   assert(size == oldSize);
165 
166 #if DEBUG_CACHE
167   confirm_size();
168 
169   for (size_t i = 0; i < oldCapacity; ++i) {
170     cell& b = oldTable[i];
171     if (!b.empty() && !b.isATomb()) {
172       assert(lookup(b.name, b.ent->getType()) == b.ent);
173     }
174   }
175 #endif
176 
177   //cout << "resized from " << oldCapacity << " to " << capacity << endl;
178 }
179 
cellByIndex(size_t i)180 cell& core_venv::cellByIndex(size_t i) {
181   return table[i & mask];
182 }
183 
cellByIndex(size_t i) const184 const cell& core_venv::cellByIndex(size_t i) const {
185   return table[i & mask];
186 }
187 
confirm_size()188 void core_venv::confirm_size() {
189   size_t sum = 0;
190   for (size_t i = 0; i < capacity; ++i) {
191     cell& b = table[i];
192     if (!b.empty() && !b.isATomb())
193       ++sum;
194   }
195   assert(sum == size);
196 }
197 
storeNew(cell & cell,symbol name,varEntry * ent)198 varEntry *core_venv::storeNew(cell& cell, symbol name, varEntry *ent) {
199   // Store the value into the cell.
200   cell.storeNew(name, ent);
201 
202   // We now have a new entry.  Update the size.
203   ++size;
204 
205   // Check if the hash table has grown too big and needs to be expanded.
206   if (2*size > capacity)
207     resize();
208 
209   // Nothing is shadowed.
210   return 0;
211 }
212 
213 
storeNonSpecialAfterTomb(size_t tombIndex,symbol name,varEntry * ent)214 varEntry *core_venv::storeNonSpecialAfterTomb(size_t tombIndex,
215                                               symbol name, varEntry *ent) {
216   DEBUG_CACHE_ASSERT(name.notSpecial());
217   DEBUG_CACHE_ASSERT(ent);
218   DEBUG_CACHE_ASSERT(ent->getType());
219 
220   signature *sig = ent->getSignature();
221 
222   for (size_t i = tombIndex+1; ; ++i)
223     {
224       cell& b = cellByIndex(i);
225 
226       if (b.empty())
227         return storeNew(cellByIndex(tombIndex), name, ent);
228 
229       if (b.matches(name, sig))
230         return b.replaceWith(name, ent);
231     }
232 }
233 
storeSpecialAfterTomb(size_t tombIndex,symbol name,varEntry * ent)234 varEntry *core_venv::storeSpecialAfterTomb(size_t tombIndex,
235                                            symbol name, varEntry *ent) {
236   DEBUG_CACHE_ASSERT(name.special());
237   DEBUG_CACHE_ASSERT(ent);
238   DEBUG_CACHE_ASSERT(ent->getType());
239 
240   ty *t = ent->getType();
241 
242   for (size_t i = tombIndex+1; ; ++i)
243     {
244       cell& b = cellByIndex(i);
245 
246       if (b.empty())
247         return storeNew(cellByIndex(tombIndex), name, ent);
248 
249       if (b.matches(name, t))
250         return b.replaceWith(name, ent);
251     }
252 }
253 
hashSig(const signature * sig)254 size_t hashSig(const signature *sig) {
255   return sig ? sig->hash() : 0;
256 }
nonSpecialHash(symbol name,const signature * sig)257 size_t nonSpecialHash(symbol name, const signature *sig) {
258   return name.hash() * 107 + hashSig(sig);
259 }
nonSpecialHash(symbol name,const ty * t)260 size_t nonSpecialHash(symbol name, const ty *t) {
261   DEBUG_CACHE_ASSERT(t);
262   return nonSpecialHash(name, t->getSignature());
263 }
specialHash(symbol name,const ty * t)264 size_t specialHash(symbol name, const ty *t) {
265   DEBUG_CACHE_ASSERT(t);
266   return name.hash() * 107 + t->hash();
267 }
268 
storeNonSpecial(symbol name,varEntry * ent)269 varEntry *core_venv::storeNonSpecial(symbol name, varEntry *ent) {
270   DEBUG_CACHE_ASSERT(name.notSpecial());
271   DEBUG_CACHE_ASSERT(ent);
272   DEBUG_CACHE_ASSERT(ent->getType());
273 
274   signature *sig = ent->getSignature();
275 
276   for (size_t i = nonSpecialHash(name, sig); ; ++i)
277     {
278       cell& b = cellByIndex(i);
279 
280       if (b.empty())
281         return storeNew(b, name, ent);
282 
283       if (b.matches(name, sig))
284         return b.replaceWith(name, ent);
285 
286       if (b.isATomb())
287         return storeNonSpecialAfterTomb(i, name, ent);
288     }
289 }
290 
storeSpecial(symbol name,varEntry * ent)291 varEntry *core_venv::storeSpecial(symbol name, varEntry *ent) {
292   DEBUG_CACHE_ASSERT(name.special());
293   DEBUG_CACHE_ASSERT(ent);
294   DEBUG_CACHE_ASSERT(ent->getType());
295 
296   ty *t = ent->getType();
297 
298   for (size_t i = specialHash(name, t); ; ++i)
299     {
300       cell& b = cellByIndex(i);
301 
302       if (b.empty())
303         return storeNew(b, name, ent);
304 
305       if (b.matches(name, t))
306         return b.replaceWith(name, ent);
307 
308       if (b.isATomb())
309         return storeSpecialAfterTomb(i, name, ent);
310     }
311 }
312 
store(symbol name,varEntry * ent)313 varEntry *core_venv::store(symbol name, varEntry *ent) {
314   DEBUG_CACHE_ASSERT(ent);
315   DEBUG_CACHE_ASSERT(ent->getType());
316 
317   return name.special() ? storeSpecial(name, ent) :
318     storeNonSpecial(name, ent);
319 }
320 
lookupSpecial(symbol name,const ty * t)321 varEntry *core_venv::lookupSpecial(symbol name, const ty *t) {
322   DEBUG_CACHE_ASSERT(name.special());
323   DEBUG_CACHE_ASSERT(t);
324 
325   for (size_t i = specialHash(name, t); ; ++i)
326     {
327       cell& b = cellByIndex(i);
328 
329       if (b.matches(name, t))
330         return b.ent;
331 
332       if (b.empty())
333         return 0;
334     }
335 }
336 
lookupNonSpecial(symbol name,const signature * sig)337 varEntry *core_venv::lookupNonSpecial(symbol name, const signature *sig) {
338   DEBUG_CACHE_ASSERT(name.notSpecial());
339 
340   for (size_t i = nonSpecialHash(name, sig); ; ++i)
341     {
342       cell& b = cellByIndex(i);
343 
344       if (b.matches(name, sig))
345         return b.ent;
346 
347       if (b.empty())
348         return 0;
349     }
350 }
351 
lookup(symbol name,const ty * t)352 varEntry *core_venv::lookup(symbol name, const ty *t) {
353   DEBUG_CACHE_ASSERT(t);
354 
355   return name.special() ? lookupSpecial(name, t) :
356     lookupNonSpecial(name, t->getSignature());
357 }
358 
removeNonSpecial(symbol name,const signature * sig)359 void core_venv::removeNonSpecial(symbol name, const signature *sig) {
360   DEBUG_CACHE_ASSERT(name.notSpecial());
361 
362   for (size_t i = nonSpecialHash(name, sig); ; ++i)
363     {
364       cell& b = cellByIndex(i);
365 
366       if (b.matches(name, sig)) {
367         b.remove();
368         --size;
369         return;
370       }
371 
372       DEBUG_CACHE_ASSERT(!b.empty());
373     }
374 }
375 
removeSpecial(symbol name,const ty * t)376 void core_venv::removeSpecial(symbol name, const ty *t) {
377   DEBUG_CACHE_ASSERT(name.special());
378   DEBUG_CACHE_ASSERT(t);
379 
380   for (size_t i = specialHash(name, t); ; ++i)
381     {
382       cell& b = cellByIndex(i);
383 
384       if (b.matches(name, t)) {
385         b.remove();
386         --size;
387         return;
388       }
389 
390       DEBUG_CACHE_ASSERT(!b.empty());
391     }
392 }
393 
remove(symbol name,const ty * t)394 void core_venv::remove(symbol name, const ty *t) {
395   DEBUG_CACHE_ASSERT(t);
396 
397   if (name.special())
398     removeSpecial(name, t);
399   else
400     removeNonSpecial(name, t->getSignature());
401 }
402 
403 
numFormals(ty * t)404 size_t numFormals(ty *t) {
405   signature *sig = t->getSignature();
406   return sig ? sig->getNumFormals() : 0;
407 }
408 
checkName(symbol name)409 void venv::checkName(symbol name)
410 {
411 #if 0
412   // This size test is too slow, even for DEBUG_CACHE.
413   core.confirm_size();
414 #endif
415 
416   // Get the type, and make it overloaded if it is not (for uniformity).
417   overloaded o;
418   ty *t = getType(name);
419   if (!t)
420     t = &o;
421   if (!t->isOverloaded()) {
422     o.add(t);
423     t = &o;
424   }
425   assert(t->isOverloaded());
426 
427   size_t maxFormals = names[name].maxFormals;
428 
429   size_t size = 0;
430   for (ty_iterator i = t->begin(); i != t->end(); ++i) {
431     assert(numFormals(*i) <= maxFormals);
432     varEntry *v = lookByType(name, *i);
433     assert(v);
434     assert(equivalent(v->getType(), *i));
435     ++size;
436   }
437 
438   size_t matches = 0;
439   core_venv::const_iterator end = core.end();
440   for (core_venv::const_iterator p = core.begin(); p != end; ++p) {
441     if (p->name == name) {
442       ++matches;
443 
444       varEntry *v=p->ent;
445       assert(v);
446       assert(equivalent(t, v->getType()));
447     }
448   }
449   assert(matches == size);
450 }
451 
rightKind(ty * t)452 void rightKind(ty *t) {
453   if (t && t->isOverloaded()) {
454     ty_vector& set=((overloaded *)t)->sub;
455     assert(set.size() > 1);
456   }
457 }
458 
459 #ifdef DEBUG_CACHE
460 #define RIGHTKIND(t) (rightKind(t))
461 #define CHECKNAME(name) (checkName(name))
462 #else
463 #define RIGHTKIND(t) (void)(t)
464 #define CHECKNAME(name) (void)(name)
465 #endif
466 
addType(ty * s)467 void venv::namevalue::addType(ty *s) {
468   RIGHTKIND(t);
469 
470 #ifdef DEBUG_CACHE
471   assert(!s->isOverloaded());
472 #endif
473 
474   if (t == 0) {
475     maxFormals = numFormals(s);
476     t = s;
477   } else {
478     if (!t->isOverloaded())
479       t = new overloaded(t);
480 
481 #ifdef DEBUG_CACHE
482     assert(t->isOverloaded());
483     assert(!equivalent(t, s));
484 #endif
485 
486     ((overloaded *)t)->add(s);
487 
488     size_t n = numFormals(s);
489     if (n > maxFormals)
490       maxFormals = n;
491   }
492 
493   RIGHTKIND(t);
494 }
495 
replaceType(ty * new_t,ty * old_t)496 void venv::namevalue::replaceType(ty *new_t, ty *old_t) {
497 #ifdef DEBUG_CACHE
498   assert(t != 0);
499   RIGHTKIND(t);
500 #endif
501 
502   // TODO: Test for equivalence.
503 
504   if (t->isOverloaded()) {
505     for (ty_iterator i = t->begin(); i != t->end(); ++i) {
506       if (equivalent(old_t, *i)) {
507         *i = new_t;
508         return;
509       }
510     }
511 
512     // An error, the type was not found.
513     assert("unreachable code" == 0);
514 
515   } else {
516 #ifdef DEBUG_CACHE
517     assert(equivalent(old_t, t));
518 #endif
519     t = new_t;
520   }
521 
522 #ifdef DEBUG_CACHE
523   assert(t != 0);
524   RIGHTKIND(t);
525 #endif
526 }
527 
528 #ifdef DEBUG_CACHE
popType(ty * s)529 void venv::namevalue::popType(ty *s)
530 #else
531   void venv::namevalue::popType()
532 #endif
533 {
534 #ifdef DEBUG_CACHE
535   assert(t);
536   RIGHTKIND(t);
537   assert(!s->isOverloaded());
538 #endif
539 
540   if (t->isOverloaded()) {
541     ty_vector& set=((overloaded *)t)->sub;
542 
543 #ifdef DEBUG_CACHE
544     assert(set.size() > 0);
545     assert(equivalent(set.back(), s));
546 #endif
547 
548     // We are relying on the fact that this was the last type added to t, and
549     // that type are added by pushing them on the end of the vector.
550     set.pop_back();
551 
552     if (set.size() == 1)
553       t = set.front();
554   } else {
555 #ifdef DEBUG_CACHE
556     assert(equivalent(t, s));
557 #endif
558     t = 0;
559   }
560 
561   RIGHTKIND(t);
562 
563   // Don't try to reduce numFormals as I doubt it is worth the cost of
564   // recalculating.
565 }
566 
remove(const addition & a)567 void venv::remove(const addition& a) {
568   CHECKNAME(a.name);
569 
570   if (a.shadowed) {
571     varEntry *popEnt = core.store(a.name, a.shadowed);
572 
573     DEBUG_CACHE_ASSERT(popEnt);
574 
575     // Unshadow the previously shadowed varEntry.
576     names[a.name].replaceType(a.shadowed->getType(), popEnt->getType());
577   }
578   else {
579     // Remove the (name,sig) key completely.
580 #if DEBUG_CACHE
581     varEntry *popEnt = core.lookup(a.name, a.t);
582     assert(popEnt);
583     names[a.name].popType(popEnt->getType());
584 #else
585     names[a.name].popType();
586 #endif
587 
588     core.remove(a.name, a.t);
589   }
590 
591   CHECKNAME(a.name);
592 }
593 
beginScope()594 void venv::beginScope() {
595   if (core.empty()) {
596     assert(scopesizes.empty());
597     ++empty_scopes;
598   } else {
599     scopesizes.push(additions.size());
600   }
601 }
602 
endScope()603 void venv::endScope() {
604   if (scopesizes.empty()) {
605     // The corresponding beginScope happened when the venv was empty, so
606     // clear the hash tables to return to that state.
607     core.clear();
608     names.clear();
609 
610     assert(empty_scopes > 0);
611     --empty_scopes;
612   } else {
613     size_t scopesize = scopesizes.top();
614     assert(additions.size() >= scopesize);
615     while (additions.size() > scopesize) {
616       remove(additions.top());
617       additions.pop();
618     }
619     scopesizes.pop();
620   }
621 }
622 
623 // Adds the definitions of the top-level scope to the level underneath,
624 // and then removes the top scope.
collapseScope()625 void venv::collapseScope() {
626   if (scopesizes.empty()) {
627     // Collapsing an empty scope.
628     assert(empty_scopes > 0);
629     --empty_scopes;
630   } else {
631     // As scopes are stored solely by the number of entries at the beginning
632     // of the scope, popping the top size will put all of the entries into the
633     // next scope down.
634     scopesizes.pop();
635   }
636 }
637 
638 
enter(symbol name,varEntry * v)639 void venv::enter(symbol name, varEntry *v)
640 {
641   CHECKNAME(name);
642 
643   // Store the new variable.  If it shadows an older variable, that varEntry
644   // will be returned.
645   varEntry *shadowed = core.store(name, v);
646 
647   ty *t = v->getType();
648 
649   // Record the addition, so it can be undone during endScope.
650   if (!scopesizes.empty())
651     additions.push(addition(name, t, shadowed));
652 
653   if (shadowed)
654     // The new value shadows an old value.  They have the same signature, but
655     // possibly different return types.  If necessary, update the type stored
656     // by name.
657     names[name].replaceType(t, shadowed->getType());
658   else
659     // Add to the names hash table.
660     names[name].addType(t);
661 
662   CHECKNAME(name);
663 }
664 
665 
lookBySignature(symbol name,signature * sig)666 varEntry *venv::lookBySignature(symbol name, signature *sig) {
667   // Rest arguments are complicated and rare.  Don't handle them here.
668   if (sig->hasRest())
669     return 0;
670 
671   // Likewise with the special operators.
672   if (name.special())
673     return 0;
674 
675   namevalue& nv = names[name];
676 
677   // Avoid ambiguities with default parameters.
678   if (nv.maxFormals != sig->getNumFormals())
679     return 0;
680 
681   // See if this exactly matches a function in the table.
682   varEntry *ve = core.lookupNonSpecial(name, sig);
683 
684   if (!ve)
685     return 0;
686 
687   // Keyword-only arguments may cause matching to fail.
688   if (ve->getSignature()->numKeywordOnly > 0)
689     return 0;
690 
691   // At this point, any function with an equivalent signature will be equal
692   // to the result of the normal overloaded function resolution.  We may
693   // safely return it.
694   return ve;
695 }
696 
add(venv & source,varEntry * qualifier,coder & c)697 void venv::add(venv& source, varEntry *qualifier, coder &c)
698 {
699   core_venv::const_iterator end = source.core.end();
700   for (core_venv::const_iterator p = source.core.begin(); p != end; ++p)
701     {
702       DEBUG_CACHE_ASSERT(p->filled());
703 
704       varEntry *v=p->ent;
705       if (v->checkPerm(READ, c)) {
706         enter(p->name, qualifyVarEntry(qualifier, v));
707       }
708     }
709 }
710 
add(symbol src,symbol dest,venv & source,varEntry * qualifier,coder & c)711 bool venv::add(symbol src, symbol dest,
712                venv& source, varEntry *qualifier, coder &c)
713 {
714   ty *t=source.getType(src);
715 
716   if (!t)
717     return false;
718 
719   if (t->isOverloaded()) {
720     bool added=false;
721     for (ty_iterator i = t->begin(); i != t->end(); ++i)
722       {
723         varEntry *v=source.lookByType(src, *i);
724         if (v->checkPerm(READ, c)) {
725           enter(dest, qualifyVarEntry(qualifier, v));
726           added=true;
727         }
728       }
729     return added;
730   }
731   else {
732     varEntry *v=source.lookByType(src, t);
733     if (v->checkPerm(READ, c)) {
734       enter(dest, qualifyVarEntry(qualifier, v));
735       return true;
736     }
737     return false;
738   }
739 }
740 
741 
getType(symbol name)742 ty *venv::getType(symbol name)
743 {
744   return names[name].t;
745 }
746 
listValue(symbol name,varEntry * v,record * module)747 void listValue(symbol name, varEntry *v, record *module)
748 {
749   if (!module || v->whereDefined() == module)
750     {
751       if (settings::getSetting<bool>("where"))
752         cout << v->getPos();
753 
754       v->getType()->printVar(cout, name);
755 
756       cout << ";\n";
757     }
758 }
759 
listValues(symbol name,record * module)760 void venv::listValues(symbol name, record *module)
761 {
762   ty *t=getType(name);
763 
764   if (t->isOverloaded())
765     for (ty_iterator i = t->begin(); i != t->end(); ++i)
766       listValue(name, lookByType(name, *i), module);
767   else
768     listValue(name, lookByType(name, t), module);
769 
770   flush(cout);
771 }
772 
list(record * module)773 void venv::list(record *module)
774 {
775   // List all functions and variables.
776   for (namemap::iterator N = names.begin(); N != names.end(); ++N)
777     listValues(N->first, module);
778 }
779 
completions(mem::list<symbol> & l,string start)780 void venv::completions(mem::list<symbol >& l, string start)
781 {
782   for(namemap::iterator N = names.begin(); N != names.end(); ++N)
783     if (prefix(start, N->first) && N->second.t)
784       l.push_back(N->first);
785 }
786 
787 } // namespace trans
788