#409 Pass Value objects as shared_ptr instances instead of by Value to battle excess stack usage

master
Marius Kintel 2014-11-23 00:59:17 -05:00
parent ef262f62a2
commit 406e6e1bac
33 changed files with 786 additions and 610 deletions

View File

@ -94,19 +94,19 @@ std::string Builtins::isDeprecated(const std::string &name)
Builtins::Builtins() Builtins::Builtins()
{ {
this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new Expression(Value(0.0))))); this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new Expression(ValuePtr(0.0)))));
this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr<Expression>(new Expression(Value(2.0))))); this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr<Expression>(new Expression(ValuePtr(2.0)))));
this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr<Expression>(new Expression(Value(12.0))))); this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr<Expression>(new Expression(ValuePtr(12.0)))));
this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new Expression(Value(0.0))))); this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new Expression(ValuePtr(0.0)))));
Value::VectorType zero3; Value::VectorType zero3;
zero3.push_back(Value(0.0)); zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0)); 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<Expression>(new Expression(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new Expression(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new Expression(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new Expression(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new Expression(500)))); this->globalscope.assignments.push_back(Assignment("$vpd", boost::shared_ptr<Expression>(new Expression(ValuePtr(500)))));
} }
Builtins::~Builtins() Builtins::~Builtins()

View File

@ -63,8 +63,11 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); 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) { if (type == MINKOWSKI) {
convexity = c.lookup_variable("convexity", true); convexity = c.lookup_variable("convexity", true);
} }
@ -81,31 +84,31 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
} }
if (type == RESIZE) { if (type == RESIZE) {
Value ns = c.lookup_variable("newsize"); ValuePtr ns = c.lookup_variable("newsize");
node->newsize << 0,0,0; node->newsize << 0,0,0;
if ( ns.type() == Value::VECTOR ) { if ( ns->type() == Value::VECTOR ) {
Value::VectorType vs = ns.toVector(); const Value::VectorType &vs = ns->toVector();
if ( vs.size() >= 1 ) node->newsize[0] = vs[0].toDouble(); if ( vs.size() >= 1 ) node->newsize[0] = vs[0].toDouble();
if ( vs.size() >= 2 ) node->newsize[1] = vs[1].toDouble(); if ( vs.size() >= 2 ) node->newsize[1] = vs[1].toDouble();
if ( vs.size() >= 3 ) node->newsize[2] = vs[2].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; node->autosize << false, false, false;
if ( autosize.type() == Value::VECTOR ) { if ( autosize->type() == Value::VECTOR ) {
Value::VectorType va = autosize.toVector(); const Value::VectorType &va = autosize->toVector();
if ( va.size() >= 1 ) node->autosize[0] = va[0].toBool(); if ( va.size() >= 1 ) node->autosize[0] = va[0].toBool();
if ( va.size() >= 2 ) node->autosize[1] = va[1].toBool(); if ( va.size() >= 2 ) node->autosize[1] = va[1].toBool();
if ( va.size() >= 3 ) node->autosize[2] = va[2].toBool(); if ( va.size() >= 3 ) node->autosize[2] = va[2].toBool();
} }
else if ( autosize.type() == Value::BOOL ) { else if ( autosize->type() == Value::BOOL ) {
node->autosize << autosize.toBool(),autosize.toBool(),autosize.toBool(); node->autosize << autosize->toBool(),autosize->toBool(),autosize->toBool();
} }
} }
node->convexity = (int)convexity.toDouble(); node->convexity = (int)convexity->toDouble();
node->path = path; node->path = path;
node->subdiv_type = subdiv_type.toString(); node->subdiv_type = subdiv_type->toString();
node->level = (int)level.toDouble(); node->level = (int)level->toDouble();
if (node->level <= 1) if (node->level <= 1)
node->level = 1; node->level = 1;
@ -150,7 +153,7 @@ std::string CgaladvNode::toString() const
stream << "(convexity = " << this->convexity << ")"; stream << "(convexity = " << this->convexity << ")";
break; break;
case GLIDE: case GLIDE:
stream << "(path = " << this->path << ", convexity = " << this->convexity << ")"; stream << "(path = " << *this->path << ", convexity = " << this->convexity << ")";
break; break;
case SUBDIV: case SUBDIV:
stream << "(level = " << this->level << ", convexity = " << this->convexity << ")"; stream << "(level = " << this->level << ", convexity = " << this->convexity << ")";

View File

@ -26,7 +26,7 @@ public:
virtual std::string toString() const; virtual std::string toString() const;
virtual std::string name() const; virtual std::string name() const;
Value path; ValuePtr path;
std::string subdiv_type; std::string subdiv_type;
int convexity, level; int convexity, level;
Vector3d newsize; Vector3d newsize;

View File

@ -219,15 +219,15 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
Value v = c.lookup_variable("c"); ValuePtr v = c.lookup_variable("c");
if (v.type() == Value::VECTOR) { if (v->type() == Value::VECTOR) {
for (size_t i = 0; i < 4; i++) { 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) 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]); 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) { } else if (v->type() == Value::STRING) {
std::string colorname = v.toString(); std::string colorname = v->toString();
boost::algorithm::to_lower(colorname); boost::algorithm::to_lower(colorname);
Color4f color; Color4f color;
if (webcolors.find(colorname) != webcolors.end()) { 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"); PRINT_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors");
} }
} }
Value alpha = c.lookup_variable("alpha"); ValuePtr alpha = c.lookup_variable("alpha");
if (alpha.type() == Value::NUMBER) { if (alpha->type() == Value::NUMBER) {
node->color[3] = alpha.toDouble(); node->color[3] = alpha->toDouble();
} }
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx); std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);

View File

