Merge remote-tracking branch 'origin/master' into stack-size-hack

Conflicts:
	src/context.h
	src/control.cc
	src/evalcontext.h
	src/localscope.cc
	src/module.cc
master
Marius Kintel 2014-11-25 11:25:37 -05:00
commit 4cd712d24d
32 changed files with 255 additions and 87 deletions

View File

@ -6,6 +6,7 @@
* min() and max() can now take a wvector argument
* concat()
* 2D minkowski and holes
* chr()
**Program Features:**
* Added --viewall cmd-line parameter
@ -14,6 +15,12 @@
* Qt5, retina
* SVG import/export
* AMF import/export
* Color schemes for viewer and editor can be user-edited
* Improved editor
* Splash screen
* Docking of GUI components
* Toolbar
* More robust STL export
**Bugfixes/improvements:**
* Internal cavity fix

View File

@ -77,11 +77,12 @@ void Builtins::initialize()
register_builtin_dxf_rotate_extrude();
register_builtin_text();
this->deprecations["dxf_linear_extrude"] = "linear_extrude";
this->deprecations["dxf_rotate_extrude"] = "rotate_extrude";
this->deprecations["import_stl"] = "import";
this->deprecations["import_dxf"] = "import";
this->deprecations["import_off"] = "import";
this->deprecations["dxf_linear_extrude"] = "linear_extrude()";
this->deprecations["dxf_rotate_extrude"] = "rotate_extrude()";
this->deprecations["import_stl"] = "import()";
this->deprecations["import_dxf"] = "import()";
this->deprecations["import_off"] = "import()";
this->deprecations["assign"] = "a regular assignment";
}
std::string Builtins::isDeprecated(const std::string &name)

View File

@ -39,10 +39,10 @@ class CgaladvModule : public AbstractModule
public:
cgaladv_type_e 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);
@ -62,6 +62,7 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
ValuePtr convexity = ValuePtr::undefined;
ValuePtr path = ValuePtr::undefined;

View File

@ -42,7 +42,7 @@ class ColorModule : public AbstractModule
public:
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:
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);
@ -218,6 +218,7 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
ValuePtr v = c.lookup_variable("c");
if (v->type() == Value::VECTOR) {

View File

@ -167,7 +167,7 @@ ValuePtr Context::evaluate_function(const std::string &name, const EvalContext *
return ValuePtr::undefined;
}
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);
print_ignore_warning("module", inst.name().c_str());

View File

@ -16,7 +16,7 @@ public:
const Context *getParent() const { return this->parent; }
virtual ValuePtr 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,
const class EvalContext *evalctx = NULL);

View File

@ -29,6 +29,7 @@
#include "node.h"
#include "evalcontext.h"
#include "modcontext.h"
#include "expression.h"
#include "builtin.h"
#include "printutils.h"
#include <sstream>
@ -55,7 +56,7 @@ public: // methods
: 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,
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);
}
} 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());
}
}
@ -155,12 +163,12 @@ AbstractNode* ControlModule::getChild(const Value& value, const EvalContext* mod
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;
if (type == CHILD)
{
switch (this->type) {
case CHILD: {
printDeprecation("DEPRECATED: child() will be removed in future releases. Use children() instead.");
int n = 0;
if (evalctx->numArgs() > 0) {
@ -192,9 +200,9 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
}
return node;
}
break;
if (type == CHILDREN)
{
case CHILDREN: {
const EvalContext *modulectx = getLastModuleCtx(evalctx);
if (modulectx==NULL) {
return NULL;
@ -251,14 +259,10 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
}
return NULL;
}
break;
if (type == INT_FOR)
node = new AbstractIntersectionNode(inst);
else
case ECHO: {
node = new AbstractNode(inst);
if (type == ECHO)
{
std::stringstream msg;
msg << "ECHO: ";
for (size_t i = 0; i < inst->arguments.size(); i++) {
@ -273,36 +277,50 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
}
PRINTB("%s", msg.str());
}
break;
if (type == ASSIGN)
{
case ASSIGN: {
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);
for (size_t i = 0; i < evalctx->numArgs(); i++) {
if (!evalctx->getArgName(i).empty())
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);
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);
}
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);
if (evalctx->numArgs() > 0 && evalctx->getArgValue(0)->toBool()) {
inst->scope.apply(*evalctx);
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
}
else {
ifelse->else_scope.apply(*evalctx);
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateElseChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
}
}
break;
}
return node;
}

View File

@ -38,11 +38,12 @@ class CsgModule : public AbstractModule
public:
OpenSCADOperator 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
{
inst->scope.apply(*evalctx);
CsgNode *node = new CsgNode(inst, type);
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());

