From 611d5ce2a7125e4d76dc95c619b10dbc2b544d7f Mon Sep 17 00:00:00 2001 From: Vicnet Date: Tue, 24 Sep 2013 07:06:44 +0200 Subject: [PATCH] add children primitive, and refactor control.cc a little --- contrib/scad-mode.el | 2 +- src/control.cc | 123 ++++++++++++++++++++++++++++--------------- src/highlighter.cc | 2 +- 3 files changed, 84 insertions(+), 43 deletions(-) diff --git a/contrib/scad-mode.el b/contrib/scad-mode.el index 68a47e6b..070caaf4 100644 --- a/contrib/scad-mode.el +++ b/contrib/scad-mode.el @@ -74,7 +74,7 @@ :group 'scad-font-lock) (defcustom scad-modules - '("child" "echo" "assign" "for" "intersection_for" "if" "else" ;;control.cc + '("child" "children" "echo" "assign" "for" "intersection_for" "if" "else" ;;control.cc "cube" "sphere" "cylinder" "polyhedron" "square" "circle" "polygon" ;;primitives.cc "scale" "rotate" "translate" "mirror" "multmatrix" ;;transform.cc "union" "difference" "intersection" ;;csgops.cc diff --git a/src/control.cc b/src/control.cc index 50e5eaec..ec13650e 100644 --- a/src/control.cc +++ b/src/control.cc @@ -33,24 +33,36 @@ #include #include "mathc99.h" -enum control_type_e { - CHILD, - ECHO, - ASSIGN, - FOR, - INT_FOR, - IF -}; - class ControlModule : public AbstractModule { -public: - control_type_e type; - ControlModule(control_type_e type) : type(type) { } - virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; -}; +public: // types + enum Type { + CHILD, + CHILDREN, + ECHO, + ASSIGN, + FOR, + INT_FOR, + IF + }; +public: // methods + ControlModule(Type type) + : type(type) + { } -void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, + virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const; + + static void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, + const Context *ctx, const EvalContext *evalctx); + + static const EvalContext* getLastModuleCtx(const EvalContext *evalctx); + +private: // data + Type type; + +}; // class ControlModule + +void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, const Context *ctx, const EvalContext *evalctx) { if (evalctx->numArgs() > l) { @@ -87,6 +99,26 @@ void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l, } } +const EvalContext* ControlModule::getLastModuleCtx(const EvalContext *evalctx) +{ + // 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 *modulectx = dynamic_cast(tmpc->parent); + if (modulectx) { + // This will trigger if trying to invoke child from the root of any file + // assert(filectx->evalctx); + if (modulectx->evalctx) { + return modulectx->evalctx; + } + return NULL; + } + tmpc = tmpc->parent; + } + return NULL; +} + AbstractNode *ControlModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const { AbstractNode *node = NULL; @@ -107,27 +139,35 @@ AbstractNode *ControlModule::instantiate(const Context *ctx, const ModuleInstant // 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(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 < (int)filectx->evalctx->numChildren()) { - node = filectx->evalctx->getChild(n)->evaluate(filectx->evalctx); - } - else { - // How to deal with negative objects in this case? + const EvalContext *modulectx = getLastModuleCtx(evalctx); + if (modulectx==NULL) { + return NULL; + } + // This will trigger if trying to invoke child from the root of any file + if (n < (int)modulectx->numChildren()) { + node = modulectx->getChild(n)->evaluate(modulectx); + } + 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->numChildren()); - } - } - return node; - } - tmpc = tmpc->parent; + PRINTB("WARNING: Child index (%d) out of bounds (%d children)", + n % modulectx->numChildren()); + } + return node; + } + + if (type == CHILDREN) + { + const EvalContext *modulectx = getLastModuleCtx(evalctx); + if (modulectx==NULL) { + return NULL; + } + AbstractNode* node = new AbstractNode(inst); + // This will trigger if trying to invoke child from the root of any file + // assert(filectx->evalctx); + for (int n = 0; n < (int)modulectx->numChildren(); ++n) { + AbstractNode* childnode = modulectx->getChild(n)->evaluate(modulectx); + node->children.push_back(childnode); } return node; } @@ -183,10 +223,11 @@ AbstractNode *ControlModule::instantiate(const Context *ctx, const ModuleInstant void register_builtin_control() { - Builtins::init("child", new ControlModule(CHILD)); - Builtins::init("echo", new ControlModule(ECHO)); - Builtins::init("assign", new ControlModule(ASSIGN)); - Builtins::init("for", new ControlModule(FOR)); - Builtins::init("intersection_for", new ControlModule(INT_FOR)); - Builtins::init("if", new ControlModule(IF)); + Builtins::init("child", new ControlModule(ControlModule::CHILD)); + Builtins::init("children", new ControlModule(ControlModule::CHILDREN)); + Builtins::init("echo", new ControlModule(ControlModule::ECHO)); + Builtins::init("assign", new ControlModule(ControlModule::ASSIGN)); + Builtins::init("for", new ControlModule(ControlModule::FOR)); + Builtins::init("intersection_for", new ControlModule(ControlModule::INT_FOR)); + Builtins::init("if", new ControlModule(ControlModule::IF)); } diff --git a/src/highlighter.cc b/src/highlighter.cc index 4b4aa304..1da0e884 100644 --- a/src/highlighter.cc +++ b/src/highlighter.cc @@ -154,7 +154,7 @@ Highlighter::Highlighter(QTextDocument *parent) tokentypes["import"] << "include" << "use" << "import_stl" << "import" << "import_dxf" << "dxf_dim" << "dxf_cross" << "surface"; typeformats["import"].setForeground(Qt::darkYellow); - tokentypes["special"] << "$children" << "child" << "$fn" << "$fa" << "$fs" << "$t" << "$vpt" << "$vpr"; + tokentypes["special"] << "$children" << "child" << "children" << "$fn" << "$fa" << "$fs" << "$t" << "$vpt" << "$vpr"; typeformats["special"].setForeground(Qt::darkGreen); tokentypes["extrude"] << "linear_extrude" << "rotate_extrude";