summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/MainWindow.h4
-rw-r--r--src/builtin.cc31
-rw-r--r--src/builtin.h8
-rw-r--r--src/cgaladv.cc21
-rw-r--r--src/color.cc15
-rw-r--r--src/context.cc150
-rw-r--r--src/context.h34
-rw-r--r--src/control.cc93
-rw-r--r--src/csgops.cc7
-rw-r--r--src/dxfdim.cc48
-rw-r--r--src/evalcontext.cc40
-rw-r--r--src/evalcontext.h24
-rw-r--r--src/expr.cc24
-rw-r--r--src/expression.h3
-rw-r--r--src/func.cc230
-rw-r--r--src/function.h12
-rw-r--r--src/import.cc36
-rw-r--r--src/lexer.l1
-rw-r--r--src/linearextrude.cc23
-rw-r--r--src/mainwin.cc8
-rw-r--r--src/modcontext.cc152
-rw-r--r--src/modcontext.h40
-rw-r--r--src/module.cc91
-rw-r--r--src/module.h30
-rw-r--r--src/openscad.cc15
-rw-r--r--src/parser.y795
-rw-r--r--src/primitives.cc26
-rw-r--r--src/printutils.cc2
-rw-r--r--src/printutils.h3
-rw-r--r--src/projection.cc15
-rw-r--r--src/render.cc15
-rw-r--r--src/rotateextrude.cc15
-rw-r--r--src/surface.cc13
-rw-r--r--src/transform.cc23
-rw-r--r--src/typedefs.h10
35 files changed, 1150 insertions, 907 deletions
diff --git a/src/MainWindow.h b/src/MainWindow.h
index 8745b8b..65deb15 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -4,7 +4,7 @@
#include <QMainWindow>
#include "ui_MainWindow.h"
#include "openscad.h"
-#include "context.h"
+#include "modcontext.h"
#include "module.h"
#include "Tree.h"
#include "memory.h"
@@ -29,7 +29,7 @@ public:
QTimer *autoReloadTimer;
std::string autoReloadId;
- Context root_ctx;
+ ModuleContext root_ctx;
Module *root_module; // Result of parsing
ModuleInstantiation root_inst; // Top level instance
AbstractNode *absolute_root_node; // Result of tree evaluation
diff --git a/src/builtin.cc b/src/builtin.cc
index 6eb32b6..bdd2d3b 100644
--- a/src/builtin.cc
+++ b/src/builtin.cc
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "function.h"
#include "module.h"
+#include "expression.h"
#include <boost/foreach.hpp>
Builtins *Builtins::instance(bool erase)
@@ -15,12 +16,12 @@ Builtins *Builtins::instance(bool erase)
void Builtins::init(const char *name, class AbstractModule *module)
{
- Builtins::instance()->builtinmodules[name] = module;
+ Builtins::instance()->rootmodule.modules[name] = module;
}
void Builtins::init(const char *name, class AbstractFunction *function)
{
- Builtins::instance()->builtinfunctions[name] = function;
+ Builtins::instance()->rootmodule.functions[name] = function;
}
extern void register_builtin_functions();
@@ -77,10 +78,28 @@ std::string Builtins::isDeprecated(const std::string &name)
return std::string();
}
+Builtins::Builtins()
+{
+ this->rootmodule.assignments_var.push_back("$fn");
+ this->rootmodule.assignments["$fn"] = new Expression(Value(0.0));
+ this->rootmodule.assignments_var.push_back("$fs");
+ this->rootmodule.assignments["$fs"] = new Expression(Value(2.0));
+ this->rootmodule.assignments_var.push_back("$fa");
+ this->rootmodule.assignments["$fa"] = new Expression(Value(12.0));
+ this->rootmodule.assignments_var.push_back("$t");
+ this->rootmodule.assignments["$t"] = new Expression(Value(0.0));
+
+ Value::VectorType zero3;
+ zero3.push_back(Value(0.0));
+ zero3.push_back(Value(0.0));
+ zero3.push_back(Value(0.0));
+ Value zero3val(zero3);
+ this->rootmodule.assignments_var.push_back("$vpt");
+ this->rootmodule.assignments["$vpt"] = new Expression(zero3val);
+ this->rootmodule.assignments_var.push_back("$vpr");
+ this->rootmodule.assignments["$vpr"] = new Expression(zero3val);
+}
+
Builtins::~Builtins()
{
- BOOST_FOREACH(FunctionContainer::value_type &f, this->builtinfunctions) delete f.second;
- this->builtinfunctions.clear();
- BOOST_FOREACH(ModuleContainer::value_type &m, this->builtinmodules) delete m.second;
- this->builtinmodules.clear();
}
diff --git a/src/builtin.h b/src/builtin.h
index bc096e5..564c951 100644
--- a/src/builtin.h
+++ b/src/builtin.h
@@ -3,6 +3,7 @@
#include <string>
#include <boost/unordered_map.hpp>
+#include "module.h"
class Builtins
{
@@ -19,16 +20,17 @@ public:
const FunctionContainer &functions() { return this->builtinfunctions; }
const ModuleContainer &modules() { return this->builtinmodules; }
+ const Module &getRootModule() { return this->rootmodule; }
+
private:
- Builtins() { }
+ Builtins();
~Builtins();
+ Module rootmodule;
FunctionContainer builtinfunctions;
ModuleContainer builtinmodules;
boost::unordered_map<std::string, std::string> deprecations;
};
-extern void register_builtin(class Context &ctx);
-
#endif
diff --git a/src/cgaladv.cc b/src/cgaladv.cc
index a4cb5ec..aad3a95 100644
--- a/src/cgaladv.cc
+++ b/src/cgaladv.cc
@@ -26,7 +26,7 @@
#include "cgaladvnode.h"
#include "module.h"
-#include "context.h"
+#include "evalcontext.h"
#include "builtin.h"
#include "PolySetEvaluator.h"
#include <sstream>
@@ -39,30 +39,29 @@ class CgaladvModule : public AbstractModule
public:
cgaladv_type_e type;
CgaladvModule(cgaladv_type_e type) : type(type) { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
CgaladvNode *node = new CgaladvNode(inst, type);
- std::vector<std::string> argnames;
- std::vector<Expression*> argexpr;
+ AssignmentList args;
if (type == MINKOWSKI)
- argnames += "convexity";
+ args += Assignment("convexity", NULL);
if (type == GLIDE)
- argnames += "path", "convexity";
+ args += Assignment("path", NULL), Assignment("convexity", NULL);
if (type == SUBDIV)
- argnames += "type", "level", "convexity";
+ args += Assignment("type", NULL), Assignment("level", NULL), Assignment("convexity", NULL);
if (type == RESIZE)
- argnames += "newsize", "auto";
+ args += Assignment("newsize", NULL), Assignment("auto", NULL);
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
Value convexity, path, subdiv_type, level;
@@ -111,7 +110,7 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat
if (node->level <= 1)
node->level = 1;
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
return node;
diff --git a/src/color.cc b/src/color.cc
index acca652..6c3aaef 100644
--- a/src/color.cc
+++ b/src/color.cc
@@ -26,7 +26,7 @@
#include "colornode.h"
#include "module.h"
-#include "context.h"
+#include "evalcontext.h"
#include "builtin.h"
#include "printutils.h"
#include <sstream>
@@ -40,27 +40,26 @@ class ColorModule : public AbstractModule
{
public:
ColorModule() { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
private:
static boost::unordered_map<std::string, Color4f> colormap;
};
#include "colormap.h"
-AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
ColorNode *node = new ColorNode(inst);
node->color[0] = node->color[1] = node->color[2] = -1.0;
node->color[3] = 1.0;
- std::vector<std::string> argnames;
- std::vector<Expression*> argexpr;
+ AssignmentList args;
- argnames += "c", "alpha";
+ args += Assignment("c", NULL), Assignment("alpha", NULL);
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
Value v = c.lookup_variable("c");
if (v.type() == Value::VECTOR) {
@@ -88,7 +87,7 @@ AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiatio
node->color[3] = alpha.toDouble();
}
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
return node;
diff --git a/src/context.cc b/src/context.cc
index 97ea5b9..706407c 100644
--- a/src/context.cc
+++ b/src/context.cc
@@ -25,6 +25,7 @@
*/
#include "context.h"
+#include "evalcontext.h"
#include "expression.h"
#include "function.h"
#include "module.h"
@@ -40,26 +41,11 @@ std::vector<const Context*> Context::ctx_stack;
/*!
Initializes this context. Optionally initializes a context for an external library
*/
-Context::Context(const Context *parent, const Module *library)
- : parent(parent), inst_p(NULL)
+Context::Context(const Context *parent)
+ : parent(parent)
{
- if (parent) recursioncount = parent->recursioncount;
ctx_stack.push_back(this);
if (parent) document_path = parent->document_path;
- if (library) {
- // FIXME: Don't access module members directly
- this->functions_p = &library->functions;
- this->modules_p = &library->modules;
- this->usedlibs_p = &library->usedlibs;
- BOOST_FOREACH(const std::string &var, library->assignments_var) {
- this->set_variable(var, library->assignments.at(var)->evaluate(this));
- }
- }
- else {
- functions_p = NULL;
- modules_p = NULL;
- usedlibs_p = NULL;
- }
}
Context::~Context()
@@ -68,25 +54,26 @@ Context::~Context()
}
/*!
- Initialize context from argument lists (function call/module instantiation)
- */
-void Context::args(const std::vector<std::string> &argnames,
- const std::vector<Expression*> &argexpr,
- const std::vector<std::string> &call_argnames,
- const std::vector<Value> &call_argvalues)
+ Initialize context from a module argument list and a evaluation context
+ which may pass variables which will be preferred over default values.
+*/
+void Context::setVariables(const AssignmentList &args,
+ const EvalContext *evalctx)
{
- for (size_t i=0; i<argnames.size(); i++) {
- set_variable(argnames[i], i < argexpr.size() && argexpr[i] ?
- argexpr[i]->evaluate(this->parent) : Value());
+ BOOST_FOREACH(const Assignment &arg, args) {
+ set_variable(arg.first, arg.second ? arg.second->evaluate(this->parent) : Value());
}
- size_t posarg = 0;
- for (size_t i=0; i<call_argnames.size(); i++) {
- if (call_argnames[i].empty()) {
- if (posarg < argnames.size())
- set_variable(argnames[posarg++], call_argvalues[i]);
- } else {
- set_variable(call_argnames[i], call_argvalues[i]);
+ if (evalctx) {
+ size_t posarg = 0;
+ for (size_t i=0; i<evalctx->eval_arguments.size(); i++) {
+ const std::string &name = evalctx->eval_arguments[i].first;
+ const Value &val = evalctx->eval_arguments[i].second;
+ if (name.empty()) {
+ if (posarg < args.size()) this->set_variable(args[posarg++].first, val);
+ } else {
+ this->set_variable(name, val);
+ }
}
}
}
@@ -130,61 +117,16 @@ Value Context::lookup_variable(const std::string &name, bool silent) const
return Value();
}
-class RecursionGuard
-{
-public:
- RecursionGuard(const Context &c, const std::string &name) : c(c), name(name) { c.recursioncount[name]++; }
- ~RecursionGuard() { if (--c.recursioncount[name] == 0) c.recursioncount.erase(name); }
- bool recursion_detected() const { return (c.recursioncount[name] > 100); }
-private:
- const Context &c;
- const std::string &name;
-};
-
-Value Context::evaluate_function(const std::string &name,
- const std::vector<std::string> &argnames,
- const std::vector<Value> &argvalues) const
+Value Context::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();
- }
- if (this->functions_p && this->functions_p->find(name) != this->functions_p->end())
- return this->functions_p->find(name)->second->evaluate(this, argnames, argvalues);
- if (this->usedlibs_p) {
- BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) {
- if (m.second->functions.find(name) != m.second->functions.end()) {
- Context ctx(this->parent, m.second);
- return m.second->functions[name]->evaluate(&ctx, argnames, argvalues);
- }
- }
- }
- if (this->parent) return this->parent->evaluate_function(name, argnames, argvalues);
+ if (this->parent) return this->parent->evaluate_function(name, evalctx);
PRINTB("WARNING: Ignoring unknown function '%s'.", name);
return Value();
}
-AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst) const
+AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) 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 (!replacement.empty()) {
- PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", inst.name() % replacement);
- }
- return m->evaluate(this, &inst);
- }
- if (this->usedlibs_p) {
- BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) {
- assert(m.second);
- if (m.second->modules.find(inst.name()) != m.second->modules.end()) {
- Context ctx(this->parent, m.second);
- return m.second->modules[inst.name()]->evaluate(&ctx, &inst);
- }
- }
- }
- if (this->parent) return this->parent->evaluate_module(inst);
+ if (this->parent) return this->parent->evaluate_module(inst, evalctx);
PRINTB("WARNING: Ignoring unknown module '%s'.", inst.name());
return NULL;
}
@@ -202,22 +144,34 @@ std::string Context::getAbsolutePath(const std::string &filename) const
}
}
-void register_builtin(Context &ctx)
+#ifdef DEBUG
+void Context::dump(const AbstractModule *mod, const ModuleInstantiation *inst)
{
- ctx.functions_p = &Builtins::instance()->functions();
- ctx.modules_p = &Builtins::instance()->modules();
- ctx.set_variable("$fn", Value(0.0));
- ctx.set_variable("$fs", Value(2.0));
- ctx.set_variable("$fa", Value(12.0));
- ctx.set_variable("$t", Value(0.0));
-
- Value::VectorType zero3;
- zero3.push_back(Value(0.0));
- zero3.push_back(Value(0.0));
- zero3.push_back(Value(0.0));
- Value zero3val(zero3);
- ctx.set_variable("$vpt", zero3val);
- ctx.set_variable("$vpr", zero3val);
+ if (inst)
+ PRINTB("ModuleContext %p (%p) for %s inst (%p)", this % this->parent % inst->name() % inst);
+ else
+ PRINTB("Context: %p (%p)", this % this->parent);
+ PRINTB(" document path: %s", this->document_path);
+ if (mod) {
+ const Module *m = dynamic_cast<const Module*>(mod);
+ if (m) {
+ PRINT(" module args:");
+ BOOST_FOREACH(const Assignment &arg, m->definition_arguments) {
+ PRINTB(" %s = %s", arg.first % variables[arg.first]);
+ }
+ }
+ }
+ typedef std::pair<std::string, Value> ValueMapType;
+ PRINT(" vars:");
+ BOOST_FOREACH(const ValueMapType &v, constants) {
+ PRINTB(" %s = %s", v.first % v.second);
+ }
+ BOOST_FOREACH(const ValueMapType &v, variables) {
+ PRINTB(" %s = %s", v.first % v.second);
+ }
+ BOOST_FOREACH(const ValueMapType &v, config_variables) {
+ PRINTB(" %s = %s", v.first % v.second);
+ }
- ctx.set_constant("PI",Value(M_PI));
}
+#endif
diff --git a/src/context.h b/src/context.h
index eb9a175..51fc45c 100644
--- a/src/context.h
+++ b/src/context.h
@@ -5,48 +5,46 @@
#include <vector>
#include <boost/unordered_map.hpp>
#include "value.h"
+#include "typedefs.h"
class Context
{
public:
- Context(const Context *parent = NULL, const class Module *library = NULL);
- ~Context();
+ Context(const Context *parent = NULL);
+ virtual ~Context();
- void args(const std::vector<std::string> &argnames,
- const std::vector<class Expression*> &argexpr,
- const std::vector<std::string> &call_argnames,
- const std::vector<Value> &call_argvalues);
+ virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const;
+ virtual class AbstractNode *evaluate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const;
+
+ void setVariables(const AssignmentList &args,
+ const class EvalContext *evalctx = NULL);
void set_variable(const std::string &name, const Value &value);
void set_constant(const std::string &name, const Value &value);
Value lookup_variable(const std::string &name, bool silent = false) const;
- Value evaluate_function(const std::string &name,
- const std::vector<std::string> &argnames,
- const std::vector<Value> &argvalues) const;
- class AbstractNode *evaluate_module(const class ModuleInstantiation &inst) const;
void setDocumentPath(const std::string &path) { this->document_path = path; }
+ const std::string &documentPath() const { return this->document_path; }
std::string getAbsolutePath(const std::string &filename) const;
public:
const Context *parent;
- const boost::unordered_map<std::string, class AbstractFunction*> *functions_p;
- const boost::unordered_map<std::string, class AbstractModule*> *modules_p;
- typedef boost::unordered_map<std::string, class Module*> ModuleContainer;
- const ModuleContainer *usedlibs_p;
- const ModuleInstantiation *inst_p;
static std::vector<const Context*> ctx_stack;
- mutable boost::unordered_map<std::string, int> recursioncount;
-
-private:
+protected:
typedef boost::unordered_map<std::string, Value> ValueMap;
ValueMap constants;
ValueMap variables;
ValueMap config_variables;
+
std::string document_path;
+
+#ifdef DEBUG
+public:
+ virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst);
+#endif
};
#endif
diff --git a/src/control.cc b/src/control.cc
index 44847f5..d47eec0 100644
--- a/src/control.cc
+++ b/src/control.cc
@@ -26,7 +26,8 @@
#include "module.h"
#include "node.h"
-#include "context.h"
+#include "evalcontext.h"
+#include "modcontext.h"
#include "builtin.h"
#include "printutils.h"
#include <sstream>
@@ -45,18 +46,16 @@ class ControlModule : public AbstractModule
public:
control_type_e type;
ControlModule(control_type_e type) : type(type) { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l,
- const std::vector<std::string> &call_argnames,
- const std::vector<Value> &call_argvalues,
- const Context *arg_context)
+ const Context *ctx, const EvalContext *evalctx)
{
- if (call_argnames.size() > l) {
- const std::string &it_name = call_argnames[l];
- const Value &it_values = call_argvalues[l];
- Context c(arg_context);
+ if (evalctx->eval_arguments.size() > l) {
+ const std::string &it_name = evalctx->eval_arguments[l].first;
+ const Value &it_values = evalctx->eval_arguments[l].second;
+ Context c(ctx);
if (it_values.type() == Value::RANGE) {
Value::RangeType range = it_values.toRange();
if (range.end < range.begin) {
@@ -67,55 +66,69 @@ void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l,
if (range.step > 0 && (range.begin-range.end)/range.step < 10000) {
for (double i = range.begin; i <= range.end; i += range.step) {
c.set_variable(it_name, Value(i));
- for_eval(node, inst, l+1, call_argnames, call_argvalues, &c);
+ for_eval(node, inst, l+1, &c, evalctx);
}
}
}
else if (it_values.type() == Value::VECTOR) {
for (size_t i = 0; i < it_values.toVector().size(); i++) {
c.set_variable(it_name, it_values.toVector()[i]);
- for_eval(node, inst, l+1, call_argnames, call_argvalues, &c);
+ for_eval(node, inst, l+1, &c, evalctx);
}
}
else if (it_values.type() != Value::UNDEFINED) {
c.set_variable(it_name, it_values);
- for_eval(node, inst, l+1, call_argnames, call_argvalues, &c);
+ for_eval(node, inst, l+1, &c, evalctx);
}
} else if (l > 0) {
- std::vector<AbstractNode *> evaluatednodes = inst.evaluateChildren(arg_context);
+ std::vector<AbstractNode *> evaluatednodes = inst.evaluateChildren(ctx);
node.children.insert(node.children.end(), evaluatednodes.begin(), evaluatednodes.end());
}
}
-AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation *inst) const
+AbstractNode *ControlModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
AbstractNode *node = NULL;
if (type == CHILD)
{
- size_t n = 0;
- if (inst->argvalues.size() > 0) {
+ int n = 0;
+ if (evalctx->eval_arguments.size() > 0) {
double v;
- if (inst->argvalues[0].getDouble(v)) {
- if (v < 0) return NULL; // Disallow negative child indices
+ if (evalctx->eval_arguments[0].second.getDouble(v)) {
n = trunc(v);
+ if (n < 0) {
+ PRINTB("WARNING: Negative child index (%d) not allowed", n);
+ return NULL; // Disallow negative child indices
+ }
}
}
- for (int i = Context::ctx_stack.size()-1; i >= 0; i--) {
- const Context *c = Context::ctx_stack[i];
- if (c->inst_p) {
- if (n < c->inst_p->children.size()) {
- node = c->inst_p->children[n]->evaluate(c->inst_p->ctx);
- // FIXME: We'd like to inherit any tags from the ModuleInstantiation
- // given as parameter to this method. However, the instantition which belongs
- // to the returned node cannot be changed. This causes the test
- // features/child-background.scad to fail.
+
+ // Find the last custom module invocation, which will contain
+ // an eval context with the children of the module invokation
+ const Context *tmpc = evalctx;
+ while (tmpc->parent) {
+ const ModuleContext *filectx = dynamic_cast<const ModuleContext*>(tmpc->parent);
+ if (filectx) {
+ // This will trigger if trying to invoke child from the root of any file
+ // assert(filectx->evalctx);
+
+ if (filectx->evalctx) {
+ if (n < filectx->evalctx->children.size()) {
+ node = filectx->evalctx->children[n]->evaluate_instance(filectx->evalctx);
+ }
+ else {
+ // How to deal with negative objects in this case?
+ // (e.g. first child of difference is invalid)
+ PRINTB("WARNING: Child index (%d) out of bounds (%d children)",
+ n % filectx->evalctx->children.size());
+ }
}
return node;
}
- c = c->parent;
+ tmpc = tmpc->parent;
}
- return NULL;
+ return node;
}
if (type == INT_FOR)
@@ -127,20 +140,20 @@ AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation
{
std::stringstream msg;
msg << "ECHO: ";
- for (size_t i = 0; i < inst->argnames.size(); i++) {
+ for (size_t i = 0; i < inst->arguments.size(); i++) {
if (i > 0) msg << ", ";
- if (!inst->argnames[i].empty()) msg << inst->argnames[i] << " = ";
- msg << inst->argvalues[i];
+ if (!evalctx->eval_arguments[i].first.empty()) msg << evalctx->eval_arguments[i].first << " = ";
+ msg << evalctx->eval_arguments[i].second;
}
PRINTB("%s", msg.str());
}
if (type == ASSIGN)
{
- Context c(inst->ctx);
- for (size_t i = 0; i < inst->argnames.size(); i++) {
- if (!inst->argnames[i].empty())
- c.set_variable(inst->argnames[i], inst->argvalues[i]);
+ Context c(evalctx);
+ for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) {
+ if (!evalctx->eval_arguments[i].first.empty())
+ c.set_variable(evalctx->eval_arguments[i].first, evalctx->eval_arguments[i].second);
}
std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(&c);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
@@ -148,18 +161,18 @@ AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation
if (type == FOR || type == INT_FOR)
{
- for_eval(*node, *inst, 0, inst->argnames, inst->argvalues, inst->ctx);
+ for_eval(*node, *inst, 0, evalctx, evalctx);
}
if (type == IF)
{
const IfElseModuleInstantiation *ifelse = dynamic_cast<const IfElseModuleInstantiation*>(inst);
- if (ifelse->argvalues.size() > 0 && ifelse->argvalues[0].toBool()) {
- std::vector<AbstractNode *> evaluatednodes = ifelse->evaluateChildren();
+ if (evalctx->eval_arguments.size() > 0 && evalctx->eval_arguments[0].second.toBool()) {
+ std::vector<AbstractNode *> evaluatednodes = ifelse->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
}
else {
- std::vector<AbstractNode *> evaluatednodes = ifelse->evaluateElseChildren();
+ std::vector<AbstractNode *> evaluatednodes = ifelse->evaluateElseChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
}
}
diff --git a/src/csgops.cc b/src/csgops.cc
index 7524559..425b747 100644
--- a/src/csgops.cc
+++ b/src/csgops.cc
@@ -26,6 +26,7 @@
#include "csgnode.h"
+#include "evalcontext.h"
#include "module.h"
#include "csgterm.h"
#include "builtin.h"
@@ -37,13 +38,13 @@ class CsgModule : public AbstractModule
public:
csg_type_e type;
CsgModule(csg_type_e type) : type(type) { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *inst) const
+AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
CsgNode *node = new CsgNode(inst, type);
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
return node;
}
diff --git a/src/dxfdim.cc b/src/dxfdim.cc
index 53bc480..fbc24c4 100644
--- a/src/dxfdim.cc
+++ b/src/dxfdim.cc
@@ -30,7 +30,7 @@
#include "dxfdata.h"
#include "builtin.h"
#include "printutils.h"
-#include "context.h"
+#include "evalcontext.h"
#include "mathc99.h"
#include <sstream>
@@ -40,7 +40,7 @@ boost::unordered_map<std::string,Value> dxf_dim_cache;
boost::unordered_map<std::string,Value> dxf_cross_cache;
namespace fs = boost::filesystem;
-Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &argnames, const std::vector<Value> &args)
+Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx)
{
std::string filename;
std::string layername;
@@ -51,18 +51,18 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &argnam
// FIXME: We don't lookup the file relative to where this function was instantiated
// since the path is only available for ModuleInstantiations, not function expressions.
- // See isse #217
- for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
- if (argnames[i] == "file")
- filename = ctx->getAbsolutePath(args[i].toString());
- if (argnames[i] == "layer")
- layername = args[i].toString();
- if (argnames[i] == "origin")
- args[i].getVec2(xorigin, yorigin);
- if (argnames[i] == "scale")
- args[i].getDouble(scale);
- if (argnames[i] == "name")
- name = args[i].toString();
+ // See issue #217
+ for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) {
+ if (evalctx->eval_arguments[i].first == "file")
+ filename = ctx->getAbsolutePath(evalctx->eval_arguments[i].second.toString());
+ if (evalctx->eval_arguments[i].first == "layer")
+ layername = evalctx->eval_arguments[i].second.toString();
+ if (evalctx->eval_arguments[i].first == "origin")
+ evalctx->eval_arguments[i].second.getVec2(xorigin, yorigin);
+ if (evalctx->eval_arguments[i].first == "scale")
+ evalctx->eval_arguments[i].second.getDouble(scale);
+ if (evalctx->eval_arguments[i].first == "name")
+ name = evalctx->eval_arguments[i].second.toString();
}
std::stringstream keystream;
@@ -135,7 +135,7 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &argnam
return Value();
}
-Value builtin_dxf_cross(const Context *ctx, const std::vector<std::string> &argnames, const std::vector<Value> &args)
+Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
{
std::string filename;
std::string layername;
@@ -146,15 +146,15 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector<std::string> &argn
// FIXME: We don't lookup the file relative to where this function was instantiated
// since the path is only available for ModuleInstantiations, not function expressions.
// See isse #217
- for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
- if (argnames[i] == "file")
- filename = ctx->getAbsolutePath(args[i].toString());
- if (argnames[i] == "layer")
- layername = args[i].toString();
- if (argnames[i] == "origin")
- args[i].getVec2(xorigin, yorigin);
- if (argnames[i] == "scale")
- args[i].getDouble(scale);
+ for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) {
+ if (evalctx->eval_arguments[i].first == "file")
+ filename = ctx->getAbsolutePath(evalctx->eval_arguments[i].second.toString());
+ if (evalctx->eval_arguments[i].first == "layer")
+ layername = evalctx->eval_arguments[i].second.toString();
+ if (evalctx->eval_arguments[i].first == "origin")
+ evalctx->eval_arguments[i].second.getVec2(xorigin, yorigin);
+ if (evalctx->eval_arguments[i].first == "scale")
+ evalctx->eval_arguments[i].second.getDouble(scale);
}
std::stringstream keystream;
diff --git a/src/evalcontext.cc b/src/evalcontext.cc
new file mode 100644
index 0000000..b7566e3
--- /dev/null
+++ b/src/evalcontext.cc
@@ -0,0 +1,40 @@
+#include "evalcontext.h"
+#include "module.h"
+#include "expression.h"
+#include "function.h"
+#include "printutils.h"
+#include "builtin.h"
+
+#include <boost/foreach.hpp>
+
+#ifdef DEBUG
+void EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst)
+{
+ if (inst)
+ PRINTB("EvalContext %p (%p) for %s inst (%p)", this % this->parent % inst->name() % inst);
+ else
+ PRINTB("Context: %p (%p)", this % this->parent);
+ PRINTB(" document path: %s", this->document_path);
+
+ PRINT(" eval args:");
+ for (int i=0;i<this->eval_arguments.size();i++) {
+ PRINTB(" %s = %s", this->eval_arguments[i].first % this->eval_arguments[i].second);
+ }
+ if (this->children.size() > 0) {
+ PRINT(" children:");
+ BOOST_FOREACH(const ModuleInstantiation *ch, this->children) {
+ PRINTB(" %s", ch->name());
+ }
+ }
+
+ if (mod) {
+ const Module *m = dynamic_cast<const Module*>(mod);
+ if (m) {
+ PRINT(" module args:");
+ BOOST_FOREACH(const Assignment &arg, m->definition_arguments) {
+ PRINTB(" %s = %s", arg.first % variables[arg.first]);
+ }
+ }
+ }
+}
+#endif
diff --git a/src/evalcontext.h b/src/evalcontext.h
new file mode 100644
index 0000000..3d7d222
--- /dev/null
+++ b/src/evalcontext.h
@@ -0,0 +1,24 @@
+#ifndef EVALCONTEXT_H_
+#define EVALCONTEXT_H_
+
+#include "context.h"
+
+/*!
+ This hold the evaluation context (the parameters actually sent
+ when calling a module or function, including the children).
+*/
+class EvalContext : public Context
+{
+public:
+ EvalContext(const Context *parent = NULL) : Context(parent) {}
+ virtual ~EvalContext() {}
+
+ std::vector<std::pair<std::string, Value> > eval_arguments;
+ std::vector<class ModuleInstantiation *> children;
+
+#ifdef DEBUG
+ virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst);
+#endif
+};
+
+#endif
diff --git a/src/expr.cc b/src/expr.cc
index 75fc47a..7a8180f 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -26,7 +26,7 @@
#include "expression.h"
#include "value.h"
-#include "context.h"
+#include "evalcontext.h"
#include <assert.h>
#include <sstream>
#include <algorithm>
@@ -127,13 +127,18 @@ Value Expression::evaluate(const Context *context) const
return Value();
}
if (this->type == "F") {
- Value::VectorType argvalues;
- std::transform(this->children.begin(), this->children.end(),
- std::back_inserter(argvalues),
- boost::bind(&Expression::evaluate, _1, context));
+ EvalContext c(context);
+ for (size_t i=0; i < this->call_arguments.size(); i++) {
+ c.eval_arguments.push_back(std::make_pair(this->call_arguments[i].first,
+ this->call_arguments[i].second->evaluate(context)));
+ }
+ // Value::VectorType argvalues;
+ // std::transform(this->children.begin(), this->children.end(),
+ // std::back_inserter(argvalues),
+ // boost::bind(&Expression::evaluate, _1, context));
// for (size_t i=0; i < this->children.size(); i++)
// argvalues.push_back(this->children[i]->evaluate(context));
- return context->evaluate_function(this->call_funcname, this->call_argnames, argvalues);
+ return context->evaluate_function(this->call_funcname, &c);
}
abort();
}
@@ -178,10 +183,11 @@ std::string Expression::toString() const
}
else if (this->type == "F") {
stream << this->call_funcname << "(";
- for (size_t i=0; i < this->children.size(); i++) {
+ for (size_t i=0; i < this->call_arguments.size(); i++) {
+ const Assignment &arg = this->call_arguments[i];
if (i > 0) stream << ", ";
- if (!this->call_argnames[i].empty()) stream << this->call_argnames[i] << " = ";
- stream << *this->children[i];
+ if (!arg.first.empty()) stream << arg.first << " = ";
+ stream << *arg.second;
}
stream << ")";
}
diff --git a/src/expression.h b/src/expression.h
index 2919b78..06becc0 100644
--- a/src/expression.h
+++ b/src/expression.h
@@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include "value.h"
+#include "typedefs.h"
class Expression
{
@@ -14,7 +15,7 @@ public:
std::string var_name;
std::string call_funcname;
- std::vector<std::string> call_argnames;
+ AssignmentList call_arguments;
// Boolean: ! && ||
// Operators: * / % + -
diff --git a/src/func.cc b/src/func.cc
index 26d7e69..88bf3c8 100644
--- a/src/func.cc
+++ b/src/func.cc
@@ -26,7 +26,7 @@
#include "function.h"
#include "expression.h"
-#include "context.h"
+#include "evalcontext.h"
#include "builtin.h"
#include <sstream>
#include <ctime>
@@ -34,6 +34,7 @@
#include <algorithm>
#include "stl-utils.h"
#include "printutils.h"
+#include <boost/foreach.hpp>
/*
Random numbers
@@ -61,7 +62,7 @@ AbstractFunction::~AbstractFunction()
{
}
-Value AbstractFunction::evaluate(const Context*, const std::vector<std::string>&, const std::vector<Value>&) const
+Value AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const
{
return Value();
}
@@ -75,16 +76,14 @@ std::string AbstractFunction::dump(const std::string &indent, const std::string
Function::~Function()
{
- std::for_each(this->argexpr.begin(), this->argexpr.end(), del_fun<Expression>());
+ BOOST_FOREACH(const Assignment &arg, this->definition_arguments) delete arg.second;
delete expr;
}
-Value Function::evaluate(const Context *ctx,
- const std::vector<std::string> &call_argnames,
- const std::vector<Value> &call_argvalues) const
+Value Function::evaluate(const Context *ctx, const EvalContext *evalctx) const
{
Context c(ctx);
- c.args(argnames, argexpr, call_argnames, call_argvalues);
+ c.setVariables(definition_arguments, evalctx);
return expr ? expr->evaluate(&c) : Value();
}
@@ -92,10 +91,11 @@ std::string Function::dump(const std::string &indent, const std::string &name) c
{
std::stringstream dump;
dump << indent << "function " << name << "(";
- for (size_t i=0; i < argnames.size(); i++) {
+ for (size_t i=0; i < definition_arguments.size(); i++) {
+ const Assignment &arg = 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 << ") = " << *expr << ";\n";
return dump.str();
@@ -105,9 +105,9 @@ BuiltinFunction::~BuiltinFunction()
{
}
-Value BuiltinFunction::evaluate(const Context *ctx, const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues) const
+Value BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const
{
- return eval_func(ctx, call_argnames, call_argvalues);
+ return eval_func(ctx, evalctx);
}
std::string BuiltinFunction::dump(const std::string &indent, const std::string &name) const
@@ -127,37 +127,37 @@ static inline double rad2deg(double x)
return x * 180.0 / M_PI;
}
-Value builtin_abs(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_abs(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(fabs(args[0].toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(fabs(evalctx->eval_arguments[0].second.toDouble()));
return Value();
}
-Value builtin_sign(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_sign(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value((args[0].toDouble()<0) ? -1.0 : ((args[0].toDouble()>0) ? 1.0 : 0.0));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value((evalctx->eval_arguments[0].second.toDouble()<0) ? -1.0 : ((evalctx->eval_arguments[0].second.toDouble()>0) ? 1.0 : 0.0));
return Value();
}
-Value builtin_rands(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_rands(const Context *, const EvalContext *evalctx)
{
bool deterministic = false;
- if (args.size() == 3 &&
- args[0].type() == Value::NUMBER &&
- args[1].type() == Value::NUMBER &&
- args[2].type() == Value::NUMBER)
+ if (evalctx->eval_arguments.size() == 3 &&
+ evalctx->eval_arguments[0].second.type() == Value::NUMBER &&
+ evalctx->eval_arguments[1].second.type() == Value::NUMBER &&
+ evalctx->eval_arguments[2].second.type() == Value::NUMBER)
{
deterministic = false;
}
- else if (args.size() == 4 &&
- args[0].type() == Value::NUMBER &&
- args[1].type() == Value::NUMBER &&
- args[2].type() == Value::NUMBER &&
- args[3].type() == Value::NUMBER)
+ else if (evalctx->eval_arguments.size() == 4 &&
+ evalctx->eval_arguments[0].second.type() == Value::NUMBER &&
+ evalctx->eval_arguments[1].second.type() == Value::NUMBER &&
+ evalctx->eval_arguments[2].second.type() == Value::NUMBER &&
+ evalctx->eval_arguments[3].second.type() == Value::NUMBER)
{
- deterministic_rng.seed( (unsigned int) args[3].toDouble() );
+ deterministic_rng.seed( (unsigned int) evalctx->eval_arguments[3].second.toDouble() );
deterministic = true;
}
else
@@ -165,11 +165,11 @@ Value builtin_rands(const Context *, const std::vector<std::string>&, const std:
return Value();
}
- double min = std::min( args[0].toDouble(), args[1].toDouble() );
- double max = std::max( args[0].toDouble(), args[1].toDouble() );
+ double min = std::min( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() );
+ double max = std::max( evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble() );
boost::uniform_real<> distributor( min, max );
Value::VectorType vec;
- for (int i=0; i<args[2].toDouble(); i++) {
+ for (int i=0; i<evalctx->eval_arguments[2].second.toDouble(); i++) {
if ( deterministic ) {
vec.push_back( Value( distributor( deterministic_rng ) ) );
} else {
@@ -181,169 +181,169 @@ Value builtin_rands(const Context *, const std::vector<std::string>&, const std:
}
-Value builtin_min(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_min(const Context *, const EvalContext *evalctx)
{
- if (args.size() >= 1 && args[0].type() == Value::NUMBER) {
- double val = args[0].toDouble();
- for (size_t i = 1; i < args.size(); i++)
- if (args[1].type() == Value::NUMBER)
- val = fmin(val, args[i].toDouble());
+ if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) {
+ double val = evalctx->eval_arguments[0].second.toDouble();
+ for (size_t i = 1; i < evalctx->eval_arguments.size(); i++)
+ if (evalctx->eval_arguments[1].second.type() == Value::NUMBER)
+ val = fmin(val, evalctx->eval_arguments[i].second.toDouble());
return Value(val);
}
return Value();
}
-Value builtin_max(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_max(const Context *, const EvalContext *evalctx)
{
- if (args.size() >= 1 && args[0].type() == Value::NUMBER) {
- double val = args[0].toDouble();
- for (size_t i = 1; i < args.size(); i++)
- if (args[1].type() == Value::NUMBER)
- val = fmax(val, args[i].toDouble());
+ if (evalctx->eval_arguments.size() >= 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER) {
+ double val = evalctx->eval_arguments[0].second.toDouble();
+ for (size_t i = 1; i < evalctx->eval_arguments.size(); i++)
+ if (evalctx->eval_arguments[1].second.type() == Value::NUMBER)
+ val = fmax(val, evalctx->eval_arguments[i].second.toDouble());
return Value(val);
}
return Value();
}
-Value builtin_sin(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_sin(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(sin(deg2rad(args[0].toDouble())));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(sin(deg2rad(evalctx->eval_arguments[0].second.toDouble())));
return Value();
}
-Value builtin_cos(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_cos(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(cos(deg2rad(args[0].toDouble())));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(cos(deg2rad(evalctx->eval_arguments[0].second.toDouble())));
return Value();
}
-Value builtin_asin(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_asin(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(rad2deg(asin(args[0].toDouble())));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(rad2deg(asin(evalctx->eval_arguments[0].second.toDouble())));
return Value();
}
-Value builtin_acos(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_acos(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(rad2deg(acos(args[0].toDouble())));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(rad2deg(acos(evalctx->eval_arguments[0].second.toDouble())));
return Value();
}
-Value builtin_tan(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_tan(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(tan(deg2rad(args[0].toDouble())));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(tan(deg2rad(evalctx->eval_arguments[0].second.toDouble())));
return Value();
}
-Value builtin_atan(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_atan(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(rad2deg(atan(args[0].toDouble())));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(rad2deg(atan(evalctx->eval_arguments[0].second.toDouble())));
return Value();
}
-Value builtin_atan2(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_atan2(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER)
- return Value(rad2deg(atan2(args[0].toDouble(), args[1].toDouble())));
+ if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER)
+ return Value(rad2deg(atan2(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble())));
return Value();
}
-Value builtin_pow(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_pow(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER)
- return Value(pow(args[0].toDouble(), args[1].toDouble()));
+ if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER)
+ return Value(pow(evalctx->eval_arguments[0].second.toDouble(), evalctx->eval_arguments[1].second.toDouble()));
return Value();
}
-Value builtin_round(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_round(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(round(args[0].toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(round(evalctx->eval_arguments[0].second.toDouble()));
return Value();
}
-Value builtin_ceil(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_ceil(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(ceil(args[0].toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(ceil(evalctx->eval_arguments[0].second.toDouble()));
return Value();
}
-Value builtin_floor(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_floor(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(floor(args[0].toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(floor(evalctx->eval_arguments[0].second.toDouble()));
return Value();
}
-Value builtin_sqrt(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_sqrt(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(sqrt(args[0].toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(sqrt(evalctx->eval_arguments[0].second.toDouble()));
return Value();
}
-Value builtin_exp(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_exp(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(exp(args[0].toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(exp(evalctx->eval_arguments[0].second.toDouble()));
return Value();
}
-Value builtin_length(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_length(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1) {
- if (args[0].type() == Value::VECTOR) return Value(int(args[0].toVector().size()));
- if (args[0].type() == Value::STRING) return Value(int(args[0].toString().size()));
+ if (evalctx->eval_arguments.size() == 1) {
+ if (evalctx->eval_arguments[0].second.type() == Value::VECTOR) return Value(int(evalctx->eval_arguments[0].second.toVector().size()));
+ if (evalctx->eval_arguments[0].second.type() == Value::STRING) return Value(int(evalctx->eval_arguments[0].second.toString().size()));
}
return Value();
}
-Value builtin_log(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_log(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER)
- return Value(log(args[1].toDouble()) / log(args[0].toDouble()));
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(log(args[0].toDouble()) / log(10.0));
+ if (evalctx->eval_arguments.size() == 2 && evalctx->eval_arguments[0].second.type() == Value::NUMBER && evalctx->eval_arguments[1].second.type() == Value::NUMBER)
+ return Value(log(evalctx->eval_arguments[1].second.toDouble()) / log(evalctx->eval_arguments[0].second.toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(log(evalctx->eval_arguments[0].second.toDouble()) / log(10.0));
return Value();
}
-Value builtin_ln(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_ln(const Context *, const EvalContext *evalctx)
{
- if (args.size() == 1 && args[0].type() == Value::NUMBER)
- return Value(log(args[0].toDouble()));
+ if (evalctx->eval_arguments.size() == 1 && evalctx->eval_arguments[0].second.type() == Value::NUMBER)
+ return Value(log(evalctx->eval_arguments[0].second.toDouble()));
return Value();
}
-Value builtin_str(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_str(const Context *, const EvalContext *evalctx)
{
std::stringstream stream;
- for (size_t i = 0; i < args.size(); i++) {
- stream << args[i].toString();
+ for (size_t i = 0; i < evalctx->eval_arguments.size(); i++) {
+ stream << evalctx->eval_arguments[i].second.toString();
}
return Value(stream.str());
}
-Value builtin_lookup(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_lookup(const Context *, const EvalContext *evalctx)
{
double p, low_p, low_v, high_p, high_v;
- if (args.size() < 2 || // Needs two args
- !args[0].getDouble(p) || // First must be a number
- args[1].toVector().size() < 2 || // Second must be a vector of vectors
- args[1].toVector()[0].toVector().size() < 2)
+ if (evalctx->eval_arguments.size() < 2 || // Needs two args
+ !evalctx->eval_arguments[0].second.getDouble(p) || // First must be a number
+ evalctx->eval_arguments[1].second.toVector().size() < 2 || // Second must be a vector of vectors
+ evalctx->eval_arguments[1].second.toVector()[0].toVector().size() < 2)
return Value();
- if (!args[1].toVector()[0].getVec2(low_p, low_v) || !args[1].toVector()[0].getVec2(high_p, high_v))
+ if (!evalctx->eval_arguments[1].second.toVector()[0].getVec2(low_p, low_v) || !evalctx->eval_arguments[1].second.toVector()[0].getVec2(high_p, high_v))
return Value();
- for (size_t i = 1; i < args[1].toVector().size(); i++) {
+ for (size_t i = 1; i < evalctx->eval_arguments[1].second.toVector().size(); i++) {
double this_p, this_v;
- if (args[1].toVector()[i].getVec2(this_p, this_v)) {
+ if (evalctx->eval_arguments[1].second.toVector()[i].getVec2(this_p, this_v)) {
if (this_p <= p && (this_p > low_p || low_p > p)) {
low_p = this_p;
low_v = this_v;
@@ -404,14 +404,14 @@ Value builtin_lookup(const Context *, const std::vector<std::string>&, const std
- returns [[0,4],[1,5],[2,6],[8]]
*/
-Value builtin_search(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
+Value builtin_search(const Context *, const EvalContext *evalctx)
{
- if (args.size() < 2) return Value();
+ if (evalctx->eval_arguments.size() < 2) return Value();
- const Value &findThis = args[0];
- const Value &searchTable = args[1];
- unsigned int num_returns_per_match = (args.size() > 2) ? args[2].toDouble() : 1;
- unsigned int index_col_num = (args.size() > 3) ? args[3].toDouble() : 0;
+ const Value &findThis = evalctx->eval_arguments[0].second;
+ const Value &searchTable = evalctx->eval_arguments[1].second;
+ unsigned int num_returns_per_match = (evalctx->eval_arguments.size() > 2) ? evalctx->eval_arguments[2].second.toDouble() : 1;
+ unsigned int index_col_num = (evalctx->eval_arguments.size() > 3) ? evalctx->eval_arguments[3].second.toDouble() : 0;
Value::VectorType returnvec;
@@ -499,7 +499,7 @@ Value builtin_search(const Context *, const std::vector<std::string>&, const std
#define QUOTE(x__) # x__
#define QUOTED(x__) QUOTE(x__)
-Value builtin_version(const Context *, const std::vector<std::string>&, const std::vector<Value> &)
+Value builtin_version(const Context *, const EvalContext *evalctx)
{
Value::VectorType val;
val.push_back(Value(double(OPENSCAD_YEAR)));
@@ -510,9 +510,9 @@ Value builtin_version(const Context *, const std::vector<std::string>&, const st
return Value(val);
}
-Value builtin_version_num(const Context *ctx, const std::vector<std::string>& call_argnames, const std::vector<Value> &args)
+Value builtin_version_num(const Context *ctx, const EvalContext *evalctx)
{
- Value val = (args.size() == 0) ? builtin_version(ctx, call_argnames, args) : args[0];
+ Value val = (evalctx->eval_arguments.size() == 0) ? builtin_version(ctx, evalctx) : evalctx->eval_arguments[0].second;
double y, m, d = 0;
if (!val.getVec3(y, m, d)) {
if (!val.getVec2(y, m)) {
diff --git a/src/function.h b/src/function.h
index 623ef7e..a1fde3c 100644
--- a/src/function.h
+++ b/src/function.h
@@ -2,6 +2,7 @@
#define FUNCTION_H_
#include "value.h"
+#include "typedefs.h"
#include <string>
#include <vector>
@@ -9,35 +10,34 @@ class AbstractFunction
{
public:
virtual ~AbstractFunction();
- virtual Value evaluate(const class Context *ctx, const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues) const;
+ virtual Value evaluate(const class Context *ctx, const class EvalContext *evalctx) const;
virtual std::string dump(const std::string &indent, const std::string &name) const;
};
class BuiltinFunction : public AbstractFunction
{
public:
- typedef Value (*eval_func_t)(const Context *ctx, const std::vector<std::string> &argnames, const std::vector<Value> &args);
+ typedef Value (*eval_func_t)(const Context *ctx, const EvalContext *evalctx);
eval_func_t eval_func;
BuiltinFunction(eval_func_t f) : eval_func(f) { }
virtual ~BuiltinFunction();
- virtual Value evaluate(const Context *ctx, const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues) const;
+ virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const;
virtual std::string dump(const std::string &indent, const std::string &name) const;
};
class Function : public AbstractFunction
{
public:
- std::vector<std::string> argnames;
- std::vector<class Expression*> argexpr;
+ AssignmentList definition_arguments;
Expression *expr;
Function() { }
virtual ~Function();
- virtual Value evaluate(const Context *ctx, const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues) const;
+ virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const;
virtual std::string dump(const std::string &indent, const std::string &name) const;
};
diff --git a/src/import.cc b/src/import.cc
index 627fb56..927c9d8 100644
--- a/src/import.cc
+++ b/src/import.cc
@@ -28,7 +28,7 @@
#include "module.h"
#include "polyset.h"
-#include "context.h"
+#include "evalcontext.h"
#include "builtin.h"
#include "dxfdata.h"
#include "dxftess.h"
@@ -60,26 +60,43 @@ class ImportModule : public AbstractModule
public:
import_type_e type;
ImportModule(import_type_e type = TYPE_UNKNOWN) : type(type) { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
- std::vector<std::string> argnames;
- argnames += "file", "layer", "convexity", "origin", "scale";
- std::vector<Expression*> argexpr;
+ AssignmentList args;
+ args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("convexity", NULL), Assignment("origin", NULL), Assignment("scale", NULL);
+ args += Assignment("filename",NULL), Assignment("layername", NULL);
+ // FIXME: This is broken. Tag as deprecated and fix
// Map old argnames to new argnames for compatibility
+ // To fix:
+ // o after c.setVariables()
+ // - if "filename" in evalctx: deprecated-warning && v.set_variable("file", value);
+ // - if "layername" in evalctx: deprecated-warning && v.set_variable("layer", value);
+#if 0
std::vector<std::string> inst_argnames = inst->argnames;
for (size_t i=0; i<inst_argnames.size(); i++) {
if (inst_argnames[i] == "filename") inst_argnames[i] = "file";
if (inst_argnames[i] == "layername") inst_argnames[i] = "layer";
}
+#endif
Context c(ctx);
- c.args(argnames, argexpr, inst_argnames, inst->argvalues);
+ c.setDocumentPath(evalctx->documentPath());
+ c.setVariables(args, evalctx);
+#if 0 && DEBUG
+ c.dump(this, inst);
+#endif
Value v = c.lookup_variable("file");
+ if (v.isUndefined()) {
+ v = c.lookup_variable("filename");
+ if (!v.isUndefined())
+ PRINT("WARNING: filename= is deprecated. Please use file=");
+ }
+
std::string filename = inst->getAbsolutePath(v.isUndefined() ? "" : v.toString());
import_type_e actualtype = this->type;
if (actualtype == TYPE_UNKNOWN) {
@@ -98,6 +115,11 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati
node->filename = filename;
Value layerval = c.lookup_variable("layer", true);
+ if (layerval.isUndefined()) {
+ layerval = c.lookup_variable("layername",true);
+ if (!layerval.isUndefined())
+ PRINT("WARNING: layername= is deprecated. Please use layer=");
+ }
node->layername = layerval.isUndefined() ? "" : layerval.toString();
node->convexity = c.lookup_variable("convexity", true).toDouble();
diff --git a/src/lexer.l b/src/lexer.l
index 4dff654..6766abc 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -26,6 +26,7 @@
%{
+#include "typedefs.h"
#include "handle_dep.h"
#include "printutils.h"
#include "parsersettings.h"
diff --git a/src/linearextrude.cc b/src/linearextrude.cc
index ff9682e..f4c1112 100644
--- a/src/linearextrude.cc
+++ b/src/linearextrude.cc
@@ -27,7 +27,7 @@
#include "linearextrudenode.h"
#include "module.h"
-#include "context.h"
+#include "evalcontext.h"
#include "printutils.h"
#include "builtin.h"
#include "PolySetEvaluator.h"
@@ -45,19 +45,18 @@ class LinearExtrudeModule : public AbstractModule
{
public:
LinearExtrudeModule() { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
LinearExtrudeNode *node = new LinearExtrudeNode(inst);
- std::vector<std::string> argnames;
- argnames += "file", "layer", "height", "origin", "scale", "center", "twist", "slices";
- std::vector<Expression*> argexpr;
+ AssignmentList args;
+ args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("height", NULL), Assignment("origin", NULL), Assignment("scale", NULL), Assignment("center", NULL), Assignment("twist", NULL), Assignment("slices", NULL);
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();
@@ -81,10 +80,10 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst
// if height not given, and first argument is a number,
// then assume it should be the height.
if (c.lookup_variable("height").isUndefined() &&
- inst->argnames.size() > 0 &&
- inst->argnames[0] == "" &&
- inst->argvalues[0].type() == Value::NUMBER) {
- height = Value(inst->argvalues[0]);
+ evalctx->eval_arguments.size() > 0 &&
+ evalctx->eval_arguments[0].first == "" &&
+ evalctx->eval_arguments[0].second.type() == Value::NUMBER) {
+ height = Value(evalctx->eval_arguments[0].second);
}
node->layername = layer.isUndefined() ? "" : layer.toString();
@@ -117,7 +116,7 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst
}
if (node->filename.empty()) {
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
}
diff --git a/src/mainwin.cc b/src/mainwin.cc
index dd855fb..2e69ec2 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -158,7 +158,7 @@ settings_valueList(const QString &key, const QList<int> &defaultList = QList<int
}
MainWindow::MainWindow(const QString &filename)
- : progresswidget(NULL)
+ : root_inst("group"), progresswidget(NULL)
{
setupUi(this);
@@ -168,7 +168,7 @@ MainWindow::MainWindow(const QString &filename)
this, SLOT(actionRenderCGALDone(CGAL_Nef_polyhedron *)));
#endif
- register_builtin(root_ctx);
+ root_ctx.registerBuiltin();
this->openglbox = NULL;
root_module = NULL;
@@ -643,8 +643,8 @@ bool MainWindow::compile(bool reload, bool procevents)
if (procevents) QApplication::processEvents();
AbstractNode::resetIndexCounter();
- this->root_inst = ModuleInstantiation();
- this->absolute_root_node = this->root_module->evaluate(&this->root_ctx, &this->root_inst);
+ this->root_inst = ModuleInstantiation("group");
+ this->absolute_root_node = this->root_module->evaluate(&this->root_ctx, &this->root_inst, NULL);
if (this->absolute_root_node) {
// Do we have an explicit root node (! modifier)?
diff --git a/src/modcontext.cc b/src/modcontext.cc
new file mode 100644
index 0000000..7d123b8
--- /dev/null
+++ b/src/modcontext.cc
@@ -0,0 +1,152 @@
+#include "modcontext.h"
+#include "module.h"
+#include "expression.h"
+#include "function.h"
+#include "printutils.h"
+#include "builtin.h"
+
+#include <boost/foreach.hpp>
+
+ModuleContext::ModuleContext(const class Module *module, const Context *parent, const EvalContext *evalctx)
+ : Context(parent)
+{
+ if (module) {
+ setModule(*module, evalctx);
+ }
+ else {
+ this->functions_p = NULL;
+ this->modules_p = NULL;
+ this->usedlibs_p = NULL;
+ }
+}
+
+ModuleContext::~ModuleContext()
+{
+}
+
+void ModuleContext::setModule(const Module &module, const EvalContext *evalctx)
+{
+ this->setVariables(module.definition_arguments, evalctx);
+ this->evalctx = evalctx;
+
+ // FIXME: Don't access module members directly
+ this->functions_p = &module.functions;
+ this->modules_p = &module.modules;
+ this->usedlibs_p = &module.usedlibs;
+ BOOST_FOREACH(const std::string &var, module.assignments_var) {
+ this->set_variable(var, module.assignments.at(var)->evaluate(this));
+ }
+
+ if (!module.modulePath().empty()) this->document_path = module.modulePath();
+}
+
+/*!
+ Only used to initialize builtins for the top-level root context
+*/
+void ModuleContext::registerBuiltin()
+{
+ this->setModule(Builtins::instance()->getRootModule());
+ this->set_constant("PI",Value(M_PI));
+}
+
+class RecursionGuard
+{
+public:
+ RecursionGuard(const ModuleContext &c, const std::string &name) : c(c), name(name) {
+ c.recursioncount[name]++;
+ }
+ ~RecursionGuard() { if (--c.recursioncount[name] == 0) c.recursioncount.erase(name); }
+ bool recursion_detected() const { return (c.recursioncount[name] > 100); }
+private:
+ const ModuleContext &c;
+ const std::string &name;
+};
+
+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();
+ }
+
+ if (this->functions_p && this->functions_p->find(name) != this->functions_p->end()) {
+ return this->functions_p->find(name)->second->evaluate(this, evalctx);
+ }
+
+ if (this->usedlibs_p) {
+ BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) {
+ if (m.second->functions.find(name) != m.second->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->functions[name]->evaluate(&ctx, evalctx);
+ }
+ }
+ }
+ return Context::evaluate_function(name, evalctx);
+}
+
+AbstractNode *ModuleContext::evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) 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 (!replacement.empty()) {
+ PRINTB("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", inst.name() % replacement);
+ }
+ return m->evaluate(this, &inst, evalctx);
+ }
+
+ if (this->usedlibs_p) {
+ BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) {
+ assert(m.second);
+ if (m.second->modules.find(inst.name()) != m.second->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->modules[inst.name()]->evaluate(&ctx, &inst, evalctx);
+ }
+ }
+ }
+
+ return Context::evaluate_module(inst, evalctx);
+}
+
+#ifdef DEBUG
+void ModuleContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst)
+{
+ if (inst)
+ PRINTB("ModuleContext %p (%p) for %s inst (%p) ", this % this->parent % inst->name() % inst);
+ else
+ PRINTB("ModuleContext: %p (%p)", this % this->parent);
+ PRINTB(" document path: %s", this->document_path);
+ if (mod) {
+ const Module *m = dynamic_cast<const Module*>(mod);
+ if (m) {
+ PRINT(" module args:");
+ BOOST_FOREACH(const Assignment &arg, m->definition_arguments) {
+ PRINTB(" %s = %s", arg.first % variables[arg.first]);
+ }
+ }
+ }
+ typedef std::pair<std::string, Value> ValueMapType;
+ PRINT(" vars:");
+ BOOST_FOREACH(const ValueMapType &v, constants) {
+ PRINTB(" %s = %s", v.first % v.second);
+ }
+ BOOST_FOREACH(const ValueMapType &v, variables) {
+ PRINTB(" %s = %s", v.first % v.second);
+ }
+ BOOST_FOREACH(const ValueMapType &v, config_variables) {
+ PRINTB(" %s = %s", v.first % v.second);
+ }
+
+}
+#endif
diff --git a/src/modcontext.h b/src/modcontext.h
new file mode 100644
index 0000000..5fce88f
--- /dev/null
+++ b/src/modcontext.h
@@ -0,0 +1,40 @@
+#ifndef FILECONTEXT_H_
+#define FILECONTEXT_H_
+
+#include "context.h"
+#include <boost/unordered_map.hpp>
+
+/*!
+ This holds the context for a Module definition; keeps track of
+ global variables, submodules and functions defined inside a module.
+
+ NB! every .scad file defines an implicit unnamed module holding the contents of the file.
+*/
+class ModuleContext : public Context
+{
+public:
+ ModuleContext(const class Module *module = NULL, const Context *parent = NULL, const EvalContext *evalctx = NULL);
+ virtual ~ModuleContext();
+
+ void setModule(const Module &module, const EvalContext *evalctx = NULL);
+ void registerBuiltin();
+
+ virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const;
+ virtual AbstractNode *evaluate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const;
+
+ const boost::unordered_map<std::string, class AbstractFunction*> *functions_p;
+ const boost::unordered_map<std::string, class AbstractModule*> *modules_p;
+ typedef boost::unordered_map<std::string, class Module*> ModuleContainer;
+ const ModuleContainer *usedlibs_p;
+
+ // FIXME: Points to the eval context for the call to this module. Not sure where it belongs
+ const class EvalContext *evalctx;
+
+#ifdef DEBUG
+ virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst);
+#endif
+
+ mutable boost::unordered_map<std::string, int> recursioncount;
+};
+
+#endif
diff --git a/src/module.cc b/src/module.cc
index 322085b..7d83975 100644
--- a/src/module.cc
+++ b/src/module.cc
@@ -27,7 +27,8 @@
#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"
@@ -43,11 +44,11 @@ AbstractModule::~AbstractModule()
{
}
-AbstractNode *AbstractModule::evaluate(const Context*, const ModuleInstantiation *inst) const
+AbstractNode *AbstractModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
AbstractNode *node = new AbstractNode(inst);
- node->children = inst->evaluateChildren();
+ node->children = inst->evaluateChildren(evalctx);
return node;
}
@@ -61,8 +62,8 @@ 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;
+ BOOST_FOREACH(ModuleInstantiation *v, children) delete v;
}
IfElseModuleInstantiation::~IfElseModuleInstantiation()
@@ -88,10 +89,11 @@ 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) {
dump << ");\n";
@@ -108,43 +110,40 @@ std::string ModuleInstantiation::dump(const std::string &indent) const
return dump.str();
}
-AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const
+AbstractNode *ModuleInstantiation::evaluate_instance(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);
+ BOOST_FOREACH(const Assignment &arg, this->arguments) {
+ c.eval_arguments.push_back(std::make_pair(arg.first,
+ arg.second ?
+ arg.second->evaluate(ctx) :
+ Value()));
}
+ c.children = this->children;
+
+#if 0 && DEBUG
+ PRINT("New eval ctx:");
+ c.dump(NULL, this);
+#endif
+ AbstractNode *node = ctx->evaluate_module(*this, &c); // Passes c as evalctx
return node;
}
-std::vector<AbstractNode*> ModuleInstantiation::evaluateChildren(const Context *ctx) const
+std::vector<AbstractNode*> ModuleInstantiation::evaluateChildren(const Context *evalctx) const
{
- if (!ctx) ctx = this->ctx;
std::vector<AbstractNode*> childnodes;
BOOST_FOREACH (ModuleInstantiation *modinst, this->children) {
- AbstractNode *node = modinst->evaluate(ctx);
+ AbstractNode *node = modinst->evaluate_instance(evalctx);
if (node) childnodes.push_back(node);
}
return childnodes;
}
-std::vector<AbstractNode*> IfElseModuleInstantiation::evaluateElseChildren(const Context *ctx) const
+std::vector<AbstractNode*> IfElseModuleInstantiation::evaluateElseChildren(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);
+ AbstractNode *node = modinst->evaluate_instance(evalctx);
if (node != NULL) childnodes.push_back(node);
}
return childnodes;
@@ -152,35 +151,24 @@ std::vector<AbstractNode*> IfElseModuleInstantiation::evaluateElseChildren(const
Module::~Module()
{
- BOOST_FOREACH (const AssignmentContainer::value_type &v, assignments) delete v.second;
+ BOOST_FOREACH (const Assignment &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
+AbstractNode *Module::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
- Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
-
- c.inst_p = inst;
+ ModuleContext c(this, ctx, evalctx);
+ // FIXME: Set document path to the path of the module
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;
-
- BOOST_FOREACH(const std::string &var, assignments_var) {
- c.set_variable(var, assignments.at(var)->evaluate(&c));
- }
+#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);
+ AbstractNode *n = children[i]->evaluate_instance(&c);
if (n != NULL)
node->children.push_back(n);
}
@@ -194,10 +182,11 @@ 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";
diff --git a/src/module.h b/src/module.h
index 1f9e303..ace3c1b 100644
--- a/src/module.h
+++ b/src/module.h
@@ -6,18 +6,18 @@
#include <list>
#include <boost/unordered_map.hpp>
#include "value.h"
+#include "typedefs.h"
class ModuleInstantiation
{
public:
ModuleInstantiation(const std::string &name = "")
- : ctx(NULL),
- tag_root(false), tag_highlight(false), tag_background(false), modname(name) { }
+ : tag_root(false), tag_highlight(false), tag_background(false), modname(name) { }
virtual ~ModuleInstantiation();
std::string dump(const std::string &indent) const;
- class AbstractNode *evaluate(const class Context *ctx) const;
- std::vector<AbstractNode*> evaluateChildren(const Context *ctx = NULL) const;
+ class AbstractNode *evaluate_instance(const class Context *ctx) const;
+ std::vector<AbstractNode*> evaluateChildren(const Context *evalctx) const;
void setPath(const std::string &path) { this->modpath = path; }
const std::string &path() const { return this->modpath; }
@@ -28,11 +28,8 @@ public:
bool isHighlight() const { return this->tag_highlight; }
bool isRoot() const { return this->tag_root; }
- std::vector<std::string> argnames;
- std::vector<Value> argvalues;
- std::vector<class Expression*> argexpr;
+ AssignmentList arguments;
std::vector<ModuleInstantiation*> children;
- const Context *ctx;
bool tag_root;
bool tag_highlight;
@@ -48,7 +45,7 @@ class IfElseModuleInstantiation : public ModuleInstantiation {
public:
IfElseModuleInstantiation() : ModuleInstantiation("if") { }
virtual ~IfElseModuleInstantiation();
- std::vector<AbstractNode*> evaluateElseChildren(const Context *ctx = NULL) const;
+ std::vector<AbstractNode*> evaluateElseChildren(const Context *evalctx) const;
std::vector<ModuleInstantiation*> else_children;
};
@@ -57,7 +54,7 @@ class AbstractModule
{
public:
virtual ~AbstractModule();
- virtual class AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual class AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const class EvalContext *evalctx = NULL) const;
virtual std::string dump(const std::string &indent, const std::string &name) const;
};
@@ -67,7 +64,10 @@ public:
Module() : is_handling_dependencies(false) { }
virtual ~Module();
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ void setModulePath(const std::string &path) { this->path = path; }
+ const std::string &modulePath() const { return this->path; }
+
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
virtual std::string dump(const std::string &indent, const std::string &name) const;
void addChild(ModuleInstantiation *ch) { this->children.push_back(ch); }
@@ -81,8 +81,8 @@ public:
bool handleDependencies();
std::list<std::string> assignments_var;
- typedef boost::unordered_map<std::string, Expression*> AssignmentContainer;
- AssignmentContainer assignments;
+ typedef boost::unordered_map<std::string, Expression*> AssignmentMap;
+ AssignmentMap assignments;
typedef boost::unordered_map<std::string, class AbstractFunction*> FunctionContainer;
FunctionContainer functions;
@@ -91,12 +91,12 @@ public:
std::vector<ModuleInstantiation*> children;
- std::vector<std::string> argnames;
- std::vector<Expression*> argexpr;
+ std::vector<Assignment> definition_arguments;
protected:
private:
+ std::string path;
};
#endif
diff --git a/src/openscad.cc b/src/openscad.cc
index 878c207..3b960f3 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -28,7 +28,7 @@
#include "MainWindow.h"
#include "node.h"
#include "module.h"
-#include "context.h"
+#include "modcontext.h"
#include "value.h"
#include "export.h"
#include "builtin.h"
@@ -327,11 +327,8 @@ int main(int argc, char **argv)
if (!filename) help(argv[0]);
- Context root_ctx;
- register_builtin(root_ctx);
-
Module *root_module;
- ModuleInstantiation root_inst;
+ ModuleInstantiation root_inst("group");
AbstractNode *root_node;
AbstractNode *absolute_root_node;
CGAL_Nef_polyhedron root_N;
@@ -351,12 +348,18 @@ int main(int argc, char **argv)
if (!root_module) exit(1);
root_module->handleDependencies();
+ ModuleContext root_ctx;
+ root_ctx.registerBuiltin();
+ PRINT("Root Context:");
+#if 0 && DEBUG
+ root_ctx.dump(NULL, NULL);
+#endif
fs::path fpath = boosty::absolute(fs::path(filename));
fs::path fparent = fpath.parent_path();
fs::current_path(fparent);
AbstractNode::resetIndexCounter();
- absolute_root_node = root_module->evaluate(&root_ctx, &root_inst);
+ absolute_root_node = root_module->evaluate(&root_ctx, &root_inst, NULL);
// Do we have an explicit root node (! modifier)?
if (!(root_node = find_root_tag(absolute_root_node)))
diff --git a/src/parser.y b/src/parser.y
index 70aebba..fd6b164 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -34,6 +34,7 @@
#include <unistd.h>
#endif
+#include "typedefs.h"
#include "module.h"
#include "expression.h"
#include "value.h"
@@ -43,50 +44,39 @@
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
-namespace fs = boost::filesystem;
+ namespace fs = boost::filesystem;
#include "boosty.h"
-int parser_error_pos = -1;
+ int parser_error_pos = -1;
-int parserlex(void);
-void yyerror(char const *s);
+ int parserlex(void);
+ void yyerror(char const *s);
-int lexerget_lineno(void);
-int lexerlex_destroy(void);
-int lexerlex(void);
+ int lexerget_lineno(void);
+ int lexerlex_destroy(void);
+ int lexerlex(void);
-std::vector<Module*> module_stack;
-Module *currmodule;
+ std::vector<Module*> module_stack;
+ Module *currmodule;
-extern void lexerdestroy();
-extern FILE *lexerin;
-extern const char *parser_input_buffer;
-const char *parser_input_buffer;
-std::string parser_source_path;
+ extern void lexerdestroy();
+ extern FILE *lexerin;
+ extern const char *parser_input_buffer;
+ const char *parser_input_buffer;
+ std::string parser_source_path;
-class ArgContainer {
-public:
- std::string argname;
- Expression *argexpr;
-};
-class ArgsContainer {
-public:
- std::vector<std::string> argnames;
- std::vector<Expression*> argexpr;
-};
-
-%}
+ %}
%union {
- char *text;
- double number;
- class Value *value;
- class Expression *expr;
- class ModuleInstantiation *inst;
- std::vector<ModuleInstantiation*> *instvec;
- class IfElseModuleInstantiation *ifelse;
- class ArgContainer *arg;
- class ArgsContainer *args;
+ char *text;
+ double number;
+ class Value *value;
+ class Expression *expr;
+ class ModuleInstantiation *inst;
+ std::vector<ModuleInstantiation*> *instvec;
+ class IfElseModuleInstantiation *ifelse;
+ Assignment *arg;
+ AssignmentList *args;
}
%token TOK_MODULE
@@ -139,427 +129,412 @@ public:
%%
input:
- /* empty */ |
- TOK_USE { currmodule->usedlibs[$1] = NULL; } input |
- statement input ;
+/* empty */ |
+TOK_USE { currmodule->usedlibs[$1] = NULL; } input |
+statement input ;
inner_input:
- /* empty */ |
- statement inner_input ;
+/* empty */ |
+statement inner_input ;
statement:
- ';' |
- '{' inner_input '}' |
- module_instantiation {
- if ($1) {
- currmodule->addChild($1);
- } else {
- delete $1;
- }
- } |
- TOK_ID '=' expr ';' {
- std::list<std::string>::iterator found = std::find(currmodule->assignments_var.begin(), currmodule->assignments_var.end(),$1);
- if (found != currmodule->assignments_var.end()) currmodule->assignments_var.erase(found);
- currmodule->assignments_var.push_back($1);
- currmodule->assignments[$1] = $3;
- } |
- TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' {
- Module *p = currmodule;
- module_stack.push_back(currmodule);
- currmodule = new Module();
- p->modules[$2] = currmodule;
- currmodule->argnames = $4->argnames;
- currmodule->argexpr = $4->argexpr;
- free($2);
- delete $4;
- } statement {
- currmodule = module_stack.back();
- module_stack.pop_back();
- } |
- TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr {
- Function *func = new Function();
- func->argnames = $4->argnames;
- func->argexpr = $4->argexpr;
- func->expr = $8;
- currmodule->functions[$2] = func;
- free($2);
- delete $4;
- } ';' ;
+';' |
+'{' inner_input '}' |
+module_instantiation {
+ if ($1) {
+ currmodule->addChild($1);
+ } else {
+ delete $1;
+ }
+} |
+TOK_ID '=' expr ';' {
+ std::list<std::string>::iterator found = std::find(currmodule->assignments_var.begin(), currmodule->assignments_var.end(),$1);
+ if (found != currmodule->assignments_var.end()) currmodule->assignments_var.erase(found);
+ currmodule->assignments_var.push_back($1);
+ currmodule->assignments[$1] = $3;
+} |
+TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' {
+ Module *p = currmodule;
+ module_stack.push_back(currmodule);
+ currmodule = new Module();
+ p->modules[$2] = currmodule;
+ currmodule->definition_arguments = *$4;
+ free($2);
+ delete $4;
+} statement {
+ currmodule = module_stack.back();
+ module_stack.pop_back();
+ } |
+ TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr {
+ Function *func = new Function();
+ func->definition_arguments = *$4;
+ func->expr = $8;
+ currmodule->functions[$2] = func;
+ free($2);
+ delete $4;
+ } ';' ;
/* Will return a dummy parent node with zero or more children */
children_instantiation:
- module_instantiation {
- $$ = new std::vector<ModuleInstantiation*>;
- if ($1) {
- $$->push_back($1);
- }
- } |
- '{' module_instantiation_list '}' {
- $$ = $2;
- } ;
+module_instantiation {
+ $$ = new std::vector<ModuleInstantiation*>;
+ if ($1) {
+ $$->push_back($1);
+ }
+} |
+'{' module_instantiation_list '}' {
+ $$ = $2;
+} ;
if_statement:
- TOK_IF '(' expr ')' children_instantiation {
- $$ = new IfElseModuleInstantiation();
- $$->argnames.push_back("");
- $$->argexpr.push_back($3);
- $$->setPath(parser_source_path);
-
- if ($$) {
- $$->children = *$5;
- } else {
- for (size_t i = 0; i < $5->size(); i++)
- delete (*$5)[i];
- }
- delete $5;
- } ;
+TOK_IF '(' expr ')' children_instantiation {
+ $$ = new IfElseModuleInstantiation();
+ $$->arguments.push_back(Assignment("", $3));
+ $$->setPath(parser_source_path);
+
+ if ($$) {
+ $$->children = *$5;
+ } else {
+ for (size_t i = 0; i < $5->size(); i++)
+ delete (*$5)[i];
+ }
+ delete $5;
+} ;
ifelse_statement:
- if_statement {
- $$ = $1;
- } |
- if_statement TOK_ELSE children_instantiation {
- $$ = $1;
- if ($$) {
- $$->else_children = *$3;
- } else {
- for (size_t i = 0; i < $3->size(); i++)
- delete (*$3)[i];
- }
- delete $3;
- } ;
+if_statement {
+ $$ = $1;
+} |
+if_statement TOK_ELSE children_instantiation {
+ $$ = $1;
+ if ($$) {
+ $$->else_children = *$3;
+ } else {
+ for (size_t i = 0; i < $3->size(); i++)
+ delete (*$3)[i];
+ }
+ delete $3;
+} ;
module_instantiation:
- '!' module_instantiation {
- $$ = $2;
- if ($$) $$->tag_root = true;
- } |
- '#' module_instantiation {
- $$ = $2;
- if ($$) $$->tag_highlight = true;
- } |
- '%' module_instantiation {
- $$ = $2;
- if ($$) $$->tag_background = true;
- } |
- '*' module_instantiation {
- delete $2;
- $$ = NULL;
- } |
- single_module_instantiation ';' {
- $$ = $1;
- } |
- single_module_instantiation children_instantiation {
- $$ = $1;
- if ($$) {
- $$->children = *$2;
- } else {
- for (size_t i = 0; i < $2->size(); i++)
- delete (*$2)[i];
- }
- delete $2;
- } |
- ifelse_statement {
- $$ = $1;
- } ;
+'!' module_instantiation {
+ $$ = $2;
+ if ($$) $$->tag_root = true;
+} |
+'#' module_instantiation {
+ $$ = $2;
+ if ($$) $$->tag_highlight = true;
+} |
+'%' module_instantiation {
+ $$ = $2;
+ if ($$) $$->tag_background = true;
+} |
+'*' module_instantiation {
+ delete $2;
+ $$ = NULL;
+} |
+single_module_instantiation ';' {
+ $$ = $1;
+} |
+single_module_instantiation children_instantiation {
+ $$ = $1;
+ if ($$) {
+ $$->children = *$2;
+ } else {
+ for (size_t i = 0; i < $2->size(); i++)
+ delete (*$2)[i];
+ }
+ delete $2;
+} |
+ifelse_statement {
+ $$ = $1;
+} ;
module_instantiation_list:
- /* empty */ {
- $$ = new std::vector<ModuleInstantiation*>;
- } |
- module_instantiation_list module_instantiation {
- $$ = $1;
- if ($$) {
- if ($2) $$->push_back($2);
- } else {
- delete $2;
- }
- } ;
+/* empty */ {
+ $$ = new std::vector<ModuleInstantiation*>;
+} |
+module_instantiation_list module_instantiation {
+ $$ = $1;
+ if ($$) {
+ if ($2) $$->push_back($2);
+ } else {
+ delete $2;
+ }
+} ;
single_module_instantiation:
- TOK_ID '(' arguments_call ')' {
- $$ = new ModuleInstantiation($1);
- $$->argnames = $3->argnames;
- $$->argexpr = $3->argexpr;
- $$->setPath(parser_source_path);
- free($1);
- delete $3;
- }
+TOK_ID '(' arguments_call ')' {
+ $$ = new ModuleInstantiation($1);
+ $$->arguments = *$3;
+ $$->setPath(parser_source_path);
+ free($1);
+ delete $3;
+}
expr:
- TOK_TRUE {
- $$ = new Expression(Value(true));
- } |
- TOK_FALSE {
- $$ = new Expression(Value(false));
- } |
- TOK_UNDEF {
- $$ = new Expression(Value::undefined);
- } |
- TOK_ID {
- $$ = new Expression();
- $$->type = "L";
- $$->var_name = $1;
- free($1);
- } |
- expr '.' TOK_ID {
- $$ = new Expression();
- $$->type = "N";
- $$->children.push_back($1);
- $$->var_name = $3;
- free($3);
- } |
- TOK_STRING {
- $$ = new Expression(Value(std::string($1)));
- free($1);
- } |
- TOK_NUMBER {
- $$ = new Expression(Value($1));
- } |
- '[' expr ':' expr ']' {
- Expression *e_one = new Expression(Value(1.0));
- $$ = new Expression();
- $$->type = "R";
- $$->children.push_back($2);
- $$->children.push_back(e_one);
- $$->children.push_back($4);
- } |
- '[' expr ':' expr ':' expr ']' {
- $$ = new Expression();
- $$->type = "R";
- $$->children.push_back($2);
- $$->children.push_back($4);
- $$->children.push_back($6);
- } |
- '[' optional_commas ']' {
- $$ = new Expression(Value(Value::VectorType()));
- } |
- '[' vector_expr optional_commas ']' {
- $$ = $2;
- } |
- expr '*' expr {
- $$ = new Expression();
- $$->type = "*";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr '/' expr {
- $$ = new Expression();
- $$->type = "/";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr '%' expr {
- $$ = new Expression();
- $$->type = "%";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr '+' expr {
- $$ = new Expression();
- $$->type = "+";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr '-' expr {
- $$ = new Expression();
- $$->type = "-";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr '<' expr {
- $$ = new Expression();
- $$->type = "<";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr LE expr {
- $$ = new Expression();
- $$->type = "<=";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr EQ expr {
- $$ = new Expression();
- $$->type = "==";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr NE expr {
- $$ = new Expression();
- $$->type = "!=";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr GE expr {
- $$ = new Expression();
- $$->type = ">=";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr '>' expr {
- $$ = new Expression();
- $$->type = ">";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr AND expr {
- $$ = new Expression();
- $$->type = "&&";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- expr OR expr {
- $$ = new Expression();
- $$->type = "||";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- '+' expr {
- $$ = $2;
- } |
- '-' expr {
- $$ = new Expression();
- $$->type = "I";
- $$->children.push_back($2);
- } |
- '!' expr {
- $$ = new Expression();
- $$->type = "!";
- $$->children.push_back($2);
- } |
- '(' expr ')' {
- $$ = $2;
- } |
- expr '?' expr ':' expr {
- $$ = new Expression();
- $$->type = "?:";
- $$->children.push_back($1);
- $$->children.push_back($3);
- $$->children.push_back($5);
- } |
- expr '[' expr ']' {
- $$ = new Expression();
- $$->type = "[]";
- $$->children.push_back($1);
- $$->children.push_back($3);
- } |
- TOK_ID '(' arguments_call ')' {
- $$ = new Expression();
- $$->type = "F";
- $$->call_funcname = $1;
- $$->call_argnames = $3->argnames;
- $$->children = $3->argexpr;
- free($1);
- delete $3;
- } ;
+TOK_TRUE {
+ $$ = new Expression(Value(true));
+} |
+TOK_FALSE {
+ $$ = new Expression(Value(false));
+} |
+TOK_UNDEF {
+ $$ = new Expression(Value::undefined);
+} |
+TOK_ID {
+ $$ = new Expression();
+ $$->type = "L";
+ $$->var_name = $1;
+ free($1);
+} |
+expr '.' TOK_ID {
+ $$ = new Expression();
+ $$->type = "N";
+ $$->children.push_back($1);
+ $$->var_name = $3;
+ free($3);
+} |
+TOK_STRING {
+ $$ = new Expression(Value(std::string($1)));
+ free($1);
+} |
+TOK_NUMBER {
+ $$ = new Expression(Value($1));
+} |
+'[' expr ':' expr ']' {
+ Expression *e_one = new Expression(Value(1.0));
+ $$ = new Expression();
+ $$->type = "R";
+ $$->children.push_back($2);
+ $$->children.push_back(e_one);
+ $$->children.push_back($4);
+} |
+'[' expr ':' expr ':' expr ']' {
+ $$ = new Expression();
+ $$->type = "R";
+ $$->children.push_back($2);
+ $$->children.push_back($4);
+ $$->children.push_back($6);
+} |
+'[' optional_commas ']' {
+ $$ = new Expression(Value(Value::VectorType()));
+} |
+'[' vector_expr optional_commas ']' {
+ $$ = $2;
+} |
+expr '*' expr {
+ $$ = new Expression();
+ $$->type = "*";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr '/' expr {
+ $$ = new Expression();
+ $$->type = "/";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr '%' expr {
+ $$ = new Expression();
+ $$->type = "%";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr '+' expr {
+ $$ = new Expression();
+ $$->type = "+";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr '-' expr {
+ $$ = new Expression();
+ $$->type = "-";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr '<' expr {
+ $$ = new Expression();
+ $$->type = "<";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr LE expr {
+ $$ = new Expression();
+ $$->type = "<=";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr EQ expr {
+ $$ = new Expression();
+ $$->type = "==";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr NE expr {
+ $$ = new Expression();
+ $$->type = "!=";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr GE expr {
+ $$ = new Expression();
+ $$->type = ">=";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr '>' expr {
+ $$ = new Expression();
+ $$->type = ">";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr AND expr {
+ $$ = new Expression();
+ $$->type = "&&";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+expr OR expr {
+ $$ = new Expression();
+ $$->type = "||";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+'+' expr {
+ $$ = $2;
+} |
+'-' expr {
+ $$ = new Expression();
+ $$->type = "I";
+ $$->children.push_back($2);
+} |
+'!' expr {
+ $$ = new Expression();
+ $$->type = "!";
+ $$->children.push_back($2);
+} |
+'(' expr ')' {
+ $$ = $2;
+} |
+expr '?' expr ':' expr {
+ $$ = new Expression();
+ $$->type = "?:";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+ $$->children.push_back($5);
+} |
+expr '[' expr ']' {
+ $$ = new Expression();
+ $$->type = "[]";
+ $$->children.push_back($1);
+ $$->children.push_back($3);
+} |
+TOK_ID '(' arguments_call ')' {
+ $$ = new Expression();
+ $$->type = "F";
+ $$->call_funcname = $1;
+ $$->call_arguments = *$3;
+ free($1);
+ delete $3;
+} ;
optional_commas:
- ',' optional_commas | ;
+',' optional_commas | ;
vector_expr:
- expr {
- $$ = new Expression();
- $$->type = 'V';
- $$->children.push_back($1);
- } |
- vector_expr ',' optional_commas expr {
- $$ = $1;
- $$->children.push_back($4);
- } ;
+expr {
+ $$ = new Expression();
+ $$->type = 'V';
+ $$->children.push_back($1);
+} |
+vector_expr ',' optional_commas expr {
+ $$ = $1;
+ $$->children.push_back($4);
+} ;
arguments_decl:
- /* empty */ {
- $$ = new ArgsContainer();
- } |
- argument_decl {
- $$ = new ArgsContainer();
- $$->argnames.push_back($1->argname);
- $$->argexpr.push_back($1->argexpr);
- delete $1;
- } |
- arguments_decl ',' optional_commas argument_decl {
- $$ = $1;
- $$->argnames.push_back($4->argname);
- $$->argexpr.push_back($4->argexpr);
- delete $4;
- } ;
+/* empty */ {
+ $$ = new AssignmentList();
+} |
+argument_decl {
+ $$ = new AssignmentList();
+ $$->push_back(*$1);
+ delete $1;
+} |
+arguments_decl ',' optional_commas argument_decl {
+ $$ = $1;
+ $$->push_back(*$4);
+ delete $4;
+} ;
argument_decl:
- TOK_ID {
- $$ = new ArgContainer();
- $$->argname = $1;
- $$->argexpr = NULL;
- free($1);
- } |
- TOK_ID '=' expr {
- $$ = new ArgContainer();
- $$->argname = $1;
- $$->argexpr = $3;
- free($1);
- } ;
+TOK_ID {
+ $$ = new Assignment($1, NULL);
+ free($1);
+} |
+TOK_ID '=' expr {
+ $$ = new Assignment($1, $3);
+ free($1);
+} ;
arguments_call:
- /* empty */ {
- $$ = new ArgsContainer();
- } |
- argument_call {
- $$ = new ArgsContainer();
- $$->argnames.push_back($1->argname);
- $$->argexpr.push_back($1->argexpr);
- delete $1;
- } |
- arguments_call ',' optional_commas argument_call {
- $$ = $1;
- $$->argnames.push_back($4->argname);
- $$->argexpr.push_back($4->argexpr);
- delete $4;
- } ;
+/* empty */ {
+ $$ = new AssignmentList();
+} |
+argument_call {
+ $$ = new AssignmentList();
+ $$->push_back(*$1);
+ delete $1;
+} |
+arguments_call ',' optional_commas argument_call {
+ $$ = $1;
+ $$->push_back(*$4);
+ delete $4;
+} ;
argument_call:
- expr {
- $$ = new ArgContainer();
- $$->argexpr = $1;
- } |
- TOK_ID '=' expr {
- $$ = new ArgContainer();
- $$->argname = $1;
- $$->argexpr = $3;
- free($1);
- } ;
+expr {
+ $$ = new Assignment("", $1);
+} |
+TOK_ID '=' expr {
+ $$ = new Assignment($1, $3);
+ free($1);
+} ;
%%
int parserlex(void)
{
- return lexerlex();
+ return lexerlex();
}
void yyerror (char const *s)
{
- // FIXME: We leak memory on parser errors...
- PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s);
- currmodule = NULL;
+ // FIXME: We leak memory on parser errors...
+ PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s);
+ currmodule = NULL;
}
Module *parse(const char *text, const char *path, int debug)
{
- lexerin = NULL;
- parser_error_pos = -1;
- parser_input_buffer = text;
- parser_source_path = boosty::absolute(std::string(path)).string();
+ lexerin = NULL;
+ parser_error_pos = -1;
+ parser_input_buffer = text;
+ parser_source_path = boosty::absolute(std::string(path)).string();
- module_stack.clear();
- Module *rootmodule = currmodule = new Module();
- // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule);
+ module_stack.clear();
+ Module *rootmodule = currmodule = new Module();
+ rootmodule->setModulePath(path);
+ // PRINTB_NOCACHE("New module: %s %p", "root" % rootmodule);
- parserdebug = debug;
- int parserretval = parserparse();
- lexerdestroy();
- lexerlex_destroy();
+ parserdebug = debug;
+ int parserretval = parserparse();
+ lexerdestroy();
+ lexerlex_destroy();
- if (parserretval != 0) return NULL;
+ if (parserretval != 0) return NULL;
- parser_error_pos = -1;
- return rootmodule;
+ parser_error_pos = -1;
+ return rootmodule;
}
diff --git a/src/primitives.cc b/src/primitives.cc
index e02df35..184b40c 100644
--- a/src/primitives.cc
+++ b/src/primitives.cc
@@ -27,12 +27,13 @@
#include "module.h"
#include "node.h"
#include "polyset.h"
-#include "context.h"
+#include "evalcontext.h"
#include "dxfdata.h"
#include "dxftess.h"
#include "builtin.h"
#include "printutils.h"
#include "visitor.h"
+#include "context.h"
#include <sstream>
#include <assert.h>
#include <boost/assign/std/vector.hpp>
@@ -55,7 +56,7 @@ class PrimitiveModule : public AbstractModule
public:
primitive_type_e type;
PrimitiveModule(primitive_type_e type) : type(type) { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
class PrimitiveNode : public AbstractPolyNode
@@ -104,44 +105,43 @@ public:
virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const;
};
-AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
PrimitiveNode *node = new PrimitiveNode(inst, this->type);
node->center = false;
node->x = node->y = node->z = node->h = node->r1 = node->r2 = 1;
- std::vector<std::string> argnames;
- std::vector<Expression*> argexpr;
+ AssignmentList args;
switch (this->type) {
case CUBE:
- argnames += "size", "center";
+ args += Assignment("size", NULL), Assignment("center", NULL);
break;
case SPHERE:
- argnames += "r";
+ args += Assignment("r", NULL);
break;
case CYLINDER:
- argnames += "h", "r1", "r2", "center";
+ args += Assignment("h", NULL), Assignment("r1", NULL), Assignment("r2", NULL), Assignment("center", NULL);
break;
case POLYHEDRON:
- argnames += "points", "triangles", "convexity";
+ args += Assignment("points", NULL), Assignment("triangles", NULL), Assignment("convexity", NULL);
break;
case SQUARE:
- argnames += "size", "center";
+ args += Assignment("size", NULL), Assignment("center", NULL);
break;
case CIRCLE:
- argnames += "r";
+ args += Assignment("r", NULL);
break;
case POLYGON:
- argnames += "points", "paths", "convexity";
+ args += Assignment("points", NULL), Assignment("paths", NULL), Assignment("convexity", NULL);
break;
default:
assert(false && "PrimitiveModule::evaluate(): Unknown node type");
}
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();
diff --git a/src/printutils.cc b/src/printutils.cc
index 698fffb..37092fa 100644
--- a/src/printutils.cc
+++ b/src/printutils.cc
@@ -69,5 +69,3 @@ std::string two_digit_exp_format( double x )
s << x;
return two_digit_exp_format( s.str() );
}
-
-
diff --git a/src/printutils.h b/src/printutils.h
index 439c884..18aadde 100644
--- a/src/printutils.h
+++ b/src/printutils.h
@@ -22,6 +22,9 @@ void PRINT(const std::string &msg);
void PRINT_NOCACHE(const std::string &msg);
#define PRINTB_NOCACHE(_fmt, _arg) do { PRINT_NOCACHE(str(boost::format(_fmt) % _arg)); } while (0)
+
+void PRINT_CONTEXT(const class Context *ctx, const class Module *mod, const class ModuleInstantiation *inst);
+
std::string two_digit_exp_format( std::string doublestr );
std::string two_digit_exp_format( double x );
diff --git a/src/projection.cc b/src/projection.cc
index 1fcf639..eeed411 100644
--- a/src/projection.cc
+++ b/src/projection.cc
@@ -26,7 +26,7 @@
#include "projectionnode.h"
#include "module.h"
-#include "context.h"
+#include "evalcontext.h"
#include "printutils.h"
#include "builtin.h"
#include "visitor.h"
@@ -41,19 +41,18 @@ class ProjectionModule : public AbstractModule
{
public:
ProjectionModule() { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
ProjectionNode *node = new ProjectionNode(inst);
- std::vector<std::string> argnames;
- argnames += "cut";
- std::vector<Expression*> argexpr;
+ AssignmentList args;
+ args += Assignment("cut", NULL);
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
Value convexity = c.lookup_variable("convexity", true);
Value cut = c.lookup_variable("cut", true);
@@ -63,7 +62,7 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant
if (cut.type() == Value::BOOL)
node->cut_mode = cut.toBool();
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
return node;
diff --git a/src/render.cc b/src/render.cc
index 81c3f7b..bb08c0c 100644
--- a/src/render.cc
+++ b/src/render.cc
@@ -26,7 +26,7 @@
#include "rendernode.h"
#include "module.h"
-#include "context.h"
+#include "evalcontext.h"
#include "builtin.h"
#include "PolySetEvaluator.h"
@@ -38,25 +38,24 @@ class RenderModule : public AbstractModule
{
public:
RenderModule() { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
RenderNode *node = new RenderNode(inst);
- std::vector<std::string> argnames;
- argnames += "convexity";
- std::vector<Expression*> argexpr;
+ AssignmentList args;
+ args += Assignment("convexity", NULL);
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
Value v = c.lookup_variable("convexity");
if (v.type() == Value::NUMBER)
node->convexity = (int)v.toDouble();
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
return node;
diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc
index c4d9342..b6edb8b 100644
--- a/src/rotateextrude.cc
+++ b/src/rotateextrude.cc
@@ -26,7 +26,7 @@
#include "rotateextrudenode.h"
#include "module.h"
-#include "context.h"
+#include "evalcontext.h"
#include "printutils.h"
#include "builtin.h"
#include "polyset.h"
@@ -45,19 +45,18 @@ class RotateExtrudeModule : public AbstractModule
{
public:
RotateExtrudeModule() { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
RotateExtrudeNode *node = new RotateExtrudeNode(inst);
- std::vector<std::string> argnames;
- argnames += "file", "layer", "origin", "scale";
- std::vector<Expression*> argexpr;
+ AssignmentList args;
+ args += Assignment("file", NULL), Assignment("layer", NULL), Assignment("origin", NULL), Assignment("scale", NULL);
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();
@@ -86,7 +85,7 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst
node->scale = 1;
if (node->filename.empty()) {
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
}
diff --git a/src/surface.cc b/src/surface.cc
index ca5031e..d8fa422 100644
--- a/src/surface.cc
+++ b/src/surface.cc
@@ -27,7 +27,7 @@
#include "module.h"
#include "node.h"
#include "polyset.h"
-#include "context.h"
+#include "evalcontext.h"
#include "builtin.h"
#include "printutils.h"
#include "handle_dep.h" // handle_dep()
@@ -50,7 +50,7 @@ class SurfaceModule : public AbstractModule
{
public:
SurfaceModule() { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
class SurfaceNode : public AbstractPolyNode
@@ -69,18 +69,17 @@ public:
virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const;
};
-AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
SurfaceNode *node = new SurfaceNode(inst);
node->center = false;
node->convexity = 1;
- std::vector<std::string> argnames;
- argnames += "file", "center", "convexity";
- std::vector<Expression*> argexpr;
+ AssignmentList args;
+ args += Assignment("file", NULL), Assignment("center", NULL), Assignment("convexity", NULL);
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
Value fileval = c.lookup_variable("file");
node->filename = inst->getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString());
diff --git a/src/transform.cc b/src/transform.cc
index b01827f..cc026fb 100644
--- a/src/transform.cc
+++ b/src/transform.cc
@@ -26,7 +26,7 @@
#include "transformnode.h"
#include "module.h"
-#include "context.h"
+#include "evalcontext.h"
#include "polyset.h"
#include "builtin.h"
#include "value.h"
@@ -50,40 +50,39 @@ class TransformModule : public AbstractModule
public:
transform_type_e type;
TransformModule(transform_type_e type) : type(type) { }
- virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
};
-AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
TransformNode *node = new TransformNode(inst);
node->matrix = Transform3d::Identity();
- std::vector<std::string> argnames;
- std::vector<Expression*> argexpr;
+ AssignmentList args;
switch (this->type) {
case SCALE:
- argnames += "v";
+ args += Assignment("v", NULL);
break;
case ROTATE:
- argnames += "a", "v";
+ args += Assignment("a", NULL), Assignment("v", NULL);
break;
case MIRROR:
- argnames += "v";
+ args += Assignment("v", NULL);
break;
case TRANSLATE:
- argnames += "v";
+ args += Assignment("v", NULL);
break;
case MULTMATRIX:
- argnames += "m";
+ args += Assignment("m", NULL);
break;
default:
assert(false);
}
Context c(ctx);
- c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+ c.setVariables(args, evalctx);
if (this->type == SCALE)
{
@@ -176,7 +175,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
}
}
- std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
+ std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren(evalctx);
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
return node;
diff --git a/src/typedefs.h b/src/typedefs.h
new file mode 100644
index 0000000..a6e9077
--- /dev/null
+++ b/src/typedefs.h
@@ -0,0 +1,10 @@
+#ifndef TYPEDEFS_H_
+#define TYPEDEFS_H_
+
+#include <string>
+#include <vector>
+
+typedef std::pair<std::string, class Expression*> Assignment;
+typedef std::vector<Assignment> AssignmentList;
+
+#endif
contact: Jan Huwald // Impressum