@ -78,14 +78,14 @@ void Context::setVariables(const AssignmentList &args,
const EvalContext *evalctx) const EvalContext *evalctx)
{ {
BOOST_FOREACH(const Assignment &arg, args) { 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) { if (evalctx) {
size_t posarg = 0; size_t posarg = 0;
for (size_t i=0; i<evalctx->numArgs(); i++) { for (size_t i=0; i<evalctx->numArgs(); i++) {
const std::string &name = evalctx->getArgName(i); const std::string &name = evalctx->getArgName(i);
const Value &val = evalctx->getArgValue(i); ValuePtr val = evalctx->getArgValue(i);
if (name.empty()) { if (name.empty()) {
if (posarg < args.size()) this->set_variable(args[posarg++].first, val); if (posarg < args.size()) this->set_variable(args[posarg++].first, val);
} else { } 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; if (is_config_variable(name)) this->config_variables[name] = value;
else this->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()) { if (this->constants.find(name) != this->constants.end()) {
PRINTB("WARNING: Attempt to modify constant '%s'.", name); 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) { if (!this->ctx_stack) {
PRINT("ERROR: Context had null stack in lookup_variable()!!"); PRINT("ERROR: Context had null stack in lookup_variable()!!");
return Value(); return ValuePtr::undefined;
} }
if (is_config_variable(name)) { if (is_config_variable(name)) {
for (int i = this->ctx_stack->size()-1; i >= 0; i--) { 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()) if (confvars.find(name) != confvars.end())
return confvars.find(name)->second; return confvars.find(name)->second;
} }
return Value(); return ValuePtr::undefined;
} }
if (!this->parent && this->constants.find(name) != this->constants.end()) if (!this->parent && this->constants.find(name) != this->constants.end())
return this->constants.find(name)->second; 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); return this->parent->lookup_variable(name, silent);
if (!silent) if (!silent)
PRINTB("WARNING: Ignoring unknown variable '%s'.", name); PRINTB("WARNING: Ignoring unknown variable '%s'.", name);
return Value(); return ValuePtr::undefined;
} }
bool Context::has_local_variable(const std::string &name) const 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(); 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); if (this->parent) return this->parent->evaluate_function(name, evalctx);
PRINTB("WARNING: Ignoring unknown function '%s'.", name); PRINTB("WARNING: Ignoring unknown function '%s'.", name);
return Value(); return ValuePtr::undefined;
} }
AbstractNode *Context::instantiate_module(const ModuleInstantiation &inst, const EvalContext *evalctx) const 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<std::string, Value> ValueMapType; typedef std::pair<std::string, ValuePtr> ValueMapType;
s << " vars:"; s << " vars:";
BOOST_FOREACH(const ValueMapType &v, constants) { BOOST_FOREACH(const ValueMapType &v, constants) {
s << boost::format(" %s = %s") % v.first % v.second; s << boost::format(" %s = %s") % v.first % v.second;

View File

@ -5,6 +5,7 @@
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include "value.h" #include "value.h"
#include "typedefs.h" #include "typedefs.h"
#include "memory.h"
class Context class Context
{ {
@ -14,16 +15,18 @@ public:
virtual ~Context(); virtual ~Context();
const Context *getParent() const { return this->parent; } 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; virtual class AbstractNode *instantiate_module(const class ModuleInstantiation &inst, const EvalContext *evalctx) const;
void setVariables(const AssignmentList &args, void setVariables(const AssignmentList &args,
const class EvalContext *evalctx = NULL); 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_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); 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; bool has_local_variable(const std::string &name) const;
void setDocumentPath(const std::string &path) { this->document_path = path; } void setDocumentPath(const std::string &path) { this->document_path = path; }
@ -36,7 +39,7 @@ protected:
const Context *parent; const Context *parent;
Stack *ctx_stack; Stack *ctx_stack;
typedef boost::unordered_map<std::string, Value> ValueMap; typedef boost::unordered_map<std::string, ValuePtr> ValueMap;
ValueMap constants; ValueMap constants;
ValueMap variables; ValueMap variables;
ValueMap config_variables; ValueMap config_variables;

View File

@ -62,7 +62,7 @@ public: // methods
static const EvalContext* getLastModuleCtx(const EvalContext *evalctx); 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 private: // data
Type type; Type type;
@ -74,27 +74,27 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst
{ {
if (evalctx->numArgs() > l) { if (evalctx->numArgs() > l) {
const std::string &it_name = evalctx->getArgName(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); Context c(ctx);
if (it_values.type() == Value::RANGE) { if (it_values->type() == Value::RANGE) {
Value::RangeType range = it_values.toRange(); Value::RangeType range = it_values->toRange();
boost::uint32_t steps = range.nbsteps(); boost::uint32_t steps = range.nbsteps();
if (steps >= 10000) { if (steps >= 10000) {
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps); PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
} else { } else {
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) { 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); for_eval(node, inst, l+1, &c, evalctx);
} }
} }
} }
else if (it_values.type() == Value::VECTOR) { else if (it_values->type() == Value::VECTOR) {
for (size_t i = 0; i < it_values.toVector().size(); i++) { for (size_t i = 0; i < it_values->toVector().size(); i++) {
c.set_variable(it_name, it_values.toVector()[i]); c.set_variable(it_name, it_values->toVector()[i]);
for_eval(node, inst, l+1, &c, evalctx); 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); c.set_variable(it_name, it_values);
for_eval(node, inst, l+1, &c, evalctx); for_eval(node, inst, l+1, &c, evalctx);
} }
@ -165,7 +165,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
int n = 0; int n = 0;
if (evalctx->numArgs() > 0) { if (evalctx->numArgs() > 0) {
double v; double v;
if (evalctx->getArgValue(0).getDouble(v)) { if (evalctx->getArgValue(0)->getDouble(v)) {
n = trunc(v); n = trunc(v);
if (n < 0) { if (n < 0) {
PRINTB("WARNING: Negative child index (%d) not allowed", n); 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) { else if (evalctx->numArgs()>0) {
// one (or more ignored) parameter // one (or more ignored) parameter
const Value& value = evalctx->getArgValue(0); ValuePtr value = evalctx->getArgValue(0);
if (value.type() == Value::NUMBER) { if (value->type() == Value::NUMBER) {
return getChild(value,modulectx); return getChild(*value, modulectx);
} }
else if (value.type() == Value::VECTOR) { else if (value->type() == Value::VECTOR) {
AbstractNode* node = new AbstractNode(inst); 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) { foreach (const Value::VectorType::value_type& vectvalue, vect) {
AbstractNode* childnode = getChild(vectvalue,modulectx); AbstractNode* childnode = getChild(vectvalue,modulectx);
if (childnode==NULL) continue; // error if (childnode==NULL) continue; // error
@ -227,9 +227,9 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
} }
return node; return node;
} }
else if (value.type() == Value::RANGE) { else if (value->type() == Value::RANGE) {
AbstractNode* node = new AbstractNode(inst); AbstractNode* node = new AbstractNode(inst);
Value::RangeType range = value.toRange(); Value::RangeType range = value->toRange();
boost::uint32_t steps = range.nbsteps(); boost::uint32_t steps = range.nbsteps();
if (steps >= 10000) { if (steps >= 10000) {
PRINTB("WARNING: Bad range parameter for children: too many elements (%lu).", steps); 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 { else {
// Invalid parameter // Invalid parameter
// (e.g. first child of difference is invalid) // (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; return NULL;
} }
} }
@ -264,11 +264,11 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
for (size_t i = 0; i < inst->arguments.size(); i++) { for (size_t i = 0; i < inst->arguments.size(); i++) {
if (i > 0) msg << ", "; if (i > 0) msg << ", ";
if (!evalctx->getArgName(i).empty()) msg << evalctx->getArgName(i) << " = "; if (!evalctx->getArgName(i).empty()) msg << evalctx->getArgName(i) << " = ";
Value val = evalctx->getArgValue(i); ValuePtr val = evalctx->getArgValue(i);
if (val.type() == Value::STRING) { if (val->type() == Value::STRING) {
msg << '"' << val.toString() << '"'; msg << '"' << val->toString() << '"';
} else { } else {
msg << val.toString(); msg << val->toString();
} }
} }
PRINTB("%s", msg.str()); PRINTB("%s", msg.str());
@ -293,7 +293,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
if (type == IF) if (type == IF)
{ {
const IfElseModuleInstantiation *ifelse = dynamic_cast<const IfElseModuleInstantiation*>(inst); const IfElseModuleInstantiation *ifelse = dynamic_cast<const IfElseModuleInstantiation*>(inst);
if (evalctx->numArgs() > 0 && evalctx->getArgValue(0).toBool()) { if (evalctx->numArgs() > 0 && evalctx->getArgValue(0)->toBool()) {
std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx); std::vector<AbstractNode *> instantiatednodes = ifelse->instantiateChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
} }

View File

@ -39,11 +39,11 @@
#include <stdint.h> #include <stdint.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
boost::unordered_map<std::string,Value> dxf_dim_cache; boost::unordered_map<std::string, ValuePtr> dxf_dim_cache;
boost::unordered_map<std::string,Value> dxf_cross_cache; boost::unordered_map<std::string, ValuePtr> dxf_cross_cache;
namespace fs = boost::filesystem; 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 filename;
std::string layername; 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. // since the path is only available for ModuleInstantiations, not function expressions.
// See issue #217 // See issue #217
for (size_t i = 0; i < evalctx->numArgs(); i++) { for (size_t i = 0; i < evalctx->numArgs(); i++) {
if (evalctx->getArgName(i) == "file") ValuePtr n = evalctx->getArgName(i);
filename = lookup_file(evalctx->getArgValue(i).toString(), ValuePtr v = evalctx->getArgValue(i);
if (evalctx->getArgName(i) == "file") {
filename = lookup_file(v->toString(),
evalctx->documentPath(), ctx->documentPath()); evalctx->documentPath(), ctx->documentPath());
if (evalctx->getArgName(i) == "layer") }
layername = evalctx->getArgValue(i).toString(); if (n == "layer") layername = v->toString();
if (evalctx->getArgName(i) == "origin") if (n == "origin") v->getVec2(xorigin, yorigin);
evalctx->getArgValue(i).getVec2(xorigin, yorigin); if (n == "scale") v->getDouble(scale);
if (evalctx->getArgName(i) == "scale") if (n == "name") name = v->toString();
evalctx->getArgValue(i).getDouble(scale);
if (evalctx->getArgName(i) == "name")
name = evalctx->getArgValue(i).toString();
} }
std::stringstream keystream; 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 y = d->coords[4][1] - d->coords[3][1];
double angle = d->angle; double angle = d->angle;
double distance_projected_on_line = fabs(x * cos(angle*M_PI/180) + y * sin(angle*M_PI/180)); 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) { else if (type == 1) {
// Aligned // Aligned
double x = d->coords[4][0] - d->coords[3][0]; double x = d->coords[4][0] - d->coords[3][0];
double y = d->coords[4][1] - d->coords[3][1]; 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) { else if (type == 2) {
// Angular // Angular
double a1 = atan2(d->coords[0][0] - d->coords[5][0], d->coords[0][1] - d->coords[5][1]); 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]); 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) { else if (type == 3 || type == 4) {
// Diameter or Radius // Diameter or Radius
double x = d->coords[5][0] - d->coords[0][0]; double x = d->coords[5][0] - d->coords[0][0];
double y = d->coords[5][1] - d->coords[0][1]; 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) { else if (type == 5) {
// Angular 3 Point // Angular 3 Point
} }
else if (type == 6) { else if (type == 6) {
// Ordinate // 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!", PRINTB("WARNING: Dimension '%s' in '%s', layer '%s' has unsupported type!",
name % filename % layername); name % filename % layername);
return Value(); return ValuePtr::undefined;
} }
PRINTB("WARNING: Can't find dimension '%s' in '%s', layer '%s'!", PRINTB("WARNING: Can't find dimension '%s' in '%s', layer '%s'!",
name % filename % layername); 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 filename;
std::string layername; 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. // since the path is only available for ModuleInstantiations, not function expressions.
// See isse #217 // See isse #217
for (size_t i = 0; i < evalctx->numArgs(); i++) { for (size_t i = 0; i < evalctx->numArgs(); i++) {
if (evalctx->getArgName(i) == "file") ValuePtr n = evalctx->getArgName(i);
filename = ctx->getAbsolutePath(evalctx->getArgValue(i).toString()); ValuePtr v = evalctx->getArgValue(i);
if (evalctx->getArgName(i) == "layer") if (n == "file") filename = ctx->getAbsolutePath(v->toString());
layername = evalctx->getArgValue(i).toString(); if (n == "layer") layername = v->toString();
if (evalctx->getArgName(i) == "origin") if (n == "origin") v->getVec2(xorigin, yorigin);
evalctx->getArgValue(i).getVec2(xorigin, yorigin); if (n == "scale") v->getDouble(scale);
if (evalctx->getArgName(i) == "scale")
evalctx->getArgValue(i).getDouble(scale);
} }
std::stringstream keystream; std::stringstream keystream;
@ -174,8 +171,9 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
<< "|" << filesize; << "|" << filesize;
std::string key = keystream.str(); 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; return dxf_cross_cache.find(key)->second;
}
DxfData dxf(36, 0, 0, filename, layername, xorigin, yorigin, scale); 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; Value::VectorType ret;
ret.push_back(Value(x)); ret.push_back(Value(x));
ret.push_back(Value(y)); 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); PRINTB("WARNING: Can't find cross in '%s', layer '%s'!", filename % layername);
return Value(); return ValuePtr::undefined;
} }
void initialize_builtin_dxf_dim() void initialize_builtin_dxf_dim()

View File

@ -3,5 +3,5 @@
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include "value.h" #include "value.h"
extern boost::unordered_map<std::string,Value> dxf_dim_cache; extern boost::unordered_map<std::string, ValuePtr> dxf_dim_cache;
extern boost::unordered_map<std::string,Value> dxf_cross_cache; extern boost::unordered_map<std::string, ValuePtr> dxf_cross_cache;

View File

@ -14,11 +14,11 @@ const std::string &EvalContext::getArgName(size_t i) const
return this->eval_arguments[i].first; 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()); assert(i < this->eval_arguments.size());
const Assignment &arg = this->eval_arguments[i]; 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 size_t EvalContext::numChildren() const
@ -56,7 +56,7 @@ std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiati
if (m) { if (m) {
s << boost::format(" module args:"); s << boost::format(" module args:");
BOOST_FOREACH(const Assignment &arg, m->definition_arguments) { 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]);
} }
} }
} }

View File

@ -18,7 +18,7 @@ public:
size_t numArgs() const { return this->eval_arguments.size(); } size_t numArgs() const { return this->eval_arguments.size(); }
const std::string &getArgName(size_t i) const; 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; size_t numChildren() const;
ModuleInstantiation *getChild(size_t i) const; ModuleInstantiation *getChild(size_t i) const;
@ -29,6 +29,6 @@ public:
private: private:
const AssignmentList &eval_arguments; const AssignmentList &eval_arguments;
std::vector<std::pair<std::string, Value> > eval_values; std::vector<std::pair<std::string, ValuePtr> > eval_values;
const LocalScope *const scope; const LocalScope *const scope;
}; };

View File

@ -52,7 +52,7 @@ Expression::Expression(const std::string &type, Expression *expr)
this->children.push_back(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<Expression>()); std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>());
} }
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); ValuePtr v1 = this->children[0]->evaluate(context);
if (v1.type() == Value::NUMBER) { if (v1->type() == Value::NUMBER) {
Value v2 = this->children[1]->evaluate(context); ValuePtr v2 = this->children[1]->evaluate(context);
if (v2.type() == Value::NUMBER) { if (v2->type() == Value::NUMBER) {
if (this->children.size() == 2) { if (this->children.size() == 2) {
Value::RangeType range(v1.toDouble(), v2.toDouble()); Value::RangeType range(v1->toDouble(), v2->toDouble());
return Value(range); return ValuePtr(range);
} else { } else {
Value v3 = this->children[2]->evaluate(context); ValuePtr v3 = this->children[2]->evaluate(context);
if (v3.type() == Value::NUMBER) { if (v3->type() == Value::NUMBER) {
Value::RangeType range(v1.toDouble(), v2.toDouble(), v3.toDouble()); Value::RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
return Value(range); 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 == "x") return v[0];
if (this->var_name == "y") return v[1]; if (this->var_name == "y") return v[1];
if (this->var_name == "z") return v[2]; if (this->var_name == "z") return v[2];
} else if (v.type() == Value::RANGE) { } else if (v->type() == Value::RANGE) {
if (this->var_name == "begin") return Value(v[0]); if (this->var_name == "begin") return v[0];
if (this->var_name == "step") return Value(v[1]); if (this->var_name == "step") return v[1];
if (this->var_name == "end") return Value(v[2]); 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; Value::VectorType vec;
BOOST_FOREACH(const Expression *e, this->children) { 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) { if (this->recursioncount >= 1000) {
PRINTB("ERROR: Recursion detected calling function '%s'", this->call_funcname); PRINTB("ERROR: Recursion detected calling function '%s'", this->call_funcname);
// TO DO: throw function_recursion_detected(); // TO DO: throw function_recursion_detected();
return Value(); return ValuePtr::undefined;
} }
this->recursioncount += 1; this->recursioncount += 1;
EvalContext c(context, this->call_arguments); 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; this->recursioncount -= 1;
return result; return result;
} }
@ -161,7 +161,7 @@ namespace {
for (int i = 0; i < let_context.numArgs(); i++) { for (int i = 0; i < let_context.numArgs(); i++) {
if (!allow_reassignment && context->has_local_variable(let_context.getArgName(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 { } else {
// NOTE: iteratively evaluated list of arguments // NOTE: iteratively evaluated list of arguments
context->set_variable(let_context.getArgName(i), let_context.getArgValue(i, context)); 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); Context c(context);
evaluate_sequential_assignment(this->call_arguments, &c); 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); 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; Value::VectorType vec;
@ -187,10 +187,10 @@ Value Expression::sub_evaluate_list_comprehension(const Context *context) const
if (this->children[1]->type == "c") { if (this->children[1]->type == "c") {
return this->children[1]->evaluate(context); return this->children[1]->evaluate(context);
} else { } 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") { } else if (this->call_funcname == "for") {
EvalContext for_context(context, this->call_arguments); 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 // comprehension for statements are by the parser reduced to only contain one single element
const std::string &it_name = for_context.getArgName(0); 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); Context c(context);
if (it_values.type() == Value::RANGE) { if (it_values->type() == Value::RANGE) {
Value::RangeType range = it_values.toRange(); Value::RangeType range = it_values->toRange();
boost::uint32_t steps = range.nbsteps(); boost::uint32_t steps = range.nbsteps();
if (steps >= 1000000) { if (steps >= 1000000) {
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps); PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
} else { } else {
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) { 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));
vec.push_back(this->children[0]->evaluate(&c)); vec.push_back((*this->children[0]->evaluate(&c)));
} }
} }
} }
else if (it_values.type() == Value::VECTOR) { else if (it_values->type() == Value::VECTOR) {
for (size_t i = 0; i < it_values.toVector().size(); i++) { for (size_t i = 0; i < it_values->toVector().size(); i++) {
c.set_variable(it_name, it_values.toVector()[i]); c.set_variable(it_name, it_values->toVector()[i]);
vec.push_back(this->children[0]->evaluate(&c)); 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); 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") { if (this->children[0]->type == "c") {
return flatten(vec); return ValuePtr(flatten(vec));
} else { } else {
return vec; return ValuePtr(vec);
} }
} else if (this->call_funcname == "let") { } else if (this->call_funcname == "let") {
Context c(context); 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())) { switch (type2int(this->type.c_str())) {
case '!': case '!':
@ -336,7 +336,7 @@ std::string Expression::toString() const
stream << "!" << *this->children[0]; stream << "!" << *this->children[0];
} }
else if (this->type == "C") { else if (this->type == "C") {
stream << this->const_value; stream << *this->const_value;
} }
else if (this->type == "R") { else if (this->type == "R") {
stream << "[" << *this->children[0] << " : " << *this->children[1]; stream << "[" << *this->children[0] << " : " << *this->children[1];

View File

@ -10,7 +10,7 @@ class Expression
public: public:
std::vector<Expression*> children; std::vector<Expression*> children;
const Value const_value; ValuePtr const_value;
std::string var_name; std::string var_name;
std::string call_funcname; std::string call_funcname;
@ -35,12 +35,12 @@ public:
std::string type; std::string type;
Expression(); Expression();
Expression(const Value &val); Expression(const ValuePtr &val);
Expression(const std::string &type, Expression *left, Expression *right); Expression(const std::string &type, Expression *left, Expression *right);
Expression(const std::string &type, Expression *expr); Expression(const std::string &type, Expression *expr);
~Expression(); ~Expression();
Value evaluate(const class Context *context) const; ValuePtr evaluate(const class Context *context) const;
std::string toString() const; std::string toString() const;
@ -48,12 +48,12 @@ private:
mutable int recursioncount; mutable int recursioncount;
// The following sub_* methods are needed to minimize stack usage only. // The following sub_* methods are needed to minimize stack usage only.
Value sub_evaluate_function(const class Context *context) const; ValuePtr sub_evaluate_function(const class Context *context) const;
Value sub_evaluate_member(const class Context *context) const; ValuePtr sub_evaluate_member(const class Context *context) const;
Value sub_evaluate_range(const class Context *context) const; ValuePtr sub_evaluate_range(const class Context *context) const;
Value sub_evaluate_vector(const class Context *context) const; ValuePtr sub_evaluate_vector(const class Context *context) const;
Value sub_evaluate_let_expression(const class Context *context) const; ValuePtr sub_evaluate_let_expression(const class Context *context) const;
Value sub_evaluate_list_comprehension(const class Context *context) const; ValuePtr sub_evaluate_list_comprehension(const class Context *context) const;
}; };
std::ostream &operator<<(std::ostream &stream, const Expression &expr); std::ostream &operator<<(std::ostream &stream, const Expression &expr);

View File

@ -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 (void)evalctx; // unusued parameter
return Value(); return ValuePtr::undefined;
} }
std::string AbstractFunction::dump(const std::string &indent, const std::string &name) const std::string AbstractFunction::dump(const std::string &indent, const std::string &name) const
@ -87,9 +88,9 @@ Function::~Function()
delete expr; 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); Context c(ctx);
c.setVariables(definition_arguments, evalctx); c.setVariables(definition_arguments, evalctx);
return expr->evaluate(&c); 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); return eval_func(ctx, evalctx);
} }
@ -135,51 +136,51 @@ static inline double rad2deg(double x)
return x * 180.0 / M_PI; 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(fabs(v.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) { if (v->type() == Value::NUMBER) {
register double x = v.toDouble(); register double x = v->toDouble();
return Value((x<0) ? -1.0 : ((x>0) ? 1.0 : 0.0)); 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(); size_t n = evalctx->numArgs();
if (n == 3 || n == 4) { if (n == 3 || n == 4) {
const Value &v0 = evalctx->getArgValue(0); ValuePtr v0 = evalctx->getArgValue(0);
if (v0.type() != Value::NUMBER) goto quit; if (v0->type() != Value::NUMBER) goto quit;
double min = v0.toDouble(); double min = v0->toDouble();
const Value &v1 = evalctx->getArgValue(1); ValuePtr v1 = evalctx->getArgValue(1);
if (v1.type() != Value::NUMBER) goto quit; if (v1->type() != Value::NUMBER) goto quit;
double max = v1.toDouble(); double max = v1->toDouble();
if (max < min) { if (max < min) {
register double tmp = min; min = max; max = tmp; register double tmp = min; min = max; max = tmp;
} }
const Value &v2 = evalctx->getArgValue(2); ValuePtr v2 = evalctx->getArgValue(2);
if (v2.type() != Value::NUMBER) goto quit; if (v2->type() != Value::NUMBER) goto quit;
size_t numresults = std::max( 0, static_cast<int>( v2.toDouble() ) ); size_t numresults = std::max(0, static_cast<int>(v2->toDouble()));
bool deterministic = false; bool deterministic = false;
if (n > 3) { if (n > 3) {
const Value &v3 = evalctx->getArgValue(3); ValuePtr v3 = evalctx->getArgValue(3);
if (v3.type() != Value::NUMBER) goto quit; if (v3->type() != Value::NUMBER) goto quit;
deterministic_rng.seed( (unsigned int) v3.toDouble() ); deterministic_rng.seed((unsigned int) v3->toDouble());
deterministic = true; deterministic = true;
} }
boost::uniform_real<> distributor( min, max ); boost::uniform_real<> distributor( min, max );
@ -190,83 +191,81 @@ Value builtin_rands(const Context *, const EvalContext *evalctx)
} else { } else {
for (size_t i=0; i < numresults; i++) { for (size_t i=0; i < numresults; i++) {
if ( deterministic ) { if ( deterministic ) {
vec.push_back( Value( distributor( deterministic_rng ) ) ); vec.push_back(Value(distributor(deterministic_rng)));
} else { } else {
vec.push_back( Value( distributor( lessdeterministic_rng ) ) ); vec.push_back(Value(distributor(lessdeterministic_rng)));
} }
} }
} }
return Value(vec); return ValuePtr(vec);
} }
quit: 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 // preserve special handling of the first argument
// as a template for vector processing // as a template for vector processing
size_t n = evalctx->numArgs(); size_t n = evalctx->numArgs();
if (n >= 1) { if (n >= 1) {
const Value &v0 = evalctx->getArgValue(0); ValuePtr v0 = evalctx->getArgValue(0);
if (n == 1 && v0.type() == Value::VECTOR && !v0.toVector().empty()) { if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
Value min = v0.toVector()[0]; Value min = v0->toVector()[0];
for (size_t i = 1; i < v0.toVector().size(); i++) { for (size_t i = 1; i < v0->toVector().size(); i++) {
if (v0.toVector()[i] < min) if (v0->toVector()[i] < min) min = v0->toVector()[i];
min = v0.toVector()[i];
} }
return min; return ValuePtr(min);
} }
if (v0.type() == Value::NUMBER) { if (v0->type() == Value::NUMBER) {
double val = v0.toDouble(); double val = v0->toDouble();
for (size_t i = 1; i < n; ++i) { 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: // 4/20/14 semantic change per discussion:
// break on any non-number // break on any non-number
if (v.type() != Value::NUMBER) goto quit; if (v->type() != Value::NUMBER) goto quit;
register double x = v.toDouble(); register double x = v->toDouble();
if (x < val) val = x; if (x < val) val = x;
} }
return Value(val); return ValuePtr(val);
} }
} }
quit: 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 // preserve special handling of the first argument
// as a template for vector processing // as a template for vector processing
size_t n = evalctx->numArgs(); size_t n = evalctx->numArgs();
if (n >= 1) { if (n >= 1) {
const Value &v0 = evalctx->getArgValue(0); ValuePtr v0 = evalctx->getArgValue(0);
if (n == 1 && v0.type() == Value::VECTOR && !v0.toVector().empty()) { if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
Value max = v0.toVector()[0]; Value max = v0->toVector()[0];
for (size_t i = 1; i < v0.toVector().size(); i++) { for (size_t i = 1; i < v0->toVector().size(); i++) {
if (v0.toVector()[i] > max) if (v0->toVector()[i] > max) max = v0->toVector()[i];
max = v0.toVector()[i];
} }
return max; return ValuePtr(max);
} }
if (v0.type() == Value::NUMBER) { if (v0->type() == Value::NUMBER) {
double val = v0.toDouble(); double val = v0->toDouble();
for (size_t i = 1; i < n; ++i) { 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: // 4/20/14 semantic change per discussion:
// break on any non-number // break on any non-number
if (v.type() != Value::NUMBER) goto quit; if (v->type() != Value::NUMBER) goto quit;
register double x = v.toDouble(); register double x = v->toDouble();
if (x > val) val = x; if (x > val) val = x;
} }
return Value(val); return ValuePtr(val);
} }
} }
quit: quit:
return Value(); return ValuePtr::undefined;
} }
// this limit assumes 26+26=52 bits mantissa // this limit assumes 26+26=52 bits mantissa
@ -307,14 +306,14 @@ double sin_degrees(register double x)
return oppose ? -x : 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(sin_degrees(v.toDouble())); return ValuePtr(sin_degrees(v->toDouble()));
} }
return Value(); return ValuePtr::undefined;
} }
double cos_degrees(register double x) double cos_degrees(register double x)
@ -354,220 +353,221 @@ double cos_degrees(register double x)
return oppose ? -x : 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(cos_degrees(v.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(rad2deg(asin(v.toDouble()))); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(rad2deg(acos(v.toDouble()))); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(tan(deg2rad(v.toDouble()))); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(rad2deg(atan(v.toDouble()))); 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) { if (evalctx->numArgs() == 2) {
Value v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1); ValuePtr v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1);
if (v0.type() == Value::NUMBER && v1.type() == Value::NUMBER) if (v0->type() == Value::NUMBER && v1->type() == Value::NUMBER)
return Value(rad2deg(atan2(v0.toDouble(), v1.toDouble()))); 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) { if (evalctx->numArgs() == 2) {
Value v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1); ValuePtr v0 = evalctx->getArgValue(0), v1 = evalctx->getArgValue(1);
if (v0.type() == Value::NUMBER && v1.type() == Value::NUMBER) if (v0->type() == Value::NUMBER && v1->type() == Value::NUMBER)
return Value(pow(v0.toDouble(), v1.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(round(v.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(ceil(v.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(floor(v.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(sqrt(v.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(exp(v.toDouble())); 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::VECTOR) return Value(int(v.toVector().size())); if (v->type() == Value::VECTOR) return ValuePtr(int(v->toVector().size()));
if (v.type() == Value::STRING) { if (v->type() == Value::STRING) {
//Unicode glyph count for the length -- rather than the string (num. of bytes) length. //Unicode glyph count for the length -- rather than the string (num. of bytes) length.
std::string text = v.toString(); std::string text = v->toString();
return Value(int( g_utf8_strlen( text.c_str(), text.size() ) )); 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(); size_t n = evalctx->numArgs();
if (n == 1 || n == 2) { if (n == 1 || n == 2) {
const Value &v0 = evalctx->getArgValue(0); ValuePtr v0 = evalctx->getArgValue(0);
if (v0.type() == Value::NUMBER) { if (v0->type() == Value::NUMBER) {
double x = 10.0, y = v0.toDouble(); double x = 10.0, y = v0->toDouble();
if (n > 1) { if (n > 1) {
const Value &v1 = evalctx->getArgValue(1); ValuePtr v1 = evalctx->getArgValue(1);
if (v1.type() != Value::NUMBER) goto quit; if (v1->type() != Value::NUMBER) goto quit;
x = y; y = v1.toDouble(); x = y; y = v1->toDouble();
} }
return Value(log(y) / log(x)); return ValuePtr(log(y) / log(x));
} }
} }
quit: 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) { if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
return Value(log(v.toDouble())); 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; std::stringstream stream;
for (size_t i = 0; i < evalctx->numArgs(); i++) { 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; std::stringstream stream;
for (size_t i = 0; i < evalctx->numArgs(); i++) { for (size_t i = 0; i < evalctx->numArgs(); i++) {
const Value v = evalctx->getArgValue(i); ValuePtr v = evalctx->getArgValue(i);
stream << v.chrString(); 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; Value::VectorType result;
for (size_t i = 0; i < evalctx->numArgs(); i++) { for (size_t i = 0; i < evalctx->numArgs(); i++) {
const Value v = evalctx->getArgValue(i); ValuePtr v = evalctx->getArgValue(i);
if (v.type() == Value::VECTOR) { if (v->type() == Value::VECTOR) {
Value::VectorType vec = v.toVector(); Value::VectorType vec = v->toVector();
for (Value::VectorType::const_iterator it = vec.begin(); it != vec.end(); it++) { for (Value::VectorType::const_iterator it = vec.begin(); it != vec.end(); it++) {
result.push_back(*it); result.push_back(*it);
} }
} else { } 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; double p, low_p, low_v, high_p, high_v;
if (evalctx->numArgs() < 2 || // Needs two args if (evalctx->numArgs() < 2 || // Needs two args
!evalctx->getArgValue(0).getDouble(p)) // First must be a number !evalctx->getArgValue(0)->getDouble(p)) // First must be a number
return Value(); 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 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)) 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++) { for (size_t i = 1; i < vec.size(); i++) {
double this_p, this_v; double this_p, this_v;
if (vec[i].getVec2(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) if (p <= low_p)
return Value(high_v); return ValuePtr(high_v);
if (p >= high_p) if (p >= high_p)
return Value(low_v); return ValuePtr(low_v);
double f = (p-low_p) / (high_p-low_p); 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; 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); ValuePtr findThis = evalctx->getArgValue(0);
const Value &searchTable = evalctx->getArgValue(1); ValuePtr searchTable = evalctx->getArgValue(1);
unsigned int num_returns_per_match = (evalctx->numArgs() > 2) ? evalctx->getArgValue(2).toDouble() : 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; unsigned int index_col_num = (evalctx->numArgs() > 3) ? evalctx->getArgValue(3)->toDouble() : 0;
Value::VectorType returnvec; Value::VectorType returnvec;
if (findThis.type() == Value::NUMBER) { if (findThis->type() == Value::NUMBER) {
unsigned int matchCount = 0; unsigned int matchCount = 0;
for (size_t j = 0; j < searchTable.toVector().size(); j++) { for (size_t j = 0; j < searchTable->toVector().size(); j++) {
const Value& search_element = searchTable.toVector()[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() && (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))); returnvec.push_back(Value(double(j)));
matchCount++; matchCount++;
if (num_returns_per_match != 0 && matchCount >= num_returns_per_match) break; if (num_returns_per_match != 0 && matchCount >= num_returns_per_match) break;
} }
} }
} else if (findThis.type() == Value::STRING) { } else if (findThis->type() == Value::STRING) {
if (searchTable.type() == Value::STRING) { if (searchTable->type() == Value::STRING) {
returnvec = search(findThis.toString(), searchTable.toString(), num_returns_per_match, index_col_num); returnvec = search(findThis->toString(), searchTable->toString(), num_returns_per_match, index_col_num);
} }
else { 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) { } else if (findThis->type() == Value::VECTOR) {
for (size_t i = 0; i < findThis.toVector().size(); i++) { for (size_t i = 0; i < findThis->toVector().size(); i++) {
unsigned int matchCount = 0; unsigned int matchCount = 0;
Value::VectorType resultvec; 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) || if ((index_col_num == 0 && find_value == search_element) ||
(index_col_num < search_element.toVector().size() && (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 (num_returns_per_match == 1 && matchCount == 0) {
if (findThis.toVector()[i].type() == Value::NUMBER) { if (findThis->toVector()[i].type() == Value::NUMBER) {
PRINTB(" WARNING: search term not found: %s",findThis.toVector()[i].toDouble()); PRINTB(" WARNING: search term not found: %s",findThis->toVector()[i].toDouble());
} }
else if (findThis.toVector()[i].type() == Value::STRING) { else if (findThis->toVector()[i].type() == Value::STRING) {
PRINTB(" WARNING: search term not found: \"%s\"",findThis.toVector()[i].toString()); 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) { if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(Value(resultvec)); returnvec.push_back(resultvec);
} }
} }
} else { } else {
PRINTB(" WARNING: search: none performed on input %s", findThis); 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 QUOTE(x__) # x__
#define QUOTED(x__) QUOTE(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 (void)evalctx; // unusued parameter
Value::VectorType val; Value::VectorType val;
val.push_back(Value(double(OPENSCAD_YEAR))); val.push_back(double(OPENSCAD_YEAR));
val.push_back(Value(double(OPENSCAD_MONTH))); val.push_back(double(OPENSCAD_MONTH));
#ifdef OPENSCAD_DAY #ifdef OPENSCAD_DAY
val.push_back(Value(double(OPENSCAD_DAY))); val.push_back(double(OPENSCAD_DAY));
#endif #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; double y, m, d = 0;
if (!val.getVec3(y, m, d)) { if (!val->getVec3(y, m, d)) {
if (!val.getVec2(y, m)) { if (!val->getVec2(y, m)) {
return Value(); 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; int n;
double d; double d;
@ -827,30 +827,30 @@ Value builtin_parent_module(const Context *, const EvalContext *evalctx)
if (evalctx->numArgs() == 0) if (evalctx->numArgs() == 0)
d=1; // parent module d=1; // parent module
else if (evalctx->numArgs() == 1) { else if (evalctx->numArgs() == 1) {
const Value &v = evalctx->getArgValue(0); ValuePtr v = evalctx->getArgValue(0);
if (v.type() != Value::NUMBER) return Value(); if (v->type() != Value::NUMBER) return ValuePtr::undefined;
v.getDouble(d); v->getDouble(d);
} else } else
return Value(); return ValuePtr::undefined;
n=trunc(d); n=trunc(d);
if (n < 0) { if (n < 0) {
PRINTB("WARNING: Negative parent module index (%d) not allowed", n); PRINTB("WARNING: Negative parent module index (%d) not allowed", n);
return Value(); return ValuePtr::undefined;
} }
if (n >= s) { if (n >= s) {
PRINTB("WARNING: Parent module index (%d) greater than the number of modules on the stack", n); 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) { if (evalctx->numArgs() == 1) {
const Value &val = evalctx->getArgValue(0); ValuePtr val = evalctx->getArgValue(0);
if (val.type() == Value::VECTOR) { if (val->type() == Value::VECTOR) {
double sum = 0; double sum = 0;
Value::VectorType v = val.toVector(); Value::VectorType v = val->toVector();
size_t n = v.size(); size_t n = v.size();
for (size_t i = 0; i < n; i++) for (size_t i = 0; i < n; i++)
if (v[i].type() == Value::NUMBER) { if (v[i].type() == Value::NUMBER) {
@ -859,48 +859,48 @@ Value builtin_norm(const Context *, const EvalContext *evalctx)
sum += x*x; sum += x*x;
} else { } else {
PRINT(" WARNING: Incorrect arguments to norm()"); 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) { if (evalctx->numArgs() != 2) {
PRINT("WARNING: Invalid number of parameters for cross()"); PRINT("WARNING: Invalid number of parameters for cross()");
return Value(); return ValuePtr::undefined;
} }
Value arg0 = evalctx->getArgValue(0); ValuePtr arg0 = evalctx->getArgValue(0);
Value arg1 = evalctx->getArgValue(1); ValuePtr arg1 = evalctx->getArgValue(1);
if ((arg0.type() != Value::VECTOR) || (arg1.type() != Value::VECTOR)) { if ((arg0->type() != Value::VECTOR) || (arg1->type() != Value::VECTOR)) {
PRINT("WARNING: Invalid type of parameters for cross()"); PRINT("WARNING: Invalid type of parameters for cross()");
return Value(); return ValuePtr::undefined;
} }
Value::VectorType v0 = arg0.toVector(); Value::VectorType v0 = arg0->toVector();
Value::VectorType v1 = arg1.toVector(); Value::VectorType v1 = arg1->toVector();
if ((v0.size() != 3) || (v1.size() != 3)) { if ((v0.size() != 3) || (v1.size() != 3)) {
PRINT("WARNING: Invalid vector size of parameter for cross()"); PRINT("WARNING: Invalid vector size of parameter for cross()");
return Value(); return ValuePtr::undefined;
} }
for (unsigned int a = 0;a < 3;a++) { for (unsigned int a = 0;a < 3;a++) {
if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) { if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) {
PRINT("WARNING: Invalid value in parameter vector for cross()"); PRINT("WARNING: Invalid value in parameter vector for cross()");
return Value(); return ValuePtr::undefined;
} }
double d0 = v0[a].toDouble(); double d0 = v0[a].toDouble();
double d1 = v1[a].toDouble(); double d1 = v1[a].toDouble();
if (boost::math::isnan(d0) || boost::math::isnan(d1)) { if (boost::math::isnan(d0) || boost::math::isnan(d1)) {
PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()"); PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()");
return Value(); return ValuePtr::undefined;
} }
if (boost::math::isinf(d0) || boost::math::isinf(d1)) { if (boost::math::isinf(d0) || boost::math::isinf(d1)) {
PRINT("WARNING: Invalid value (INF) in parameter vector for cross()"); 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(x));
result.push_back(Value(y)); result.push_back(Value(y));
result.push_back(Value(z)); result.push_back(Value(z));
return Value(result); return ValuePtr(result);
} }
void register_builtin_functions() void register_builtin_functions()

View File

@ -11,28 +11,28 @@
class AbstractFunction class AbstractFunction
{ {
private: private:
const Feature *feature; const Feature *feature;
public: public:
AbstractFunction() : feature(NULL) {} AbstractFunction() : feature(NULL) {}
AbstractFunction(const Feature& feature) : feature(&feature) {} AbstractFunction(const Feature& feature) : feature(&feature) {}
virtual ~AbstractFunction(); virtual ~AbstractFunction();
virtual bool is_experimental() const { return feature != NULL; } virtual bool is_experimental() const { return feature != NULL; }
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); } virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); }
virtual Value evaluate(const class Context *ctx, const class EvalContext *evalctx) const; 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; virtual std::string dump(const std::string &indent, const std::string &name) const;
}; };
class BuiltinFunction : public AbstractFunction class BuiltinFunction : public AbstractFunction
{ {
public: 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; eval_func_t eval_func;
BuiltinFunction(eval_func_t f) : eval_func(f) { } BuiltinFunction(eval_func_t f) : eval_func(f) { }
BuiltinFunction(eval_func_t f, const Feature& feature) : AbstractFunction(feature), eval_func(f) { } BuiltinFunction(eval_func_t f, const Feature& feature) : AbstractFunction(feature), eval_func(f) { }
virtual ~BuiltinFunction(); 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; virtual std::string dump(const std::string &indent, const std::string &name) const;
}; };
@ -46,6 +46,6 @@ public:
Function() { } Function() { }
virtual ~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; virtual std::string dump(const std::string &indent, const std::string &name) const;
}; };

View File

@ -91,18 +91,18 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti
c.dump(this, inst); c.dump(this, inst);
#endif #endif
Value v = c.lookup_variable("file"); ValuePtr v = c.lookup_variable("file");
if (v.isUndefined()) { if (v->isUndefined()) {
v = c.lookup_variable("filename"); v = c.lookup_variable("filename");
if (!v.isUndefined()) { if (!v->isUndefined()) {
printDeprecation("DEPRECATED: filename= is deprecated. Please use file="); 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; import_type_e actualtype = this->type;
if (actualtype == TYPE_UNKNOWN) { if (actualtype == TYPE_UNKNOWN) {
std::string extraw = boosty::extension_str( fs::path(filename) ); std::string extraw = boosty::extension_str(fs::path(filename));
std::string ext = boost::algorithm::to_lower_copy( extraw ); std::string ext = boost::algorithm::to_lower_copy(extraw);
if (ext == ".stl") actualtype = TYPE_STL; if (ext == ".stl") actualtype = TYPE_STL;
else if (ext == ".off") actualtype = TYPE_OFF; else if (ext == ".off") actualtype = TYPE_OFF;
else if (ext == ".dxf") actualtype = TYPE_DXF; 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); ImportNode *node = new ImportNode(inst, actualtype);
node->fn = c.lookup_variable("$fn").toDouble(); node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs").toDouble(); node->fs = c.lookup_variable("$fs")->toDouble();
node->fa = c.lookup_variable("$fa").toDouble(); node->fa = c.lookup_variable("$fa")->toDouble();
node->filename = filename; node->filename = filename;
Value layerval = c.lookup_variable("layer", true); Value layerval = *c.lookup_variable("layer", true);
if (layerval.isUndefined()) { if (layerval.isUndefined()) {
layerval = c.lookup_variable("layername"); layerval = *c.lookup_variable("layername");
if (!layerval.isUndefined()) { if (!layerval.isUndefined()) {
printDeprecation("DEPRECATED: layername= is deprecated. Please use layer="); printDeprecation("DEPRECATED: layername= is deprecated. Please use layer=");
} }
} }
node->layername = layerval.isUndefined() ? "" : layerval.toString(); 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; 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; 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) if (node->scale <= 0) node->scale = 1;
node->scale = 1;
return node; return node;
} }

View File

@ -59,46 +59,46 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble(); node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs").toDouble(); node->fs = c.lookup_variable("$fs")->toDouble();
node->fa = c.lookup_variable("$fa").toDouble(); node->fa = c.lookup_variable("$fa")->toDouble();
Value file = c.lookup_variable("file"); ValuePtr file = c.lookup_variable("file");
Value layer = c.lookup_variable("layer", true); ValuePtr layer = c.lookup_variable("layer", true);
Value height = c.lookup_variable("height", true); ValuePtr height = c.lookup_variable("height", true);
Value convexity = c.lookup_variable("convexity", true); ValuePtr convexity = c.lookup_variable("convexity", true);
Value origin = c.lookup_variable("origin", true); ValuePtr origin = c.lookup_variable("origin", true);
Value scale = c.lookup_variable("scale", true); ValuePtr scale = c.lookup_variable("scale", true);
Value center = c.lookup_variable("center", true); ValuePtr center = c.lookup_variable("center", true);
Value twist = c.lookup_variable("twist", true); ValuePtr twist = c.lookup_variable("twist", true);
Value slices = c.lookup_variable("slices", 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."); 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, // if height not given, and first argument is a number,
// then assume it should be the height. // then assume it should be the height.
if (c.lookup_variable("height").isUndefined() && if (c.lookup_variable("height")->isUndefined() &&
evalctx->numArgs() > 0 && evalctx->numArgs() > 0 &&
evalctx->getArgName(0) == "") { evalctx->getArgName(0) == "") {
const Value &val = evalctx->getArgValue(0); ValuePtr val = evalctx->getArgValue(0);
if (val.type() == Value::NUMBER) height = val; if (val->type() == Value::NUMBER) height = val;
} }
node->layername = layer.isUndefined() ? "" : layer.toString(); node->layername = layer->isUndefined() ? "" : layer->toString();
node->height = 100; node->height = 100;
height.getDouble(node->height); height->getDouble(node->height);
node->convexity = (int)convexity.toDouble(); node->convexity = (int)convexity->toDouble();
origin.getVec2(node->origin_x, node->origin_y); origin->getVec2(node->origin_x, node->origin_y);
node->scale_x = node->scale_y = 1; node->scale_x = node->scale_y = 1;
scale.getDouble(node->scale_x); scale->getDouble(node->scale_x);
scale.getDouble(node->scale_y); scale->getDouble(node->scale_y);
scale.getVec2(node->scale_x, node->scale_y); scale->getVec2(node->scale_x, node->scale_y);
if (center.type() == Value::BOOL) if (center->type() == Value::BOOL)
node->center = center.toBool(); node->center = center->toBool();
if (node->height <= 0) node->height = 0; 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_x < 0) node->scale_x = 0;
if (node->scale_y < 0) node->scale_y = 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) { if (twist->type() == Value::NUMBER) {
node->twist = twist.toDouble(); node->twist = twist->toDouble();
if (node->twist != 0.0) { if (node->twist != 0.0) {
if (node->slices == 0) { if (node->slices == 0) {
node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height, node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height,

View File

@ -1485,7 +1485,7 @@ bool MainWindow::eventFilter(QObject* obj, QEvent *event)
void MainWindow::updateTemporalVariables() 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; Value::VectorType vpt;
vpt.push_back(Value(-qglview->cam.object_trans.x())); 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.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.y(), 360)));
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.z(), 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) { BOOST_FOREACH(const Assignment &a, root_module->scope.assignments) {
double x, y, z; double x, y, z;
if ("$vpr" == a.first) { if ("$vpr" == a.first) {
const Value vpr = a.second.get()->evaluate(&mc); ValuePtr vpr = a.second.get()->evaluate(&mc);
if (vpr.getVec3(x, y, z)) { if (vpr->getVec3(x, y, z)) {
rx = x; rx = x;
ry = y; ry = y;
rz = z; rz = z;
camera_set = true; camera_set = true;
} }
} else if ("$vpt" == a.first) { } else if ("$vpt" == a.first) {
const Value vpt = a.second.get()->evaluate(&mc); ValuePtr vpt = a.second.get()->evaluate(&mc);
if (vpt.getVec3(x, y, z)) { if (vpt->getVec3(x, y, z)) {
tx = x; tx = x;
ty = y; ty = y;
tz = z; tz = z;
camera_set = true; camera_set = true;
} }
} else if ("$vpd" == a.first) { } else if ("$vpd" == a.first) {
const Value vpd = a.second.get()->evaluate(&mc); ValuePtr vpd = a.second.get()->evaluate(&mc);
if (vpd.type() == Value::NUMBER) { if (vpd->type() == Value::NUMBER) {
d = vpd.toDouble(); d = vpd->toDouble();
camera_set = true; camera_set = true;
} }
} }

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
using boost::shared_ptr; using boost::shared_ptr;
using boost::make_shared;
using boost::dynamic_pointer_cast; using boost::dynamic_pointer_cast;
using boost::static_pointer_cast; using boost::static_pointer_cast;

View File

@ -24,8 +24,8 @@ void ModuleContext::evaluateAssignments(const AssignmentList &assignments)
// First, assign all simple variables // First, assign all simple variables
std::list<std::string> undefined_vars; std::list<std::string> undefined_vars;
BOOST_FOREACH(const Assignment &ass, assignments) { BOOST_FOREACH(const Assignment &ass, assignments) {
Value tmpval = ass.second->evaluate(this); ValuePtr tmpval = ass.second->evaluate(this);
if (tmpval.isUndefined()) undefined_vars.push_back(ass.first); if (tmpval->isUndefined()) undefined_vars.push_back(ass.first);
else this->set_variable(ass.first, tmpval); else this->set_variable(ass.first, tmpval);
} }
@ -46,12 +46,12 @@ void ModuleContext::evaluateAssignments(const AssignmentList &assignments)
boost::unordered_map<std::string, Expression *>::iterator found = tmpass.find(*curr); boost::unordered_map<std::string, Expression *>::iterator found = tmpass.find(*curr);
if (found != tmpass.end()) { if (found != tmpass.end()) {
const Expression *expr = found->second; const Expression *expr = found->second;
Value tmpval = expr->evaluate(this); ValuePtr tmpval = expr->evaluate(this);
// FIXME: it's not enough to check for undefined; // FIXME: it's not enough to check for undefined;
// we need to check for any undefined variable in the subexpression // we need to check for any undefined variable in the subexpression
// For now, ignore this and revisit the validity and order of variable // For now, ignore this and revisit the validity and order of variable
// assignments later // assignments later
if (!tmpval.isUndefined()) { if (!tmpval->isUndefined()) {
changed = true; changed = true;
this->set_variable(*curr, tmpval); this->set_variable(*curr, tmpval);
undefined_vars.erase(curr); undefined_vars.erase(curr);
@ -89,7 +89,7 @@ void ModuleContext::registerBuiltin()
this->set_variable(ass.first, ass.second->evaluate(this)); 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 const AbstractFunction *ModuleContext::findLocalFunction(const std::string &name) const
@ -122,7 +122,8 @@ const AbstractModule *ModuleContext::findLocalModule(const std::string &name) co
return NULL; 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); const AbstractFunction *foundf = findLocalFunction(name);
if (foundf) return foundf->evaluate(this, evalctx); if (foundf) return foundf->evaluate(this, evalctx);
@ -156,7 +157,7 @@ std::string ModuleContext::dump(const AbstractModule *mod, const ModuleInstantia
} }
} }
} }
typedef std::pair<std::string, Value> ValueMapType; typedef std::pair<std::string, ValuePtr> ValueMapType;
s << " vars:"; s << " vars:";
BOOST_FOREACH(const ValueMapType &v, constants) { BOOST_FOREACH(const ValueMapType &v, constants) {
s << boost::format(" %s = %s") % v.first % v.second; 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(); if (!module.modulePath().empty()) this->document_path = module.modulePath();
} }
Value FileContext::sub_evaluate_function(const std::string &name, const EvalContext *evalctx, ValuePtr FileContext::sub_evaluate_function(const std::string &name,
const EvalContext *evalctx,
FileModule *usedmod) const FileModule *usedmod) const
{ {
FileContext ctx(*usedmod, this->parent); 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); 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); const AbstractFunction *foundf = findLocalFunction(name);
if (foundf) return foundf->evaluate(this, evalctx); if (foundf) return foundf->evaluate(this, evalctx);

View File

@ -18,8 +18,8 @@ public:
void initializeModule(const Module &m); void initializeModule(const Module &m);
void registerBuiltin(); void registerBuiltin();
virtual Value evaluate_function(const std::string &name, virtual ValuePtr evaluate_function(const std::string &name,
const EvalContext *evalctx) const; const EvalContext *evalctx) const;
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst, virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
const EvalContext *evalctx) const; const EvalContext *evalctx) const;
@ -45,7 +45,8 @@ class FileContext : public ModuleContext
public: public:
FileContext(const class FileModule &module, const Context *parent); FileContext(const class FileModule &module, const Context *parent);
virtual ~FileContext() {} 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, virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
const EvalContext *evalctx) const; const EvalContext *evalctx) const;
@ -53,5 +54,7 @@ private:
const FileModule::ModuleContainer &usedlibs; const FileModule::ModuleContainer &usedlibs;
// This sub_* method is needed to minimize stack usage only. // 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;
}; };

View File

@ -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 double AbstractModule::lookup_double_variable_with_default(Context &c, std::string variable, double def) const
{ {
const Value v = c.lookup_variable(variable, true); ValuePtr v = c.lookup_variable(variable, true);
return (v.type() == Value::NUMBER) ? v.toDouble() : def; 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 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); ValuePtr v = c.lookup_variable(variable, true);
return (v.type() == Value::STRING) ? v.toString() : def; return (v->type() == Value::STRING) ? v->toString() : def;
} }
std::string AbstractModule::dump(const std::string &indent, const std::string &name) const 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); ModuleContext c(ctx, evalctx);
// set $children first since we might have variables depending on it // set $children first since we might have variables depending on it
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()); 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); c.initializeModule(*this);
// FIXME: Set document path to the path of the module // FIXME: Set document path to the path of the module
#if 0 && DEBUG #if 0 && DEBUG

View File

@ -59,21 +59,21 @@ AbstractNode *OffsetModule::instantiate(const Context *ctx, const ModuleInstanti
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble(); node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs").toDouble(); node->fs = c.lookup_variable("$fs")->toDouble();
node->fa = c.lookup_variable("$fa").toDouble(); node->fa = c.lookup_variable("$fa")->toDouble();
Value delta = c.lookup_variable("delta"); ValuePtr delta = c.lookup_variable("delta");
node->delta = 1; 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; 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); ValuePtr join_type = c.lookup_variable("join_type", true);
if (join_type.type() == Value::STRING) { if (join_type->type() == Value::STRING) {
std::string jt = join_type.toString(); std::string jt = join_type->toString();
if (std::string("bevel") == jt) { if (std::string("bevel") == jt) {
node->join_type = ClipperLib::jtSquare; node->join_type = ClipperLib::jtSquare;
} else if (std::string("round") == jt) { } 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); 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); PRINTB("WARNING: miter_limit is ignored in offset() for join_type: '%s'", jt);
} }
} }

View File

@ -308,15 +308,15 @@ single_module_instantiation:
expr: expr:
TOK_TRUE TOK_TRUE
{ {
$$ = new Expression(Value(true)); $$ = new Expression(ValuePtr(true));
} }
| TOK_FALSE | TOK_FALSE
{ {
$$ = new Expression(Value(false)); $$ = new Expression(ValuePtr(false));
} }
| TOK_UNDEF | TOK_UNDEF
{ {
$$ = new Expression(Value::undefined); $$ = new Expression(ValuePtr::undefined);
} }
| TOK_ID | TOK_ID
{ {
@ -333,12 +333,12 @@ expr:
} }
| TOK_STRING | TOK_STRING
{ {
$$ = new Expression(Value(std::string($1))); $$ = new Expression(ValuePtr(std::string($1)));
free($1); free($1);
} }
| TOK_NUMBER | TOK_NUMBER
{ {
$$ = new Expression(Value($1)); $$ = new Expression(ValuePtr($1));
} }
| TOK_LET '(' arguments_call ')' expr %prec LET | TOK_LET '(' arguments_call ')' expr %prec LET
{ {
@ -371,7 +371,7 @@ expr:
} }
| '[' optional_commas ']' | '[' optional_commas ']'
{ {
$$ = new Expression(Value(Value::VectorType())); $$ = new Expression(ValuePtr(Value::VectorType()));
} }
| '[' vector_expr optional_commas ']' | '[' vector_expr optional_commas ']'
{ {

View File

@ -108,7 +108,7 @@ public:
double fn, fs, fa; double fn, fs, fa;
primitive_type_e type; primitive_type_e type;
int convexity; int convexity;
Value points, paths, faces; ValuePtr points, paths, faces;
virtual Geometry *createGeometry() const; 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 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); ValuePtr d = ctx.lookup_variable(diameter_var, true);
const Value r = ctx.lookup_variable(radius_var, true); ValuePtr r = ctx.lookup_variable(radius_var, true);
const bool r_defined = (r.type() == Value::NUMBER); const bool r_defined = (r->type() == Value::NUMBER);
if (d.type() == Value::NUMBER) { if (d->type() == Value::NUMBER) {
if (r_defined) { if (r_defined) {
PRINTB("WARNING: Ignoring radius variable '%s' as diameter '%s' is defined too.", radius_var % diameter_var); 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) { } else if (r_defined) {
return r; return *r;
} else { } else {
return Value(); return Value::undefined;
} }
} }
@ -179,9 +179,9 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble(); node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs").toDouble(); node->fs = c.lookup_variable("$fs")->toDouble();
node->fa = c.lookup_variable("$fa").toDouble(); node->fa = c.lookup_variable("$fa")->toDouble();
if (node->fs < F_MINIMUM) { if (node->fs < F_MINIMUM) {
PRINTB("WARNING: $fs too small - clamping to %f", 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) { switch (this->type) {
case CUBE: { case CUBE: {
Value size = c.lookup_variable("size"); ValuePtr size = c.lookup_variable("size");
Value center = c.lookup_variable("center"); ValuePtr center = c.lookup_variable("center");
size.getDouble(node->x); size->getDouble(node->x);
size.getDouble(node->y); size->getDouble(node->y);
size.getDouble(node->z); size->getDouble(node->z);
size.getVec3(node->x, node->y, node->z); size->getVec3(node->x, node->y, node->z);
if (center.type() == Value::BOOL) { if (center->type() == Value::BOOL) {
node->center = center.toBool(); node->center = center->toBool();
} }
break; break;
} }
@ -213,9 +213,9 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
break; break;
} }
case CYLINDER: { case CYLINDER: {
const Value h = c.lookup_variable("h"); ValuePtr h = c.lookup_variable("h");
if (h.type() == Value::NUMBER) { if (h->type() == Value::NUMBER) {
node->h = h.toDouble(); node->h = h->toDouble();
} }
const Value r = lookup_radius(c, "d", "r"); const Value r = lookup_radius(c, "d", "r");
@ -232,32 +232,32 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
node->r2 = r2.toDouble(); node->r2 = r2.toDouble();
} }
const Value center = c.lookup_variable("center"); ValuePtr center = c.lookup_variable("center");
if (center.type() == Value::BOOL) { if (center->type() == Value::BOOL) {
node->center = center.toBool(); node->center = center->toBool();
} }
break; break;
} }
case POLYHEDRON: { case POLYHEDRON: {
node->points = c.lookup_variable("points"); node->points = c.lookup_variable("points");
node->faces = c.lookup_variable("faces"); node->faces = c.lookup_variable("faces");
if (node->faces.type() == Value::UNDEFINED) { if (node->faces->type() == Value::UNDEFINED) {
// backwards compatible // backwards compatible
node->faces = c.lookup_variable("triangles", true); 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."); printDeprecation("DEPRECATED: polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead.");
} }
} }
break; break;
} }
case SQUARE: { case SQUARE: {
Value size = c.lookup_variable("size"); ValuePtr size = c.lookup_variable("size");
Value center = c.lookup_variable("center"); ValuePtr center = c.lookup_variable("center");
size.getDouble(node->x); size->getDouble(node->x);
size.getDouble(node->y); size->getDouble(node->y);
size.getVec2(node->x, node->y); size->getVec2(node->x, node->y);
if (center.type() == Value::BOOL) { if (center->type() == Value::BOOL) {
node->center = center.toBool(); node->center = center->toBool();
} }
break; 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) if (node->convexity < 1)
node->convexity = 1; node->convexity = 1;
@ -505,15 +505,15 @@ Geometry *PrimitiveNode::createGeometry() const
PolySet *p = new PolySet(3); PolySet *p = new PolySet(3);
g = p; g = p;
p->setConvexity(this->convexity); p->setConvexity(this->convexity);
for (size_t i=0; i<this->faces.toVector().size(); i++) for (size_t i=0; i<this->faces->toVector().size(); i++)
{ {
p->append_poly(); 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; j<vec.size(); j++) { for (size_t j=0; j<vec.size(); j++) {
size_t pt = vec[j].toDouble(); size_t pt = vec[j].toDouble();
if (pt < this->points.toVector().size()) { if (pt < this->points->toVector().size()) {
double px, py, pz; 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)) { isinf(px) || isinf(py) || isinf(pz)) {
PRINTB("ERROR: Unable to convert point at index %d to a vec3 of numbers", j); PRINTB("ERROR: Unable to convert point at index %d to a vec3 of numbers", j);
delete p; delete p;
@ -571,7 +571,7 @@ Geometry *PrimitiveNode::createGeometry() const
Outline2d outline; Outline2d outline;
double x,y; double x,y;
const Value::VectorType &vec = this->points.toVector(); const Value::VectorType &vec = this->points->toVector();
for (unsigned int i=0;i<vec.size();i++) { for (unsigned int i=0;i<vec.size();i++) {
const Value &val = vec[i]; const Value &val = vec[i];
if (!val.getVec2(x, y) || if (!val.getVec2(x, y) ||
@ -584,11 +584,11 @@ Geometry *PrimitiveNode::createGeometry() const
outline.vertices.push_back(Vector2d(x, y)); outline.vertices.push_back(Vector2d(x, y));
} }
if (this->paths.toVector().size() == 0 && outline.vertices.size() > 2) { if (this->paths->toVector().size() == 0 && outline.vertices.size() > 2) {
p->addOutline(outline); p->addOutline(outline);
} }
else { else {
BOOST_FOREACH(const Value &polygon, this->paths.toVector()) { BOOST_FOREACH(const Value &polygon, this->paths->toVector()) {
Outline2d curroutline; Outline2d curroutline;
BOOST_FOREACH(const Value &index, polygon.toVector()) { BOOST_FOREACH(const Value &index, polygon.toVector()) {
unsigned int idx = index.toDouble(); unsigned int idx = index.toDouble();
@ -635,8 +635,8 @@ std::string PrimitiveNode::toString() const
<< ", r2 = " << this->r2 << ", center = " << (center ? "true" : "false") << ")"; << ", r2 = " << this->r2 << ", center = " << (center ? "true" : "false") << ")";
break; break;
case POLYHEDRON: case POLYHEDRON:
stream << "(points = " << this->points stream << "(points = " << *this->points
<< ", faces = " << this->faces << ", faces = " << *this->faces
<< ", convexity = " << this->convexity << ")"; << ", convexity = " << this->convexity << ")";
break; break;
case SQUARE: case SQUARE:
@ -648,7 +648,7 @@ std::string PrimitiveNode::toString() const
<< ", $fs = " << this->fs << ", r = " << this->r1 << ")"; << ", $fs = " << this->fs << ", r = " << this->r1 << ")";
break; break;
case POLYGON: case POLYGON:
stream << "(points = " << this->points << ", paths = " << this->paths << ", convexity = " << this->convexity << ")"; stream << "(points = " << *this->points << ", paths = " << *this->paths << ", convexity = " << this->convexity << ")";
break; break;
default: default:
assert(false); assert(false);

View File

@ -54,13 +54,13 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
Value convexity = c.lookup_variable("convexity", true); ValuePtr convexity = c.lookup_variable("convexity", true);
Value cut = c.lookup_variable("cut", true); ValuePtr cut = c.lookup_variable("cut", true);
node->convexity = (int)convexity.toDouble(); node->convexity = (int)convexity->toDouble();
if (cut.type() == Value::BOOL) if (cut->type() == Value::BOOL)
node->cut_mode = cut.toBool(); node->cut_mode = cut->toBool();
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx); std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());

View File

@ -51,9 +51,9 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
Value v = c.lookup_variable("convexity"); ValuePtr v = c.lookup_variable("convexity");
if (v.type() == Value::NUMBER) if (v->type() == Value::NUMBER)
node->convexity = (int)v.toDouble(); node->convexity = (int)v->toDouble();
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx); std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());

View File

@ -57,25 +57,25 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble(); node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs").toDouble(); node->fs = c.lookup_variable("$fs")->toDouble();
node->fa = c.lookup_variable("$fa").toDouble(); node->fa = c.lookup_variable("$fa")->toDouble();
Value file = c.lookup_variable("file"); ValuePtr file = c.lookup_variable("file");
Value layer = c.lookup_variable("layer", true); ValuePtr layer = c.lookup_variable("layer", true);
Value convexity = c.lookup_variable("convexity", true); ValuePtr convexity = c.lookup_variable("convexity", true);
Value origin = c.lookup_variable("origin", true); ValuePtr origin = c.lookup_variable("origin", true);
Value scale = c.lookup_variable("scale", 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."); 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->layername = layer->isUndefined() ? "" : layer->toString();
node->convexity = (int)convexity.toDouble(); node->convexity = (int)convexity->toDouble();
origin.getVec2(node->origin_x, node->origin_y); origin->getVec2(node->origin_x, node->origin_y);
node->scale = scale.toDouble(); node->scale = scale->toDouble();
if (node->convexity <= 0) if (node->convexity <= 0)
node->convexity = 1; node->convexity = 1;

View File

@ -93,22 +93,22 @@ AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstant
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
Value fileval = c.lookup_variable("file"); ValuePtr fileval = c.lookup_variable("file");
node->filename = lookup_file(fileval.isUndefined() ? "" : fileval.toString(), inst->path(), c.documentPath()); node->filename = lookup_file(fileval->isUndefined() ? "" : fileval->toString(), inst->path(), c.documentPath());
Value center = c.lookup_variable("center", true); ValuePtr center = c.lookup_variable("center", true);
if (center.type() == Value::BOOL) { if (center->type() == Value::BOOL) {
node->center = center.toBool(); node->center = center->toBool();
} }
Value convexity = c.lookup_variable("convexity", true); ValuePtr convexity = c.lookup_variable("convexity", true);
if (convexity.type() == Value::NUMBER) { if (convexity->type() == Value::NUMBER) {
node->convexity = (int)convexity.toDouble(); node->convexity = (int)convexity->toDouble();
} }
Value invert = c.lookup_variable("invert", true); ValuePtr invert = c.lookup_variable("invert", true);
if (invert.type() == Value::BOOL) { if (invert->type() == Value::BOOL) {
node->invert = invert.toBool(); node->invert = invert->toBool();
} }
return node; return node;

View File

@ -54,9 +54,9 @@ AbstractNode *TextModule::instantiate(const Context *ctx, const ModuleInstantiat
Context c(ctx); Context c(ctx);
c.setVariables(args, evalctx); c.setVariables(args, evalctx);
double fn = c.lookup_variable("$fn").toDouble(); double fn = c.lookup_variable("$fn")->toDouble();
double fa = c.lookup_variable("$fa").toDouble(); double fa = c.lookup_variable("$fa")->toDouble();
double fs = c.lookup_variable("$fs").toDouble(); double fs = c.lookup_variable("$fs")->toDouble();
node->params.set_fn(fn); node->params.set_fn(fn);
node->params.set_fa(fa); node->params.set_fa(fa);

View File

@ -87,45 +87,45 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
if (this->type == SCALE) if (this->type == SCALE)
{ {
Vector3d scalevec(1,1,1); Vector3d scalevec(1,1,1);
Value v = c.lookup_variable("v"); ValuePtr v = c.lookup_variable("v");
if (!v.getVec3(scalevec[0], scalevec[1], scalevec[2], 1.0)) { if (!v->getVec3(scalevec[0], scalevec[1], scalevec[2], 1.0)) {
double num; double num;
if (v.getDouble(num)) scalevec.setConstant(num); if (v->getDouble(num)) scalevec.setConstant(num);
} }
node->matrix.scale(scalevec); node->matrix.scale(scalevec);
} }
else if (this->type == ROTATE) else if (this->type == ROTATE)
{ {
Value val_a = c.lookup_variable("a"); ValuePtr val_a = c.lookup_variable("a");
if (val_a.type() == Value::VECTOR) if (val_a->type() == Value::VECTOR)
{ {
Eigen::AngleAxisd rotx(0, Vector3d::UnitX()); Eigen::AngleAxisd rotx(0, Vector3d::UnitX());
Eigen::AngleAxisd roty(0, Vector3d::UnitY()); Eigen::AngleAxisd roty(0, Vector3d::UnitY());
Eigen::AngleAxisd rotz(0, Vector3d::UnitZ()); Eigen::AngleAxisd rotz(0, Vector3d::UnitZ());
double a; double a;
if (val_a.toVector().size() > 0) { if (val_a->toVector().size() > 0) {
val_a.toVector()[0].getDouble(a); val_a->toVector()[0].getDouble(a);
rotx = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitX()); rotx = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitX());
} }
if (val_a.toVector().size() > 1) { if (val_a->toVector().size() > 1) {
val_a.toVector()[1].getDouble(a); val_a->toVector()[1].getDouble(a);
roty = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitY()); roty = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitY());
} }
if (val_a.toVector().size() > 2) { if (val_a->toVector().size() > 2) {
val_a.toVector()[2].getDouble(a); val_a->toVector()[2].getDouble(a);
rotz = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitZ()); rotz = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitZ());
} }
node->matrix.rotate(rotz * roty * rotx); node->matrix.rotate(rotz * roty * rotx);
} }
else else
{ {
Value val_v = c.lookup_variable("v"); ValuePtr val_v = c.lookup_variable("v");
double a = 0; double a = 0;
val_a.getDouble(a); val_a->getDouble(a);
Vector3d axis(0,0,1); 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(); if (axis.squaredNorm() > 0) axis.normalize();
} }
@ -136,10 +136,10 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
} }
else if (this->type == MIRROR) 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; 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) { if (x != 0.0 || y != 0.0 || z != 0.0) {
double sn = 1.0 / sqrt(x*x + y*y + z*z); double sn = 1.0 / sqrt(x*x + y*y + z*z);
x *= sn, y *= sn, z *= sn; x *= sn, y *= sn, z *= sn;
@ -158,19 +158,20 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
} }
else if (this->type == TRANSLATE) else if (this->type == TRANSLATE)
{ {
Value v = c.lookup_variable("v"); ValuePtr v = c.lookup_variable("v");
Vector3d translatevec(0,0,0); 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); node->matrix.translate(translatevec);
} }
else if (this->type == MULTMATRIX) else if (this->type == MULTMATRIX)
{ {
Value v = c.lookup_variable("m"); ValuePtr v = c.lookup_variable("m");
if (v.type() == Value::VECTOR) { if (v->type() == Value::VECTOR) {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
size_t x = i / 4, y = i % 4; 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()) if (y < v->toVector().size() && v->toVector()[y].type() ==
v.toVector()[y].toVector()[x].getDouble(node->matrix(y, x)); 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++) { for (int j=0;j<4;j++) {
stream << "["; stream << "[";
for (int i=0;i<4;i++) { for (int i=0;i<4;i++) {
Value v( this->matrix(j, i) ); Value v(this->matrix(j, i));
stream << v; stream << v;
if (i != 3) stream << ", "; if (i != 3) stream << ", ";
} }

View File

@ -41,6 +41,9 @@
#include <boost/math/special_functions/fpclassify.hpp> #include <boost/math/special_functions/fpclassify.hpp>
Value Value::undefined;
ValuePtr ValuePtr::undefined;
std::ostream &operator<<(std::ostream &stream, const Filename &filename) std::ostream &operator<<(std::ostream &stream, const Filename &filename)
{ {
fs::path fnpath = fs::path( (std::string)filename ); fs::path fnpath = fs::path( (std::string)filename );
@ -77,8 +80,6 @@ std::ostream &operator<<(std::ostream &stream, const QuotedString &s)
return stream; return stream;
} }
Value Value::undefined;
Value::Value() : value(boost::blank()) Value::Value() : value(boost::blank())
{ {
// std::cout << "creating undef\n"; // 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); 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); 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);
}

View File

@ -11,6 +11,7 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#endif #endif
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "memory.h"
class QuotedString : public std::string class QuotedString : public std::string
{ {
@ -138,7 +139,7 @@ public:
bool operator>=(const Value &v) const; bool operator>=(const Value &v) const;
bool operator>(const Value &v) const; bool operator>(const Value &v) const;
Value operator-() 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; 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; Variant value;
}; };
class ValuePtr : public shared_ptr<const Value>
{
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:
};