View File

@ -9,6 +9,12 @@
#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
{
assert(i < this->eval_arguments.size());

View File

@ -12,8 +12,7 @@ public:
typedef std::vector<class ModuleInstantiation *> InstanceList;
EvalContext(const Context *parent,
const AssignmentList &args, const class LocalScope *const scope = NULL)
: Context(parent), eval_arguments(args), scope(scope) {}
const AssignmentList &args, const class LocalScope *const scope = NULL);
virtual ~EvalContext() {}
size_t numArgs() const { return this->eval_arguments.size(); }
@ -29,6 +28,5 @@ public:
private:
const AssignmentList &eval_arguments;
std::vector<std::pair<std::string, ValuePtr> > eval_values;
const LocalScope *const scope;
};

View File

@ -61,10 +61,10 @@ class ImportModule : public AbstractModule
public:
import_type_e 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;
args += Assignment("file"), Assignment("layer"), Assignment("convexity"), Assignment("origin"), Assignment("scale");

View File

@ -46,10 +46,10 @@ class LinearExtrudeModule : public AbstractModule
{
public:
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);
@ -58,6 +58,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs")->toDouble();

View File

@ -42,13 +42,28 @@ std::string LocalScope::dump(const std::string &indent) const
return dump.str();
}
std::vector<AbstractNode*> LocalScope::instantiateChildren(const Context *evalctx, FileContext *filectx) 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) const
{
std::vector<AbstractNode*> childnodes;
BOOST_FOREACH (ModuleInstantiation *modinst, this->children) {
AbstractNode *node = modinst->evaluate(filectx ? filectx : evalctx);
AbstractNode *node = modinst->evaluate(evalctx);
if (node) childnodes.push_back(node);
}
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));
}
}

View File

@ -11,8 +11,9 @@ public:
size_t numElements() const { return assignments.size() + children.size(); }
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 apply(Context &ctx) const;
AssignmentList assignments;
ModuleInstantiationList children;

View File

@ -71,6 +71,7 @@ void ModuleContext::initializeModule(const class Module &module)
BOOST_FOREACH(const Assignment &ass, module.scope.assignments) {
this->set_variable(ass.first, ass.second->evaluate(this));
}
// Experimental code. See issue #399
// evaluateAssignments(module.scope.assignments);
}
@ -115,7 +116,7 @@ const AbstractModule *ModuleContext::findLocalModule(const std::string &name) co
}
std::string replacement = Builtins::instance()->isDeprecated(name);
if (!replacement.empty()) {
PRINT_DEPRECATION("DEPRECATED: The %s() module will be removed in future releases. Use %s() instead.", name % replacement);
PRINT_DEPRECATION("DEPRECATED: The %s() module will be removed in future releases. Use %s instead.", name % replacement);
}
return m;
}
@ -131,7 +132,7 @@ ValuePtr ModuleContext::evaluate_function(const std::string &name,
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());
if (foundm) return foundm->instantiate(this, &inst, evalctx);
@ -209,7 +210,7 @@ ValuePtr FileContext::evaluate_function(const std::string &name,
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());
if (foundm) return foundm->instantiate(this, &inst, evalctx);

View File

@ -21,7 +21,7 @@ public:
virtual ValuePtr evaluate_function(const std::string &name,
const EvalContext *evalctx) const;
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
const EvalContext *evalctx) const;
EvalContext *evalctx) const;
const AbstractModule *findLocalModule(const std::string &name) const;
const AbstractFunction *findLocalFunction(const std::string &name) const;
@ -48,7 +48,7 @@ public:
virtual ValuePtr evaluate_function(const std::string &name,
const EvalContext *evalctx) const;
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
const EvalContext *evalctx) const;
EvalContext *evalctx) const;
private:
const FileModule::ModuleContainer &usedlibs;

View File

