diff options
Diffstat (limited to 'src/modcontext.cc')
-rw-r--r-- | src/modcontext.cc | 164 |
1 files changed, 97 insertions, 67 deletions
diff --git a/src/modcontext.cc b/src/modcontext.cc index df341f9..44c2002 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -7,28 +7,18 @@ #include <boost/foreach.hpp> -ModuleContext::ModuleContext(const class Module *module, const Context *parent, const EvalContext *evalctx) - : Context(parent), functions_p(NULL), modules_p(NULL), usedlibs_p(NULL) +ModuleContext::ModuleContext(const Context *parent, const EvalContext *evalctx) + : Context(parent), functions_p(NULL), modules_p(NULL), evalctx(evalctx) { - if (module) setModule(*module, evalctx); } ModuleContext::~ModuleContext() { } -void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) +void ModuleContext::initializeModule(const class Module &module) { this->setVariables(module.definition_arguments, evalctx); - this->evalctx = evalctx; - - // FIXME: Hack - split out file context into separate class? - const FileModule *fm = dynamic_cast<const FileModule*>(&module); - if (fm) { - this->usedlibs_p = &(fm->usedlibs); - if (!fm->modulePath().empty()) this->document_path = fm->modulePath(); - } - // FIXME: Don't access module members directly this->functions_p = &module.scope.functions; this->modules_p = &module.scope.modules; @@ -37,17 +27,6 @@ void ModuleContext::setModule(const Module &module, const EvalContext *evalctx) } } -/*! - Only used to initialize builtins for the top-level root context -*/ -void ModuleContext::registerBuiltin() -{ - // FIXME: built-ins only contains variables, setModule isn't really needed for this - // FIXME: Where to put set_variable from setModule? - this->setModule(Builtins::instance()->getRootModule()); - this->set_constant("PI",Value(M_PI)); -} - class RecursionGuard { public: @@ -61,60 +40,64 @@ private: const std::string &name; }; -Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const + +/*! + Only used to initialize builtins for the top-level root context +*/ +void ModuleContext::registerBuiltin() { - RecursionGuard g(*this, name); - if (g.recursion_detected()) { - PRINTB("Recursion detected calling function '%s'", name); - return Value(); + const LocalScope &scope = Builtins::instance()->getGlobalScope(); + + // FIXME: Don't access module members directly + this->functions_p = &scope.functions; + this->modules_p = &scope.modules; + BOOST_FOREACH(const Assignment &ass, scope.assignments) { + this->set_variable(ass.first, ass.second->evaluate(this)); } + this->set_constant("PI",Value(M_PI)); +} + +const AbstractFunction *ModuleContext::findLocalFunction(const std::string &name) const +{ if (this->functions_p && this->functions_p->find(name) != this->functions_p->end()) { - return this->functions_p->find(name)->second->evaluate(this, evalctx); + return this->functions_p->find(name)->second; } - - if (this->usedlibs_p) { - BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, *this->usedlibs_p) { - if (m.second->scope.functions.find(name) != m.second->scope.functions.end()) { - ModuleContext ctx(m.second, this->parent); - // FIXME: Set document path -#if 0 && DEBUG - PRINTB("New lib Context for %s func:", name); - ctx.dump(NULL, NULL); -#endif - return m.second->scope.functions[name]->evaluate(&ctx, evalctx); - } - } - } - return Context::evaluate_function(name, evalctx); + return NULL; } -AbstractNode *ModuleContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +const AbstractModule *ModuleContext::findLocalModule(const std::string &name) const { - if (this->modules_p && this->modules_p->find(inst.name()) != this->modules_p->end()) { - AbstractModule *m = this->modules_p->find(inst.name())->second; - std::string replacement = Builtins::instance()->isDeprecated(inst.name()); + if (this->modules_p && this->modules_p->find(name) != this->modules_p->end()) { + AbstractModule *m = this->modules_p->find(name)->second; + std::string replacement = Builtins::instance()->isDeprecated(name); if (!replacement.empty()) { - PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", inst.name() % replacement); + PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", name % replacement); } - return m->instantiate(this, &inst, evalctx); + return m; } + return NULL; +} - if (this->usedlibs_p) { - BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, *this->usedlibs_p) { - assert(m.second); - if (m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) { - ModuleContext ctx(m.second, this->parent); - // FIXME: Set document path -#if 0 && DEBUG - PRINT("New lib Context:"); - ctx.dump(NULL, &inst); -#endif - return m.second->scope.modules[inst.name()]->instantiate(&ctx, &inst, evalctx); - } - } +Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const +{ + RecursionGuard g(*this, name); + if (g.recursion_detected()) { + PRINTB("Recursion detected calling function '%s'", name); + return Value(); } + const AbstractFunction *foundf = findLocalFunction(name); + if (foundf) return foundf->evaluate(this, evalctx); + + return Context::evaluate_function(name, evalctx); +} + +AbstractNode *ModuleContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +{ + const AbstractModule *foundm = this->findLocalModule(inst.name()); + if (foundm) return foundm->instantiate(this, &inst, evalctx); + return Context::instantiate_module(inst, evalctx); } @@ -150,10 +133,57 @@ void ModuleContext::dump(const AbstractModule *mod, const ModuleInstantiation *i } #endif -FileContext::FileContext(const class FileModule &module, - const Context *parent, const EvalContext *evalctx) - :ModuleContext(&module, parent, evalctx) +FileContext::FileContext(const class FileModule &module, const Context *parent) + : usedlibs(module.usedlibs), ModuleContext(parent) +{ + if (!module.modulePath().empty()) this->document_path = module.modulePath(); +} + +Value FileContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const { + RecursionGuard g(*this, name); + if (g.recursion_detected()) { + PRINTB("Recursion detected calling function '%s'", name); + return Value(); + } + + const AbstractFunction *foundf = findLocalFunction(name); + if (foundf) return foundf->evaluate(this, evalctx); + BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) { + if (m.second->scope.functions.find(name) != m.second->scope.functions.end()) { + FileContext ctx(*m.second, this->parent); + ctx.initializeModule(*m.second); + // FIXME: Set document path +#if 0 && DEBUG + PRINTB("New lib Context for %s func:", name); + ctx.dump(NULL, NULL); +#endif + return m.second->scope.functions[name]->evaluate(&ctx, evalctx); + } + } + + return ModuleContext::evaluate_function(name, evalctx); } +AbstractNode *FileContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const +{ + const AbstractModule *foundm = this->findLocalModule(inst.name()); + if (foundm) return foundm->instantiate(this, &inst, evalctx); + + BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) { + assert(m.second); + if (m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) { + FileContext ctx(*m.second, this->parent); + ctx.initializeModule(*m.second); + // FIXME: Set document path +#if 0 && DEBUG + PRINT("New file Context:"); + ctx.dump(NULL, &inst); +#endif + return m.second->scope.modules[inst.name()]->instantiate(&ctx, &inst, evalctx); + } + } + + return ModuleContext::instantiate_module(inst, evalctx); +} |