From 400d28d753aa8af8de60a7f82851ffdc3cdae672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Stelmach?= Date: Sun, 18 Aug 2013 17:18:43 +0200 Subject: Enable module stack introspection from within an SCAD script The _current_module and _parent_module variables have been replaced by a built-in function parent_module(n). It takes one numeric parameter n, and returns n-th element from the module stack. If no argument provided, n defaults to 1 and the function returns the name of the direct parent module. If n is equal 0 current module name is returned. diff --git a/src/func.cc b/src/func.cc index 20f487a..865a2b4 100644 --- a/src/func.cc +++ b/src/func.cc @@ -528,6 +528,29 @@ Value builtin_version_num(const Context *ctx, const EvalContext *evalctx) return Value(y * 10000 + m * 100 + d); } +Value builtin_parent_module(const Context *, const EvalContext *evalctx) +{ + int n; + double d; + int s = Module::stack_size(); + if (evalctx->numArgs() == 0) + d=1; // parent module + else if (evalctx->numArgs() == 1 && evalctx->getArgValue(0).type() == Value::NUMBER) + evalctx->getArgValue(0).getDouble(d); + else + return Value(); + n=trunc(d); + if (n < 0) { + PRINTB("WARNING: Negative parent module index (%d) not allowed", n); + return Value(); + } + if (n >= s) { + PRINTB("WARNING: Parent module index (%d) greater than the number of modules on the stack", n); + return Value(); + } + return Value(Module::stack_element(s - 1 - n)); +} + void register_builtin_functions() { Builtins::init("abs", new BuiltinFunction(&builtin_abs)); @@ -556,4 +579,5 @@ void register_builtin_functions() Builtins::init("search", new BuiltinFunction(&builtin_search)); Builtins::init("version", new BuiltinFunction(&builtin_version)); Builtins::init("version_num", new BuiltinFunction(&builtin_version_num)); + Builtins::init("parent_module", new BuiltinFunction(&builtin_parent_module)); } diff --git a/src/module.cc b/src/module.cc index 970dd56..9c3541f 100644 --- a/src/module.cc +++ b/src/module.cc @@ -153,7 +153,7 @@ std::vector IfElseModuleInstantiation::instantiateElseChildren(co return this->else_scope.instantiateChildren(evalctx); } -std::stack Module::stack; +std::deque Module::module_stack; Module::~Module() { @@ -183,20 +183,18 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation ModuleContext c(ctx, evalctx); c.initializeModule(*this); - c.set_variable("_current_module", inst->name()); - if (!stack.empty()) - c.set_variable("_parent_module", stack.top()); + module_stack.push_back(inst->name()); + c.set_variable("$parent_modules", Value(double(module_stack.size()))); 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 - stack.push(inst->name()); AbstractNode *node = new AbstractNode(inst); std::vector instantiatednodes = this->scope.instantiateChildren(&c); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); - stack.pop(); + module_stack.pop_back(); return node; } diff --git a/src/module.h b/src/module.h index fca88e3..8414706 100644 --- a/src/module.h +++ b/src/module.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -74,12 +74,15 @@ public: virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const; virtual std::string dump(const std::string &indent, const std::string &name) const; + static const std::string& stack_element(int n) { return module_stack[n]; }; + static int stack_size() { return module_stack.size(); }; AssignmentList definition_arguments; LocalScope scope; + private: - static std::stack stack; + static std::deque module_stack; }; // FIXME: A FileModule doesn't have definition arguments, so we shouldn't really -- cgit v0.10.1