@ -48,7 +48,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
@ -173,13 +173,17 @@ Module::~Module()
{
}
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
{
if (StackCheck::inst()->check()) {
throw RecursionException("module", inst->name());
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
inst->scope.apply(*evalctx);
ModuleContext c(ctx, evalctx);
// set $children first since we might have variables depending on it
c.set_variable("$children", ValuePtr(double(inst->scope.children.size())));
@ -329,7 +333,7 @@ bool FileModule::handleDependencies()
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);
FileContext c(*this, ctx);
@ -341,7 +345,7 @@ AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiat
AbstractNode *node = new AbstractNode(inst);
try {
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());
}
catch (RecursionException &e) {

View File

@ -67,7 +67,7 @@ public:
virtual ~AbstractModule();
virtual bool is_experimental() const { return feature != NULL; }
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 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;
@ -80,7 +80,7 @@ public:
Module(const Feature& feature) : AbstractModule(feature) { }
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;
static const std::string& stack_element(int n) { return module_stack[n]; };
static int stack_size() { return module_stack.size(); };
@ -107,7 +107,7 @@ public:
void registerInclude(const std::string &localpath, const std::string &fullpath);
bool includesChanged() const;
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 usesLibraries() const { return !this->usedlibs.empty(); }
bool isHandlingDependencies() const { return this->is_handling_dependencies; }

View File

@ -46,10 +46,10 @@ class OffsetModule : public AbstractModule
{
public:
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);
@ -58,6 +58,7 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs")->toDouble();

View File

@ -270,6 +270,7 @@ if_statement:
child_statements:
/* empty */
| child_statements child_statement
| child_statements assignment
;
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
module_id:
TOK_ID { $$ = $1; }

View File

@ -61,7 +61,7 @@ class PrimitiveModule : public AbstractModule
public:
primitive_type_e 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:
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);

View File

@ -41,10 +41,10 @@ class ProjectionModule : public AbstractModule
{
public:
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);
@ -53,6 +53,7 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
ValuePtr convexity = c.lookup_variable("convexity", true);
ValuePtr cut = c.lookup_variable("cut", true);

View File

@ -38,10 +38,10 @@ class RenderModule : public AbstractModule
{
public:
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);
@ -50,6 +50,7 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
ValuePtr v = c.lookup_variable("convexity");
if (v->type() == Value::NUMBER)

View File

@ -44,10 +44,10 @@ class RotateExtrudeModule : public AbstractModule
{
public:
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);
@ -56,6 +56,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs")->toDouble();

View File

@ -52,7 +52,7 @@ class SurfaceModule : public AbstractModule
{
public:
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;
@ -80,7 +80,7 @@ private:
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);
node->center = false;

View File

@ -41,10 +41,10 @@ class TextModule : public AbstractModule
{
public:
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);

View File

@ -50,10 +50,10 @@ class TransformModule : public AbstractModule
public:
transform_type_e 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);
@ -83,6 +83,7 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
Context c(ctx);
c.setVariables(args, evalctx);
inst->scope.apply(*evalctx);
if (this->type == SCALE)
{

View File

@ -0,0 +1,85 @@
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("if scope:");
if (true) {
d = 8;
echo("d (8)", d);
}
echo("else scope:");
if (false) {
} else {
d = 9;
echo("d (9)", d);
}
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);
}
echo("override variable in assign scope:");
assign(i=9) {
i=10;
echo("i (10)", i);
}

View File

@ -2,16 +2,13 @@
//Helper function that pretty prints our search test
//Expected result is checked against execution of a search() invocation and OK/FAIL is indicated
module test_search_and_echo( exp_res, search_to_find, search_to_search, search_up_to_num_matches = undef)
{
if(undef != search_up_to_num_matches)
{
assign( test_res = search(search_to_find, search_to_search, search_up_to_num_matches) )
module test_search_and_echo( exp_res, search_to_find, search_to_search, search_up_to_num_matches = undef) {
if (undef != search_up_to_num_matches) {
test_res = search(search_to_find, search_to_search, search_up_to_num_matches);
echo(str("Expect ", exp_res, " for search(", search_to_find, ", ", search_to_search, ", ", search_up_to_num_matches, ")=", test_res, ". ", (exp_res == test_res)?"OK":"FAIL" ));
}
else
{
assign( test_res = search(search_to_find, search_to_search) )
else {
test_res = search(search_to_find, search_to_search);
echo(str("Expect ", exp_res, " for search(", search_to_find, ", ", search_to_search, ")=", test_res, ". ", (exp_res == test_res)?"OK":"FAIL" ));
}
}

View File

@ -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-tests2.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/expression-shortcircuit-tests.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/parent_module-tests.scad

View File

@ -0,0 +1,30 @@
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: "if scope:"
ECHO: "d (8)", 8
ECHO: "else scope:"
ECHO: "d (9)", 9
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
ECHO: "override variable in assign scope:"
DEPRECATED: The assign() module will be removed in future releases. Use a regular assignment instead.
ECHO: "i (10)", 10

View File

@ -18,6 +18,7 @@ ECHO: "user-defined special variables as parameter"
ECHO: 7
ECHO: 7
ECHO: "assign only visible in children's scope"
DEPRECATED: The assign() module will be removed in future releases. Use a regular assignment instead.
WARNING: Ignoring unknown variable 'c'.
ECHO: undef
ECHO: 5