// Instances of this class are passed to types::ty objects so that they can
// call back to env when checking casting of subtypes.
class envCaster : public caster {
protoenv &e;
symbol name;
public:
envCaster(protoenv &e, symbol name)
: e(e), name(name) {}
// If errors already exist, don't report more. This may, however, cause
// problems with resoving the signature of an overloaded function. The
// abstract syntax should check if any of the parameters had an error before
// finding the signature.
if (target->kind == ty_error || source->kind == ty_error)
return &id;
else if (equivalent(target,source))
return &id;
else {
varEntry *v=lookupVarByType(name,new function(target,source));
return v ? v->getLocation() : 0;
}
}
access *protoenv::lookupCast(ty *target, ty *source, symbol name) {
access *a=baseLookupCast(target, source, name);
if (a)
return a;
// To avoid memory allocation, fill one static variable with new parameters
// in each call.
// Warning: This is not re-entrant if asy ever goes multi-threaded.
static types::function castFunc(primVoid(), primVoid());
castFunc.result = target;
if (source->kind == types::ty_overloaded) {
bool result = false;
types::ty_vector& v = ((overloaded *)source)->sub;
for (size_t i = 0; i < v.size(); ++i) {
castFunc.sig.formals[0].t = v[i];
if (lookupVarByType(symbol::castsym, &castFunc)) {
result = true;
break;
}
}
//assert(result == castable(target, source, symbol::castsym));
//cout << "fc OVERLOADED " << (result ? "CAST" : "FAIL") << endl;
return result;
}
//else cout << "fc SIMPLE" << endl;
// Don't test for equivalent, as that is already done by the castScore
// code. Assert disabled for speed.
#if 0
assert(!equivalent(target, source));
#endif
castFunc.sig.formals[0].t = source;
if (lookupVarByType(symbol::castsym, &castFunc))
return true;
// Test for generic casts of null. This should be moved to a types.h
// routine.
return source->kind == ty_null && target->isReference();
}
env::env(genv &ge)
: protoenv(venv::file_env_tag()), ge(ge)
{
// NOTE: May want to make this initial environment into a "builtin" module,
// and then import the builtin module.
base_tenv(te);
base_venv(ve);
}
env::~env()
{
}
record *env::getModule(symbol id, string filename)
{
return ge.getModule(id, filename);
}
record *env::getTemplatedModule(string filename,
mem::vector<absyntax::namedTy*>* args)
{
return ge.getTemplatedModule(filename, args);
}
record *env::getLoadedModule(symbol id)
{
return ge.getLoadedModule(id);
}