diff --git a/src/builtin.cc b/src/builtin.cc index c20f9f03..b04d2b53 100644 --- a/src/builtin.cc +++ b/src/builtin.cc @@ -94,19 +94,19 @@ std::string Builtins::isDeprecated(const std::string &name) Builtins::Builtins() { - this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr(new Expression(Value(0.0))))); - this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr(new Expression(Value(2.0))))); - this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr(new Expression(Value(12.0))))); - this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr(new Expression(Value(0.0))))); + this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr(new Expression(ValuePtr(0.0))))); + this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr(new Expression(ValuePtr(2.0))))); + this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr(new Expression(ValuePtr(12.0))))); + this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr(new Expression(ValuePtr(0.0))))); Value::VectorType zero3; zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0)); - Value zero3val(zero3); + ValuePtr zero3val(zero3); this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr(new Expression(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr(new Expression(zero3val)))); - this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr(new Expression(500)))); + this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr(new Expression(ValuePtr(500))))); } Builtins::~Builtins() diff --git a/src/cgaladv.cc b/src/cgaladv.cc index c6c66ff6..55610621 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -63,8 +63,11 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant Context c(ctx); c.setVariables(args, evalctx); - Value convexity, path, subdiv_type, level; - + ValuePtr convexity = ValuePtr::undefined; + ValuePtr path = ValuePtr::undefined; + ValuePtr subdiv_type = ValuePtr::undefined; + ValuePtr level = ValuePtr::undefined; + if (type == MINKOWSKI) { convexity = c.lookup_variable("convexity", true); } @@ -81,31 +84,31 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant } if (type == RESIZE) { - Value ns = c.lookup_variable("newsize"); + ValuePtr ns = c.lookup_variable("newsize"); node->newsize << 0,0,0; - if ( ns.type() == Value::VECTOR ) { - Value::VectorType vs = ns.toVector(); + if ( ns->type() == Value::VECTOR ) { + const Value::VectorType &vs = ns->toVector(); if ( vs.size() >= 1 ) node->newsize[0] = vs[0].toDouble(); if ( vs.size() >= 2 ) node->newsize[1] = vs[1].toDouble(); if ( vs.size() >= 3 ) node->newsize[2] = vs[2].toDouble(); } - Value autosize = c.lookup_variable("auto"); + ValuePtr autosize = c.lookup_variable("auto"); node->autosize << false, false, false; - if ( autosize.type() == Value::VECTOR ) { - Value::VectorType va = autosize.toVector(); + if ( autosize->type() == Value::VECTOR ) { + const Value::VectorType &va = autosize->toVector(); if ( va.size() >= 1 ) node->autosize[0] = va[0].toBool(); if ( va.size() >= 2 ) node->autosize[1] = va[1].toBool(); if ( va.size() >= 3 ) node->autosize[2] = va[2].toBool(); } - else if ( autosize.type() == Value::BOOL ) { - node->autosize << autosize.toBool(),autosize.toBool(),autosize.toBool(); + else if ( autosize->type() == Value::BOOL ) { + node->autosize << autosize->toBool(),autosize->toBool(),autosize->toBool(); } } - node->convexity = (int)convexity.toDouble(); + node->convexity = (int)convexity->toDouble(); node->path = path; - node->subdiv_type = subdiv_type.toString(); - node->level = (int)level.toDouble(); + node->subdiv_type = subdiv_type->toString(); + node->level = (int)level->toDouble(); if (node->level <= 1) node->level = 1; @@ -150,7 +153,7 @@ std::string CgaladvNode::toString() const stream << "(convexity = " << this->convexity << ")"; break; case GLIDE: - stream << "(path = " << this->path << ", convexity = " << this->convexity << ")"; + stream << "(path = " << *this->path << ", convexity = " << this->convexity << ")"; break; case SUBDIV: stream << "(level = " << this->level << ", convexity = " << this->convexity << ")"; diff --git a/src/cgaladvnode.h b/src/cgaladvnode.h index 6794ae90..a2f81fe7 100644 --- a/src/cgaladvnode.h +++ b/src/cgaladvnode.h @@ -26,7 +26,7 @@ public: virtual std::string toString() const; virtual std::string name() const; - Value path; + ValuePtr path; std::string subdiv_type; int convexity, level; Vector3d newsize; diff --git a/src/color.cc b/src/color.cc index 7792f0bf..ced7a0b9 100644 --- a/src/color.cc +++ b/src/color.cc @@ -219,15 +219,15 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia Context c(ctx); c.setVariables(args, evalctx); - Value v = c.lookup_variable("c"); - if (v.type() == Value::VECTOR) { + ValuePtr v = c.lookup_variable("c"); + if (v->type() == Value::VECTOR) { for (size_t i = 0; i < 4; i++) { - node->color[i] = i < v.toVector().size() ? v.toVector()[i].toDouble() : 1.0; + node->color[i] = i < v->toVector().size() ? v->toVector()[i].toDouble() : 1.0; if (node->color[i] > 1) PRINTB_NOCACHE("WARNING: color() expects numbers between 0.0 and 1.0. Value of %.1f is too large.", node->color[i]); } - } else if (v.type() == Value::STRING) { - std::string colorname = v.toString(); + } else if (v->type() == Value::STRING) { + std::string colorname = v->toString(); boost::algorithm::to_lower(colorname); Color4f color; if (webcolors.find(colorname) != webcolors.end()) { @@ -237,9 +237,9 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia PRINT_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors"); } } - Value alpha = c.lookup_variable("alpha"); - if (alpha.type() == Value::NUMBER) { - node->color[3] = alpha.toDouble(); + ValuePtr alpha = c.lookup_variable("alpha"); + if (alpha->type() == Value::NUMBER) { + node->color[3] = alpha->toDouble(); } std::vector instantiatednodes = inst->instantiateChildren(evalctx); diff --git a/src/context.cc b/src/context.cc index 2fdeceeb..fdbe9990 100644 --- a/src/context.cc +++ b/src/context.cc @@ -78,14 +78,14 @@ void Context::setVariables(const AssignmentList &args, const EvalContext *evalctx) { BOOST_FOREACH(const Assignment &arg, args) { - set_variable(arg.first, arg.second ? arg.second->evaluate(this->parent) : Value()); + set_variable(arg.first, arg.second ? arg.second->evaluate(this->parent) : ValuePtr::undefined); } if (evalctx) { size_t posarg = 0; for (size_t i=0; inumArgs(); i++) { const std::string &name = evalctx->getArgName(i); - const Value &val = evalctx->getArgValue(i); + ValuePtr val = evalctx->getArgValue(i); if (name.empty()) { if (posarg < args.size()) this->set_variable(args[posarg++].first, val); } else { @@ -95,13 +95,18 @@ void Context::setVariables(const AssignmentList &args, } } -void Context::set_variable(const std::string &name, const Value &value) +void Context::set_variable(const std::string &name, const ValuePtr &value) { if (is_config_variable(name)) this->config_variables[name] = value; else this->variables[name] = value; } -void Context::set_constant(const std::string &name, const Value &value) +void Context::set_variable(const std::string &name, const Value &value) +{ + set_variable(name, ValuePtr(value)); +} + +void Context::set_constant(const std::string &name, const ValuePtr &value) { if (this->constants.find(name) != this->constants.end()) { PRINTB("WARNING: Attempt to modify constant '%s'.", name); @@ -111,11 +116,16 @@ void Context::set_constant(const std::string &name, const Value &value) } } -Value Context::lookup_variable(const std::string &name, bool silent) const +void Context::set_constant(const std::string &name, const Value &value) +{ + set_constant(name, ValuePtr(value)); +} + +ValuePtr Context::lookup_variable(const std::string &name, bool silent) const { if (!this->ctx_stack) { PRINT("ERROR: Context had null stack in lookup_variable()!!"); - return Value(); + return ValuePtr::undefined; } if (is_config_variable(name)) { for (int i = this->ctx_stack->size()-1; i >= 0; i--) { @@ -123,7 +133,7 @@ Value Context::lookup_variable(const std::string &name, bool silent) const if (confvars.find(name) != confvars.end()) return confvars.find(name)->second; } - return Value(); + return ValuePtr::undefined; } if (!this->parent && this->constants.find(name) != this->constants.end()) return this->constants.find(name)->second; @@ -133,7 +143,7 @@ Value Context::lookup_variable(const std::string &name, bool silent) const return this->parent->lookup_variable(name, silent); if (!silent) PRINTB("WARNING: Ignoring unknown variable '%s'.", name); - return Value(); + return ValuePtr::undefined; } bool Context::has_local_variable(const std::string &name) const @@ -145,11 +155,11 @@ bool Context::has_local_variable(const std::string &name) const return variables.find(name) != variables.end(); } -Value Context::evaluate_function(const std::string &name, const EvalContext *evalctx) const +ValuePtr Context::evaluate_function(const std::string &name, const EvalContext *evalctx) const { if (this->parent) return this->parent->evaluate_function(name, evalctx); PRINTB("WARNING: Ignoring unknown function '%s'.", name); - return Value(); + return ValuePtr::undefined; } AbstractNode *Context::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const @@ -190,7 +200,7 @@ std::string Context::dump(const AbstractModule *mod, const ModuleInstantiation * } } } - typedef std::pair ValueMapType; + typedef std::pair ValueMapType; s << " vars:"; BOOST_FOREACH(const ValueMapType &v, constants) { s << boost::format(" %s = %s") % v.first % v.second; diff --git a/src/context.h b/src/context.h index 3465c946..d80c0bef 100644 --- a/src/context.h +++ b/src/context.h @@ -5,6 +5,7 @@ #include #include "value.h" #include "typedefs.h" +#include "memory.h" class Context { @@ -14,16 +15,18 @@ public: virtual ~Context(); const Context *getParent() const { return this->parent; } - virtual Value evaluate_function(const std::string &name, const class EvalContext *evalctx) const; + 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; void setVariables(const AssignmentList &args, const class EvalContext *evalctx = NULL); + void set_variable(const std::string &name, const ValuePtr &value); void set_variable(const std::string &name, const Value &value); + void set_constant(const std::string &name, const ValuePtr &value); void set_constant(const std::string &name, const Value &value); - Value lookup_variable(const std::string &name, bool silent = false) const; + ValuePtr lookup_variable(const std::string &name, bool silent = false) const; bool has_local_variable(const std::string &name) const; void setDocumentPath(const std::string &path) { this->document_path = path; } @@ -36,7 +39,7 @@ protected: const Context *parent; Stack *ctx_stack; - typedef boost::unordered_map ValueMap; + typedef boost::unordered_map ValueMap; ValueMap constants; ValueMap variables; ValueMap config_variables; diff --git a/src/control.cc b/src/control.cc index 79ce6910..ee8c7e54 100644 --- a/src/control.cc +++ b/src/control.cc @@ -62,7 +62,7 @@ public: // methods static const EvalContext* getLastModuleCtx(const EvalContext *evalctx); - static AbstractNode* getChild(const Value& value, const EvalContext* modulectx); + static AbstractNode* getChild(const Value &value, const EvalContext* modulectx); private: // data Type type; @@ -74,27 +74,27 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst { if (evalctx->numArgs() > l) { const std::string &it_name = evalctx->getArgName(l); - const Value &it_values = evalctx->getArgValue(l, ctx); + ValuePtr it_values = evalctx->getArgValue(l, ctx); Context c(ctx); - if (it_values.type() == Value::RANGE) { - Value::RangeType range = it_values.toRange(); + if (it_values->type() == Value::RANGE) { + Value::RangeType range = it_values->toRange(); boost::uint32_t steps = range.nbsteps(); if (steps >= 10000) { PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps); } else { for (Value::RangeType::iterator it = range.begin();it != range.end();it++) { - c.set_variable(it_name, Value(*it)); + c.set_variable(it_name, ValuePtr(*it)); for_eval(node, inst, l+1, &c, evalctx); } } } - else if (it_values.type() == Value::VECTOR) { - for (size_t i = 0; i < it_values.toVector().size(); i++) { - c.set_variable(it_name, it_values.toVector()[i]); + else if (it_values->type() == Value::VECTOR) { + for (size_t i = 0; i < it_values->toVector().size(); i++) { + c.set_variable(it_name, it_values->toVector()[i]); for_eval(node, inst, l+1, &c, evalctx); } } - else if (it_values.type() != Value::UNDEFINED) { + else if (it_values->type() != Value::UNDEFINED) { c.set_variable(it_name, it_values); for_eval(node, inst, l+1, &c, evalctx); } @@ -165,7 +165,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns int n = 0; if (evalctx->numArgs() > 0) { double v; - if (evalctx->getArgValue(0).getDouble(v)) { + if (evalctx->getArgValue(0)->getDouble(v)) { n = trunc(v); if (n < 0) { PRINTB("WARNING: Negative child index (%d) not allowed", n); @@ -213,13 +213,13 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns } else if (evalctx->numArgs()>0) { // one (or more ignored) parameter - const Value& value = evalctx->getArgValue(0); - if (value.type() == Value::NUMBER) { - return getChild(value,modulectx); + ValuePtr value = evalctx->getArgValue(0); + if (value->type() == Value::NUMBER) { + return getChild(*value, modulectx); } - else if (value.type() == Value::VECTOR) { + else if (value->type() == Value::VECTOR) { AbstractNode* node = new AbstractNode(inst); - const Value::VectorType& vect = value.toVector(); + const Value::VectorType& vect = value->toVector(); foreach (const Value::VectorType::value_type& vectvalue, vect) { AbstractNode* childnode = getChild(vectvalue,modulectx); if (childnode==NULL) continue; // error @@ -227,9 +227,9 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns } return node; } - else if (value.type() == Value::RANGE) { + else if (value->type() == Value::RANGE) { AbstractNode* node = new AbstractNode(inst); - Value::RangeType range = value.toRange(); + Value::RangeType range = value->toRange(); boost::uint32_t steps = range.nbsteps(); if (steps >= 10000) { PRINTB("WARNING: Bad range parameter for children: too many elements (%lu).", steps); @@ -245,7 +245,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns else { // Invalid parameter // (e.g. first child of difference is invalid) - PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value.toString()); + PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value->toString()); return NULL; } } @@ -264,11 +264,11 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns for (size_t i = 0; i < inst->arguments.size(); i++) { if (i > 0) msg << ", "; if (!evalctx->getArgName(i).empty()) msg << evalctx->getArgName(i) << " = "; - Value val = evalctx->getArgValue(i); - if (val.type() == Value::STRING) { - msg << '"' << val.toString() << '"'; + ValuePtr val = evalctx->getArgValue(i); + if (val->type() == Value::STRING) { + msg << '"' << val->toString() << '"'; } else { - msg << val.toString(); + msg << val->toString(); } } PRINTB("%s", msg.str()); @@ -293,7 +293,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns if (type == IF) { const IfElseModuleInstantiation *ifelse = dynamic_cast(inst); - if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) { + if (evalctx->numArgs() > 0 && evalctx->getArgValue(0)->toBool()) { std::vector instantiatednodes = ifelse->instantiateChildren(evalctx); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 8f55a2fa..8bcd1bc5 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -39,11 +39,11 @@ #include #include -boost::unordered_map dxf_dim_cache; -boost::unordered_map dxf_cross_cache; +boost::unordered_map dxf_dim_cache; +boost::unordered_map dxf_cross_cache; namespace fs = boost::filesystem; -Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) +ValuePtr builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) { std::string filename; std::string layername; @@ -56,17 +56,16 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) // since the path is only available for ModuleInstantiations, not function expressions. // See issue #217 for (size_t i = 0; i < evalctx->numArgs(); i++) { - if (evalctx->getArgName(i) == "file") - filename = lookup_file(evalctx->getArgValue(i).toString(), + ValuePtr n = evalctx->getArgName(i); + ValuePtr v = evalctx->getArgValue(i); + if (evalctx->getArgName(i) == "file") { + filename = lookup_file(v->toString(), evalctx->documentPath(), ctx->documentPath()); - if (evalctx->getArgName(i) == "layer") - layername = evalctx->getArgValue(i).toString(); - if (evalctx->getArgName(i) == "origin") - evalctx->getArgValue(i).getVec2(xorigin, yorigin); - if (evalctx->getArgName(i) == "scale") - evalctx->getArgValue(i).getDouble(scale); - if (evalctx->getArgName(i) == "name") - name = evalctx->getArgValue(i).toString(); + } + if (n == "layer") layername = v->toString(); + if (n == "origin") v->getVec2(xorigin, yorigin); + if (n == "scale") v->getDouble(scale); + if (n == "name") name = v->toString(); } std::stringstream keystream; @@ -100,46 +99,46 @@ Value builtin_dxf_dim(const Context *ctx, const EvalContext *evalctx) double y = d->coords[4][1] - d->coords[3][1]; double angle = d->angle; double distance_projected_on_line = fabs(x * cos(angle*M_PI/180) + y * sin(angle*M_PI/180)); - return dxf_dim_cache[key] = Value(distance_projected_on_line); + return dxf_dim_cache[key] = ValuePtr(distance_projected_on_line); } else if (type == 1) { // Aligned double x = d->coords[4][0] - d->coords[3][0]; double y = d->coords[4][1] - d->coords[3][1]; - return dxf_dim_cache[key] = Value(sqrt(x*x + y*y)); + return dxf_dim_cache[key] = ValuePtr(sqrt(x*x + y*y)); } else if (type == 2) { // Angular double a1 = atan2(d->coords[0][0] - d->coords[5][0], d->coords[0][1] - d->coords[5][1]); double a2 = atan2(d->coords[4][0] - d->coords[3][0], d->coords[4][1] - d->coords[3][1]); - return dxf_dim_cache[key] = Value(fabs(a1 - a2) * 180 / M_PI); + return dxf_dim_cache[key] = ValuePtr(fabs(a1 - a2) * 180 / M_PI); } else if (type == 3 || type == 4) { // Diameter or Radius double x = d->coords[5][0] - d->coords[0][0]; double y = d->coords[5][1] - d->coords[0][1]; - return dxf_dim_cache[key] = Value(sqrt(x*x + y*y)); + return dxf_dim_cache[key] = ValuePtr(sqrt(x*x + y*y)); } else if (type == 5) { // Angular 3 Point } else if (type == 6) { // Ordinate - return dxf_dim_cache[key] = Value((d->type & 64) ? d->coords[3][0] : d->coords[3][1]); + return dxf_dim_cache[key] = ValuePtr((d->type & 64) ? d->coords[3][0] : d->coords[3][1]); } PRINTB("WARNING: Dimension '%s' in '%s', layer '%s' has unsupported type!", name % filename % layername); - return Value(); + return ValuePtr::undefined; } PRINTB("WARNING: Can't find dimension '%s' in '%s', layer '%s'!", name % filename % layername); - return Value(); + return ValuePtr::undefined; } -Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) +ValuePtr builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) { std::string filename; std::string layername; @@ -151,14 +150,12 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) // since the path is only available for ModuleInstantiations, not function expressions. // See isse #217 for (size_t i = 0; i < evalctx->numArgs(); i++) { - if (evalctx->getArgName(i) == "file") - filename = ctx->getAbsolutePath(evalctx->getArgValue(i).toString()); - if (evalctx->getArgName(i) == "layer") - layername = evalctx->getArgValue(i).toString(); - if (evalctx->getArgName(i) == "origin") - evalctx->getArgValue(i).getVec2(xorigin, yorigin); - if (evalctx->getArgName(i) == "scale") - evalctx->getArgValue(i).getDouble(scale); + ValuePtr n = evalctx->getArgName(i); + ValuePtr v = evalctx->getArgValue(i); + if (n == "file") filename = ctx->getAbsolutePath(v->toString()); + if (n == "layer") layername = v->toString(); + if (n == "origin") v->getVec2(xorigin, yorigin); + if (n == "scale") v->getDouble(scale); } std::stringstream keystream; @@ -174,8 +171,9 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) << "|" << filesize; std::string key = keystream.str(); - if (dxf_cross_cache.find(key) != dxf_cross_cache.end()) + if (dxf_cross_cache.find(key) != dxf_cross_cache.end()) { return dxf_cross_cache.find(key)->second; + } DxfData dxf(36, 0, 0, filename, layername, xorigin, yorigin, scale); @@ -204,13 +202,13 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) Value::VectorType ret; ret.push_back(Value(x)); ret.push_back(Value(y)); - return dxf_cross_cache[key] = Value(ret); + return dxf_cross_cache[key] = ValuePtr(ret); } } PRINTB("WARNING: Can't find cross in '%s', layer '%s'!", filename % layername); - return Value(); + return ValuePtr::undefined; } void initialize_builtin_dxf_dim() diff --git a/src/dxfdim.h b/src/dxfdim.h index d84d07ce..bdadcee3 100644 --- a/src/dxfdim.h +++ b/src/dxfdim.h @@ -3,5 +3,5 @@ #include #include "value.h" -extern boost::unordered_map dxf_dim_cache; -extern boost::unordered_map dxf_cross_cache; +extern boost::unordered_map dxf_dim_cache; +extern boost::unordered_map dxf_cross_cache; diff --git a/src/evalcontext.cc b/src/evalcontext.cc index 1b3624e7..085a5f8f 100644 --- a/src/evalcontext.cc +++ b/src/evalcontext.cc @@ -14,11 +14,11 @@ const std::string &EvalContext::getArgName(size_t i) const return this->eval_arguments[i].first; } -Value EvalContext::getArgValue(size_t i, const Context *ctx) const +ValuePtr EvalContext::getArgValue(size_t i, const Context *ctx) const { assert(i < this->eval_arguments.size()); const Assignment &arg = this->eval_arguments[i]; - return arg.second ? arg.second->evaluate(ctx ? ctx : this) : Value(); + return arg.second ? arg.second->evaluate(ctx ? ctx : this) : ValuePtr::undefined; } size_t EvalContext::numChildren() const @@ -56,7 +56,7 @@ std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiati if (m) { s << boost::format(" module args:"); BOOST_FOREACH(const Assignment &arg, m->definition_arguments) { - s << boost::format(" %s = %s") % arg.first % variables[arg.first]; + s << boost::format(" %s = %s") % arg.first % *(variables[arg.first]); } } } diff --git a/src/evalcontext.h b/src/evalcontext.h index 928e96f6..108de1cf 100644 --- a/src/evalcontext.h +++ b/src/evalcontext.h @@ -18,7 +18,7 @@ public: size_t numArgs() const { return this->eval_arguments.size(); } const std::string &getArgName(size_t i) const; - Value getArgValue(size_t i, const Context *ctx = NULL) const; + ValuePtr getArgValue(size_t i, const Context *ctx = NULL) const; size_t numChildren() const; ModuleInstantiation *getChild(size_t i) const; @@ -29,6 +29,6 @@ public: private: const AssignmentList &eval_arguments; - std::vector > eval_values; + std::vector > eval_values; const LocalScope *const scope; }; diff --git a/src/expr.cc b/src/expr.cc index ea83ba24..b2fa061d 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -52,7 +52,7 @@ Expression::Expression(const std::string &type, Expression *expr) this->children.push_back(expr); } -Expression::Expression(const Value &val) : const_value(val), type("C"), recursioncount(0) +Expression::Expression(const ValuePtr &val) : const_value(val), type("C"), recursioncount(0) { } @@ -61,62 +61,62 @@ Expression::~Expression() std::for_each(this->children.begin(), this->children.end(), del_fun()); } -Value Expression::sub_evaluate_range(const Context *context) const +ValuePtr Expression::sub_evaluate_range(const Context *context) const { - Value v1 = this->children[0]->evaluate(context); - if (v1.type() == Value::NUMBER) { - Value v2 = this->children[1]->evaluate(context); - if (v2.type() == Value::NUMBER) { + ValuePtr v1 = this->children[0]->evaluate(context); + if (v1->type() == Value::NUMBER) { + ValuePtr v2 = this->children[1]->evaluate(context); + if (v2->type() == Value::NUMBER) { if (this->children.size() == 2) { - Value::RangeType range(v1.toDouble(), v2.toDouble()); - return Value(range); + Value::RangeType range(v1->toDouble(), v2->toDouble()); + return ValuePtr(range); } else { - Value v3 = this->children[2]->evaluate(context); - if (v3.type() == Value::NUMBER) { - Value::RangeType range(v1.toDouble(), v2.toDouble(), v3.toDouble()); - return Value(range); + ValuePtr v3 = this->children[2]->evaluate(context); + if (v3->type() == Value::NUMBER) { + Value::RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble()); + return ValuePtr(range); } } } } - return Value(); + return ValuePtr::undefined; } -Value Expression::sub_evaluate_member(const Context *context) const +ValuePtr Expression::sub_evaluate_member(const Context *context) const { - Value v = this->children[0]->evaluate(context); + ValuePtr v = this->children[0]->evaluate(context); - if (v.type() == Value::VECTOR) { + if (v->type() == Value::VECTOR) { if (this->var_name == "x") return v[0]; if (this->var_name == "y") return v[1]; if (this->var_name == "z") return v[2]; - } else if (v.type() == Value::RANGE) { - if (this->var_name == "begin") return Value(v[0]); - if (this->var_name == "step") return Value(v[1]); - if (this->var_name == "end") return Value(v[2]); + } else if (v->type() == Value::RANGE) { + if (this->var_name == "begin") return v[0]; + if (this->var_name == "step") return v[1]; + if (this->var_name == "end") return v[2]; } - return Value(); + return ValuePtr::undefined; } -Value Expression::sub_evaluate_vector(const Context *context) const +ValuePtr Expression::sub_evaluate_vector(const Context *context) const { Value::VectorType vec; BOOST_FOREACH(const Expression *e, this->children) { - vec.push_back(e->evaluate(context)); + vec.push_back(*(e->evaluate(context))); } - return Value(vec); + return ValuePtr(vec); } -Value Expression::sub_evaluate_function(const Context *context) const +ValuePtr Expression::sub_evaluate_function(const Context *context) const { if (this->recursioncount >= 1000) { PRINTB("ERROR: Recursion detected calling function '%s'", this->call_funcname); // TO DO: throw function_recursion_detected(); - return Value(); + return ValuePtr::undefined; } this->recursioncount += 1; EvalContext c(context, this->call_arguments); - const Value &result = context->evaluate_function(this->call_funcname, &c); + ValuePtr result = context->evaluate_function(this->call_funcname, &c); this->recursioncount -= 1; return result; } @@ -161,7 +161,7 @@ namespace { for (int i = 0; i < let_context.numArgs(); i++) { if (!allow_reassignment && context->has_local_variable(let_context.getArgName(i))) { - PRINTB("WARNING: Ignoring duplicate variable assignment %s = %s", let_context.getArgName(i) % let_context.getArgValue(i, context).toString()); + PRINTB("WARNING: Ignoring duplicate variable assignment %s = %s", let_context.getArgName(i) % let_context.getArgValue(i, context)->toString()); } else { // NOTE: iteratively evaluated list of arguments context->set_variable(let_context.getArgName(i), let_context.getArgValue(i, context)); @@ -170,7 +170,7 @@ namespace { } } -Value Expression::sub_evaluate_let_expression(const Context *context) const +ValuePtr Expression::sub_evaluate_let_expression(const Context *context) const { Context c(context); evaluate_sequential_assignment(this->call_arguments, &c); @@ -178,7 +178,7 @@ Value Expression::sub_evaluate_let_expression(const Context *context) const return this->children[0]->evaluate(&c); } -Value Expression::sub_evaluate_list_comprehension(const Context *context) const +ValuePtr Expression::sub_evaluate_list_comprehension(const Context *context) const { Value::VectorType vec; @@ -187,10 +187,10 @@ Value Expression::sub_evaluate_list_comprehension(const Context *context) const if (this->children[1]->type == "c") { return this->children[1]->evaluate(context); } else { - vec.push_back(this->children[1]->evaluate(context)); + vec.push_back((*this->children[1]->evaluate(context))); } } - return vec; + return ValuePtr(vec); } else if (this->call_funcname == "for") { EvalContext for_context(context, this->call_arguments); @@ -198,36 +198,36 @@ Value Expression::sub_evaluate_list_comprehension(const Context *context) const // comprehension for statements are by the parser reduced to only contain one single element const std::string &it_name = for_context.getArgName(0); - const Value &it_values = for_context.getArgValue(0, &assign_context); + ValuePtr it_values = for_context.getArgValue(0, &assign_context); Context c(context); - if (it_values.type() == Value::RANGE) { - Value::RangeType range = it_values.toRange(); + if (it_values->type() == Value::RANGE) { + Value::RangeType range = it_values->toRange(); boost::uint32_t steps = range.nbsteps(); if (steps >= 1000000) { PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps); } else { for (Value::RangeType::iterator it = range.begin();it != range.end();it++) { - c.set_variable(it_name, Value(*it)); - vec.push_back(this->children[0]->evaluate(&c)); + c.set_variable(it_name, ValuePtr(*it)); + vec.push_back((*this->children[0]->evaluate(&c))); } } } - else if (it_values.type() == Value::VECTOR) { - for (size_t i = 0; i < it_values.toVector().size(); i++) { - c.set_variable(it_name, it_values.toVector()[i]); - vec.push_back(this->children[0]->evaluate(&c)); + else if (it_values->type() == Value::VECTOR) { + for (size_t i = 0; i < it_values->toVector().size(); i++) { + c.set_variable(it_name, it_values->toVector()[i]); + vec.push_back((*this->children[0]->evaluate(&c))); } } - else if (it_values.type() != Value::UNDEFINED) { + else if (it_values->type() != Value::UNDEFINED) { c.set_variable(it_name, it_values); - vec.push_back(this->children[0]->evaluate(&c)); + vec.push_back((*this->children[0]->evaluate(&c))); } if (this->children[0]->type == "c") { - return flatten(vec); + return ValuePtr(flatten(vec)); } else { - return vec; + return ValuePtr(vec); } } else if (this->call_funcname == "let") { Context c(context); @@ -240,7 +240,7 @@ Value Expression::sub_evaluate_list_comprehension(const Context *context) const } -Value Expression::evaluate(const Context *context) const +ValuePtr Expression::evaluate(const Context *context) const { switch (type2int(this->type.c_str())) { case '!': @@ -336,7 +336,7 @@ std::string Expression::toString() const stream << "!" << *this->children[0]; } else if (this->type == "C") { - stream << this->const_value; + stream << *this->const_value; } else if (this->type == "R") { stream << "[" << *this->children[0] << " : " << *this->children[1]; diff --git a/src/expression.h b/src/expression.h index b17496e5..07237ab7 100644 --- a/src/expression.h +++ b/src/expression.h @@ -10,7 +10,7 @@ class Expression public: std::vector children; - const Value const_value; + ValuePtr const_value; std::string var_name; std::string call_funcname; @@ -35,12 +35,12 @@ public: std::string type; Expression(); - Expression(const Value &val); + Expression(const ValuePtr &val); Expression(const std::string &type, Expression *left, Expression *right); Expression(const std::string &type, Expression *expr); ~Expression(); - Value evaluate(const class Context *context) const; + ValuePtr evaluate(const class Context *context) const; std::string toString() const; @@ -48,12 +48,12 @@ private: mutable int recursioncount; // The following sub_* methods are needed to minimize stack usage only. - Value sub_evaluate_function(const class Context *context) const; - Value sub_evaluate_member(const class Context *context) const; - Value sub_evaluate_range(const class Context *context) const; - Value sub_evaluate_vector(const class Context *context) const; - Value sub_evaluate_let_expression(const class Context *context) const; - Value sub_evaluate_list_comprehension(const class Context *context) const; + ValuePtr sub_evaluate_function(const class Context *context) const; + ValuePtr sub_evaluate_member(const class Context *context) const; + ValuePtr sub_evaluate_range(const class Context *context) const; + ValuePtr sub_evaluate_vector(const class Context *context) const; + ValuePtr sub_evaluate_let_expression(const class Context *context) const; + ValuePtr sub_evaluate_list_comprehension(const class Context *context) const; }; std::ostream &operator<<(std::ostream &stream, const Expression &expr); diff --git a/src/func.cc b/src/func.cc index f26f44c5..f1c9ada4 100644 --- a/src/func.cc +++ b/src/func.cc @@ -69,10 +69,11 @@ AbstractFunction::~AbstractFunction() { } -Value AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const +// FIXME: Is this needed? +ValuePtr AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const { (void)evalctx; // unusued parameter - return Value(); + return ValuePtr::undefined; } std::string AbstractFunction::dump(const std::string &indent, const std::string &name) const @@ -87,9 +88,9 @@ Function::~Function() delete expr; } -Value Function::evaluate(const Context *ctx, const EvalContext *evalctx) const +ValuePtr Function::evaluate(const Context *ctx, const EvalContext *evalctx) const { - if (!expr) return Value(); + if (!expr) return ValuePtr::undefined; Context c(ctx); c.setVariables(definition_arguments, evalctx); return expr->evaluate(&c); @@ -113,7 +114,7 @@ BuiltinFunction::~BuiltinFunction() { } -Value BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const +ValuePtr BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const { return eval_func(ctx, evalctx); } @@ -135,51 +136,51 @@ static inline double rad2deg(double x) return x * 180.0 / M_PI; } -Value builtin_abs(const Context *, const EvalContext *evalctx) +ValuePtr builtin_abs(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(fabs(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(fabs(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_sign(const Context *, const EvalContext *evalctx) +ValuePtr builtin_sign(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) { - register double x = v.toDouble(); - return Value((x<0) ? -1.0 : ((x>0) ? 1.0 : 0.0)); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) { + register double x = v->toDouble(); + return ValuePtr((x<0) ? -1.0 : ((x>0) ? 1.0 : 0.0)); } } - return Value(); + return ValuePtr::undefined; } -Value builtin_rands(const Context *, const EvalContext *evalctx) +ValuePtr builtin_rands(const Context *, const EvalContext *evalctx) { size_t n = evalctx->numArgs(); if (n == 3 || n == 4) { - const Value &v0 = evalctx->getArgValue(0); - if (v0.type() != Value::NUMBER) goto quit; - double min = v0.toDouble(); + ValuePtr v0 = evalctx->getArgValue(0); + if (v0->type() != Value::NUMBER) goto quit; + double min = v0->toDouble(); - const Value &v1 = evalctx->getArgValue(1); - if (v1.type() != Value::NUMBER) goto quit; - double max = v1.toDouble(); + ValuePtr v1 = evalctx->getArgValue(1); + if (v1->type() != Value::NUMBER) goto quit; + double max = v1->toDouble(); if (max < min) { register double tmp = min; min = max; max = tmp; } - const Value &v2 = evalctx->getArgValue(2); - if (v2.type() != Value::NUMBER) goto quit; - size_t numresults = std::max( 0, static_cast( v2.toDouble() ) ); + ValuePtr v2 = evalctx->getArgValue(2); + if (v2->type() != Value::NUMBER) goto quit; + size_t numresults = std::max(0, static_cast(v2->toDouble())); bool deterministic = false; if (n > 3) { - const Value &v3 = evalctx->getArgValue(3); - if (v3.type() != Value::NUMBER) goto quit; - deterministic_rng.seed( (unsigned int) v3.toDouble() ); + ValuePtr v3 = evalctx->getArgValue(3); + if (v3->type() != Value::NUMBER) goto quit; + deterministic_rng.seed((unsigned int) v3->toDouble()); deterministic = true; } boost::uniform_real<> distributor( min, max ); @@ -190,83 +191,81 @@ Value builtin_rands(const Context *, const EvalContext *evalctx) } else { for (size_t i=0; i < numresults; i++) { if ( deterministic ) { - vec.push_back( Value( distributor( deterministic_rng ) ) ); + vec.push_back(Value(distributor(deterministic_rng))); } else { - vec.push_back( Value( distributor( lessdeterministic_rng ) ) ); + vec.push_back(Value(distributor(lessdeterministic_rng))); } } } - return Value(vec); + return ValuePtr(vec); } quit: - return Value(); + return ValuePtr::undefined; } -Value builtin_min(const Context *, const EvalContext *evalctx) +ValuePtr builtin_min(const Context *, const EvalContext *evalctx) { // preserve special handling of the first argument // as a template for vector processing size_t n = evalctx->numArgs(); if (n >= 1) { - const Value &v0 = evalctx->getArgValue(0); + ValuePtr v0 = evalctx->getArgValue(0); - if (n == 1 && v0.type() == Value::VECTOR && !v0.toVector().empty()) { - Value min = v0.toVector()[0]; - for (size_t i = 1; i < v0.toVector().size(); i++) { - if (v0.toVector()[i] < min) - min = v0.toVector()[i]; + if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) { + Value min = v0->toVector()[0]; + for (size_t i = 1; i < v0->toVector().size(); i++) { + if (v0->toVector()[i] < min) min = v0->toVector()[i]; } - return min; + return ValuePtr(min); } - if (v0.type() == Value::NUMBER) { - double val = v0.toDouble(); + if (v0->type() == Value::NUMBER) { + double val = v0->toDouble(); for (size_t i = 1; i < n; ++i) { - const Value &v = evalctx->getArgValue(i); + ValuePtr v = evalctx->getArgValue(i); // 4/20/14 semantic change per discussion: // break on any non-number - if (v.type() != Value::NUMBER) goto quit; - register double x = v.toDouble(); + if (v->type() != Value::NUMBER) goto quit; + register double x = v->toDouble(); if (x < val) val = x; } - return Value(val); + return ValuePtr(val); } } quit: - return Value(); + return ValuePtr::undefined; } -Value builtin_max(const Context *, const EvalContext *evalctx) +ValuePtr builtin_max(const Context *, const EvalContext *evalctx) { // preserve special handling of the first argument // as a template for vector processing size_t n = evalctx->numArgs(); if (n >= 1) { - const Value &v0 = evalctx->getArgValue(0); + ValuePtr v0 = evalctx->getArgValue(0); - if (n == 1 && v0.type() == Value::VECTOR && !v0.toVector().empty()) { - Value max = v0.toVector()[0]; - for (size_t i = 1; i < v0.toVector().size(); i++) { - if (v0.toVector()[i] > max) - max = v0.toVector()[i]; + if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) { + Value max = v0->toVector()[0]; + for (size_t i = 1; i < v0->toVector().size(); i++) { + if (v0->toVector()[i] > max) max = v0->toVector()[i]; } - return max; + return ValuePtr(max); } - if (v0.type() == Value::NUMBER) { - double val = v0.toDouble(); + if (v0->type() == Value::NUMBER) { + double val = v0->toDouble(); for (size_t i = 1; i < n; ++i) { - const Value &v = evalctx->getArgValue(i); + ValuePtr v = evalctx->getArgValue(i); // 4/20/14 semantic change per discussion: // break on any non-number - if (v.type() != Value::NUMBER) goto quit; - register double x = v.toDouble(); + if (v->type() != Value::NUMBER) goto quit; + register double x = v->toDouble(); if (x > val) val = x; } - return Value(val); + return ValuePtr(val); } } quit: - return Value(); + return ValuePtr::undefined; } // this limit assumes 26+26=52 bits mantissa @@ -307,14 +306,14 @@ double sin_degrees(register double x) return oppose ? -x : x; } -Value builtin_sin(const Context *, const EvalContext *evalctx) +ValuePtr builtin_sin(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(sin_degrees(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(sin_degrees(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } double cos_degrees(register double x) @@ -354,220 +353,221 @@ double cos_degrees(register double x) return oppose ? -x : x; } -Value builtin_cos(const Context *, const EvalContext *evalctx) +ValuePtr builtin_cos(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(cos_degrees(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(cos_degrees(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_asin(const Context *, const EvalContext *evalctx) +ValuePtr builtin_asin(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(rad2deg(asin(v.toDouble()))); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(rad2deg(asin(v->toDouble()))); } - return Value(); + return ValuePtr::undefined; } -Value builtin_acos(const Context *, const EvalContext *evalctx) +ValuePtr builtin_acos(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(rad2deg(acos(v.toDouble()))); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(rad2deg(acos(v->toDouble()))); } - return Value(); + return ValuePtr::undefined; } -Value builtin_tan(const Context *, const EvalContext *evalctx) +ValuePtr builtin_tan(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(tan(deg2rad(v.toDouble()))); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(tan(deg2rad(v->toDouble()))); } - return Value(); + return ValuePtr::undefined; } -Value builtin_atan(const Context *, const EvalContext *evalctx) +ValuePtr builtin_atan(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(rad2deg(atan(v.toDouble()))); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(rad2deg(atan(v->toDouble()))); } - return Value(); + return ValuePtr::undefined; } -Value builtin_atan2(const Context *, const EvalContext *evalctx) +ValuePtr builtin_atan2(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 2) { - Value v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1); - if (v0.type() == Value::NUMBER && v1.type() == Value::NUMBER) - return Value(rad2deg(atan2(v0.toDouble(), v1.toDouble()))); + ValuePtr v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1); + if (v0->type() == Value::NUMBER && v1->type() == Value::NUMBER) + return ValuePtr(rad2deg(atan2(v0->toDouble(), v1->toDouble()))); } - return Value(); + return ValuePtr::undefined; } -Value builtin_pow(const Context *, const EvalContext *evalctx) +ValuePtr builtin_pow(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 2) { - Value v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1); - if (v0.type() == Value::NUMBER && v1.type() == Value::NUMBER) - return Value(pow(v0.toDouble(), v1.toDouble())); + ValuePtr v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1); + if (v0->type() == Value::NUMBER && v1->type() == Value::NUMBER) + return ValuePtr(pow(v0->toDouble(), v1->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_round(const Context *, const EvalContext *evalctx) +ValuePtr builtin_round(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(round(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(round(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_ceil(const Context *, const EvalContext *evalctx) +ValuePtr builtin_ceil(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(ceil(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(ceil(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_floor(const Context *, const EvalContext *evalctx) +ValuePtr builtin_floor(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(floor(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(floor(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_sqrt(const Context *, const EvalContext *evalctx) +ValuePtr builtin_sqrt(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(sqrt(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(sqrt(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_exp(const Context *, const EvalContext *evalctx) +ValuePtr builtin_exp(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(exp(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(exp(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_length(const Context *, const EvalContext *evalctx) +ValuePtr builtin_length(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::VECTOR) return Value(int(v.toVector().size())); - if (v.type() == Value::STRING) { + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::VECTOR) return ValuePtr(int(v->toVector().size())); + if (v->type() == Value::STRING) { //Unicode glyph count for the length -- rather than the string (num. of bytes) length. - std::string text = v.toString(); - return Value(int( g_utf8_strlen( text.c_str(), text.size() ) )); + std::string text = v->toString(); + return ValuePtr(int( g_utf8_strlen( text.c_str(), text.size() ) )); } } - return Value(); + return ValuePtr::undefined; } -Value builtin_log(const Context *, const EvalContext *evalctx) +ValuePtr builtin_log(const Context *, const EvalContext *evalctx) { size_t n = evalctx->numArgs(); if (n == 1 || n == 2) { - const Value &v0 = evalctx->getArgValue(0); - if (v0.type() == Value::NUMBER) { - double x = 10.0, y = v0.toDouble(); + ValuePtr v0 = evalctx->getArgValue(0); + if (v0->type() == Value::NUMBER) { + double x = 10.0, y = v0->toDouble(); if (n > 1) { - const Value &v1 = evalctx->getArgValue(1); - if (v1.type() != Value::NUMBER) goto quit; - x = y; y = v1.toDouble(); + ValuePtr v1 = evalctx->getArgValue(1); + if (v1->type() != Value::NUMBER) goto quit; + x = y; y = v1->toDouble(); } - return Value(log(y) / log(x)); + return ValuePtr(log(y) / log(x)); } } quit: - return Value(); + return ValuePtr::undefined; } -Value builtin_ln(const Context *, const EvalContext *evalctx) +ValuePtr builtin_ln(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() == Value::NUMBER) - return Value(log(v.toDouble())); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() == Value::NUMBER) + return ValuePtr(log(v->toDouble())); } - return Value(); + return ValuePtr::undefined; } -Value builtin_str(const Context *, const EvalContext *evalctx) +ValuePtr builtin_str(const Context *, const EvalContext *evalctx) { std::stringstream stream; for (size_t i = 0; i < evalctx->numArgs(); i++) { - stream << evalctx->getArgValue(i).toString(); + stream << evalctx->getArgValue(i)->toString(); } - return Value(stream.str()); + return ValuePtr(stream.str()); } -Value builtin_chr(const Context *, const EvalContext *evalctx) +ValuePtr builtin_chr(const Context *, const EvalContext *evalctx) { std::stringstream stream; for (size_t i = 0; i < evalctx->numArgs(); i++) { - const Value v = evalctx->getArgValue(i); - stream << v.chrString(); + ValuePtr v = evalctx->getArgValue(i); + stream << v->chrString(); } - return Value(stream.str()); + return ValuePtr(stream.str()); } -Value builtin_concat(const Context *, const EvalContext *evalctx) +ValuePtr builtin_concat(const Context *, const EvalContext *evalctx) { Value::VectorType result; for (size_t i = 0; i < evalctx->numArgs(); i++) { - const Value v = evalctx->getArgValue(i); - if (v.type() == Value::VECTOR) { - Value::VectorType vec = v.toVector(); + ValuePtr v = evalctx->getArgValue(i); + if (v->type() == Value::VECTOR) { + Value::VectorType vec = v->toVector(); for (Value::VectorType::const_iterator it = vec.begin(); it != vec.end(); it++) { result.push_back(*it); } } else { - result.push_back(v); + result.push_back(*v); } } - return Value(result); + return ValuePtr(result); } -Value builtin_lookup(const Context *, const EvalContext *evalctx) +ValuePtr builtin_lookup(const Context *, const EvalContext *evalctx) { double p, low_p, low_v, high_p, high_v; if (evalctx->numArgs() < 2 || // Needs two args - !evalctx->getArgValue(0).getDouble(p)) // First must be a number - return Value(); + !evalctx->getArgValue(0)->getDouble(p)) // First must be a number + return ValuePtr::undefined; - const Value::VectorType vec = evalctx->getArgValue(1).toVector(); + ValuePtr v1 = evalctx->getArgValue(1); + const Value::VectorType &vec = v1->toVector(); if (vec[0].toVector().size() < 2) // Second must be a vector of vectors - return Value(); + return ValuePtr::undefined; if (!vec[0].getVec2(low_p, low_v) || !vec[0].getVec2(high_p, high_v)) - return Value(); + return ValuePtr::undefined; for (size_t i = 1; i < vec.size(); i++) { double this_p, this_v; if (vec[i].getVec2(this_p, this_v)) { @@ -582,11 +582,11 @@ Value builtin_lookup(const Context *, const EvalContext *evalctx) } } if (p <= low_p) - return Value(high_v); + return ValuePtr(high_v); if (p >= high_p) - return Value(low_v); + return ValuePtr(low_v); double f = (p-low_p) / (high_p-low_p); - return Value(high_v * f + low_v * (1-f)); + return ValuePtr(high_v * f + low_v * (1-f)); } /* @@ -715,48 +715,48 @@ static Value::VectorType search(const std::string &find, const Value::VectorType return returnvec; } -Value builtin_search(const Context *, const EvalContext *evalctx) +ValuePtr builtin_search(const Context *, const EvalContext *evalctx) { - if (evalctx->numArgs() < 2) return Value(); + if (evalctx->numArgs() < 2) return ValuePtr::undefined; - const Value &findThis = evalctx->getArgValue(0); - const Value &searchTable = evalctx->getArgValue(1); - unsigned int num_returns_per_match = (evalctx->numArgs() > 2) ? evalctx->getArgValue(2).toDouble() : 1; - unsigned int index_col_num = (evalctx->numArgs() > 3) ? evalctx->getArgValue(3).toDouble() : 0; + ValuePtr findThis = evalctx->getArgValue(0); + ValuePtr searchTable = evalctx->getArgValue(1); + unsigned int num_returns_per_match = (evalctx->numArgs() > 2) ? evalctx->getArgValue(2)->toDouble() : 1; + unsigned int index_col_num = (evalctx->numArgs() > 3) ? evalctx->getArgValue(3)->toDouble() : 0; Value::VectorType returnvec; - if (findThis.type() == Value::NUMBER) { + if (findThis->type() == Value::NUMBER) { unsigned int matchCount = 0; - for (size_t j = 0; j < searchTable.toVector().size(); j++) { - const Value& search_element = searchTable.toVector()[j]; + for (size_t j = 0; j < searchTable->toVector().size(); j++) { + const Value &search_element = searchTable->toVector()[j]; - if ((index_col_num == 0 && findThis == search_element) || + if ((index_col_num == 0 && *findThis == search_element) || (index_col_num < search_element.toVector().size() && - findThis == search_element.toVector()[index_col_num])) { + *findThis == search_element.toVector()[index_col_num])) { returnvec.push_back(Value(double(j))); matchCount++; if (num_returns_per_match != 0 && matchCount >= num_returns_per_match) break; } } - } else if (findThis.type() == Value::STRING) { - if (searchTable.type() == Value::STRING) { - returnvec = search(findThis.toString(), searchTable.toString(), num_returns_per_match, index_col_num); + } else if (findThis->type() == Value::STRING) { + if (searchTable->type() == Value::STRING) { + returnvec = search(findThis->toString(), searchTable->toString(), num_returns_per_match, index_col_num); } else { - returnvec = search(findThis.toString(), searchTable.toVector(), num_returns_per_match, index_col_num); + returnvec = search(findThis->toString(), searchTable->toVector(), num_returns_per_match, index_col_num); } - } else if (findThis.type() == Value::VECTOR) { - for (size_t i = 0; i < findThis.toVector().size(); i++) { + } else if (findThis->type() == Value::VECTOR) { + for (size_t i = 0; i < findThis->toVector().size(); i++) { unsigned int matchCount = 0; Value::VectorType resultvec; - Value const& find_value = findThis.toVector()[i]; + Value const& find_value = findThis->toVector()[i]; - for (size_t j = 0; j < searchTable.toVector().size(); j++) { + for (size_t j = 0; j < searchTable->toVector().size(); j++) { - Value const& search_element = searchTable.toVector()[j]; + Value const& search_element = searchTable->toVector()[j]; if ((index_col_num == 0 && find_value == search_element) || (index_col_num < search_element.toVector().size() && @@ -773,53 +773,53 @@ Value builtin_search(const Context *, const EvalContext *evalctx) } } if (num_returns_per_match == 1 && matchCount == 0) { - if (findThis.toVector()[i].type() == Value::NUMBER) { - PRINTB(" WARNING: search term not found: %s",findThis.toVector()[i].toDouble()); + if (findThis->toVector()[i].type() == Value::NUMBER) { + PRINTB(" WARNING: search term not found: %s",findThis->toVector()[i].toDouble()); } - else if (findThis.toVector()[i].type() == Value::STRING) { - PRINTB(" WARNING: search term not found: \"%s\"",findThis.toVector()[i].toString()); + else if (findThis->toVector()[i].type() == Value::STRING) { + PRINTB(" WARNING: search term not found: \"%s\"",findThis->toVector()[i].toString()); } - returnvec.push_back(Value(resultvec)); + returnvec.push_back(resultvec); } if (num_returns_per_match == 0 || num_returns_per_match > 1) { - returnvec.push_back(Value(resultvec)); + returnvec.push_back(resultvec); } } } else { PRINTB(" WARNING: search: none performed on input %s", findThis); - return Value(); + return ValuePtr::undefined; } - return Value(returnvec); + return ValuePtr(returnvec); } #define QUOTE(x__) # x__ #define QUOTED(x__) QUOTE(x__) -Value builtin_version(const Context *, const EvalContext *evalctx) +ValuePtr builtin_version(const Context *, const EvalContext *evalctx) { (void)evalctx; // unusued parameter Value::VectorType val; - val.push_back(Value(double(OPENSCAD_YEAR))); - val.push_back(Value(double(OPENSCAD_MONTH))); + val.push_back(double(OPENSCAD_YEAR)); + val.push_back(double(OPENSCAD_MONTH)); #ifdef OPENSCAD_DAY - val.push_back(Value(double(OPENSCAD_DAY))); + val.push_back(double(OPENSCAD_DAY)); #endif - return Value(val); + return ValuePtr(val); } -Value builtin_version_num(const Context *ctx, const EvalContext *evalctx) +ValuePtr builtin_version_num(const Context *ctx, const EvalContext *evalctx) { - Value val = (evalctx->numArgs() == 0) ? builtin_version(ctx, evalctx) : evalctx->getArgValue(0); + ValuePtr val = (evalctx->numArgs() == 0) ? builtin_version(ctx, evalctx) : evalctx->getArgValue(0); double y, m, d = 0; - if (!val.getVec3(y, m, d)) { - if (!val.getVec2(y, m)) { - return Value(); + if (!val->getVec3(y, m, d)) { + if (!val->getVec2(y, m)) { + return ValuePtr::undefined; } } - return Value(y * 10000 + m * 100 + d); + return ValuePtr(y * 10000 + m * 100 + d); } -Value builtin_parent_module(const Context *, const EvalContext *evalctx) +ValuePtr builtin_parent_module(const Context *, const EvalContext *evalctx) { int n; double d; @@ -827,30 +827,30 @@ Value builtin_parent_module(const Context *, const EvalContext *evalctx) if (evalctx->numArgs() == 0) d=1; // parent module else if (evalctx->numArgs() == 1) { - const Value &v = evalctx->getArgValue(0); - if (v.type() != Value::NUMBER) return Value(); - v.getDouble(d); + ValuePtr v = evalctx->getArgValue(0); + if (v->type() != Value::NUMBER) return ValuePtr::undefined; + v->getDouble(d); } else - return Value(); + return ValuePtr::undefined; n=trunc(d); if (n < 0) { PRINTB("WARNING: Negative parent module index (%d) not allowed", n); - return Value(); + return ValuePtr::undefined; } if (n >= s) { PRINTB("WARNING: Parent module index (%d) greater than the number of modules on the stack", n); - return Value(); + return ValuePtr::undefined; } - return Value(Module::stack_element(s - 1 - n)); + return ValuePtr(Module::stack_element(s - 1 - n)); } -Value builtin_norm(const Context *, const EvalContext *evalctx) +ValuePtr builtin_norm(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() == 1) { - const Value &val = evalctx->getArgValue(0); - if (val.type() == Value::VECTOR) { + ValuePtr val = evalctx->getArgValue(0); + if (val->type() == Value::VECTOR) { double sum = 0; - Value::VectorType v = val.toVector(); + Value::VectorType v = val->toVector(); size_t n = v.size(); for (size_t i = 0; i < n; i++) if (v[i].type() == Value::NUMBER) { @@ -859,48 +859,48 @@ Value builtin_norm(const Context *, const EvalContext *evalctx) sum += x*x; } else { PRINT(" WARNING: Incorrect arguments to norm()"); - return Value(); + return ValuePtr::undefined; } - return Value(sqrt(sum)); + return ValuePtr(sqrt(sum)); } } - return Value(); + return ValuePtr::undefined; } -Value builtin_cross(const Context *, const EvalContext *evalctx) +ValuePtr builtin_cross(const Context *, const EvalContext *evalctx) { if (evalctx->numArgs() != 2) { PRINT("WARNING: Invalid number of parameters for cross()"); - return Value(); + return ValuePtr::undefined; } - Value arg0 = evalctx->getArgValue(0); - Value arg1 = evalctx->getArgValue(1); - if ((arg0.type() != Value::VECTOR) || (arg1.type() != Value::VECTOR)) { + ValuePtr arg0 = evalctx->getArgValue(0); + ValuePtr arg1 = evalctx->getArgValue(1); + if ((arg0->type() != Value::VECTOR) || (arg1->type() != Value::VECTOR)) { PRINT("WARNING: Invalid type of parameters for cross()"); - return Value(); + return ValuePtr::undefined; } - Value::VectorType v0 = arg0.toVector(); - Value::VectorType v1 = arg1.toVector(); + Value::VectorType v0 = arg0->toVector(); + Value::VectorType v1 = arg1->toVector(); if ((v0.size() != 3) || (v1.size() != 3)) { PRINT("WARNING: Invalid vector size of parameter for cross()"); - return Value(); + return ValuePtr::undefined; } for (unsigned int a = 0;a < 3;a++) { if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) { PRINT("WARNING: Invalid value in parameter vector for cross()"); - return Value(); + return ValuePtr::undefined; } double d0 = v0[a].toDouble(); double d1 = v1[a].toDouble(); if (boost::math::isnan(d0) || boost::math::isnan(d1)) { PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()"); - return Value(); + return ValuePtr::undefined; } if (boost::math::isinf(d0) || boost::math::isinf(d1)) { PRINT("WARNING: Invalid value (INF) in parameter vector for cross()"); - return Value(); + return ValuePtr::undefined; } } @@ -912,7 +912,7 @@ Value builtin_cross(const Context *, const EvalContext *evalctx) result.push_back(Value(x)); result.push_back(Value(y)); result.push_back(Value(z)); - return Value(result); + return ValuePtr(result); } void register_builtin_functions() diff --git a/src/function.h b/src/function.h index d8e3ad77..fe39f61f 100644 --- a/src/function.h +++ b/src/function.h @@ -11,28 +11,28 @@ class AbstractFunction { private: - const Feature *feature; + const Feature *feature; public: - AbstractFunction() : feature(NULL) {} - AbstractFunction(const Feature& feature) : feature(&feature) {} + AbstractFunction() : feature(NULL) {} + AbstractFunction(const Feature& feature) : feature(&feature) {} virtual ~AbstractFunction(); - virtual bool is_experimental() const { return feature != NULL; } - virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); } - virtual Value evaluate(const class Context *ctx, const class EvalContext *evalctx) const; + virtual bool is_experimental() const { return feature != NULL; } + virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); } + virtual ValuePtr evaluate(const class Context *ctx, const class EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; class BuiltinFunction : public AbstractFunction { public: - typedef Value (*eval_func_t)(const Context *ctx, const EvalContext *evalctx); + typedef ValuePtr (*eval_func_t)(const Context *ctx, const EvalContext *evalctx); eval_func_t eval_func; BuiltinFunction(eval_func_t f) : eval_func(f) { } BuiltinFunction(eval_func_t f, const Feature& feature) : AbstractFunction(feature), eval_func(f) { } virtual ~BuiltinFunction(); - virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const; + virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; @@ -46,6 +46,6 @@ public: Function() { } virtual ~Function(); - virtual Value evaluate(const Context *ctx, const EvalContext *evalctx) const; + virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const; virtual std::string dump(const std::string &indent, const std::string &name) const; }; diff --git a/src/import.cc b/src/import.cc index 3841dc02..79ebb4bc 100644 --- a/src/import.cc +++ b/src/import.cc @@ -91,18 +91,18 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti c.dump(this, inst); #endif - Value v = c.lookup_variable("file"); - if (v.isUndefined()) { + ValuePtr v = c.lookup_variable("file"); + if (v->isUndefined()) { v = c.lookup_variable("filename"); - if (!v.isUndefined()) { + if (!v->isUndefined()) { printDeprecation("DEPRECATED: filename= is deprecated. Please use file="); } } - std::string filename = lookup_file(v.isUndefined() ? "" : v.toString(), inst->path(), ctx->documentPath()); + std::string filename = lookup_file(v->isUndefined() ? "" : v->toString(), inst->path(), ctx->documentPath()); import_type_e actualtype = this->type; if (actualtype == TYPE_UNKNOWN) { - std::string extraw = boosty::extension_str( fs::path(filename) ); - std::string ext = boost::algorithm::to_lower_copy( extraw ); + std::string extraw = boosty::extension_str(fs::path(filename)); + std::string ext = boost::algorithm::to_lower_copy(extraw); if (ext == ".stl") actualtype = TYPE_STL; else if (ext == ".off") actualtype = TYPE_OFF; else if (ext == ".dxf") actualtype = TYPE_DXF; @@ -110,31 +110,30 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti ImportNode *node = new ImportNode(inst, actualtype); - node->fn = c.lookup_variable("$fn").toDouble(); - node->fs = c.lookup_variable("$fs").toDouble(); - node->fa = c.lookup_variable("$fa").toDouble(); + node->fn = c.lookup_variable("$fn")->toDouble(); + node->fs = c.lookup_variable("$fs")->toDouble(); + node->fa = c.lookup_variable("$fa")->toDouble(); node->filename = filename; - Value layerval = c.lookup_variable("layer", true); + Value layerval = *c.lookup_variable("layer", true); if (layerval.isUndefined()) { - layerval = c.lookup_variable("layername"); + layerval = *c.lookup_variable("layername"); if (!layerval.isUndefined()) { printDeprecation("DEPRECATED: layername= is deprecated. Please use layer="); } } node->layername = layerval.isUndefined() ? "" : layerval.toString(); - node->convexity = c.lookup_variable("convexity", true).toDouble(); + node->convexity = c.lookup_variable("convexity", true)->toDouble(); if (node->convexity <= 0) node->convexity = 1; - Value origin = c.lookup_variable("origin", true); + ValuePtr origin = c.lookup_variable("origin", true); node->origin_x = node->origin_y = 0; - origin.getVec2(node->origin_x, node->origin_y); + origin->getVec2(node->origin_x, node->origin_y); - node->scale = c.lookup_variable("scale", true).toDouble(); + node->scale = c.lookup_variable("scale", true)->toDouble(); - if (node->scale <= 0) - node->scale = 1; + if (node->scale <= 0) node->scale = 1; return node; } diff --git a/src/linearextrude.cc b/src/linearextrude.cc index c3ba1ee6..c6bd8256 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -59,46 +59,46 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI Context c(ctx); c.setVariables(args, evalctx); - node->fn = c.lookup_variable("$fn").toDouble(); - node->fs = c.lookup_variable("$fs").toDouble(); - node->fa = c.lookup_variable("$fa").toDouble(); + node->fn = c.lookup_variable("$fn")->toDouble(); + node->fs = c.lookup_variable("$fs")->toDouble(); + node->fa = c.lookup_variable("$fa")->toDouble(); - Value file = c.lookup_variable("file"); - Value layer = c.lookup_variable("layer", true); - Value height = c.lookup_variable("height", true); - Value convexity = c.lookup_variable("convexity", true); - Value origin = c.lookup_variable("origin", true); - Value scale = c.lookup_variable("scale", true); - Value center = c.lookup_variable("center", true); - Value twist = c.lookup_variable("twist", true); - Value slices = c.lookup_variable("slices", true); + ValuePtr file = c.lookup_variable("file"); + ValuePtr layer = c.lookup_variable("layer", true); + ValuePtr height = c.lookup_variable("height", true); + ValuePtr convexity = c.lookup_variable("convexity", true); + ValuePtr origin = c.lookup_variable("origin", true); + ValuePtr scale = c.lookup_variable("scale", true); + ValuePtr center = c.lookup_variable("center", true); + ValuePtr twist = c.lookup_variable("twist", true); + ValuePtr slices = c.lookup_variable("slices", true); - if (!file.isUndefined() && file.type() == Value::STRING) { + if (!file->isUndefined() && file->type() == Value::STRING) { printDeprecation("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); - node->filename = lookup_file(file.toString(), inst->path(), c.documentPath()); + node->filename = lookup_file(file->toString(), inst->path(), c.documentPath()); } // if height not given, and first argument is a number, // then assume it should be the height. - if (c.lookup_variable("height").isUndefined() && + if (c.lookup_variable("height")->isUndefined() && evalctx->numArgs() > 0 && evalctx->getArgName(0) == "") { - const Value &val = evalctx->getArgValue(0); - if (val.type() == Value::NUMBER) height = val; + ValuePtr val = evalctx->getArgValue(0); + if (val->type() == Value::NUMBER) height = val; } - node->layername = layer.isUndefined() ? "" : layer.toString(); + node->layername = layer->isUndefined() ? "" : layer->toString(); node->height = 100; - height.getDouble(node->height); - node->convexity = (int)convexity.toDouble(); - origin.getVec2(node->origin_x, node->origin_y); + height->getDouble(node->height); + node->convexity = (int)convexity->toDouble(); + origin->getVec2(node->origin_x, node->origin_y); node->scale_x = node->scale_y = 1; - scale.getDouble(node->scale_x); - scale.getDouble(node->scale_y); - scale.getVec2(node->scale_x, node->scale_y); + scale->getDouble(node->scale_x); + scale->getDouble(node->scale_y); + scale->getVec2(node->scale_x, node->scale_y); - if (center.type() == Value::BOOL) - node->center = center.toBool(); + if (center->type() == Value::BOOL) + node->center = center->toBool(); if (node->height <= 0) node->height = 0; @@ -108,10 +108,10 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (node->scale_x < 0) node->scale_x = 0; if (node->scale_y < 0) node->scale_y = 0; - if (slices.type() == Value::NUMBER) node->slices = (int)slices.toDouble(); + if (slices->type() == Value::NUMBER) node->slices = (int)slices->toDouble(); - if (twist.type() == Value::NUMBER) { - node->twist = twist.toDouble(); + if (twist->type() == Value::NUMBER) { + node->twist = twist->toDouble(); if (node->twist != 0.0) { if (node->slices == 0) { node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height, diff --git a/src/mainwin.cc b/src/mainwin.cc index 776a46ed..4d830742 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -1485,7 +1485,7 @@ bool MainWindow::eventFilter(QObject* obj, QEvent *event) void MainWindow::updateTemporalVariables() { - this->top_ctx.set_variable("$t", Value(this->e_tval->text().toDouble())); + this->top_ctx.set_variable("$t", ValuePtr(this->e_tval->text().toDouble())); Value::VectorType vpt; vpt.push_back(Value(-qglview->cam.object_trans.x())); @@ -1497,9 +1497,9 @@ void MainWindow::updateTemporalVariables() vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.x() + 90, 360))); vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.y(), 360))); vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.z(), 360))); - top_ctx.set_variable("$vpr", Value(vpr)); + top_ctx.set_variable("$vpr", ValuePtr(vpr)); - top_ctx.set_variable("$vpd", Value(qglview->cam.viewer_distance)); + top_ctx.set_variable("$vpd", ValuePtr(qglview->cam.viewer_distance)); } @@ -1531,25 +1531,25 @@ void MainWindow::updateCamera() BOOST_FOREACH(const Assignment &a, root_module->scope.assignments) { double x, y, z; if ("$vpr" == a.first) { - const Value vpr = a.second.get()->evaluate(&mc); - if (vpr.getVec3(x, y, z)) { + ValuePtr vpr = a.second.get()->evaluate(&mc); + if (vpr->getVec3(x, y, z)) { rx = x; ry = y; rz = z; camera_set = true; } } else if ("$vpt" == a.first) { - const Value vpt = a.second.get()->evaluate(&mc); - if (vpt.getVec3(x, y, z)) { + ValuePtr vpt = a.second.get()->evaluate(&mc); + if (vpt->getVec3(x, y, z)) { tx = x; ty = y; tz = z; camera_set = true; } } else if ("$vpd" == a.first) { - const Value vpd = a.second.get()->evaluate(&mc); - if (vpd.type() == Value::NUMBER) { - d = vpd.toDouble(); + ValuePtr vpd = a.second.get()->evaluate(&mc); + if (vpd->type() == Value::NUMBER) { + d = vpd->toDouble(); camera_set = true; } } diff --git a/src/memory.h b/src/memory.h index 1f54e4b3..86cd6aba 100644 --- a/src/memory.h +++ b/src/memory.h @@ -1,6 +1,8 @@ #pragma once #include +#include using boost::shared_ptr; +using boost::make_shared; using boost::dynamic_pointer_cast; using boost::static_pointer_cast; diff --git a/src/modcontext.cc b/src/modcontext.cc index c6210f42..7269f6e0 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -24,8 +24,8 @@ void ModuleContext::evaluateAssignments(const AssignmentList &assignments) // First, assign all simple variables std::list undefined_vars; BOOST_FOREACH(const Assignment &ass, assignments) { - Value tmpval = ass.second->evaluate(this); - if (tmpval.isUndefined()) undefined_vars.push_back(ass.first); + ValuePtr tmpval = ass.second->evaluate(this); + if (tmpval->isUndefined()) undefined_vars.push_back(ass.first); else this->set_variable(ass.first, tmpval); } @@ -46,12 +46,12 @@ void ModuleContext::evaluateAssignments(const AssignmentList &assignments) boost::unordered_map::iterator found = tmpass.find(*curr); if (found != tmpass.end()) { const Expression *expr = found->second; - Value tmpval = expr->evaluate(this); + ValuePtr tmpval = expr->evaluate(this); // FIXME: it's not enough to check for undefined; // we need to check for any undefined variable in the subexpression // For now, ignore this and revisit the validity and order of variable // assignments later - if (!tmpval.isUndefined()) { + if (!tmpval->isUndefined()) { changed = true; this->set_variable(*curr, tmpval); undefined_vars.erase(curr); @@ -89,7 +89,7 @@ void ModuleContext::registerBuiltin() this->set_variable(ass.first, ass.second->evaluate(this)); } - this->set_constant("PI",Value(M_PI)); + this->set_constant("PI", ValuePtr(M_PI)); } const AbstractFunction *ModuleContext::findLocalFunction(const std::string &name) const @@ -122,7 +122,8 @@ const AbstractModule *ModuleContext::findLocalModule(const std::string &name) co return NULL; } -Value ModuleContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const +ValuePtr ModuleContext::evaluate_function(const std::string &name, + const EvalContext *evalctx) const { const AbstractFunction *foundf = findLocalFunction(name); if (foundf) return foundf->evaluate(this, evalctx); @@ -156,7 +157,7 @@ std::string ModuleContext::dump(const AbstractModule *mod, const ModuleInstantia } } } - typedef std::pair ValueMapType; + typedef std::pair ValueMapType; s << " vars:"; BOOST_FOREACH(const ValueMapType &v, constants) { s << boost::format(" %s = %s") % v.first % v.second; @@ -177,9 +178,9 @@ FileContext::FileContext(const class FileModule &module, const Context *parent) if (!module.modulePath().empty()) this->document_path = module.modulePath(); } -Value FileContext::sub_evaluate_function(const std::string &name, const EvalContext *evalctx, - - FileModule *usedmod) const +ValuePtr FileContext::sub_evaluate_function(const std::string &name, + const EvalContext *evalctx, + FileModule *usedmod) const { FileContext ctx(*usedmod, this->parent); @@ -192,7 +193,8 @@ Value FileContext::sub_evaluate_function(const std::string &name, const EvalCont return usedmod->scope.functions[name]->evaluate(&ctx, evalctx); } -Value FileContext::evaluate_function(const std::string &name, const EvalContext *evalctx) const +ValuePtr FileContext::evaluate_function(const std::string &name, + const EvalContext *evalctx) const { const AbstractFunction *foundf = findLocalFunction(name); if (foundf) return foundf->evaluate(this, evalctx); diff --git a/src/modcontext.h b/src/modcontext.h index 2e33c962..ce6a9d51 100644 --- a/src/modcontext.h +++ b/src/modcontext.h @@ -18,8 +18,8 @@ public: void initializeModule(const Module &m); void registerBuiltin(); - virtual Value evaluate_function(const std::string &name, - const EvalContext *evalctx) const; + virtual ValuePtr evaluate_function(const std::string &name, + const EvalContext *evalctx) const; virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const; @@ -45,7 +45,8 @@ class FileContext : public ModuleContext public: FileContext(const class FileModule &module, const Context *parent); virtual ~FileContext() {} - virtual Value evaluate_function(const std::string &name, const EvalContext *evalctx) const; + virtual ValuePtr evaluate_function(const std::string &name, + const EvalContext *evalctx) const; virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const; @@ -53,5 +54,7 @@ private: const FileModule::ModuleContainer &usedlibs; // This sub_* method is needed to minimize stack usage only. - Value sub_evaluate_function(const std::string &name, const EvalContext *evalctx, FileModule *usedmod) const; + ValuePtr sub_evaluate_function(const std::string &name, + const EvalContext *evalctx, + FileModule *usedmod) const; }; diff --git a/src/module.cc b/src/module.cc index 95224be8..82a16320 100644 --- a/src/module.cc +++ b/src/module.cc @@ -59,14 +59,14 @@ AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstan double AbstractModule::lookup_double_variable_with_default(Context &c, std::string variable, double def) const { - const Value v = c.lookup_variable(variable, true); - return (v.type() == Value::NUMBER) ? v.toDouble() : def; + ValuePtr v = c.lookup_variable(variable, true); + return (v->type() == Value::NUMBER) ? v->toDouble() : def; } std::string AbstractModule::lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const { - const Value v = c.lookup_variable(variable, true); - return (v.type() == Value::STRING) ? v.toString() : def; + ValuePtr v = c.lookup_variable(variable, true); + return (v->type() == Value::STRING) ? v->toString() : def; } std::string AbstractModule::dump(const std::string &indent, const std::string &name) const @@ -195,9 +195,9 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation ModuleContext c(ctx, evalctx); // set $children first since we might have variables depending on it - c.set_variable("$children", Value(double(inst->scope.children.size()))); + c.set_variable("$children", ValuePtr(double(inst->scope.children.size()))); module_stack.push_back(inst->name()); - c.set_variable("$parent_modules", Value(double(module_stack.size()))); + c.set_variable("$parent_modules", ValuePtr(double(module_stack.size()))); c.initializeModule(*this); // FIXME: Set document path to the path of the module #if 0 && DEBUG diff --git a/src/offset.cc b/src/offset.cc index 1b2c7160..a5803430 100644 --- a/src/offset.cc +++ b/src/offset.cc @@ -59,21 +59,21 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti Context c(ctx); c.setVariables(args, evalctx); - node->fn = c.lookup_variable("$fn").toDouble(); - node->fs = c.lookup_variable("$fs").toDouble(); - node->fa = c.lookup_variable("$fa").toDouble(); + node->fn = c.lookup_variable("$fn")->toDouble(); + node->fs = c.lookup_variable("$fs")->toDouble(); + node->fa = c.lookup_variable("$fa")->toDouble(); - Value delta = c.lookup_variable("delta"); + ValuePtr delta = c.lookup_variable("delta"); node->delta = 1; - delta.getDouble(node->delta); + delta->getDouble(node->delta); - Value miter_limit = c.lookup_variable("miter_limit", true); + ValuePtr miter_limit = c.lookup_variable("miter_limit", true); node->miter_limit = 2; - miter_limit.getDouble(node->miter_limit); + miter_limit->getDouble(node->miter_limit); - Value join_type = c.lookup_variable("join_type", true); - if (join_type.type() == Value::STRING) { - std::string jt = join_type.toString(); + ValuePtr join_type = c.lookup_variable("join_type", true); + if (join_type->type() == Value::STRING) { + std::string jt = join_type->toString(); if (std::string("bevel") == jt) { node->join_type = ClipperLib::jtSquare; } else if (std::string("round") == jt) { @@ -84,7 +84,7 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti PRINTB("WARNING: Unknown join_type for offset(): '%s'", jt); } - if ((node->join_type != ClipperLib::jtMiter) && !miter_limit.isUndefined()) { + if ((node->join_type != ClipperLib::jtMiter) && !miter_limit->isUndefined()) { PRINTB("WARNING: miter_limit is ignored in offset() for join_type: '%s'", jt); } } diff --git a/src/parser.y b/src/parser.y index 6c0d5379..79a42a68 100644 --- a/src/parser.y +++ b/src/parser.y @@ -308,15 +308,15 @@ single_module_instantiation: expr: TOK_TRUE { - $$ = new Expression(Value(true)); + $$ = new Expression(ValuePtr(true)); } | TOK_FALSE { - $$ = new Expression(Value(false)); + $$ = new Expression(ValuePtr(false)); } | TOK_UNDEF { - $$ = new Expression(Value::undefined); + $$ = new Expression(ValuePtr::undefined); } | TOK_ID { @@ -333,12 +333,12 @@ expr: } | TOK_STRING { - $$ = new Expression(Value(std::string($1))); + $$ = new Expression(ValuePtr(std::string($1))); free($1); } | TOK_NUMBER { - $$ = new Expression(Value($1)); + $$ = new Expression(ValuePtr($1)); } | TOK_LET '(' arguments_call ')' expr %prec LET { @@ -371,7 +371,7 @@ expr: } | '[' optional_commas ']' { - $$ = new Expression(Value(Value::VectorType())); + $$ = new Expression(ValuePtr(Value::VectorType())); } | '[' vector_expr optional_commas ']' { diff --git a/src/primitives.cc b/src/primitives.cc index 33e59109..ef816b28 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -108,7 +108,7 @@ public: double fn, fs, fa; primitive_type_e type; int convexity; - Value points, paths, faces; + ValuePtr points, paths, faces; virtual Geometry *createGeometry() const; }; @@ -125,19 +125,19 @@ public: */ Value PrimitiveModule::lookup_radius(const Context &ctx, const std::string &diameter_var, const std::string &radius_var) const { - const Value d = ctx.lookup_variable(diameter_var, true); - const Value r = ctx.lookup_variable(radius_var, true); - const bool r_defined = (r.type() == Value::NUMBER); + ValuePtr d = ctx.lookup_variable(diameter_var, true); + ValuePtr r = ctx.lookup_variable(radius_var, true); + const bool r_defined = (r->type() == Value::NUMBER); - if (d.type() == Value::NUMBER) { + if (d->type() == Value::NUMBER) { if (r_defined) { PRINTB("WARNING: Ignoring radius variable '%s' as diameter '%s' is defined too.", radius_var % diameter_var); } - return Value(d.toDouble() / 2.0); + return Value(d->toDouble() / 2.0); } else if (r_defined) { - return r; + return *r; } else { - return Value(); + return Value::undefined; } } @@ -179,9 +179,9 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta Context c(ctx); c.setVariables(args, evalctx); - node->fn = c.lookup_variable("$fn").toDouble(); - node->fs = c.lookup_variable("$fs").toDouble(); - node->fa = c.lookup_variable("$fa").toDouble(); + node->fn = c.lookup_variable("$fn")->toDouble(); + node->fs = c.lookup_variable("$fs")->toDouble(); + node->fa = c.lookup_variable("$fa")->toDouble(); if (node->fs < F_MINIMUM) { PRINTB("WARNING: $fs too small - clamping to %f", F_MINIMUM); @@ -194,14 +194,14 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta switch (this->type) { case CUBE: { - Value size = c.lookup_variable("size"); - Value center = c.lookup_variable("center"); - size.getDouble(node->x); - size.getDouble(node->y); - size.getDouble(node->z); - size.getVec3(node->x, node->y, node->z); - if (center.type() == Value::BOOL) { - node->center = center.toBool(); + ValuePtr size = c.lookup_variable("size"); + ValuePtr center = c.lookup_variable("center"); + size->getDouble(node->x); + size->getDouble(node->y); + size->getDouble(node->z); + size->getVec3(node->x, node->y, node->z); + if (center->type() == Value::BOOL) { + node->center = center->toBool(); } break; } @@ -213,9 +213,9 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta break; } case CYLINDER: { - const Value h = c.lookup_variable("h"); - if (h.type() == Value::NUMBER) { - node->h = h.toDouble(); + ValuePtr h = c.lookup_variable("h"); + if (h->type() == Value::NUMBER) { + node->h = h->toDouble(); } const Value r = lookup_radius(c, "d", "r"); @@ -232,32 +232,32 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta node->r2 = r2.toDouble(); } - const Value center = c.lookup_variable("center"); - if (center.type() == Value::BOOL) { - node->center = center.toBool(); + ValuePtr center = c.lookup_variable("center"); + if (center->type() == Value::BOOL) { + node->center = center->toBool(); } break; } case POLYHEDRON: { node->points = c.lookup_variable("points"); node->faces = c.lookup_variable("faces"); - if (node->faces.type() == Value::UNDEFINED) { + if (node->faces->type() == Value::UNDEFINED) { // backwards compatible node->faces = c.lookup_variable("triangles", true); - if (node->faces.type() != Value::UNDEFINED) { + if (node->faces->type() != Value::UNDEFINED) { printDeprecation("DEPRECATED: polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead."); } } break; } case SQUARE: { - Value size = c.lookup_variable("size"); - Value center = c.lookup_variable("center"); - size.getDouble(node->x); - size.getDouble(node->y); - size.getVec2(node->x, node->y); - if (center.type() == Value::BOOL) { - node->center = center.toBool(); + ValuePtr size = c.lookup_variable("size"); + ValuePtr center = c.lookup_variable("center"); + size->getDouble(node->x); + size->getDouble(node->y); + size->getVec2(node->x, node->y); + if (center->type() == Value::BOOL) { + node->center = center->toBool(); } break; } @@ -275,7 +275,7 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta } } - node->convexity = c.lookup_variable("convexity", true).toDouble(); + node->convexity = c.lookup_variable("convexity", true)->toDouble(); if (node->convexity < 1) node->convexity = 1; @@ -505,15 +505,15 @@ Geometry *PrimitiveNode::createGeometry() const PolySet *p = new PolySet(3); g = p; p->setConvexity(this->convexity); - for (size_t i=0; ifaces.toVector().size(); i++) + for (size_t i=0; ifaces->toVector().size(); i++) { p->append_poly(); - const Value::VectorType &vec = this->faces.toVector()[i].toVector(); + const Value::VectorType &vec = this->faces->toVector()[i].toVector(); for (size_t j=0; jpoints.toVector().size()) { + if (pt < this->points->toVector().size()) { double px, py, pz; - if (!this->points.toVector()[pt].getVec3(px, py, pz) || + if (!this->points->toVector()[pt].getVec3(px, py, pz) || isinf(px) || isinf(py) || isinf(pz)) { PRINTB("ERROR: Unable to convert point at index %d to a vec3 of numbers", j); delete p; @@ -571,7 +571,7 @@ Geometry *PrimitiveNode::createGeometry() const Outline2d outline; double x,y; - const Value::VectorType &vec = this->points.toVector(); + const Value::VectorType &vec = this->points->toVector(); for (unsigned int i=0;ipaths.toVector().size() == 0 && outline.vertices.size() > 2) { + if (this->paths->toVector().size() == 0 && outline.vertices.size() > 2) { p->addOutline(outline); } else { - BOOST_FOREACH(const Value &polygon, this->paths.toVector()) { + BOOST_FOREACH(const Value &polygon, this->paths->toVector()) { Outline2d curroutline; BOOST_FOREACH(const Value &index, polygon.toVector()) { unsigned int idx = index.toDouble(); @@ -635,8 +635,8 @@ std::string PrimitiveNode::toString() const << ", r2 = " << this->r2 << ", center = " << (center ? "true" : "false") << ")"; break; case POLYHEDRON: - stream << "(points = " << this->points - << ", faces = " << this->faces + stream << "(points = " << *this->points + << ", faces = " << *this->faces << ", convexity = " << this->convexity << ")"; break; case SQUARE: @@ -648,7 +648,7 @@ std::string PrimitiveNode::toString() const << ", $fs = " << this->fs << ", r = " << this->r1 << ")"; break; case POLYGON: - stream << "(points = " << this->points << ", paths = " << this->paths << ", convexity = " << this->convexity << ")"; + stream << "(points = " << *this->points << ", paths = " << *this->paths << ", convexity = " << this->convexity << ")"; break; default: assert(false); diff --git a/src/projection.cc b/src/projection.cc index 7afd0e46..ef9de3df 100644 --- a/src/projection.cc +++ b/src/projection.cc @@ -54,13 +54,13 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst Context c(ctx); c.setVariables(args, evalctx); - Value convexity = c.lookup_variable("convexity", true); - Value cut = c.lookup_variable("cut", true); + ValuePtr convexity = c.lookup_variable("convexity", true); + ValuePtr cut = c.lookup_variable("cut", true); - node->convexity = (int)convexity.toDouble(); + node->convexity = (int)convexity->toDouble(); - if (cut.type() == Value::BOOL) - node->cut_mode = cut.toBool(); + if (cut->type() == Value::BOOL) + node->cut_mode = cut->toBool(); std::vector instantiatednodes = inst->instantiateChildren(evalctx); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); diff --git a/src/render.cc b/src/render.cc index d29a3886..f2bbf22a 100644 --- a/src/render.cc +++ b/src/render.cc @@ -51,9 +51,9 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti Context c(ctx); c.setVariables(args, evalctx); - Value v = c.lookup_variable("convexity"); - if (v.type() == Value::NUMBER) - node->convexity = (int)v.toDouble(); + ValuePtr v = c.lookup_variable("convexity"); + if (v->type() == Value::NUMBER) + node->convexity = (int)v->toDouble(); std::vector instantiatednodes = inst->instantiateChildren(evalctx); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index ce52fd79..eac1d7b9 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -57,25 +57,25 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI Context c(ctx); c.setVariables(args, evalctx); - node->fn = c.lookup_variable("$fn").toDouble(); - node->fs = c.lookup_variable("$fs").toDouble(); - node->fa = c.lookup_variable("$fa").toDouble(); + node->fn = c.lookup_variable("$fn")->toDouble(); + node->fs = c.lookup_variable("$fs")->toDouble(); + node->fa = c.lookup_variable("$fa")->toDouble(); - Value file = c.lookup_variable("file"); - Value layer = c.lookup_variable("layer", true); - Value convexity = c.lookup_variable("convexity", true); - Value origin = c.lookup_variable("origin", true); - Value scale = c.lookup_variable("scale", true); + ValuePtr file = c.lookup_variable("file"); + ValuePtr layer = c.lookup_variable("layer", true); + ValuePtr convexity = c.lookup_variable("convexity", true); + ValuePtr origin = c.lookup_variable("origin", true); + ValuePtr scale = c.lookup_variable("scale", true); - if (!file.isUndefined()) { + if (!file->isUndefined()) { printDeprecation("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); - node->filename = lookup_file(file.toString(), inst->path(), c.documentPath()); + node->filename = lookup_file(file->toString(), inst->path(), c.documentPath()); } - node->layername = layer.isUndefined() ? "" : layer.toString(); - node->convexity = (int)convexity.toDouble(); - origin.getVec2(node->origin_x, node->origin_y); - node->scale = scale.toDouble(); + node->layername = layer->isUndefined() ? "" : layer->toString(); + node->convexity = (int)convexity->toDouble(); + origin->getVec2(node->origin_x, node->origin_y); + node->scale = scale->toDouble(); if (node->convexity <= 0) node->convexity = 1; diff --git a/src/surface.cc b/src/surface.cc index e8a93355..dbfac901 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -93,22 +93,22 @@ AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstant Context c(ctx); c.setVariables(args, evalctx); - Value fileval = c.lookup_variable("file"); - node->filename = lookup_file(fileval.isUndefined() ? "" : fileval.toString(), inst->path(), c.documentPath()); + ValuePtr fileval = c.lookup_variable("file"); + node->filename = lookup_file(fileval->isUndefined() ? "" : fileval->toString(), inst->path(), c.documentPath()); - Value center = c.lookup_variable("center", true); - if (center.type() == Value::BOOL) { - node->center = center.toBool(); + ValuePtr center = c.lookup_variable("center", true); + if (center->type() == Value::BOOL) { + node->center = center->toBool(); } - Value convexity = c.lookup_variable("convexity", true); - if (convexity.type() == Value::NUMBER) { - node->convexity = (int)convexity.toDouble(); + ValuePtr convexity = c.lookup_variable("convexity", true); + if (convexity->type() == Value::NUMBER) { + node->convexity = (int)convexity->toDouble(); } - Value invert = c.lookup_variable("invert", true); - if (invert.type() == Value::BOOL) { - node->invert = invert.toBool(); + ValuePtr invert = c.lookup_variable("invert", true); + if (invert->type() == Value::BOOL) { + node->invert = invert->toBool(); } return node; diff --git a/src/text.cc b/src/text.cc index 64254b90..0cc12889 100644 --- a/src/text.cc +++ b/src/text.cc @@ -54,9 +54,9 @@ AbstractNode *TextModule::instantiate(const Context *ctx, const ModuleInstantiat Context c(ctx); c.setVariables(args, evalctx); - double fn = c.lookup_variable("$fn").toDouble(); - double fa = c.lookup_variable("$fa").toDouble(); - double fs = c.lookup_variable("$fs").toDouble(); + double fn = c.lookup_variable("$fn")->toDouble(); + double fa = c.lookup_variable("$fa")->toDouble(); + double fs = c.lookup_variable("$fs")->toDouble(); node->params.set_fn(fn); node->params.set_fa(fa); diff --git a/src/transform.cc b/src/transform.cc index 25723fec..74a7f7be 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -87,45 +87,45 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta if (this->type == SCALE) { Vector3d scalevec(1,1,1); - Value v = c.lookup_variable("v"); - if (!v.getVec3(scalevec[0], scalevec[1], scalevec[2], 1.0)) { + ValuePtr v = c.lookup_variable("v"); + if (!v->getVec3(scalevec[0], scalevec[1], scalevec[2], 1.0)) { double num; - if (v.getDouble(num)) scalevec.setConstant(num); + if (v->getDouble(num)) scalevec.setConstant(num); } node->matrix.scale(scalevec); } else if (this->type == ROTATE) { - Value val_a = c.lookup_variable("a"); - if (val_a.type() == Value::VECTOR) + ValuePtr val_a = c.lookup_variable("a"); + if (val_a->type() == Value::VECTOR) { Eigen::AngleAxisd rotx(0, Vector3d::UnitX()); Eigen::AngleAxisd roty(0, Vector3d::UnitY()); Eigen::AngleAxisd rotz(0, Vector3d::UnitZ()); double a; - if (val_a.toVector().size() > 0) { - val_a.toVector()[0].getDouble(a); + if (val_a->toVector().size() > 0) { + val_a->toVector()[0].getDouble(a); rotx = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitX()); } - if (val_a.toVector().size() > 1) { - val_a.toVector()[1].getDouble(a); + if (val_a->toVector().size() > 1) { + val_a->toVector()[1].getDouble(a); roty = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitY()); } - if (val_a.toVector().size() > 2) { - val_a.toVector()[2].getDouble(a); + if (val_a->toVector().size() > 2) { + val_a->toVector()[2].getDouble(a); rotz = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitZ()); } node->matrix.rotate(rotz * roty * rotx); } else { - Value val_v = c.lookup_variable("v"); + ValuePtr val_v = c.lookup_variable("v"); double a = 0; - val_a.getDouble(a); + val_a->getDouble(a); Vector3d axis(0,0,1); - if (val_v.getVec3(axis[0], axis[1], axis[2])) { + if (val_v->getVec3(axis[0], axis[1], axis[2])) { if (axis.squaredNorm() > 0) axis.normalize(); } @@ -136,10 +136,10 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta } else if (this->type == MIRROR) { - Value val_v = c.lookup_variable("v"); + ValuePtr val_v = c.lookup_variable("v"); double x = 1, y = 0, z = 0; - if (val_v.getVec3(x, y, z)) { + if (val_v->getVec3(x, y, z)) { if (x != 0.0 || y != 0.0 || z != 0.0) { double sn = 1.0 / sqrt(x*x + y*y + z*z); x *= sn, y *= sn, z *= sn; @@ -158,19 +158,20 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta } else if (this->type == TRANSLATE) { - Value v = c.lookup_variable("v"); + ValuePtr v = c.lookup_variable("v"); Vector3d translatevec(0,0,0); - v.getVec3(translatevec[0], translatevec[1], translatevec[2]); + v->getVec3(translatevec[0], translatevec[1], translatevec[2]); node->matrix.translate(translatevec); } else if (this->type == MULTMATRIX) { - Value v = c.lookup_variable("m"); - if (v.type() == Value::VECTOR) { + ValuePtr v = c.lookup_variable("m"); + if (v->type() == Value::VECTOR) { for (int i = 0; i < 16; i++) { size_t x = i / 4, y = i % 4; - if (y < v.toVector().size() && v.toVector()[y].type() == Value::VECTOR && x < v.toVector()[y].toVector().size()) - v.toVector()[y].toVector()[x].getDouble(node->matrix(y, x)); + if (y < v->toVector().size() && v->toVector()[y].type() == + Value::VECTOR && x < v->toVector()[y].toVector().size()) + v->toVector()[y].toVector()[x].getDouble(node->matrix(y, x)); } } } @@ -189,7 +190,7 @@ std::string TransformNode::toString() const for (int j=0;j<4;j++) { stream << "["; for (int i=0;i<4;i++) { - Value v( this->matrix(j, i) ); + Value v(this->matrix(j, i)); stream << v; if (i != 3) stream << ", "; } diff --git a/src/value.cc b/src/value.cc index 66391a95..3180f2b0 100644 --- a/src/value.cc +++ b/src/value.cc @@ -41,6 +41,9 @@ #include +Value Value::undefined; +ValuePtr ValuePtr::undefined; + std::ostream &operator<<(std::ostream &stream, const Filename &filename) { fs::path fnpath = fs::path( (std::string)filename ); @@ -77,8 +80,6 @@ std::ostream &operator<<(std::ostream &stream, const QuotedString &s) return stream; } -Value Value::undefined; - Value::Value() : value(boost::blank()) { // std::cout << "creating undef\n"; @@ -688,7 +689,7 @@ public: } }; -Value Value::operator[](const Value &v) +Value Value::operator[](const Value &v) const { return boost::apply_visitor(bracket_visitor(), this->value, v.value); } @@ -790,3 +791,119 @@ bool Value::RangeType::iterator::operator!=(const self_type &other) const { return !(*this == other); } + +ValuePtr::ValuePtr() +{ + this->reset(new Value()); +} + +ValuePtr::ValuePtr(const Value &v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(bool v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(int v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(double v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(const std::string &v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(const char *v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(const char v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(const Value::VectorType &v) +{ + this->reset(new Value(v)); +} + +ValuePtr::ValuePtr(const Value::RangeType &v) +{ + this->reset(new Value(v)); +} + +bool ValuePtr::operator==(const ValuePtr &v) const +{ + return ValuePtr(**this == *v); +} + +bool ValuePtr::operator!=(const ValuePtr &v) const +{ + return ValuePtr(**this != *v); +} + +bool ValuePtr::operator<(const ValuePtr &v) const +{ + return ValuePtr(**this < *v); +} + +bool ValuePtr::operator<=(const ValuePtr &v) const +{ + return ValuePtr(**this <= *v); +} + +bool ValuePtr::operator>=(const ValuePtr &v) const +{ + return ValuePtr(**this >= *v); +} + +bool ValuePtr::operator>(const ValuePtr &v) const +{ + return ValuePtr(**this > *v); +} + +ValuePtr ValuePtr::operator-() const +{ + return ValuePtr(-**this); +} + +ValuePtr ValuePtr::operator[](const ValuePtr &v) const +{ + return ValuePtr((**this)[*v]); +} + +ValuePtr ValuePtr::operator+(const ValuePtr &v) const +{ + return ValuePtr(**this + *v); +} + +ValuePtr ValuePtr::operator-(const ValuePtr &v) const +{ + return ValuePtr(**this - *v); +} + +ValuePtr ValuePtr::operator*(const ValuePtr &v) const +{ + return ValuePtr(**this * *v); +} + +ValuePtr ValuePtr::operator/(const ValuePtr &v) const +{ + return ValuePtr(**this / *v); +} + +ValuePtr ValuePtr::operator%(const ValuePtr &v) const +{ + return ValuePtr(**this % *v); +} + diff --git a/src/value.h b/src/value.h index 6c59ef2c..bfd08376 100644 --- a/src/value.h +++ b/src/value.h @@ -11,6 +11,7 @@ #include #endif #include +#include "memory.h" class QuotedString : public std::string { @@ -138,7 +139,7 @@ public: bool operator>=(const Value &v) const; bool operator>(const Value &v) const; Value operator-() const; - Value operator[](const Value &v); + Value operator[](const Value &v) const; Value operator+(const Value &v) const; Value operator-(const Value &v) const; Value operator*(const Value &v) const; @@ -160,3 +161,40 @@ private: Variant value; }; + +class ValuePtr : public shared_ptr +{ +public: + static ValuePtr undefined; + + ValuePtr(); + explicit ValuePtr(const Value &v); + ValuePtr(bool v); + ValuePtr(int v); + ValuePtr(double v); + ValuePtr(const std::string &v); + ValuePtr(const char *v); + ValuePtr(const char v); + ValuePtr(const Value::VectorType &v); + ValuePtr(const Value::RangeType &v); + + operator bool() const { return **this; } + + bool operator==(const ValuePtr &v) const; + bool operator!=(const ValuePtr &v) const; + bool operator<(const ValuePtr &v) const; + bool operator<=(const ValuePtr &v) const; + bool operator>=(const ValuePtr &v) const; + bool operator>(const ValuePtr &v) const; + ValuePtr operator-() const; + ValuePtr operator[](const ValuePtr &v) const; + ValuePtr operator+(const ValuePtr &v) const; + ValuePtr operator-(const ValuePtr &v) const; + ValuePtr operator*(const ValuePtr &v) const; + ValuePtr operator/(const ValuePtr &v) const; + ValuePtr operator%(const ValuePtr &v) const; + + const Value &operator*() const { return *this->get(); } + +private: +};