mirror of https://github.com/vitalif/openscad
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.ccmaster
commit
4cd712d24d
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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" ));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue