using sym::symbol;
using types::ty;
using types::function;
using types::record;
class genv;
class coenv;
// Keeps track of the name bindings of variables and types. This is used for
// the fields of a record, whereas the derived class env is used for
// unqualified names in translation.
class protoenv {
//protected:
public:
// These tables keep track of type and variable definitions.
tenv te;
venv ve;
access *baseLookupCast(ty *target, ty *source, symbol name);
public:
// Start an environment for a file-level module.
protoenv() {}
access *lookupInitializer(ty *t)
{
// The initializer's type is a function returning the desired type.
function *it=new function(t);
varEntry *v=lookupVarByType(symbol::initsym,it);
// If not in the environment, try the type itself.
return v ? v->getLocation() : t->initializer();
}
// Find the function that handles casting between the types.
// The name is "operator cast" for implicit casting and "operator ecast" for
// explicit.
access *lookupCast(ty *target, ty *source, symbol name);
bool castable(ty *target, ty *source, symbol name);
// A cast lookup designed to work quickly with the application matching
// code. The target type must not be overloaded.
bool fastCastable(ty *target, ty *source);
// For the lookup, neither target nor source may be overloaded.
access *fastLookupCast(ty *target, ty *source);
// Given overloaded types, this resolves which types should be the target and
// the source of the cast.
ty *castTarget(ty *target, ty *source, symbol name);
ty *castSource(ty *target, ty *source, symbol name);
ty *varGetType(symbol name)
{
return ve.getType(name);
}
void addVar(symbol name, varEntry *desc)
{
// Don't check for multiple variables, as this makes adding casts
// and initializers harder.
ve.enter(name, desc);
}
// Add another environment, say from a record.
void add(protoenv &source, varEntry *qualifier, coder &c)
{
te.add(source.te, qualifier, c);
ve.add(source.ve, qualifier, c);
}
// Add variables and types of name src from another environment under the
// name dest in this environment.
Added *add(symbol src, symbol dest,
protoenv &source, varEntry *qualifier, coder &c)
{
Added *retv = new Added();
retv->typeAdded=te.add(src, dest, source.te, qualifier, c);
bool varAdded=ve.add(src, dest, source.ve, qualifier, c, &retv->varsAdded);
assert(varAdded == (retv->varsAdded.size() > 0));
return retv;
}
// Add the standard functions for a new type.
void addArrayOps(types::array *t);
void addRecordOps(types::record *r);
void list(record *r=0)
{
ve.list(r);
}
// Adds to a list the keywords in the environment that start with the given
// prefix. Used for automatic completion at the interactive prompt.
typedef mem::list<symbol> symbol_list;
void completions(symbol_list &l, string start)
{
te.completions(l, start);
ve.completions(l, start);
}
// Environment used in translating statements and expressions at all scopes. As
// opposed to protoenv which is suitable for keeping track of the fields of
// records, this also keeps track of the global env, for loading modules.
class env : public protoenv {
// The global environment - keeps track of modules.
genv ≥
public:
// Start an environment for a file-level module.
env(genv &ge);
~env();
record *getModule(symbol id, string filename);
record *getTemplatedModule(string filename,
mem::vector<absyntax::namedTy*> *args);
record *getLoadedModule(symbol id);
};