diff options
author | Marius Kintel <marius@kintel.net> | 2013-05-24 14:16:20 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2013-05-24 14:16:20 (GMT) |
commit | 26046f6f0c4a774cbbb2af8ae7dc0e687963440c (patch) | |
tree | 38ff04fc460e8aa55134fb1ee6167fafb90a3423 /src/module.cc | |
parent | eefcd6d0b271642d470cd55bc47d1579d943938e (diff) | |
parent | 95e399e06c6522f3fa67679808a1d52815368efa (diff) |
Merge branch 'master' into epec-kernel
Diffstat (limited to 'src/module.cc')
-rw-r--r-- | src/module.cc | 189 |
1 files changed, 98 insertions, 91 deletions
diff --git a/src/module.cc b/src/module.cc index e6dcb57..e853457 100644 --- a/src/module.cc +++ b/src/module.cc @@ -27,11 +27,15 @@ #include "module.h" #include "ModuleCache.h" #include "node.h" -#include "context.h" +#include "modcontext.h" +#include "evalcontext.h" #include "expression.h" #include "function.h" #include "printutils.h" +#include <boost/filesystem.hpp> +namespace fs = boost::filesystem; +#include "boosty.h" #include <boost/foreach.hpp> #include <sstream> #include <sys/stat.h> @@ -40,11 +44,11 @@ AbstractModule::~AbstractModule() { } -AbstractNode *AbstractModule::evaluate(const Context*, const ModuleInstantiation *inst) const +AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { AbstractNode *node = new AbstractNode(inst); - node->children = inst->evaluateChildren(); + node->children = inst->instantiateChildren(evalctx); return node; } @@ -58,13 +62,27 @@ std::string AbstractModule::dump(const std::string &indent, const std::string &n ModuleInstantiation::~ModuleInstantiation() { - BOOST_FOREACH (Expression *v, argexpr) delete v; - BOOST_FOREACH (ModuleInstantiation *v, children) delete v; + BOOST_FOREACH(const Assignment &arg, this->arguments) delete arg.second; } IfElseModuleInstantiation::~IfElseModuleInstantiation() { - BOOST_FOREACH (ModuleInstantiation *v, else_children) delete v; +} + +/*! + Returns the absolute path to the given filename, unless it's empty. + + NB! This will actually search for the file, to be backwards compatible with <= 2013.01 + (see issue #217) +*/ +std::string ModuleInstantiation::getAbsolutePath(const std::string &filename) const +{ + if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) { + return boosty::absolute(fs::path(this->modpath) / filename).string(); + } + else { + return filename; + } } std::string ModuleInstantiation::dump(const std::string &indent) const @@ -72,21 +90,20 @@ std::string ModuleInstantiation::dump(const std::string &indent) const std::stringstream dump; dump << indent; dump << modname + "("; - for (size_t i=0; i < argnames.size(); i++) { + for (size_t i=0; i < this->arguments.size(); i++) { + const Assignment &arg = this->arguments[i]; if (i > 0) dump << ", "; - if (!argnames[i].empty()) dump << argnames[i] << " = "; - dump << *argexpr[i]; + if (!arg.first.empty()) dump << arg.first << " = "; + dump << *arg.second; } - if (children.size() == 0) { + if (scope.numElements() == 0) { dump << ");\n"; - } else if (children.size() == 1) { + } else if (scope.numElements() == 1) { dump << ")\n"; - dump << children[0]->dump(indent + "\t"); + dump << scope.dump(indent + "\t"); } else { dump << ") {\n"; - for (size_t i = 0; i < children.size(); i++) { - dump << children[i]->dump(indent + "\t"); - } + scope.dump(indent + "\t"); dump << indent << "}\n"; } return dump.str(); @@ -94,80 +111,63 @@ std::string ModuleInstantiation::dump(const std::string &indent) const AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const { - AbstractNode *node = NULL; - if (this->ctx) { - PRINTB("WARNING: Ignoring recursive module instantiation of '%s'.", modname); - } else { - // FIXME: Casting away const.. - ModuleInstantiation *that = (ModuleInstantiation*)this; - that->argvalues.clear(); - BOOST_FOREACH (Expression *expr, that->argexpr) { - that->argvalues.push_back(expr->evaluate(ctx)); - } - that->ctx = ctx; - node = ctx->evaluate_module(*this); - that->ctx = NULL; - that->argvalues.clear(); - } + EvalContext c(ctx, this->arguments, &this->scope); + +#if 0 && DEBUG + PRINT("New eval ctx:"); + c.dump(NULL, this); +#endif + AbstractNode *node = ctx->instantiate_module(*this, &c); // Passes c as evalctx return node; } -std::vector<AbstractNode*> ModuleInstantiation::evaluateChildren(const Context *ctx) const +std::vector<AbstractNode*> ModuleInstantiation::instantiateChildren(const Context *evalctx) const { - if (!ctx) ctx = this->ctx; - std::vector<AbstractNode*> childnodes; - BOOST_FOREACH (ModuleInstantiation *modinst, this->children) { - AbstractNode *node = modinst->evaluate(ctx); - if (node) childnodes.push_back(node); - } - return childnodes; + return this->scope.instantiateChildren(evalctx); } -std::vector<AbstractNode*> IfElseModuleInstantiation::evaluateElseChildren(const Context *ctx) const +std::vector<AbstractNode*> IfElseModuleInstantiation::instantiateElseChildren(const Context *evalctx) const { - if (!ctx) ctx = this->ctx; - std::vector<AbstractNode*> childnodes; - BOOST_FOREACH (ModuleInstantiation *modinst, this->else_children) { - AbstractNode *node = modinst->evaluate(ctx); - if (node != NULL) childnodes.push_back(node); - } - return childnodes; + return this->else_scope.instantiateChildren(evalctx); } Module::~Module() { - BOOST_FOREACH (const AssignmentContainer::value_type &v, assignments) delete v.second; - BOOST_FOREACH (FunctionContainer::value_type &f, functions) delete f.second; - BOOST_FOREACH (AbstractModuleContainer::value_type &m, modules) delete m.second; - BOOST_FOREACH (ModuleInstantiation *v, children) delete v; } -AbstractNode *Module::evaluate(const Context *ctx, const ModuleInstantiation *inst) const +class ModRecursionGuard { - Context c(ctx); - c.args(argnames, argexpr, inst->argnames, inst->argvalues); - - c.inst_p = inst; - c.set_variable("$children", Value(double(inst->children.size()))); - - c.functions_p = &functions; - c.modules_p = &modules; - - if (!usedlibs.empty()) - c.usedlibs_p = &usedlibs; - else - c.usedlibs_p = NULL; +public: + ModRecursionGuard(const ModuleInstantiation &inst) : inst(inst) { + inst.recursioncount++; + } + ~ModRecursionGuard() { + inst.recursioncount--; + } + bool recursion_detected() const { return (inst.recursioncount > 100); } +private: + const ModuleInstantiation &inst; +}; - BOOST_FOREACH(const std::string &var, assignments_var) { - c.set_variable(var, assignments.at(var)->evaluate(&c)); +AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +{ + ModRecursionGuard g(*inst); + if (g.recursion_detected()) { + PRINTB("ERROR: Recursion detected calling module '%s'", inst->name()); + return NULL; } + ModuleContext c(ctx, evalctx); + c.initializeModule(*this); + c.set_variable("$children", Value(double(inst->scope.children.size()))); + // FIXME: Set document path to the path of the module +#if 0 && DEBUG + c.dump(this, inst); +#endif + AbstractNode *node = new AbstractNode(inst); - for (size_t i = 0; i < children.size(); i++) { - AbstractNode *n = children[i]->evaluate(&c); - if (n != NULL) - node->children.push_back(n); - } + std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(&c); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); return node; } @@ -178,33 +178,23 @@ std::string Module::dump(const std::string &indent, const std::string &name) con std::string tab; if (!name.empty()) { dump << indent << "module " << name << "("; - for (size_t i=0; i < argnames.size(); i++) { + for (size_t i=0; i < this->definition_arguments.size(); i++) { + const Assignment &arg = this->definition_arguments[i]; if (i > 0) dump << ", "; - dump << argnames[i]; - if (argexpr[i]) dump << " = " << *argexpr[i]; + dump << arg.first; + if (arg.second) dump << " = " << *arg.second; } dump << ") {\n"; tab = "\t"; } - BOOST_FOREACH(const FunctionContainer::value_type &f, functions) { - dump << f.second->dump(indent + tab, f.first); - } - BOOST_FOREACH(const AbstractModuleContainer::value_type &m, modules) { - dump << m.second->dump(indent + tab, m.first); - } - BOOST_FOREACH(const std::string &var, assignments_var) { - dump << indent << tab << var << " = " << *assignments.at(var) << ";\n"; - } - for (size_t i = 0; i < children.size(); i++) { - dump << children[i]->dump(indent + tab); - } + dump << scope.dump(indent + tab); if (!name.empty()) { dump << indent << "}\n"; } return dump.str(); } -void Module::registerInclude(const std::string &filename) +void FileModule::registerInclude(const std::string &filename) { struct stat st; memset(&st, 0, sizeof(struct stat)); @@ -216,17 +206,17 @@ void Module::registerInclude(const std::string &filename) Check if any dependencies have been modified and recompile them. Returns true if anything was recompiled. */ -bool Module::handleDependencies() +bool FileModule::handleDependencies() { if (this->is_handling_dependencies) return false; this->is_handling_dependencies = true; bool changed = false; // Iterating manually since we want to modify the container while iterating - Module::ModuleContainer::iterator iter = this->usedlibs.begin(); + FileModule::ModuleContainer::iterator iter = this->usedlibs.begin(); while (iter != this->usedlibs.end()) { - Module::ModuleContainer::iterator curr = iter++; - Module *oldmodule = curr->second; + FileModule::ModuleContainer::iterator curr = iter++; + FileModule *oldmodule = curr->second; curr->second = ModuleCache::instance()->evaluate(curr->first); if (curr->second != oldmodule) { changed = true; @@ -243,3 +233,20 @@ bool Module::handleDependencies() this->is_handling_dependencies = false; return changed; } + +AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const +{ + assert(evalctx == NULL); + FileContext c(*this, ctx); + c.initializeModule(*this); + // FIXME: Set document path to the path of the module +#if 0 && DEBUG + c.dump(this, inst); +#endif + + AbstractNode *node = new AbstractNode(inst); + std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(ctx, &c); + node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); + + return node; +} |