mirror of https://github.com/vitalif/openscad
Some cleanup of the Context class
parent
16b74df941
commit
f58c0a3eb5
137
src/context.cc
137
src/context.cc
|
@ -33,15 +33,30 @@
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
Context::Context(const Context *parent)
|
std::vector<const Context*> Context::ctx_stack;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Initializes this context. Optionally initializes a context for an external library
|
||||||
|
*/
|
||||||
|
Context::Context(const Context *parent, const Module *library)
|
||||||
|
: parent(parent), inst_p(NULL)
|
||||||
{
|
{
|
||||||
this->parent = parent;
|
|
||||||
functions_p = NULL;
|
|
||||||
modules_p = NULL;
|
|
||||||
usedlibs_p = NULL;
|
|
||||||
inst_p = NULL;
|
|
||||||
if (parent) document_path = parent->document_path;
|
|
||||||
ctx_stack.push_back(this);
|
ctx_stack.push_back(this);
|
||||||
|
if (parent) document_path = parent->document_path;
|
||||||
|
if (library) {
|
||||||
|
this->functions_p = &library->functions;
|
||||||
|
this->modules_p = &library->modules;
|
||||||
|
this->usedlibs_p = &library->usedlibs;
|
||||||
|
for (size_t j = 0; j < library->assignments_var.size(); j++) {
|
||||||
|
this->set_variable(library->assignments_var[j],
|
||||||
|
library->assignments_expr[j]->evaluate(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
functions_p = NULL;
|
||||||
|
modules_p = NULL;
|
||||||
|
usedlibs_p = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context::~Context()
|
Context::~Context()
|
||||||
|
@ -49,11 +64,17 @@ Context::~Context()
|
||||||
ctx_stack.pop_back();
|
ctx_stack.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::args(const std::vector<std::string> &argnames, const std::vector<Expression*> &argexpr,
|
/*!
|
||||||
const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues)
|
Initialize context from argument lists (function call/module instantiation)
|
||||||
|
*/
|
||||||
|
void Context::args(const std::vector<std::string> &argnames,
|
||||||
|
const std::vector<Expression*> &argexpr,
|
||||||
|
const std::vector<std::string> &call_argnames,
|
||||||
|
const std::vector<Value> &call_argvalues)
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<argnames.size(); i++) {
|
for (size_t i=0; i<argnames.size(); i++) {
|
||||||
set_variable(argnames[i], i < argexpr.size() && argexpr[i] ? argexpr[i]->evaluate(this->parent) : Value());
|
set_variable(argnames[i], i < argexpr.size() && argexpr[i] ?
|
||||||
|
argexpr[i]->evaluate(this->parent) : Value());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t posarg = 0;
|
size_t posarg = 0;
|
||||||
|
@ -67,14 +88,20 @@ void Context::args(const std::vector<std::string> &argnames, const std::vector<E
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const Context*> Context::ctx_stack;
|
void Context::set_variable(const std::string &name, const Value &value)
|
||||||
|
|
||||||
void Context::set_variable(const std::string &name, Value value)
|
|
||||||
{
|
{
|
||||||
if (name[0] == '$')
|
if (name[0] == '$')
|
||||||
config_variables[name] = value;
|
this->config_variables[name] = value;
|
||||||
else
|
else
|
||||||
variables[name] = value;
|
this->variables[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Context::set_constant(const std::string &name, const Value &value)
|
||||||
|
{
|
||||||
|
if (this->constants.find(name) != this->constants.end())
|
||||||
|
PRINTF("WARNING: Attempt to modify constant '%s'.",name.c_str());
|
||||||
|
else
|
||||||
|
this->constants[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Context::lookup_variable(const std::string &name, bool silent) const
|
Value Context::lookup_variable(const std::string &name, bool silent) const
|
||||||
|
@ -87,79 +114,58 @@ Value Context::lookup_variable(const std::string &name, bool silent) const
|
||||||
}
|
}
|
||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
if (!parent && constants.find(name) != constants.end())
|
if (!this->parent && this->constants.find(name) != this->constants.end())
|
||||||
return constants.find(name)->second;
|
return this->constants.find(name)->second;
|
||||||
if (variables.find(name) != variables.end())
|
if (this->variables.find(name) != this->variables.end())
|
||||||
return variables.find(name)->second;
|
return this->variables.find(name)->second;
|
||||||
if (parent)
|
if (this->parent)
|
||||||
return parent->lookup_variable(name, silent);
|
return this->parent->lookup_variable(name, silent);
|
||||||
if (!silent)
|
if (!silent)
|
||||||
PRINTF("WARNING: Ignoring unknown variable '%s'.", name.c_str());
|
PRINTF("WARNING: Ignoring unknown variable '%s'.", name.c_str());
|
||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::set_constant(const std::string &name, Value value)
|
Value Context::evaluate_function(const std::string &name,
|
||||||
|
const std::vector<std::string> &argnames,
|
||||||
|
const std::vector<Value> &argvalues) const
|
||||||
{
|
{
|
||||||
if (constants.count(name))
|
if (this->functions_p && this->functions_p->find(name) != this->functions_p->end())
|
||||||
PRINTF("WARNING: Attempt to modify constant '%s'.",name.c_str());
|
return this->functions_p->find(name)->second->evaluate(this, argnames, argvalues);
|
||||||
else
|
if (this->usedlibs_p) {
|
||||||
constants[name] = value;
|
BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) {
|
||||||
}
|
if (m.second->functions.find(name) != m.second->functions.end()) {
|
||||||
|
Context ctx(this->parent, m.second);
|
||||||
Value Context::evaluate_function(const std::string &name, const std::vector<std::string> &argnames, const std::vector<Value> &argvalues) const
|
|
||||||
{
|
|
||||||
if (functions_p && functions_p->find(name) != functions_p->end())
|
|
||||||
return functions_p->find(name)->second->evaluate(this, argnames, argvalues);
|
|
||||||
if (usedlibs_p) {
|
|
||||||
BOOST_FOREACH(const ModuleContainer::value_type &m, *usedlibs_p) {
|
|
||||||
if (m.second->functions.count(name)) {
|
|
||||||
Module *lib = m.second;
|
|
||||||
Context ctx(parent);
|
|
||||||
ctx.functions_p = &lib->functions;
|
|
||||||
ctx.modules_p = &lib->modules;
|
|
||||||
ctx.usedlibs_p = &lib->usedlibs;
|
|
||||||
for (size_t j = 0; j < lib->assignments_var.size(); j++) {
|
|
||||||
ctx.set_variable(lib->assignments_var[j], lib->assignments_expr[j]->evaluate(&ctx));
|
|
||||||
}
|
|
||||||
return m.second->functions[name]->evaluate(&ctx, argnames, argvalues);
|
return m.second->functions[name]->evaluate(&ctx, argnames, argvalues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parent)
|
if (this->parent)
|
||||||
return parent->evaluate_function(name, argnames, argvalues);
|
return this->parent->evaluate_function(name, argnames, argvalues);
|
||||||
PRINTF("WARNING: Ignoring unkown function '%s'.", name.c_str());
|
PRINTF("WARNING: Ignoring unknown function '%s'.", name.c_str());
|
||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractNode *Context::evaluate_module(const ModuleInstantiation *inst) const
|
AbstractNode *Context::evaluate_module(const ModuleInstantiation &inst) const
|
||||||
{
|
{
|
||||||
if (modules_p && modules_p->find(inst->modname) != modules_p->end())
|
if (this->modules_p && this->modules_p->find(inst.modname) != this->modules_p->end())
|
||||||
return modules_p->find(inst->modname)->second->evaluate(this, inst);
|
return this->modules_p->find(inst.modname)->second->evaluate(this, &inst);
|
||||||
if (usedlibs_p) {
|
if (this->usedlibs_p) {
|
||||||
BOOST_FOREACH(const ModuleContainer::value_type &m, *usedlibs_p) {
|
BOOST_FOREACH(const ModuleContainer::value_type &m, *this->usedlibs_p) {
|
||||||
if (m.second->modules.count(inst->modname)) {
|
if (m.second->modules.find(inst.modname) != m.second->modules.end()) {
|
||||||
Module *lib = m.second;
|
Context ctx(this->parent, m.second);
|
||||||
Context ctx(parent);
|
return m.second->modules[inst.modname]->evaluate(&ctx, &inst);
|
||||||
ctx.functions_p = &lib->functions;
|
|
||||||
ctx.modules_p = &lib->modules;
|
|
||||||
ctx.usedlibs_p = &lib->usedlibs;
|
|
||||||
for (size_t j = 0; j < lib->assignments_var.size(); j++) {
|
|
||||||
ctx.set_variable(lib->assignments_var[j], lib->assignments_expr[j]->evaluate(&ctx));
|
|
||||||
}
|
|
||||||
return m.second->modules[inst->modname]->evaluate(&ctx, inst);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parent)
|
if (this->parent) return this->parent->evaluate_module(inst);
|
||||||
return parent->evaluate_module(inst);
|
PRINTF("WARNING: Ignoring unknown module '%s'.", inst.modname.c_str());
|
||||||
PRINTF("WARNING: Ignoring unkown module '%s'.", inst->modname.c_str());
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the absolute path to the given filename, unless it's empty.
|
Returns the absolute path to the given filename, unless it's empty.
|
||||||
*/
|
*/
|
||||||
std::string Context::get_absolute_path(const std::string &filename) const
|
std::string Context::getAbsolutePath(const std::string &filename) const
|
||||||
{
|
{
|
||||||
if (!filename.empty()) {
|
if (!filename.empty()) {
|
||||||
return QFileInfo(QDir(QString::fromStdString(this->document_path)),
|
return QFileInfo(QDir(QString::fromStdString(this->document_path)),
|
||||||
|
@ -169,4 +175,3 @@ std::string Context::get_absolute_path(const std::string &filename) const
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,35 +10,43 @@ using boost::unordered_map;
|
||||||
|
|
||||||
class Context
|
class Context
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Context(const Context *parent = NULL, const class Module *library = NULL);
|
||||||
|
~Context();
|
||||||
|
|
||||||
|
void args(const std::vector<std::string> &argnames,
|
||||||
|
const std::vector<class Expression*> &argexpr,
|
||||||
|
const std::vector<std::string> &call_argnames,
|
||||||
|
const std::vector<Value> &call_argvalues);
|
||||||
|
|
||||||
|
void set_variable(const std::string &name, const Value &value);
|
||||||
|
void set_constant(const std::string &name, const Value &value);
|
||||||
|
|
||||||
|
Value lookup_variable(const std::string &name, bool silent = false) const;
|
||||||
|
Value evaluate_function(const std::string &name,
|
||||||
|
const std::vector<std::string> &argnames,
|
||||||
|
const std::vector<Value> &argvalues) const;
|
||||||
|
class AbstractNode *evaluate_module(const class ModuleInstantiation &inst) const;
|
||||||
|
|
||||||
|
void setDocumentPath(const std::string &path) { this->document_path = path; }
|
||||||
|
std::string getAbsolutePath(const std::string &filename) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const Context *parent;
|
const Context *parent;
|
||||||
typedef unordered_map<std::string, Value> ValueMap;
|
|
||||||
ValueMap constants;
|
|
||||||
ValueMap variables;
|
|
||||||
ValueMap config_variables;
|
|
||||||
const unordered_map<std::string, class AbstractFunction*> *functions_p;
|
const unordered_map<std::string, class AbstractFunction*> *functions_p;
|
||||||
const unordered_map<std::string, class AbstractModule*> *modules_p;
|
const unordered_map<std::string, class AbstractModule*> *modules_p;
|
||||||
typedef unordered_map<std::string, class Module*> ModuleContainer;
|
typedef unordered_map<std::string, class Module*> ModuleContainer;
|
||||||
const ModuleContainer *usedlibs_p;
|
const ModuleContainer *usedlibs_p;
|
||||||
const class ModuleInstantiation *inst_p;
|
const ModuleInstantiation *inst_p;
|
||||||
std::string document_path;
|
|
||||||
|
|
||||||
static std::vector<const Context*> ctx_stack;
|
static std::vector<const Context*> ctx_stack;
|
||||||
|
|
||||||
Context(const Context *parent = NULL);
|
private:
|
||||||
~Context();
|
typedef unordered_map<std::string, Value> ValueMap;
|
||||||
|
ValueMap constants;
|
||||||
void args(const std::vector<std::string> &argnames, const std::vector<class Expression*> &argexpr, const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues);
|
ValueMap variables;
|
||||||
|
ValueMap config_variables;
|
||||||
void set_variable(const std::string &name, Value value);
|
std::string document_path;
|
||||||
Value lookup_variable(const std::string &name, bool silent = false) const;
|
|
||||||
|
|
||||||
void set_constant(const std::string &name, Value value);
|
|
||||||
|
|
||||||
std::string get_absolute_path(const std::string &filename) const;
|
|
||||||
|
|
||||||
Value evaluate_function(const std::string &name, const std::vector<std::string> &argnames, const std::vector<Value> &argvalues) const;
|
|
||||||
class AbstractNode *evaluate_module(const ModuleInstantiation *inst) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,7 +51,7 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &argnam
|
||||||
|
|
||||||
for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
|
for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
|
||||||
if (argnames[i] == "file")
|
if (argnames[i] == "file")
|
||||||
filename = ctx->get_absolute_path(args[i].text);
|
filename = ctx->getAbsolutePath(args[i].text);
|
||||||
if (argnames[i] == "layer")
|
if (argnames[i] == "layer")
|
||||||
layername = args[i].text;
|
layername = args[i].text;
|
||||||
if (argnames[i] == "origin")
|
if (argnames[i] == "origin")
|
||||||
|
@ -135,7 +135,7 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector<std::string> &argn
|
||||||
|
|
||||||
for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
|
for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
|
||||||
if (argnames[i] == "file")
|
if (argnames[i] == "file")
|
||||||
filename = ctx->get_absolute_path(args[i].text);
|
filename = ctx->getAbsolutePath(args[i].text);
|
||||||
if (argnames[i] == "layer")
|
if (argnames[i] == "layer")
|
||||||
layername = args[i].text;
|
layername = args[i].text;
|
||||||
if (argnames[i] == "origin")
|
if (argnames[i] == "origin")
|
||||||
|
|
|
@ -77,7 +77,7 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI
|
||||||
Value slices = c.lookup_variable("slices", true);
|
Value slices = c.lookup_variable("slices", true);
|
||||||
|
|
||||||
if (!file.text.empty())
|
if (!file.text.empty())
|
||||||
node->filename = c.get_absolute_path(file.text);
|
node->filename = c.getAbsolutePath(file.text);
|
||||||
|
|
||||||
node->layername = layer.text;
|
node->layername = layer.text;
|
||||||
node->height = height.num;
|
node->height = height.num;
|
||||||
|
|
|
@ -71,7 +71,7 @@ AbstractNode *DxfRotateExtrudeModule::evaluate(const Context *ctx, const ModuleI
|
||||||
Value scale = c.lookup_variable("scale", true);
|
Value scale = c.lookup_variable("scale", true);
|
||||||
|
|
||||||
if (!file.text.empty())
|
if (!file.text.empty())
|
||||||
node->filename = c.get_absolute_path(file.text);
|
node->filename = c.getAbsolutePath(file.text);
|
||||||
|
|
||||||
node->layername = layer.text;
|
node->layername = layer.text;
|
||||||
node->convexity = (int)convexity.num;
|
node->convexity = (int)convexity.num;
|
||||||
|
|
|
@ -58,7 +58,9 @@ Function::~Function()
|
||||||
delete expr;
|
delete expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Function::evaluate(const Context *ctx, const std::vector<std::string> &call_argnames, const std::vector<Value> &call_argvalues) const
|
Value Function::evaluate(const Context *ctx,
|
||||||
|
const std::vector<std::string> &call_argnames,
|
||||||
|
const std::vector<Value> &call_argvalues) const
|
||||||
{
|
{
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.args(argnames, argexpr, call_argnames, call_argvalues);
|
c.args(argnames, argexpr, call_argnames, call_argvalues);
|
||||||
|
|
|
@ -82,8 +82,8 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati
|
||||||
node->fa = c.lookup_variable("$fa").num;
|
node->fa = c.lookup_variable("$fa").num;
|
||||||
|
|
||||||
Value v = c.lookup_variable("file");
|
Value v = c.lookup_variable("file");
|
||||||
node->filename = c.get_absolute_path(v.text);
|
node->filename = c.getAbsolutePath(v.text);
|
||||||
// node->filename = c.get_absolute_path(c.lookup_variable("file").text);
|
// node->filename = c.getAbsolutePath(c.lookup_variable("file").text);
|
||||||
node->layername = c.lookup_variable("layer", true).text;
|
node->layername = c.lookup_variable("layer", true).text;
|
||||||
node->convexity = c.lookup_variable("convexity", true).num;
|
node->convexity = c.lookup_variable("convexity", true).num;
|
||||||
|
|
||||||
|
|
|
@ -495,7 +495,7 @@ MainWindow::setFileName(const QString &filename)
|
||||||
{
|
{
|
||||||
if (filename.isEmpty()) {
|
if (filename.isEmpty()) {
|
||||||
this->fileName.clear();
|
this->fileName.clear();
|
||||||
this->root_ctx.document_path = currentdir.toStdString();
|
this->root_ctx.setDocumentPath(currentdir.toStdString());
|
||||||
setWindowTitle("OpenSCAD - New Document[*]");
|
setWindowTitle("OpenSCAD - New Document[*]");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -518,7 +518,7 @@ MainWindow::setFileName(const QString &filename)
|
||||||
this->fileName = fileinfo.fileName();
|
this->fileName = fileinfo.fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->root_ctx.document_path = fileinfo.dir().absolutePath().toStdString();
|
this->root_ctx.setDocumentPath(fileinfo.dir().absolutePath().toStdString());
|
||||||
QDir::setCurrent(fileinfo.dir().absolutePath());
|
QDir::setCurrent(fileinfo.dir().absolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const
|
||||||
{
|
{
|
||||||
AbstractNode *node = NULL;
|
AbstractNode *node = NULL;
|
||||||
if (this->ctx) {
|
if (this->ctx) {
|
||||||
PRINTF("WARNING: Ignoring recursive module instanciation of '%s'.", modname.c_str());
|
PRINTF("WARNING: Ignoring recursive module instantiation of '%s'.", modname.c_str());
|
||||||
} else {
|
} else {
|
||||||
ModuleInstantiation *that = (ModuleInstantiation*)this;
|
ModuleInstantiation *that = (ModuleInstantiation*)this;
|
||||||
that->argvalues.clear();
|
that->argvalues.clear();
|
||||||
|
@ -110,7 +110,7 @@ AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const
|
||||||
that->argvalues.push_back(v->evaluate(ctx));
|
that->argvalues.push_back(v->evaluate(ctx));
|
||||||
}
|
}
|
||||||
that->ctx = ctx;
|
that->ctx = ctx;
|
||||||
node = ctx->evaluate_module(this);
|
node = ctx->evaluate_module(*this);
|
||||||
that->ctx = NULL;
|
that->ctx = NULL;
|
||||||
that->argvalues.clear();
|
that->argvalues.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiat
|
||||||
Context c(ctx);
|
Context c(ctx);
|
||||||
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
|
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
|
||||||
|
|
||||||
node->filename = c.get_absolute_path(c.lookup_variable("file").text);
|
node->filename = c.getAbsolutePath(c.lookup_variable("file").text);
|
||||||
|
|
||||||
Value center = c.lookup_variable("center", true);
|
Value center = c.lookup_variable("center", true);
|
||||||
if (center.type == Value::BOOL) {
|
if (center.type == Value::BOOL) {
|
||||||
|
|
Loading…
Reference in New Issue