mirror of https://github.com/vitalif/openscad
bugfix: Correctly handle else scopes, handle overrides inside assign scopes
parent
d195d05008
commit
23c9dee265
|
@ -62,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
Value convexity, path, subdiv_type, level;
|
Value convexity, path, subdiv_type, level;
|
||||||
|
|
||||||
|
|
|
@ -218,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
Value v = c.lookup_variable("c");
|
Value v = c.lookup_variable("c");
|
||||||
if (v.type() == Value::VECTOR) {
|
if (v.type() == Value::VECTOR) {
|
||||||
|
|
|
@ -167,10 +167,6 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
{
|
{
|
||||||
AbstractNode *node = NULL;
|
AbstractNode *node = NULL;
|
||||||
|
|
||||||
if (this->type != FOR && this->type != INT_FOR) {
|
|
||||||
evalctx->applyScope();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this->type) {
|
switch (this->type) {
|
||||||
case CHILD: {
|
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.");
|
||||||
|
@ -285,11 +281,15 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
|
|
||||||
case ASSIGN: {
|
case ASSIGN: {
|
||||||
node = new AbstractNode(inst);
|
node = new AbstractNode(inst);
|
||||||
|
// We create a new context to avoid parameters from influencing each other
|
||||||
|
// -> parallel evaluation. This is to be backwards compatible.
|
||||||
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())
|
||||||
c.set_variable(evalctx->getArgName(i), evalctx->getArgValue(i));
|
c.set_variable(evalctx->getArgName(i), evalctx->getArgValue(i));
|
||||||
}
|
}
|
||||||
|
// Let any local variables override the parameters
|
||||||
|
inst->scope.apply(c);
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
@ -309,10 +309,12 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
|
||||||
node = new AbstractNode(inst);
|
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()) {
|
||||||
|
inst->scope.apply(*evalctx);
|
||||||
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
|
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
|
||||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
ifelse->else_scope.apply(*evalctx);
|
||||||
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateElseChildren(evalctx);
|
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateElseChildren(evalctx);
|
||||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
|
|
||||||
AbstractNode *CsgModule::instantiate(const Context*, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
AbstractNode *CsgModule::instantiate(const Context*, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||||
{
|
{
|
||||||
evalctx->applyScope();
|
inst->scope.apply(*evalctx);
|
||||||
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());
|
||||||
|
|
|
@ -37,22 +37,6 @@ 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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,8 +22,6 @@ 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
|
||||||
|
|
|
@ -58,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -54,3 +54,16 @@ std::vector<AbstractNode*> LocalScope::instantiateChildren(const Context *evalct
|
||||||
return childnodes;
|
return childnodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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 LocalScope::apply(Context &ctx) const
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const Assignment &ass, this->assignments) {
|
||||||
|
ctx.set_variable(ass.first, ass.second->evaluate(&ctx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ public:
|
||||||
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) const;
|
std::vector<class AbstractNode*> instantiateChildren(const class Context *evalctx) const;
|
||||||
void addChild(ModuleInstantiation *ch);
|
void addChild(ModuleInstantiation *ch);
|
||||||
|
void apply(Context &ctx) const;
|
||||||
|
|
||||||
AssignmentList assignments;
|
AssignmentList assignments;
|
||||||
ModuleInstantiationList children;
|
ModuleInstantiationList children;
|
||||||
|
|
|
@ -195,7 +195,7 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation
|
||||||
|
|
||||||
// At this point we know that nobody will modify the dependencies of the local scope
|
// 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
|
// passed to this instance, so we can populate the context
|
||||||
evalctx->applyScope();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -58,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -53,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -50,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
Value v = c.lookup_variable("convexity");
|
Value v = c.lookup_variable("convexity");
|
||||||
if (v.type() == Value::NUMBER)
|
if (v.type() == Value::NUMBER)
|
||||||
|
|
|
@ -56,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
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();
|
||||||
|
|
|
@ -83,7 +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();
|
inst->scope.apply(*evalctx);
|
||||||
|
|
||||||
if (this->type == SCALE)
|
if (this->type == SCALE)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue