mirror of https://github.com/vitalif/openscad
Support variable assignment in local blocks. This should fix #347 but more testing is needed
parent
1263042fc9
commit
ea1d561c46
|
@ -39,10 +39,10 @@ class CgaladvModule : public AbstractModule
|
||||||
public:
|
public:
|
||||||
cgaladv_type_e type;
|
cgaladv_type_e type;
|
||||||
CgaladvModule(cgaladv_type_e type) : type(type) { }
|
CgaladvModule(cgaladv_type_e type) : type(type) { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
CgaladvNode *node = new CgaladvNode(inst, type);
|
CgaladvNode *node = new CgaladvNode(inst, type);
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
Value convexity, path, subdiv_type, level;
|
Value convexity, path, subdiv_type, level;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ColorModule : public AbstractModule
|
||||||
public:
|
public:
|
||||||
ColorModule();
|
ColorModule();
|
||||||
virtual ~ColorModule();
|
virtual ~ColorModule();
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::unordered_map<std::string, Color4f> webcolors;
|
boost::unordered_map<std::string, Color4f> webcolors;
|
||||||
|
@ -205,7 +205,7 @@ ColorModule::~ColorModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
ColorNode *node = new ColorNode(inst);
|
ColorNode *node = new ColorNode(inst);
|
||||||
|
|
||||||
|
@ -218,6 +218,7 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
Value v = c.lookup_variable("c");
|
Value v = c.lookup_variable("c");
|
||||||
if (v.type() == Value::VECTOR) {
|
if (v.type() == Value::VECTOR) {
|
||||||
|
|
|
@ -152,7 +152,7 @@ Value Context::evaluate_function(const std::string &name, const EvalContext *eva
|
||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *Context::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const
|
AbstractNode *Context::instantiate_module(const ModuleInstantiation &inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
if (this->parent) return this->parent->instantiate_module(inst, evalctx);
|
if (this->parent) return this->parent->instantiate_module(inst, evalctx);
|
||||||
PRINTB("WARNING: Ignoring unknown module '%s'.", inst.name());
|
PRINTB("WARNING: Ignoring unknown module '%s'.", inst.name());
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
|
|
||||||
const Context *getParent() const { return this->parent; }
|
const Context *getParent() const { return this->parent; }
|
||||||
virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const;
|
virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const;
|
||||||
virtual class AbstractNode *instantiate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const;
|
virtual class AbstractNode *instantiate_module(const class ModuleInstantiation &inst, EvalContext *evalctx) const;
|
||||||
|
|
||||||
void setVariables(const AssignmentList &args,
|
void setVariables(const AssignmentList &args,
|
||||||
const class EvalContext *evalctx = NULL);
|
const class EvalContext *evalctx = NULL);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "evalcontext.h"
|
#include "evalcontext.h"
|
||||||
#include "modcontext.h"
|
#include "modcontext.h"
|
||||||
|
#include "expression.h"
|
||||||
#include "builtin.h"
|
#include "builtin.h"
|
||||||
#include "printutils.h"
|
#include "printutils.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -55,7 +56,7 @@ public: // methods
|
||||||
: type(type)
|
: type(type)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
|
|
||||||
static void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l,
|
static void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l,
|
||||||
const Context *ctx, const EvalContext *evalctx);
|
const Context *ctx, const EvalContext *evalctx);
|
||||||
|
@ -99,7 +100,14 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst
|
||||||
for_eval(node, inst, l+1, &c, evalctx);
|
for_eval(node, inst, l+1, &c, evalctx);
|
||||||
}
|
}
|
||||||
} else if (l > 0) {
|
} else if (l > 0) {
|
||||||
std::vector<AbstractNode *> instantiatednodes = inst.instantiateChildren(ctx);
|
// At this point, the for loop variables have been set and we can initialize
|
||||||
|
// the local scope (as they may depend on the for loop variables
|
||||||
|
Context c(ctx);
|
||||||
|
BOOST_FOREACH(const Assignment &ass, inst.scope.assignments) {
|
||||||
|
c.set_variable(ass.first, ass.second->evaluate(&c));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AbstractNode *> instantiatednodes = inst.instantiateChildren(&c);
|
||||||
node.children.insert(node.children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
node.children.insert(node.children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,12 +163,16 @@ AbstractNode* ControlModule::getChild(const Value& value, const EvalContext* mod
|
||||||
return modulectx->getChild(n)->evaluate(modulectx);
|
return modulectx->getChild(n)->evaluate(modulectx);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
AbstractNode *node = NULL;
|
AbstractNode *node = NULL;
|
||||||
|
|
||||||
if (type == CHILD)
|
if (this->type != FOR && this->type != INT_FOR) {
|
||||||
{
|
evalctx->applyScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this->type) {
|
||||||
|
case CHILD: {
|
||||||
printDeprecation("DEPRECATED: child() will be removed in future releases. Use children() instead.");
|
printDeprecation("DEPRECATED: child() will be removed in future releases. Use children() instead.");
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if (evalctx->numArgs() > 0) {
|
if (evalctx->numArgs() > 0) {
|
||||||
|
@ -192,9 +204,9 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (type == CHILDREN)
|
case CHILDREN: {
|
||||||
{
|
|
||||||
const EvalContext *modulectx = getLastModuleCtx(evalctx);
|
const EvalContext *modulectx = getLastModuleCtx(evalctx);
|
||||||
if (modulectx==NULL) {
|
if (modulectx==NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -251,14 +263,10 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (type == INT_FOR)
|
case ECHO: {
|
||||||
node = new AbstractIntersectionNode(inst);
|
|
||||||
else
|
|
||||||
node = new AbstractNode(inst);
|
node = new AbstractNode(inst);
|
||||||
|
|
||||||
if (type == ECHO)
|
|
||||||
{
|
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "ECHO: ";
|
msg << "ECHO: ";
|
||||||
for (size_t i = 0; i < inst->arguments.size(); i++) {
|
for (size_t i = 0; i < inst->arguments.size(); i++) {
|
||||||
|
@ -273,9 +281,10 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
}
|
}
|
||||||
PRINTB("%s", msg.str());
|
PRINTB("%s", msg.str());
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (type == ASSIGN)
|
case ASSIGN: {
|
||||||
{
|
node = new AbstractNode(inst);
|
||||||
Context c(evalctx);
|
Context c(evalctx);
|
||||||
for (size_t i = 0; i < evalctx->numArgs(); i++) {
|
for (size_t i = 0; i < evalctx->numArgs(); i++) {
|
||||||
if (!evalctx->getArgName(i).empty())
|
if (!evalctx->getArgName(i).empty())
|
||||||
|
@ -284,14 +293,20 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(&c);
|
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(&c);
|
||||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if (type == FOR || type == INT_FOR)
|
case FOR:
|
||||||
{
|
node = new AbstractNode(inst);
|
||||||
for_eval(*node, *inst, 0, evalctx, evalctx);
|
for_eval(*node, *inst, 0, evalctx, evalctx);
|
||||||
}
|
break;
|
||||||
|
|
||||||
if (type == IF)
|
case INT_FOR:
|
||||||
{
|
node = new AbstractIntersectionNode(inst);
|
||||||
|
for_eval(*node, *inst, 0, evalctx, evalctx);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IF: {
|
||||||
|
node = new AbstractNode(inst);
|
||||||
const IfElseModuleInstantiation *ifelse = dynamic_cast<const IfElseModuleInstantiation*>(inst);
|
const IfElseModuleInstantiation *ifelse = dynamic_cast<const IfElseModuleInstantiation*>(inst);
|
||||||
if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) {
|
if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) {
|
||||||
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
|
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
|
||||||
|
@ -302,7 +317,8 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,11 +38,12 @@ class CsgModule : public AbstractModule
|
||||||
public:
|
public:
|
||||||
OpenSCADOperator type;
|
OpenSCADOperator type;
|
||||||
CsgModule(OpenSCADOperator type) : type(type) { }
|
CsgModule(OpenSCADOperator type) : type(type) { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *CsgModule::instantiate(const Context*, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *CsgModule::instantiate(const Context*, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
|
evalctx->applyScope();
|
||||||
CsgNode *node = new CsgNode(inst, type);
|
CsgNode *node = new CsgNode(inst, type);
|
||||||
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
|
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
|
||||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
EvalContext::EvalContext(const Context *parent,
|
||||||
|
const AssignmentList &args, const class LocalScope *const scope)
|
||||||
|
: Context(parent), eval_arguments(args), scope(scope)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const std::string &EvalContext::getArgName(size_t i) const
|
const std::string &EvalContext::getArgName(size_t i) const
|
||||||
{
|
{
|
||||||
assert(i < this->eval_arguments.size());
|
assert(i < this->eval_arguments.size());
|
||||||
|
@ -31,6 +37,22 @@ ModuleInstantiation *EvalContext::getChild(size_t i) const
|
||||||
return this->scope ? this->scope->children[i] : NULL;
|
return this->scope ? this->scope->children[i] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
When instantiating a module which can take a scope as parameter (i.e. non-leaf nodes),
|
||||||
|
use this method to apply the local scope definitions to the evaluation context.
|
||||||
|
This will enable variables defined in local blocks.
|
||||||
|
NB! for loops are special as the local block may depend on variables evaluated by the
|
||||||
|
for loop parameters. The for loop code will handle this specially.
|
||||||
|
*/
|
||||||
|
void EvalContext::applyScope()
|
||||||
|
{
|
||||||
|
if (this->scope) {
|
||||||
|
BOOST_FOREACH(const Assignment &ass, this->scope->assignments) {
|
||||||
|
this->set_variable(ass.first, ass.second->evaluate(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst)
|
std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiation *inst)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,8 +12,7 @@ public:
|
||||||
typedef std::vector<class ModuleInstantiation *> InstanceList;
|
typedef std::vector<class ModuleInstantiation *> InstanceList;
|
||||||
|
|
||||||
EvalContext(const Context *parent,
|
EvalContext(const Context *parent,
|
||||||
const AssignmentList &args, const class LocalScope *const scope = NULL)
|
const AssignmentList &args, const class LocalScope *const scope = NULL);
|
||||||
: Context(parent), eval_arguments(args), scope(scope) {}
|
|
||||||
virtual ~EvalContext() {}
|
virtual ~EvalContext() {}
|
||||||
|
|
||||||
size_t numArgs() const { return this->eval_arguments.size(); }
|
size_t numArgs() const { return this->eval_arguments.size(); }
|
||||||
|
@ -23,6 +22,8 @@ public:
|
||||||
size_t numChildren() const;
|
size_t numChildren() const;
|
||||||
ModuleInstantiation *getChild(size_t i) const;
|
ModuleInstantiation *getChild(size_t i) const;
|
||||||
|
|
||||||
|
void applyScope();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
virtual std::string dump(const class AbstractModule *mod, const ModuleInstantiation *inst);
|
virtual std::string dump(const class AbstractModule *mod, const ModuleInstantiation *inst);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,10 +61,10 @@ class ImportModule : public AbstractModule
|
||||||
public:
|
public:
|
||||||
import_type_e type;
|
import_type_e type;
|
||||||
ImportModule(import_type_e type = TYPE_UNKNOWN) : type(type) { }
|
ImportModule(import_type_e type = TYPE_UNKNOWN) : type(type) { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
AssignmentList args;
|
AssignmentList args;
|
||||||
args += Assignment("file"), Assignment("layer"), Assignment("convexity"), Assignment("origin"), Assignment("scale");
|
args += Assignment("file"), Assignment("layer"), Assignment("convexity"), Assignment("origin"), Assignment("scale");
|
||||||
|
|
|
@ -46,10 +46,10 @@ class LinearExtrudeModule : public AbstractModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LinearExtrudeModule() { }
|
LinearExtrudeModule() { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
LinearExtrudeNode *node = new LinearExtrudeNode(inst);
|
LinearExtrudeNode *node = new LinearExtrudeNode(inst);
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
node->fn = c.lookup_variable("$fn").toDouble();
|
node->fn = c.lookup_variable("$fn").toDouble();
|
||||||
node->fs = c.lookup_variable("$fs").toDouble();
|
node->fs = c.lookup_variable("$fs").toDouble();
|
||||||
|
|
|
@ -43,32 +43,14 @@ std::string LocalScope::dump(const std::string &indent) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Two parameters here is a hack. Rather have separate types of scopes, or check the type of the first parameter. Note const vs. non-const
|
// FIXME: Two parameters here is a hack. Rather have separate types of scopes, or check the type of the first parameter. Note const vs. non-const
|
||||||
std::vector<AbstractNode*> LocalScope::instantiateChildren(const Context *evalctx, FileContext *filectx) const
|
std::vector<AbstractNode*> LocalScope::instantiateChildren(const Context *evalctx) const
|
||||||
{
|
{
|
||||||
Context *c = filectx;
|
|
||||||
|
|
||||||
if (!c) {
|
|
||||||
c = new Context(evalctx);
|
|
||||||
|
|
||||||
// FIXME: If we make c a ModuleContext, child() doesn't work anymore
|
|
||||||
// c->functions_p = &this->functions;
|
|
||||||
// c->modules_p = &this->modules;
|
|
||||||
|
|
||||||
// Uncommenting the following would allow assignments in local scopes,
|
|
||||||
// but would cause duplicate evaluation of module scopes
|
|
||||||
// BOOST_FOREACH (const Assignment &ass, this->assignments) {
|
|
||||||
// c->set_variable(ass.first, ass.second->evaluate(c));
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<AbstractNode*> childnodes;
|
std::vector<AbstractNode*> childnodes;
|
||||||
BOOST_FOREACH (ModuleInstantiation *modinst, this->children) {
|
BOOST_FOREACH (ModuleInstantiation *modinst, this->children) {
|
||||||
AbstractNode *node = modinst->evaluate(c);
|
AbstractNode *node = modinst->evaluate(evalctx);
|
||||||
if (node) childnodes.push_back(node);
|
if (node) childnodes.push_back(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c != filectx) delete c;
|
|
||||||
|
|
||||||
return childnodes;
|
return childnodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ public:
|
||||||
|
|
||||||
size_t numElements() const { return assignments.size() + children.size(); }
|
size_t numElements() const { return assignments.size() + children.size(); }
|
||||||
std::string dump(const std::string &indent) const;
|
std::string dump(const std::string &indent) const;
|
||||||
std::vector<class AbstractNode*> instantiateChildren(const class Context *evalctx, class FileContext *filectx = NULL) const;
|
std::vector<class AbstractNode*> instantiateChildren(const class Context *evalctx) const;
|
||||||
void addChild(ModuleInstantiation *ch);
|
void addChild(ModuleInstantiation *ch);
|
||||||
|
|
||||||
AssignmentList assignments;
|
AssignmentList assignments;
|
||||||
|
|
|
@ -71,6 +71,7 @@ void ModuleContext::initializeModule(const class Module &module)
|
||||||
BOOST_FOREACH(const Assignment &ass, module.scope.assignments) {
|
BOOST_FOREACH(const Assignment &ass, module.scope.assignments) {
|
||||||
this->set_variable(ass.first, ass.second->evaluate(this));
|
this->set_variable(ass.first, ass.second->evaluate(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Experimental code. See issue #399
|
// Experimental code. See issue #399
|
||||||
// evaluateAssignments(module.scope.assignments);
|
// evaluateAssignments(module.scope.assignments);
|
||||||
}
|
}
|
||||||
|
@ -130,7 +131,7 @@ Value ModuleContext::evaluate_function(const std::string &name, const EvalContex
|
||||||
return Context::evaluate_function(name, evalctx);
|
return Context::evaluate_function(name, evalctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *ModuleContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const
|
AbstractNode *ModuleContext::instantiate_module(const ModuleInstantiation &inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
const AbstractModule *foundm = this->findLocalModule(inst.name());
|
const AbstractModule *foundm = this->findLocalModule(inst.name());
|
||||||
if (foundm) return foundm->instantiate(this, &inst, evalctx);
|
if (foundm) return foundm->instantiate(this, &inst, evalctx);
|
||||||
|
@ -207,7 +208,7 @@ Value FileContext::evaluate_function(const std::string &name, const EvalContext
|
||||||
return ModuleContext::evaluate_function(name, evalctx);
|
return ModuleContext::evaluate_function(name, evalctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *FileContext::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const
|
AbstractNode *FileContext::instantiate_module(const ModuleInstantiation &inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
const AbstractModule *foundm = this->findLocalModule(inst.name());
|
const AbstractModule *foundm = this->findLocalModule(inst.name());
|
||||||
if (foundm) return foundm->instantiate(this, &inst, evalctx);
|
if (foundm) return foundm->instantiate(this, &inst, evalctx);
|
||||||
|
|
|
@ -21,7 +21,7 @@ public:
|
||||||
virtual Value evaluate_function(const std::string &name,
|
virtual Value evaluate_function(const std::string &name,
|
||||||
const EvalContext *evalctx) const;
|
const EvalContext *evalctx) const;
|
||||||
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
|
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
|
||||||
const EvalContext *evalctx) const;
|
EvalContext *evalctx) const;
|
||||||
|
|
||||||
const AbstractModule *findLocalModule(const std::string &name) const;
|
const AbstractModule *findLocalModule(const std::string &name) const;
|
||||||
const AbstractFunction *findLocalFunction(const std::string &name) const;
|
const AbstractFunction *findLocalFunction(const std::string &name) const;
|
||||||
|
@ -47,7 +47,7 @@ public:
|
||||||
virtual ~FileContext() {}
|
virtual ~FileContext() {}
|
||||||
virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const;
|
virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const;
|
||||||
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
|
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
|
||||||
const EvalContext *evalctx) const;
|
EvalContext *evalctx) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FileModule::ModuleContainer &usedlibs;
|
const FileModule::ModuleContainer &usedlibs;
|
||||||
|
|
|
@ -46,7 +46,7 @@ AbstractModule::~AbstractModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
(void)ctx; // avoid unusued parameter warning
|
(void)ctx; // avoid unusued parameter warning
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ private:
|
||||||
const ModuleInstantiation &inst;
|
const ModuleInstantiation &inst;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
ModRecursionGuard g(*inst);
|
ModRecursionGuard g(*inst);
|
||||||
if (g.recursion_detected()) {
|
if (g.recursion_detected()) {
|
||||||
|
@ -193,6 +193,10 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At this point we know that nobody will modify the dependencies of the local scope
|
||||||
|
// passed to this instance, so we can populate the context
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
ModuleContext c(ctx, evalctx);
|
ModuleContext c(ctx, evalctx);
|
||||||
// set $children first since we might have variables depending on it
|
// set $children first since we might have variables depending on it
|
||||||
c.set_variable("$children", Value(double(inst->scope.children.size())));
|
c.set_variable("$children", Value(double(inst->scope.children.size())));
|
||||||
|
@ -342,7 +346,7 @@ bool FileModule::handleDependencies()
|
||||||
return somethingchanged;
|
return somethingchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
assert(evalctx == NULL);
|
assert(evalctx == NULL);
|
||||||
FileContext c(*this, ctx);
|
FileContext c(*this, ctx);
|
||||||
|
@ -353,7 +357,7 @@ AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AbstractNode *node = new AbstractNode(inst);
|
AbstractNode *node = new AbstractNode(inst);
|
||||||
std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(ctx, &c);
|
std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(&c);
|
||||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
virtual ~AbstractModule();
|
virtual ~AbstractModule();
|
||||||
virtual bool is_experimental() const { return feature != NULL; }
|
virtual bool is_experimental() const { return feature != NULL; }
|
||||||
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); }
|
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); }
|
||||||
virtual class AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const class EvalContext *evalctx = NULL) const;
|
virtual class AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, class EvalContext *evalctx = NULL) const;
|
||||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||||
virtual double lookup_double_variable_with_default(Context &c, std::string variable, double def) const;
|
virtual double lookup_double_variable_with_default(Context &c, std::string variable, double def) const;
|
||||||
virtual std::string lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const;
|
virtual std::string lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const;
|
||||||
|
@ -81,7 +81,7 @@ public:
|
||||||
Module(const Feature& feature) : AbstractModule(feature) { }
|
Module(const Feature& feature) : AbstractModule(feature) { }
|
||||||
virtual ~Module();
|
virtual ~Module();
|
||||||
|
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx = NULL) const;
|
||||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||||
static const std::string& stack_element(int n) { return module_stack[n]; };
|
static const std::string& stack_element(int n) { return module_stack[n]; };
|
||||||
static int stack_size() { return module_stack.size(); };
|
static int stack_size() { return module_stack.size(); };
|
||||||
|
@ -108,7 +108,7 @@ public:
|
||||||
void registerInclude(const std::string &localpath, const std::string &fullpath);
|
void registerInclude(const std::string &localpath, const std::string &fullpath);
|
||||||
bool includesChanged() const;
|
bool includesChanged() const;
|
||||||
bool handleDependencies();
|
bool handleDependencies();
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx = NULL) const;
|
||||||
bool hasIncludes() const { return !this->includes.empty(); }
|
bool hasIncludes() const { return !this->includes.empty(); }
|
||||||
bool usesLibraries() const { return !this->usedlibs.empty(); }
|
bool usesLibraries() const { return !this->usedlibs.empty(); }
|
||||||
bool isHandlingDependencies() const { return this->is_handling_dependencies; }
|
bool isHandlingDependencies() const { return this->is_handling_dependencies; }
|
||||||
|
|
|
@ -46,10 +46,10 @@ class OffsetModule : public AbstractModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OffsetModule() { }
|
OffsetModule() { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
OffsetNode *node = new OffsetNode(inst);
|
OffsetNode *node = new OffsetNode(inst);
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
node->fn = c.lookup_variable("$fn").toDouble();
|
node->fn = c.lookup_variable("$fn").toDouble();
|
||||||
node->fs = c.lookup_variable("$fs").toDouble();
|
node->fs = c.lookup_variable("$fs").toDouble();
|
||||||
|
|
|
@ -270,6 +270,7 @@ if_statement:
|
||||||
child_statements:
|
child_statements:
|
||||||
/* empty */
|
/* empty */
|
||||||
| child_statements child_statement
|
| child_statements child_statement
|
||||||
|
| child_statements assignment
|
||||||
;
|
;
|
||||||
|
|
||||||
child_statement:
|
child_statement:
|
||||||
|
@ -281,13 +282,6 @@ child_statement:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
|
||||||
FIXME: This allows for variable declaration in child blocks, not activated yet
|
|
||||||
|
|
|
||||||
assignment ;
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// "for" is a valid module identifier
|
// "for" is a valid module identifier
|
||||||
module_id:
|
module_id:
|
||||||
TOK_ID { $$ = $1; }
|
TOK_ID { $$ = $1; }
|
||||||
|
|
|
@ -61,7 +61,7 @@ class PrimitiveModule : public AbstractModule
|
||||||
public:
|
public:
|
||||||
primitive_type_e type;
|
primitive_type_e type;
|
||||||
PrimitiveModule(primitive_type_e type) : type(type) { }
|
PrimitiveModule(primitive_type_e type) : type(type) { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
private:
|
private:
|
||||||
Value lookup_radius(const Context &ctx, const std::string &radius_var, const std::string &diameter_var) const;
|
Value lookup_radius(const Context &ctx, const std::string &radius_var, const std::string &diameter_var) const;
|
||||||
};
|
};
|
||||||
|
@ -141,7 +141,7 @@ Value PrimitiveModule::lookup_radius(const Context &ctx, const std::string &diam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
PrimitiveNode *node = new PrimitiveNode(inst, this->type);
|
PrimitiveNode *node = new PrimitiveNode(inst, this->type);
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,10 @@ class ProjectionModule : public AbstractModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectionModule() { }
|
ProjectionModule() { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
ProjectionNode *node = new ProjectionNode(inst);
|
ProjectionNode *node = new ProjectionNode(inst);
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
Value convexity = c.lookup_variable("convexity", true);
|
Value convexity = c.lookup_variable("convexity", true);
|
||||||
Value cut = c.lookup_variable("cut", true);
|
Value cut = c.lookup_variable("cut", true);
|
||||||
|
|
|
@ -38,10 +38,10 @@ class RenderModule : public AbstractModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderModule() { }
|
RenderModule() { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
RenderNode *node = new RenderNode(inst);
|
RenderNode *node = new RenderNode(inst);
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
Value v = c.lookup_variable("convexity");
|
Value v = c.lookup_variable("convexity");
|
||||||
if (v.type() == Value::NUMBER)
|
if (v.type() == Value::NUMBER)
|
||||||
|
|
|
@ -44,10 +44,10 @@ class RotateExtrudeModule : public AbstractModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RotateExtrudeModule() { }
|
RotateExtrudeModule() { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
RotateExtrudeNode *node = new RotateExtrudeNode(inst);
|
RotateExtrudeNode *node = new RotateExtrudeNode(inst);
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
node->fn = c.lookup_variable("$fn").toDouble();
|
node->fn = c.lookup_variable("$fn").toDouble();
|
||||||
node->fs = c.lookup_variable("$fs").toDouble();
|
node->fs = c.lookup_variable("$fs").toDouble();
|
||||||
|
|
|
@ -52,7 +52,7 @@ class SurfaceModule : public AbstractModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SurfaceModule() { }
|
SurfaceModule() { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::unordered_map<std::pair<int,int>,double> img_data_t;
|
typedef boost::unordered_map<std::pair<int,int>,double> img_data_t;
|
||||||
|
@ -80,7 +80,7 @@ private:
|
||||||
img_data_t read_png_or_dat(std::string filename) const;
|
img_data_t read_png_or_dat(std::string filename) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
SurfaceNode *node = new SurfaceNode(inst);
|
SurfaceNode *node = new SurfaceNode(inst);
|
||||||
node->center = false;
|
node->center = false;
|
||||||
|
|
|
@ -41,10 +41,10 @@ class TextModule : public AbstractModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextModule() : AbstractModule(Feature::ExperimentalTextModule) { }
|
TextModule() : AbstractModule(Feature::ExperimentalTextModule) { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *TextModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *TextModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
TextNode *node = new TextNode(inst);
|
TextNode *node = new TextNode(inst);
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,10 @@ class TransformModule : public AbstractModule
|
||||||
public:
|
public:
|
||||||
transform_type_e type;
|
transform_type_e type;
|
||||||
TransformModule(transform_type_e type) : type(type) { }
|
TransformModule(transform_type_e type) : type(type) { }
|
||||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
|
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
|
AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
TransformNode *node = new TransformNode(inst);
|
TransformNode *node = new TransformNode(inst);
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
|
||||||
|
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.setVariables(args, evalctx);
|
c.setVariables(args, evalctx);
|
||||||
|
evalctx->applyScope();
|
||||||
|
|
||||||
if (this->type == SCALE)
|
if (this->type == SCALE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
echo("union scope");
|
||||||
|
a = 4;
|
||||||
|
union() {
|
||||||
|
a = 5;
|
||||||
|
echo("local a (5):", a);
|
||||||
|
}
|
||||||
|
echo("global a (4):", a);
|
||||||
|
|
||||||
|
|
||||||
|
echo("module scope:");
|
||||||
|
module mymodule(b=6) {
|
||||||
|
b = 7;
|
||||||
|
echo("local b (7)", b);
|
||||||
|
}
|
||||||
|
mymodule();
|
||||||
|
mymodule(8);
|
||||||
|
|
||||||
|
|
||||||
|
echo("module children scope:");
|
||||||
|
module mymodule2(b2=6) {
|
||||||
|
b2 = 2;
|
||||||
|
children(0);
|
||||||
|
}
|
||||||
|
mymodule2(b2=7) {
|
||||||
|
b2 = 3;
|
||||||
|
echo("b2 (3)", b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("for loop (c = 0,1,25):");
|
||||||
|
for (i=[0:2]) {
|
||||||
|
c = (i > 1) ? i + 23 : i;
|
||||||
|
echo("c", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("anonymous inner scope (scope ignored):");
|
||||||
|
union() {
|
||||||
|
e = 2;
|
||||||
|
echo("outer e (3)", e);
|
||||||
|
{
|
||||||
|
e = 3;
|
||||||
|
echo("inner e (3)", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("anonymous scope (scope ignored):");
|
||||||
|
f=1;
|
||||||
|
echo("outer f (2)", f);
|
||||||
|
{
|
||||||
|
f=2;
|
||||||
|
echo("inner f (2)", f);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("anonymous scope reassign:");
|
||||||
|
{
|
||||||
|
g=1;
|
||||||
|
echo("g (2)", g);
|
||||||
|
g=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("anonymous reassign using outer (scope ignored)", h);
|
||||||
|
h=5;
|
||||||
|
{
|
||||||
|
h=h*2; // Not allowed
|
||||||
|
echo("h (undef)", h);
|
||||||
|
}
|
|
@ -1046,6 +1046,7 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES}
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad
|
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad
|
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/variable-scope-tests.scad
|
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/variable-scope-tests.scad
|
||||||
|
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/scope-assignment-tests.scad
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/lookup-tests.scad
|
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/lookup-tests.scad
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/expression-shortcircuit-tests.scad
|
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/expression-shortcircuit-tests.scad
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/parent_module-tests.scad
|
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/parent_module-tests.scad
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
WARNING: Ignoring unknown variable 'h'.
|
||||||
|
ECHO: "union scope"
|
||||||
|
ECHO: "local a (5):", 5
|
||||||
|
ECHO: "global a (4):", 4
|
||||||
|
ECHO: "module scope:"
|
||||||
|
ECHO: "local b (7)", 7
|
||||||
|
ECHO: "local b (7)", 7
|
||||||
|
ECHO: "module children scope:"
|
||||||
|
ECHO: "b2 (3)", 3
|
||||||
|
ECHO: "for loop (c = 0,1,25):"
|
||||||
|
ECHO: "c", 0
|
||||||
|
ECHO: "c", 1
|
||||||
|
ECHO: "c", 25
|
||||||
|
ECHO: "anonymous inner scope (scope ignored):"
|
||||||
|
ECHO: "outer e (3)", 3
|
||||||
|
ECHO: "inner e (3)", 3
|
||||||
|
ECHO: "anonymous scope (scope ignored):"
|
||||||
|
ECHO: "outer f (2)", 2
|
||||||
|
ECHO: "inner f (2)", 2
|
||||||
|
ECHO: "anonymous scope reassign:"
|
||||||
|
ECHO: "g (2)", 2
|
||||||
|
ECHO: "anonymous reassign using outer (scope ignored)", undef
|
||||||
|
ECHO: "h (undef)", undef
|
Loading…
Reference in New Issue