#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()
{
this->globalscope.assignments.push_back(Assignment("$fn", boost::shared_ptr<Expression>(new Expression(Value(0.0)))));
this->globalscope.assignments.push_back(Assignment("$fs", boost::shared_ptr<Expression>(new Expression(Value(2.0)))));
this->globalscope.assignments.push_back(Assignment("$fa", boost::shared_ptr<Expression>(new Expression(Value(12.0)))));
this->globalscope.assignments.push_back(Assignment("$t", 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(ValuePtr(2.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(ValuePtr(0.0)))));
Value::VectorType zero3;
zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0));
Value zero3val(zero3);
ValuePtr zero3val(zero3);
this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<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()

View File

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

View File

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

View File

@ -219,15 +219,15 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
Context c(ctx);
c.setVariables(args, evalctx);
Value v = c.lookup_variable("c");
if (v.type() == Value::VECTOR) {
ValuePtr v = c.lookup_variable("c");
if (v->type() == Value::VECTOR) {
for (size_t i = 0; i < 4; i++) {
node->color[i] = i < v.toVector().size() ? v.toVector()[i].toDouble() : 1.0;
node->color[i] = i < v->toVector().size() ? v->toVector()[i].toDouble() : 1.0;
if (node->color[i] > 1)
PRINTB_NOCACHE("WARNING: color() expects numbers between 0.0 and 1.0. Value of %.1f is too large.", node->color[i]);
}
} else if (v.type() == Value::STRING) {
std::string colorname = v.toString();
} else if (v->type() == Value::STRING) {
std::string colorname = v->toString();
boost::algorithm::to_lower(colorname);
Color4f color;
if (webcolors.find(colorname) != webcolors.end()) {
@ -237,9 +237,9 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
PRINT_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors");
}
}
Value alpha = c.lookup_variable("alpha");
if (alpha.type() == Value::NUMBER) {
node->color[3] = alpha.toDouble();
ValuePtr alpha = c.lookup_variable("alpha");
if (alpha->type() == Value::NUMBER) {
node->color[3] = alpha->toDouble();
}
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);

View File

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

View File

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

View File

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

View File

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

View File

@ -3,5 +3,5 @@
#include <boost/unordered_map.hpp>
#include "value.h"
extern boost::unordered_map<std::string,Value> dxf_dim_cache;
extern boost::unordered_map<std::string,Value> dxf_cross_cache;
extern boost::unordered_map<std::string, ValuePtr> dxf_dim_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;
}
Value EvalContext::getArgValue(size_t i, const Context *ctx) const
ValuePtr EvalContext::getArgValue(size_t i, const Context *ctx) const
{
assert(i < this->eval_arguments.size());
const Assignment &arg = this->eval_arguments[i];
return arg.second ? arg.second->evaluate(ctx ? ctx : this) : Value();
return arg.second ? arg.second->evaluate(ctx ? ctx : this) : ValuePtr::undefined;
}
size_t EvalContext::numChildren() const
@ -56,7 +56,7 @@ std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiati
if (m) {
s << boost::format(" module args:");
BOOST_FOREACH(const Assignment &arg, m->definition_arguments) {
s << boost::format(" %s = %s") % arg.first % variables[arg.first];
s << boost::format(" %s = %s") % arg.first % *(variables[arg.first]);
}
}
}

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -59,46 +59,46 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
Context c(ctx);
c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();
node->fa = c.lookup_variable("$fa").toDouble();
node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs")->toDouble();
node->fa = c.lookup_variable("$fa")->toDouble();
Value file = c.lookup_variable("file");
Value layer = c.lookup_variable("layer", true);
Value height = c.lookup_variable("height", true);
Value convexity = c.lookup_variable("convexity", true);
Value origin = c.lookup_variable("origin", true);
Value scale = c.lookup_variable("scale", true);
Value center = c.lookup_variable("center", true);
Value twist = c.lookup_variable("twist", true);
Value slices = c.lookup_variable("slices", true);
ValuePtr file = c.lookup_variable("file");
ValuePtr layer = c.lookup_variable("layer", true);
ValuePtr height = c.lookup_variable("height", true);
ValuePtr convexity = c.lookup_variable("convexity", true);
ValuePtr origin = c.lookup_variable("origin", true);
ValuePtr scale = c.lookup_variable("scale", true);
ValuePtr center = c.lookup_variable("center", true);
ValuePtr twist = c.lookup_variable("twist", true);
ValuePtr slices = c.lookup_variable("slices", true);
if (!file.isUndefined() && file.type() == Value::STRING) {
if (!file->isUndefined() && file->type() == Value::STRING) {
printDeprecation("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead.");
node->filename = lookup_file(file.toString(), inst->path(), c.documentPath());
node->filename = lookup_file(file->toString(), inst->path(), c.documentPath());
}
// if height not given, and first argument is a number,
// then assume it should be the height.
if (c.lookup_variable("height").isUndefined() &&
if (c.lookup_variable("height")->isUndefined() &&
evalctx->numArgs() > 0 &&
evalctx->getArgName(0) == "") {
const Value &val = evalctx->getArgValue(0);
if (val.type() == Value::NUMBER) height = val;
ValuePtr val = evalctx->getArgValue(0);
if (val->type() == Value::NUMBER) height = val;
}
node->layername = layer.isUndefined() ? "" : layer.toString();
node->layername = layer->isUndefined() ? "" : layer->toString();
node->height = 100;
height.getDouble(node->height);
node->convexity = (int)convexity.toDouble();
origin.getVec2(node->origin_x, node->origin_y);
height->getDouble(node->height);
node->convexity = (int)convexity->toDouble();
origin->getVec2(node->origin_x, node->origin_y);
node->scale_x = node->scale_y = 1;
scale.getDouble(node->scale_x);
scale.getDouble(node->scale_y);
scale.getVec2(node->scale_x, node->scale_y);
scale->getDouble(node->scale_x);
scale->getDouble(node->scale_y);
scale->getVec2(node->scale_x, node->scale_y);
if (center.type() == Value::BOOL)
node->center = center.toBool();
if (center->type() == Value::BOOL)
node->center = center->toBool();
if (node->height <= 0) node->height = 0;
@ -108,10 +108,10 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
if (node->scale_x < 0) node->scale_x = 0;
if (node->scale_y < 0) node->scale_y = 0;
if (slices.type() == Value::NUMBER) node->slices = (int)slices.toDouble();
if (slices->type() == Value::NUMBER) node->slices = (int)slices->toDouble();
if (twist.type() == Value::NUMBER) {
node->twist = twist.toDouble();
if (twist->type() == Value::NUMBER) {
node->twist = twist->toDouble();
if (node->twist != 0.0) {
if (node->slices == 0) {
node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height,

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@ -54,13 +54,13 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst
Context c(ctx);
c.setVariables(args, evalctx);
Value convexity = c.lookup_variable("convexity", true);
Value cut = c.lookup_variable("cut", true);
ValuePtr convexity = c.lookup_variable("convexity", true);
ValuePtr cut = c.lookup_variable("cut", true);
node->convexity = (int)convexity.toDouble();
node->convexity = (int)convexity->toDouble();
if (cut.type() == Value::BOOL)
node->cut_mode = cut.toBool();
if (cut->type() == Value::BOOL)
node->cut_mode = cut->toBool();
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
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);
c.setVariables(args, evalctx);
Value v = c.lookup_variable("convexity");
if (v.type() == Value::NUMBER)
node->convexity = (int)v.toDouble();
ValuePtr v = c.lookup_variable("convexity");
if (v->type() == Value::NUMBER)
node->convexity = (int)v->toDouble();
std::vector<AbstractNode *> instantiatednodes = inst->instantiateChildren(evalctx);
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);
c.setVariables(args, evalctx);
node->fn = c.lookup_variable("$fn").toDouble();
node->fs = c.lookup_variable("$fs").toDouble();
node->fa = c.lookup_variable("$fa").toDouble();
node->fn = c.lookup_variable("$fn")->toDouble();
node->fs = c.lookup_variable("$fs")->toDouble();
node->fa = c.lookup_variable("$fa")->toDouble();
Value file = c.lookup_variable("file");
Value layer = c.lookup_variable("layer", true);
Value convexity = c.lookup_variable("convexity", true);
Value origin = c.lookup_variable("origin", true);
Value scale = c.lookup_variable("scale", true);
ValuePtr file = c.lookup_variable("file");
ValuePtr layer = c.lookup_variable("layer", true);
ValuePtr convexity = c.lookup_variable("convexity", true);
ValuePtr origin = c.lookup_variable("origin", true);
ValuePtr scale = c.lookup_variable("scale", true);
if (!file.isUndefined()) {
if (!file->isUndefined()) {
printDeprecation("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead.");
node->filename = lookup_file(file.toString(), inst->path(), c.documentPath());
node->filename = lookup_file(file->toString(), inst->path(), c.documentPath());
}
node->layername = layer.isUndefined() ? "" : layer.toString();
node->convexity = (int)convexity.toDouble();
origin.getVec2(node->origin_x, node->origin_y);
node->scale = scale.toDouble();
node->layername = layer->isUndefined() ? "" : layer->toString();
node->convexity = (int)convexity->toDouble();
origin->getVec2(node->origin_x, node->origin_y);
node->scale = scale->toDouble();
if (node->convexity <= 0)
node->convexity = 1;

View File

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

View File

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

View File

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

View File

@ -41,6 +41,9 @@
#include <boost/math/special_functions/fpclassify.hpp>
Value Value::undefined;
ValuePtr ValuePtr::undefined;
std::ostream &operator<<(std::ostream &stream, const Filename &filename)
{
fs::path fnpath = fs::path( (std::string)filename );
@ -77,8 +80,6 @@ std::ostream &operator<<(std::ostream &stream, const QuotedString &s)
return stream;
}
Value Value::undefined;
Value::Value() : value(boost::blank())
{
// std::cout << "creating undef\n";
@ -688,7 +689,7 @@ public:
}
};
Value Value::operator[](const Value &v)
Value Value::operator[](const Value &v) const
{
return boost::apply_visitor(bracket_visitor(), this->value, v.value);
}
@ -790,3 +791,119 @@ bool Value::RangeType::iterator::operator!=(const self_type &other) const
{
return !(*this == other);
}
ValuePtr::ValuePtr()
{
this->reset(new Value());
}
ValuePtr::ValuePtr(const Value &v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(bool v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(int v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(double v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(const std::string &v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(const char *v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(const char v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(const Value::VectorType &v)
{
this->reset(new Value(v));
}
ValuePtr::ValuePtr(const Value::RangeType &v)
{
this->reset(new Value(v));
}
bool ValuePtr::operator==(const ValuePtr &v) const
{
return ValuePtr(**this == *v);
}
bool ValuePtr::operator!=(const ValuePtr &v) const
{
return ValuePtr(**this != *v);
}
bool ValuePtr::operator<(const ValuePtr &v) const
{
return ValuePtr(**this < *v);
}
bool ValuePtr::operator<=(const ValuePtr &v) const
{
return ValuePtr(**this <= *v);
}
bool ValuePtr::operator>=(const ValuePtr &v) const
{
return ValuePtr(**this >= *v);
}
bool ValuePtr::operator>(const ValuePtr &v) const
{
return ValuePtr(**this > *v);
}
ValuePtr ValuePtr::operator-() const
{
return ValuePtr(-**this);
}
ValuePtr ValuePtr::operator[](const ValuePtr &v) const
{
return ValuePtr((**this)[*v]);
}
ValuePtr ValuePtr::operator+(const ValuePtr &v) const
{
return ValuePtr(**this + *v);
}
ValuePtr ValuePtr::operator-(const ValuePtr &v) const
{
return ValuePtr(**this - *v);
}
ValuePtr ValuePtr::operator*(const ValuePtr &v) const
{
return ValuePtr(**this * *v);
}
ValuePtr ValuePtr::operator/(const ValuePtr &v) const
{
return ValuePtr(**this / *v);
}
ValuePtr ValuePtr::operator%(const ValuePtr &v) const
{
return ValuePtr(**this % *v);
}

View File

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