summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2012-03-27 22:05:00 (GMT)
committerMarius Kintel <marius@kintel.net>2012-03-27 22:05:58 (GMT)
commit327310f190bbd81c7b71b568d5bf72bb900cc9db (patch)
tree9399bb490ecafe9f0c7fd209c680311d829eb631 /src
parent4394c7a030ce7a08c95bd1af2e8c38ffcf972439 (diff)
Rewrote the Value class to be based on boost::variant - this should reduce memory footprint and improve performance
Diffstat (limited to 'src')
-rw-r--r--src/cgaladv.cc6
-rw-r--r--src/color.cc12
-rw-r--r--src/context.cc14
-rw-r--r--src/control.cc28
-rw-r--r--src/dxfdim.cc27
-rw-r--r--src/expr.cc80
-rw-r--r--src/expression.h4
-rw-r--r--src/func.cc244
-rw-r--r--src/import.cc26
-rw-r--r--src/linearextrude.cc32
-rw-r--r--src/mainwin.cc22
-rw-r--r--src/parser.y31
-rw-r--r--src/primitives.cc84
-rw-r--r--src/projection.cc6
-rw-r--r--src/render.cc4
-rw-r--r--src/rotateextrude.cc18
-rw-r--r--src/surface.cc11
-rw-r--r--src/transform.cc32
-rw-r--r--src/value.cc1000
-rw-r--r--src/value.h149
20 files changed, 955 insertions, 875 deletions
diff --git a/src/cgaladv.cc b/src/cgaladv.cc
index 9abf87c..1773a90 100644
--- a/src/cgaladv.cc
+++ b/src/cgaladv.cc
@@ -78,10 +78,10 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat
level = c.lookup_variable("level", true);
}
- node->convexity = (int)convexity.num;
+ node->convexity = (int)convexity.toDouble();
node->path = path;
- node->subdiv_type = subdiv_type.text;
- node->level = (int)level.num;
+ node->subdiv_type = subdiv_type.toString();
+ node->level = (int)level.toDouble();
if (node->level <= 1)
node->level = 1;
diff --git a/src/color.cc b/src/color.cc
index e458bfb..4220396 100644
--- a/src/color.cc
+++ b/src/color.cc
@@ -63,11 +63,11 @@ AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiatio
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
Value v = c.lookup_variable("c");
- if (v.type == Value::VECTOR) {
+ if (v.type() == Value::VECTOR) {
for (size_t i = 0; i < 4; i++)
- node->color[i] = i < v.vec.size() ? v.vec[i]->num : 1.0;
- } else if (v.type == Value::STRING) {
- std::string colorname = v.text;
+ node->color[i] = i < v.toVector().size() ? v.toVector()[i].toDouble() : 1.0;
+ } else if (v.type() == Value::STRING) {
+ std::string colorname = v.toString();
boost::algorithm::to_lower(colorname);
Color4f color;
if (colormap.find(colorname) != colormap.end()) {
@@ -81,8 +81,8 @@ AbstractNode *ColorModule::evaluate(const Context *ctx, const ModuleInstantiatio
}
}
Value alpha = c.lookup_variable("alpha");
- if (alpha.type == Value::NUMBER) {
- node->color[3] = alpha.num;
+ if (alpha.type() == Value::NUMBER) {
+ node->color[3] = alpha.toDouble();
}
std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
diff --git a/src/context.cc b/src/context.cc
index f96a45b..2decc48 100644
--- a/src/context.cc
+++ b/src/context.cc
@@ -196,13 +196,13 @@ void register_builtin(Context &ctx)
ctx.set_variable("$fa", Value(12.0));
ctx.set_variable("$t", Value(0.0));
- Value zero3;
- zero3.type = Value::VECTOR;
- zero3.append(new Value(0.0));
- zero3.append(new Value(0.0));
- zero3.append(new Value(0.0));
- ctx.set_variable("$vpt", zero3);
- ctx.set_variable("$vpr", zero3);
+ Value::VectorType zero3;
+ zero3.push_back(Value(0.0));
+ zero3.push_back(Value(0.0));
+ zero3.push_back(Value(0.0));
+ Value zero3val(zero3);
+ ctx.set_variable("$vpt", zero3val);
+ ctx.set_variable("$vpr", zero3val);
ctx.set_constant("PI",Value(M_PI));
}
diff --git a/src/control.cc b/src/control.cc
index 1d87551..bdd0f40 100644
--- a/src/control.cc
+++ b/src/control.cc
@@ -57,29 +57,27 @@ void for_eval(AbstractNode &node, const ModuleInstantiation &inst, size_t l,
const std::string &it_name = call_argnames[l];
const Value &it_values = call_argvalues[l];
Context c(arg_context);
- if (it_values.type == Value::RANGE) {
- double range_begin = it_values.range_begin;
- double range_end = it_values.range_end;
- double range_step = it_values.range_step;
- if (range_end < range_begin) {
- double t = range_begin;
- range_begin = range_end;
- range_end = t;
+ if (it_values.type() == Value::RANGE) {
+ Value::RangeType range = it_values.toRange();
+ if (range.end < range.begin) {
+ double t = range.begin;
+ range.begin = range.end;
+ range.end = t;
}
- if (range_step > 0 && (range_begin-range_end)/range_step < 10000) {
- for (double i = range_begin; i <= range_end; i += range_step) {
+ if (range.step > 0 && (range.begin-range.end)/range.step < 10000) {
+ for (double i = range.begin; i <= range.end; i += range.step) {
c.set_variable(it_name, Value(i));
for_eval(node, inst, l+1, call_argnames, call_argvalues, &c);
}
}
}
- else if (it_values.type == Value::VECTOR) {
- for (size_t i = 0; i < it_values.vec.size(); i++) {
- c.set_variable(it_name, *it_values.vec[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, call_argnames, call_argvalues, &c);
}
}
- 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, call_argnames, call_argvalues, &c);
}
@@ -98,7 +96,7 @@ AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation
size_t n = 0;
if (inst->argvalues.size() > 0) {
double v;
- if (inst->argvalues[0].getnum(v))
+ if (inst->argvalues[0].getDouble(v))
n = v;
}
for (int i = Context::ctx_stack.size()-1; i >= 0; i--) {
diff --git a/src/dxfdim.cc b/src/dxfdim.cc
index 664fdb5..8f68ac6 100644
--- a/src/dxfdim.cc
+++ b/src/dxfdim.cc
@@ -52,15 +52,15 @@ Value builtin_dxf_dim(const Context *ctx, const std::vector<std::string> &argnam
for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
if (argnames[i] == "file")
- filename = ctx->getAbsolutePath(args[i].text);
+ filename = ctx->getAbsolutePath(args[i].toString());
if (argnames[i] == "layer")
- layername = args[i].text;
+ layername = args[i].toString();
if (argnames[i] == "origin")
- args[i].getv2(xorigin, yorigin);
+ args[i].getVec2(xorigin, yorigin);
if (argnames[i] == "scale")
- args[i].getnum(scale);
+ args[i].getDouble(scale);
if (argnames[i] == "name")
- name = args[i].text;
+ name = args[i].toString();
}
std::stringstream keystream;
@@ -136,13 +136,13 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector<std::string> &argn
for (size_t i = 0; i < argnames.size() && i < args.size(); i++) {
if (argnames[i] == "file")
- filename = ctx->getAbsolutePath(args[i].text);
+ filename = ctx->getAbsolutePath(args[i].toString());
if (argnames[i] == "layer")
- layername = args[i].text;
+ layername = args[i].toString();
if (argnames[i] == "origin")
- args[i].getv2(xorigin, yorigin);
+ args[i].getVec2(xorigin, yorigin);
if (argnames[i] == "scale")
- args[i].getnum(scale);
+ args[i].getDouble(scale);
}
std::stringstream keystream;
@@ -178,11 +178,10 @@ Value builtin_dxf_cross(const Context *ctx, const std::vector<std::string> &argn
// double ub = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)) / dem;
double x = x1 + ua*(x2 - x1);
double y = y1 + ua*(y2 - y1);
- Value ret;
- ret.type = Value::VECTOR;
- ret.append(new Value(x));
- ret.append(new Value(y));
- return dxf_cross_cache[key] = ret;
+ Value::VectorType ret;
+ ret.push_back(Value(x));
+ ret.push_back(Value(y));
+ return dxf_cross_cache[key] = Value(ret);
}
}
diff --git a/src/expr.cc b/src/expr.cc
index 671553c..75fc47a 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -31,16 +31,20 @@
#include <sstream>
#include <algorithm>
#include "stl-utils.h"
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
Expression::Expression()
{
- this->const_value = NULL;
+}
+
+Expression::Expression(const Value &val) : const_value(val), type("C")
+{
}
Expression::~Expression()
{
std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>());
- delete this->const_value;
}
Value Expression::evaluate(const Context *context) const
@@ -78,44 +82,27 @@ Value Expression::evaluate(const Context *context) const
return this->children[v.toBool() ? 1 : 2]->evaluate(context);
}
if (this->type == "[]") {
- Value v1 = this->children[0]->evaluate(context);
- Value v2 = this->children[1]->evaluate(context);
- if (v1.type == Value::VECTOR && v2.type == Value::NUMBER) {
- int i = int(v2.num);
- if (i >= 0 && i < int(v1.vec.size()))
- return *v1.vec[i];
- }
- if (v1.type == Value::STRING && v2.type == Value::NUMBER) {
- unsigned int i = int(v2.num);
- if (i < v1.text.size())
- return Value(v1.text.substr(i, 1));
- }
- return Value();
+ return this->children[0]->evaluate(context)[this->children[1]->evaluate(context)];
}
if (this->type == "I")
- return this->children[0]->evaluate(context).inv();
+ return -this->children[0]->evaluate(context);
if (this->type == "C")
- return *this->const_value;
+ return this->const_value;
if (this->type == "R") {
Value v1 = this->children[0]->evaluate(context);
Value v2 = this->children[1]->evaluate(context);
Value v3 = this->children[2]->evaluate(context);
- if (v1.type == Value::NUMBER && v2.type == Value::NUMBER && v3.type == Value::NUMBER) {
- Value r = Value();
- r.type = Value::RANGE;
- r.range_begin = v1.num;
- r.range_step = v2.num;
- r.range_end = v3.num;
- return r;
+ if (v1.type() == Value::NUMBER && v2.type() == Value::NUMBER && v3.type() == Value::NUMBER) {
+ return Value(v1.toDouble(), v2.toDouble(), v3.toDouble());
}
return Value();
}
if (this->type == "V") {
- Value v;
- v.type = Value::VECTOR;
- for (size_t i = 0; i < this->children.size(); i++)
- v.append(new Value(this->children[i]->evaluate(context)));
- return v;
+ Value::VectorType vec;
+ BOOST_FOREACH(const Expression *e, this->children) {
+ vec.push_back(e->evaluate(context));
+ }
+ return Value(vec);
}
if (this->type == "L")
return context->lookup_variable(this->var_name);
@@ -123,26 +110,29 @@ Value Expression::evaluate(const Context *context) const
{
Value v = this->children[0]->evaluate(context);
- if (v.type == Value::VECTOR && this->var_name == "x")
- return *v.vec[0];
- if (v.type == Value::VECTOR && this->var_name == "y")
- return *v.vec[1];
- if (v.type == Value::VECTOR && this->var_name == "z")
- return *v.vec[2];
+ if (v.type() == Value::VECTOR && this->var_name == "x")
+ return v[0];
+ if (v.type() == Value::VECTOR && this->var_name == "y")
+ return v[1];
+ if (v.type() == Value::VECTOR && this->var_name == "z")
+ return v[2];
- if (v.type == Value::RANGE && this->var_name == "begin")
- return Value(v.range_begin);
- if (v.type == Value::RANGE && this->var_name == "step")
- return Value(v.range_step);
- if (v.type == Value::RANGE && this->var_name == "end")
- return Value(v.range_end);
+ if (v.type() == Value::RANGE && this->var_name == "begin")
+ return Value(v[0]);
+ if (v.type() == Value::RANGE && this->var_name == "step")
+ return Value(v[1]);
+ if (v.type() == Value::RANGE && this->var_name == "end")
+ return Value(v[2]);
return Value();
}
if (this->type == "F") {
- std::vector<Value> argvalues;
- for (size_t i=0; i < this->children.size(); i++)
- argvalues.push_back(this->children[i]->evaluate(context));
+ Value::VectorType argvalues;
+ std::transform(this->children.begin(), this->children.end(),
+ std::back_inserter(argvalues),
+ boost::bind(&Expression::evaluate, _1, context));
+ // for (size_t i=0; i < this->children.size(); i++)
+ // argvalues.push_back(this->children[i]->evaluate(context));
return context->evaluate_function(this->call_funcname, this->call_argnames, argvalues);
}
abort();
@@ -167,7 +157,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] << " : " << this->children[2] << "]";
diff --git a/src/expression.h b/src/expression.h
index acbd6aa..2919b78 100644
--- a/src/expression.h
+++ b/src/expression.h
@@ -3,13 +3,14 @@
#include <string>
#include <vector>
+#include "value.h"
class Expression
{
public:
std::vector<Expression*> children;
- class Value *const_value;
+ const Value const_value;
std::string var_name;
std::string call_funcname;
@@ -31,6 +32,7 @@ public:
std::string type;
Expression();
+ Expression(const Value &val);
~Expression();
Value evaluate(const class Context *context) const;
diff --git a/src/func.cc b/src/func.cc
index 0c9b450..6c5f070 100644
--- a/src/func.cc
+++ b/src/func.cc
@@ -109,15 +109,15 @@ static inline double rad2deg(double x)
Value builtin_abs(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(fabs(args[0].num));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(fabs(args[0].toDouble()));
return Value();
}
Value builtin_sign(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value((args[0].num<0) ? -1.0 : ((args[0].num>0) ? 1.0 : 0.0));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value((args[0].toDouble()<0) ? -1.0 : ((args[0].toDouble()>0) ? 1.0 : 0.0));
return Value();
}
@@ -134,45 +134,41 @@ double frand(double min, double max)
Value builtin_rands(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
if (args.size() == 3 &&
- args[0].type == Value::NUMBER &&
- args[1].type == Value::NUMBER &&
- args[2].type == Value::NUMBER)
+ args[0].type() == Value::NUMBER &&
+ args[1].type() == Value::NUMBER &&
+ args[2].type() == Value::NUMBER)
{
srand((unsigned int)time(0));
}
else if (args.size() == 4 &&
- args[0].type == Value::NUMBER &&
- args[1].type == Value::NUMBER &&
- args[2].type == Value::NUMBER &&
- args[3].type == Value::NUMBER)
+ args[0].type() == Value::NUMBER &&
+ args[1].type() == Value::NUMBER &&
+ args[2].type() == Value::NUMBER &&
+ args[3].type() == Value::NUMBER)
{
- srand((unsigned int)args[3].num);
+ srand((unsigned int)args[3].toDouble());
}
else
{
return Value();
}
- Value v;
- v.type = Value::VECTOR;
-
- for (int i=0; i<args[2].num; i++)
- {
- Value * r = new Value(frand(args[0].num, args[1].num));
- v.vec.push_back(r);
+ Value::VectorType vec;
+ for (int i=0; i<args[2].toDouble(); i++) {
+ vec.push_back(Value(frand(args[0].toDouble(), args[1].toDouble())));
}
- return v;
+ return Value(vec);
}
Value builtin_min(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() >= 1 && args[0].type == Value::NUMBER) {
- double val = args[0].num;
+ if (args.size() >= 1 && args[0].type() == Value::NUMBER) {
+ double val = args[0].toDouble();
for (size_t i = 1; i < args.size(); i++)
- if (args[1].type == Value::NUMBER)
- val = fmin(val, args[i].num);
+ if (args[1].type() == Value::NUMBER)
+ val = fmin(val, args[i].toDouble());
return Value(val);
}
return Value();
@@ -180,11 +176,11 @@ Value builtin_min(const Context *, const std::vector<std::string>&, const std::v
Value builtin_max(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() >= 1 && args[0].type == Value::NUMBER) {
- double val = args[0].num;
+ if (args.size() >= 1 && args[0].type() == Value::NUMBER) {
+ double val = args[0].toDouble();
for (size_t i = 1; i < args.size(); i++)
- if (args[1].type == Value::NUMBER)
- val = fmax(val, args[i].num);
+ if (args[1].type() == Value::NUMBER)
+ val = fmax(val, args[i].toDouble());
return Value(val);
}
return Value();
@@ -192,119 +188,117 @@ Value builtin_max(const Context *, const std::vector<std::string>&, const std::v
Value builtin_sin(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(sin(deg2rad(args[0].num)));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(sin(deg2rad(args[0].toDouble())));
return Value();
}
Value builtin_cos(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(cos(deg2rad(args[0].num)));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(cos(deg2rad(args[0].toDouble())));
return Value();
}
Value builtin_asin(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(rad2deg(asin(args[0].num)));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(rad2deg(asin(args[0].toDouble())));
return Value();
}
Value builtin_acos(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(rad2deg(acos(args[0].num)));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(rad2deg(acos(args[0].toDouble())));
return Value();
}
Value builtin_tan(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(tan(deg2rad(args[0].num)));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(tan(deg2rad(args[0].toDouble())));
return Value();
}
Value builtin_atan(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(rad2deg(atan(args[0].num)));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(rad2deg(atan(args[0].toDouble())));
return Value();
}
Value builtin_atan2(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 2 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER)
- return Value(rad2deg(atan2(args[0].num, args[1].num)));
+ if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER)
+ return Value(rad2deg(atan2(args[0].toDouble(), args[1].toDouble())));
return Value();
}
Value builtin_pow(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 2 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER)
- return Value(pow(args[0].num, args[1].num));
+ if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER)
+ return Value(pow(args[0].toDouble(), args[1].toDouble()));
return Value();
}
Value builtin_round(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(round(args[0].num));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(round(args[0].toDouble()));
return Value();
}
Value builtin_ceil(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(ceil(args[0].num));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(ceil(args[0].toDouble()));
return Value();
}
Value builtin_floor(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(floor(args[0].num));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(floor(args[0].toDouble()));
return Value();
}
Value builtin_sqrt(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(sqrt(args[0].num));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(sqrt(args[0].toDouble()));
return Value();
}
Value builtin_exp(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(exp(args[0].num));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(exp(args[0].toDouble()));
return Value();
}
Value builtin_length(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1){
- if (args[0].type == Value::VECTOR)
- return Value((double) args[0].vec.size());
- if (args[0].type == Value::STRING)
- return Value((double) args[0].text.size());
+ if (args.size() == 1) {
+ if (args[0].type() == Value::VECTOR) return Value(int(args[0].toVector().size()));
+ if (args[0].type() == Value::STRING) return Value(int(args[0].toString().size()));
}
return Value();
}
Value builtin_log(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 2 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER)
- return Value(log(args[1].num) / log(args[0].num));
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(log(args[0].num) / log(10.0));
+ if (args.size() == 2 && args[0].type() == Value::NUMBER && args[1].type() == Value::NUMBER)
+ return Value(log(args[1].toDouble()) / log(args[0].toDouble()));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(log(args[0].toDouble()) / log(10.0));
return Value();
}
Value builtin_ln(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
- if (args.size() == 1 && args[0].type == Value::NUMBER)
- return Value(log(args[0].num));
+ if (args.size() == 1 && args[0].type() == Value::NUMBER)
+ return Value(log(args[0].toDouble()));
return Value();
}
@@ -321,13 +315,16 @@ Value builtin_str(const Context *, const std::vector<std::string>&, const std::v
Value builtin_lookup(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)
{
double p, low_p, low_v, high_p, high_v;
- if (args.size() < 2 || !args[0].getnum(p) || args[1].vec.size() < 2 || args[1].vec[0]->vec.size() < 2)
+ if (args.size() < 2 || // Needs two args
+ !args[0].getDouble(p) || // First must be a number
+ args[1].toVector().size() < 2 || // Second must be a vector of vectors
+ args[1].toVector()[0].toVector().size() < 2)
return Value();
- if (!args[1].vec[0]->getv2(low_p, low_v) || !args[1].vec[0]->getv2(high_p, high_v))
+ if (!args[1].toVector()[0].getVec2(low_p, low_v) || !args[1].toVector()[0].getVec2(high_p, high_v))
return Value();
- for (size_t i = 1; i < args[1].vec.size(); i++) {
+ for (size_t i = 1; i < args[1].toVector().size(); i++) {
double this_p, this_v;
- if (args[1].vec[i]->getv2(this_p, this_v)) {
+ if (args[1].toVector()[i].getVec2(this_p, this_v)) {
if (this_p <= p && (this_p > low_p || low_p > p)) {
low_p = this_p;
low_v = this_v;
@@ -394,94 +391,90 @@ Value builtin_search(const Context *, const std::vector<std::string>&, const std
const Value &findThis = args[0];
const Value &searchTable = args[1];
- unsigned int num_returns_per_match = (args.size() > 2) ? args[2].num : 1;
- unsigned int index_col_num = (args.size() > 3) ? args[3].num : 0;
+ unsigned int num_returns_per_match = (args.size() > 2) ? args[2].toDouble() : 1;
+ unsigned int index_col_num = (args.size() > 3) ? args[3].toDouble() : 0;
- Value returnVector;
- returnVector.type = Value::VECTOR;
+ Value::VectorType returnvec;
- if (findThis.type == Value::NUMBER) {
+ if (findThis.type() == Value::NUMBER) {
unsigned int matchCount = 0;
- Value *resultVector = new Value();
- resultVector->type = Value::VECTOR;
- for (size_t j = 0; j < searchTable.vec.size(); j++) {
- if (searchTable.vec[j]->vec[index_col_num]->type == Value::NUMBER &&
- findThis.num == searchTable.vec[j]->vec[index_col_num]->num) {
- returnVector.append(new Value(double(j)));
+ Value::VectorType resultvec;
+ for (size_t j = 0; j < searchTable.toVector().size(); j++) {
+ if (searchTable.toVector()[j].toVector()[index_col_num].type() == Value::NUMBER &&
+ findThis.toDouble() == searchTable.toVector()[j].toVector()[index_col_num].toDouble()) {
+ 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) {
+ } else if (findThis.type() == Value::STRING) {
unsigned int searchTableSize;
- if (searchTable.type == Value::STRING) searchTableSize = searchTable.text.size();
- else searchTableSize = searchTable.vec.size();
- for (size_t i = 0; i < findThis.text.size(); i++) {
+ if (searchTable.type() == Value::STRING) searchTableSize = searchTable.toString().size();
+ else searchTableSize = searchTable.toVector().size();
+ for (size_t i = 0; i < findThis.toString().size(); i++) {
unsigned int matchCount = 0;
- Value *resultVector = new Value();
- resultVector->type = Value::VECTOR;
+ Value::VectorType resultvec;
for (size_t j = 0; j < searchTableSize; j++) {
- if ((searchTable.type == Value::VECTOR &&
- findThis.text[i] == searchTable.vec[j]->vec[index_col_num]->text[0]) ||
- (searchTable.type == Value::STRING &&
- findThis.text[i] == searchTable.text[j])) {
- Value *resultValue = new Value(double(j));
+ if ((searchTable.type() == Value::VECTOR &&
+ findThis.toString()[i] == searchTable.toVector()[j].toVector()[index_col_num].toString()[0]) ||
+ (searchTable.type() == Value::STRING &&
+ findThis.toString()[i] == searchTable.toString()[j])) {
+ Value resultValue((double(j)));
matchCount++;
- if (num_returns_per_match==1) {
- returnVector.append(resultValue);
+ if (num_returns_per_match == 1) {
+ returnvec.push_back(resultValue);
break;
} else {
- resultVector->append(resultValue);
+ resultvec.push_back(resultValue);
}
if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) break;
}
}
- if (matchCount == 0) PRINTB(" search term not found: \"%s\"", findThis.text[i]);
+ if (matchCount == 0) PRINTB(" search term not found: \"%s\"", findThis.toString()[i]);
if (num_returns_per_match == 0 || num_returns_per_match > 1) {
- returnVector.append(resultVector);
+ returnvec.push_back(Value(resultvec));
}
}
- } else if (findThis.type == Value::VECTOR) {
- for (size_t i = 0; i < findThis.vec.size(); i++) {
+ } else if (findThis.type() == Value::VECTOR) {
+ for (size_t i = 0; i < findThis.toVector().size(); i++) {
unsigned int matchCount = 0;
- Value *resultVector = new Value();
- resultVector->type = Value::VECTOR;
- for (size_t j = 0; j < searchTable.vec.size(); j++) {
- if ((findThis.vec[i]->type == Value::NUMBER &&
- searchTable.vec[j]->vec[index_col_num]->type == Value::NUMBER &&
- findThis.vec[i]->num == searchTable.vec[j]->vec[index_col_num]->num) ||
- (findThis.vec[i]->type == Value::STRING &&
- searchTable.vec[j]->vec[index_col_num]->type == Value::STRING &&
- findThis.vec[i]->text == searchTable.vec[j]->vec[index_col_num]->text)) {
- Value *resultValue = new Value(double(j));
+ Value::VectorType resultvec;
+ for (size_t j = 0; j < searchTable.toVector().size(); j++) {
+ if ((findThis.toVector()[i].type() == Value::NUMBER &&
+ searchTable.toVector()[j].toVector()[index_col_num].type() == Value::NUMBER &&
+ findThis.toVector()[i].toDouble() == searchTable.toVector()[j].toVector()[index_col_num].toDouble()) ||
+ (findThis.toVector()[i].type() == Value::STRING &&
+ searchTable.toVector()[j].toVector()[index_col_num].type() == Value::STRING &&
+ findThis.toVector()[i].toString() == searchTable.toVector()[j].toVector()[index_col_num].toString())) {
+ Value resultValue((double(j)));
matchCount++;
- if (num_returns_per_match==1) {
- returnVector.append(resultValue);
+ if (num_returns_per_match == 1) {
+ returnvec.push_back(resultValue);
break;
} else {
- resultVector->append(resultValue);
+ resultvec.push_back(resultValue);
}
if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) break;
}
}
if (num_returns_per_match == 1 && matchCount == 0) {
- if (findThis.vec[i]->type == Value::NUMBER) {
- PRINTB(" search term not found: %s",findThis.vec[i]->num);
+ if (findThis.toVector()[i].type() == Value::NUMBER) {
+ PRINTB(" search term not found: %s",findThis.toVector()[i].toDouble());
}
- else if (findThis.vec[i]->type == Value::STRING) {
- PRINTB(" search term not found: \"%s\"",findThis.vec[i]->text);
+ else if (findThis.toVector()[i].type() == Value::STRING) {
+ PRINTB(" search term not found: \"%s\"",findThis.toVector()[i].toString());
}
- returnVector.append(resultVector);
+ returnvec.push_back(Value(resultvec));
}
if (num_returns_per_match == 0 || num_returns_per_match > 1) {
- returnVector.append(resultVector);
+ returnvec.push_back(Value(resultvec));
}
}
} else {
PRINTB(" search: none performed on input %s", findThis);
return Value();
}
- return returnVector;
+ return Value(returnvec);
}
#define QUOTE(x__) # x__
@@ -489,22 +482,21 @@ Value builtin_search(const Context *, const std::vector<std::string>&, const std
Value builtin_version(const Context *, const std::vector<std::string>&, const std::vector<Value> &)
{
- Value val;
- val.type = Value::VECTOR;
- val.append(new Value(double(OPENSCAD_YEAR)));
- val.append(new Value(double(OPENSCAD_MONTH)));
+ Value::VectorType val;
+ val.push_back(Value(double(OPENSCAD_YEAR)));
+ val.push_back(Value(double(OPENSCAD_MONTH)));
#ifdef OPENSCAD_DAY
- val.append(new Value(double(OPENSCAD_DAY)));
+ val.push_back(Value(double(OPENSCAD_DAY)));
#endif
- return val;
+ return Value(val);
}
Value builtin_version_num(const Context *ctx, const std::vector<std::string>& call_argnames, const std::vector<Value> &args)
{
Value val = (args.size() == 0) ? builtin_version(ctx, call_argnames, args) : args[0];
double y, m, d = 0;
- if (!val.getv3(y, m, d)) {
- if (!val.getv2(y, m)) {
+ if (!val.getVec3(y, m, d)) {
+ if (!val.getVec2(y, m)) {
return Value();
}
}
diff --git a/src/import.cc b/src/import.cc
index 597ecfb..221ee55 100644
--- a/src/import.cc
+++ b/src/import.cc
@@ -69,17 +69,15 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati
// Map old argnames to new argnames for compatibility
std::vector<std::string> inst_argnames = inst->argnames;
for (size_t i=0; i<inst_argnames.size(); i++) {
- if (inst_argnames[i] == "filename")
- inst_argnames[i] = "file";
- if (inst_argnames[i] == "layername")
- inst_argnames[i] = "layer";
+ if (inst_argnames[i] == "filename") inst_argnames[i] = "file";
+ if (inst_argnames[i] == "layername") inst_argnames[i] = "layer";
}
Context c(ctx);
c.args(argnames, argexpr, inst_argnames, inst->argvalues);
Value v = c.lookup_variable("file");
- std::string filename = c.getAbsolutePath(v.text);
+ std::string filename = c.getAbsolutePath(v.isUndefined() ? "" : v.toString());
import_type_e actualtype = this->type;
if (actualtype == TYPE_UNKNOWN) {
std::string extraw = boosty::extension_str( path(filename) );
@@ -91,22 +89,22 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati
ImportNode *node = new ImportNode(inst, actualtype);
- node->fn = c.lookup_variable("$fn").num;
- node->fs = c.lookup_variable("$fs").num;
- node->fa = c.lookup_variable("$fa").num;
+ node->fn = c.lookup_variable("$fn").toDouble();
+ node->fs = c.lookup_variable("$fs").toDouble();
+ node->fa = c.lookup_variable("$fa").toDouble();
node->filename = filename;
- node->layername = c.lookup_variable("layer", true).text;
- node->convexity = c.lookup_variable("convexity", true).num;
+ Value layerval = c.lookup_variable("layer", true);
+ node->layername = layerval.isUndefined() ? "" : layerval.toString();
+ node->convexity = c.lookup_variable("convexity", true).toDouble();
- if (node->convexity <= 0)
- node->convexity = 1;
+ if (node->convexity <= 0) node->convexity = 1;
Value origin = c.lookup_variable("origin", true);
node->origin_x = node->origin_y = 0;
- origin.getv2(node->origin_x, node->origin_y);
+ origin.getVec2(node->origin_x, node->origin_y);
- node->scale = c.lookup_variable("scale", true).num;
+ node->scale = c.lookup_variable("scale", true).toDouble();
if (node->scale <= 0)
node->scale = 1;
diff --git a/src/linearextrude.cc b/src/linearextrude.cc
index 4f5fd14..b193181 100644
--- a/src/linearextrude.cc
+++ b/src/linearextrude.cc
@@ -56,9 +56,9 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst
Context c(ctx);
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
- node->fn = c.lookup_variable("$fn").num;
- node->fs = c.lookup_variable("$fs").num;
- node->fa = c.lookup_variable("$fa").num;
+ 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);
@@ -70,19 +70,19 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst
Value twist = c.lookup_variable("twist", true);
Value slices = c.lookup_variable("slices", true);
- if (!file.text.empty()) {
+ if (!file.isUndefined()) {
PRINT("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead.");
- node->filename = c.getAbsolutePath(file.text);
+ node->filename = c.getAbsolutePath(file.toString());
}
- node->layername = layer.text;
- node->height = height.num;
- node->convexity = (int)convexity.num;
- origin.getv2(node->origin_x, node->origin_y);
- node->scale = scale.num;
+ node->layername = layer.isUndefined() ? "" : layer.toString();
+ node->height = height.toDouble();
+ node->convexity = (int)convexity.toDouble();
+ origin.getVec2(node->origin_x, node->origin_y);
+ node->scale = scale.toDouble();
- if (center.type == Value::BOOL)
- node->center = center.b;
+ if (center.type() == Value::BOOL)
+ node->center = center.toBool();
if (node->height <= 0)
node->height = 100;
@@ -93,10 +93,10 @@ AbstractNode *LinearExtrudeModule::evaluate(const Context *ctx, const ModuleInst
if (node->scale <= 0)
node->scale = 1;
- if (twist.type == Value::NUMBER) {
- node->twist = twist.num;
- if (slices.type == Value::NUMBER) {
- node->slices = (int)slices.num;
+ if (twist.type() == Value::NUMBER) {
+ node->twist = twist.toDouble();
+ if (slices.type() == Value::NUMBER) {
+ node->slices = (int)slices.toDouble();
} else {
node->slices = (int)fmax(2, fabs(get_fragments_from_r(node->height,
node->fn, node->fs, node->fa) * node->twist / 360));
diff --git a/src/mainwin.cc b/src/mainwin.cc
index bb0f90d..daea6e3 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -972,19 +972,17 @@ void MainWindow::updateTemporalVariables()
{
this->root_ctx.set_variable("$t", Value(this->e_tval->text().toDouble()));
- Value vpt;
- vpt.type = Value::VECTOR;
- vpt.append(new Value(-this->glview->object_trans_x));
- vpt.append(new Value(-this->glview->object_trans_y));
- vpt.append(new Value(-this->glview->object_trans_z));
- this->root_ctx.set_variable("$vpt", vpt);
+ Value::VectorType vpt;
+ vpt.push_back(Value(-this->glview->object_trans_x));
+ vpt.push_back(Value(-this->glview->object_trans_y));
+ vpt.push_back(Value(-this->glview->object_trans_z));
+ this->root_ctx.set_variable("$vpt", Value(vpt));
- Value vpr;
- vpr.type = Value::VECTOR;
- vpr.append(new Value(fmodf(360 - this->glview->object_rot_x + 90, 360)));
- vpr.append(new Value(fmodf(360 - this->glview->object_rot_y, 360)));
- vpr.append(new Value(fmodf(360 - this->glview->object_rot_z, 360)));
- root_ctx.set_variable("$vpr", vpr);
+ Value::VectorType vpr;
+ vpr.push_back(Value(fmodf(360 - this->glview->object_rot_x + 90, 360)));
+ vpr.push_back(Value(fmodf(360 - this->glview->object_rot_y, 360)));
+ vpr.push_back(Value(fmodf(360 - this->glview->object_rot_z, 360)));
+ root_ctx.set_variable("$vpr", Value(vpr));
}
bool MainWindow::fileChangedOnDisk()
diff --git a/src/parser.y b/src/parser.y
index 2f4379a..58ca695 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -295,19 +295,13 @@ single_module_instantiation:
expr:
TOK_TRUE {
- $$ = new Expression();
- $$->type = "C";
- $$->const_value = new Value(true);
+ $$ = new Expression(Value(true));
} |
TOK_FALSE {
- $$ = new Expression();
- $$->type = "C";
- $$->const_value = new Value(false);
+ $$ = new Expression(Value(false));
} |
TOK_UNDEF {
- $$ = new Expression();
- $$->type = "C";
- $$->const_value = new Value();
+ $$ = new Expression(Value::undefined);
} |
TOK_ID {
$$ = new Expression();
@@ -323,20 +317,14 @@ expr:
free($3);
} |
TOK_STRING {
- $$ = new Expression();
- $$->type = "C";
- $$->const_value = new Value(std::string($1));
- free($1);
+ $$ = new Expression(Value(std::string($1)));
+ free($1);
} |
TOK_NUMBER {
- $$ = new Expression();
- $$->type = "C";
- $$->const_value = new Value($1);
+ $$ = new Expression(Value($1));
} |
'[' expr ':' expr ']' {
- Expression *e_one = new Expression();
- e_one->type = "C";
- e_one->const_value = new Value(1.0);
+ Expression *e_one = new Expression(Value(1.0));
$$ = new Expression();
$$->type = "R";
$$->children.push_back($2);
@@ -351,10 +339,7 @@ expr:
$$->children.push_back($6);
} |
'[' optional_commas ']' {
- $$ = new Expression();
- $$->type = "C";
- $$->const_value = new Value();
- $$->const_value->type = Value::VECTOR;
+ $$ = new Expression(Value(Value::VectorType()));
} |
'[' vector_expr optional_commas ']' {
$$ = $2;
diff --git a/src/primitives.cc b/src/primitives.cc
index ce52550..e02df35 100644
--- a/src/primitives.cc
+++ b/src/primitives.cc
@@ -143,9 +143,9 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti
Context c(ctx);
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
- node->fn = c.lookup_variable("$fn").num;
- node->fs = c.lookup_variable("$fs").num;
- node->fa = c.lookup_variable("$fa").num;
+ 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);
@@ -160,19 +160,19 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti
if (type == CUBE) {
Value size = c.lookup_variable("size");
Value center = c.lookup_variable("center");
- size.getnum(node->x);
- size.getnum(node->y);
- size.getnum(node->z);
- size.getv3(node->x, node->y, node->z);
- if (center.type == Value::BOOL) {
- node->center = center.b;
+ 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();
}
}
if (type == SPHERE) {
Value r = c.lookup_variable("r");
- if (r.type == Value::NUMBER) {
- node->r1 = r.num;
+ if (r.type() == Value::NUMBER) {
+ node->r1 = r.toDouble();
}
}
@@ -183,21 +183,21 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti
r2 = c.lookup_variable("r2");
r = c.lookup_variable("r", true); // silence warning since r has no default value
Value center = c.lookup_variable("center");
- if (h.type == Value::NUMBER) {
- node->h = h.num;
+ if (h.type() == Value::NUMBER) {
+ node->h = h.toDouble();
}
- if (r.type == Value::NUMBER) {
- node->r1 = r.num;
- node->r2 = r.num;
+ if (r.type() == Value::NUMBER) {
+ node->r1 = r.toDouble();
+ node->r2 = r.toDouble();
}
- if (r1.type == Value::NUMBER) {
- node->r1 = r1.num;
+ if (r1.type() == Value::NUMBER) {
+ node->r1 = r1.toDouble();
}
- if (r2.type == Value::NUMBER) {
- node->r2 = r2.num;
+ if (r2.type() == Value::NUMBER) {
+ node->r2 = r2.toDouble();
}
- if (center.type == Value::BOOL) {
- node->center = center.b;
+ if (center.type() == Value::BOOL) {
+ node->center = center.toBool();
}
}
@@ -209,18 +209,18 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti
if (type == SQUARE) {
Value size = c.lookup_variable("size");
Value center = c.lookup_variable("center");
- size.getnum(node->x);
- size.getnum(node->y);
- size.getv2(node->x, node->y);
- if (center.type == Value::BOOL) {
- node->center = center.b;
+ size.getDouble(node->x);
+ size.getDouble(node->y);
+ size.getVec2(node->x, node->y);
+ if (center.type() == Value::BOOL) {
+ node->center = center.toBool();
}
}
if (type == CIRCLE) {
Value r = c.lookup_variable("r");
- if (r.type == Value::NUMBER) {
- node->r1 = r.num;
+ if (r.type() == Value::NUMBER) {
+ node->r1 = r.toDouble();
}
}
@@ -229,7 +229,7 @@ AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstanti
node->paths = c.lookup_variable("paths");
}
- node->convexity = c.lookup_variable("convexity", true).num;
+ node->convexity = c.lookup_variable("convexity", true).toDouble();
if (node->convexity < 1)
node->convexity = 1;
@@ -449,14 +449,14 @@ sphere_next_r2:
if (this->type == POLYHEDRON)
{
p->convexity = this->convexity;
- for (size_t i=0; i<this->triangles.vec.size(); i++)
+ for (size_t i=0; i<this->triangles.toVector().size(); i++)
{
p->append_poly();
- for (size_t j=0; j<this->triangles.vec[i]->vec.size(); j++) {
- size_t pt = this->triangles.vec[i]->vec[j]->num;
- if (pt < this->points.vec.size()) {
+ for (size_t j=0; j<this->triangles.toVector()[i].toVector().size(); j++) {
+ size_t pt = this->triangles.toVector()[i].toVector()[j].toDouble();
+ if (pt < this->points.toVector().size()) {
double px, py, pz;
- if (this->points.vec[pt]->getv3(px, py, pz))
+ if (this->points.toVector()[pt].getVec3(px, py, pz))
p->insert_vertex(px, py, pz);
}
}
@@ -502,9 +502,9 @@ sphere_next_r2:
{
DxfData dd;
- for (size_t i=0; i<this->points.vec.size(); i++) {
+ for (size_t i=0; i<this->points.toVector().size(); i++) {
double x,y;
- if (!this->points.vec[i]->getv2(x, y)) {
+ if (!this->points.toVector()[i].getVec2(x, y)) {
PRINTB("ERROR: Unable to convert point at index %d to a vec2 of numbers", i);
delete p;
return NULL;
@@ -512,10 +512,10 @@ sphere_next_r2:
dd.points.push_back(Vector2d(x, y));
}
- if (this->paths.vec.size() == 0)
+ if (this->paths.toVector().size() == 0)
{
dd.paths.push_back(DxfData::Path());
- for (size_t i=0; i<this->points.vec.size(); i++) {
+ for (size_t i=0; i<this->points.toVector().size(); i++) {
assert(i < dd.points.size()); // FIXME: Not needed, but this used to be an 'if'
dd.paths.back().indices.push_back(i);
}
@@ -526,11 +526,11 @@ sphere_next_r2:
}
else
{
- for (size_t i=0; i<this->paths.vec.size(); i++)
+ for (size_t i=0; i<this->paths.toVector().size(); i++)
{
dd.paths.push_back(DxfData::Path());
- for (size_t j=0; j<this->paths.vec[i]->vec.size(); j++) {
- unsigned int idx = this->paths.vec[i]->vec[j]->num;
+ for (size_t j=0; j<this->paths.toVector()[i].toVector().size(); j++) {
+ unsigned int idx = this->paths.toVector()[i].toVector()[j].toDouble();
if (idx < dd.points.size()) {
dd.paths.back().indices.push_back(idx);
}
diff --git a/src/projection.cc b/src/projection.cc
index d3e7e94..1fcf639 100644
--- a/src/projection.cc
+++ b/src/projection.cc
@@ -58,10 +58,10 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant
Value convexity = c.lookup_variable("convexity", true);
Value cut = c.lookup_variable("cut", true);
- node->convexity = (int)convexity.num;
+ node->convexity = (int)convexity.toDouble();
- if (cut.type == Value::BOOL)
- node->cut_mode = cut.b;
+ if (cut.type() == Value::BOOL)
+ node->cut_mode = cut.toBool();
std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
diff --git a/src/render.cc b/src/render.cc
index 7b0ced5..81c3f7b 100644
--- a/src/render.cc
+++ b/src/render.cc
@@ -53,8 +53,8 @@ AbstractNode *RenderModule::evaluate(const Context *ctx, const ModuleInstantiati
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
Value v = c.lookup_variable("convexity");
- if (v.type == Value::NUMBER)
- node->convexity = (int)v.num;
+ if (v.type() == Value::NUMBER)
+ node->convexity = (int)v.toDouble();
std::vector<AbstractNode *> evaluatednodes = inst->evaluateChildren();
node->children.insert(node->children.end(), evaluatednodes.begin(), evaluatednodes.end());
diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc
index e279cf1..10a8ef9 100644
--- a/src/rotateextrude.cc
+++ b/src/rotateextrude.cc
@@ -56,9 +56,9 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst
Context c(ctx);
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
- node->fn = c.lookup_variable("$fn").num;
- node->fs = c.lookup_variable("$fs").num;
- node->fa = c.lookup_variable("$fa").num;
+ 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);
@@ -66,15 +66,15 @@ AbstractNode *RotateExtrudeModule::evaluate(const Context *ctx, const ModuleInst
Value origin = c.lookup_variable("origin", true);
Value scale = c.lookup_variable("scale", true);
- if (!file.text.empty()) {
+ if (!file.isUndefined()) {
PRINT("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead.");
- node->filename = c.getAbsolutePath(file.text);
+ node->filename = c.getAbsolutePath(file.toString());
}
- node->layername = layer.text;
- node->convexity = (int)convexity.num;
- origin.getv2(node->origin_x, node->origin_y);
- node->scale = scale.num;
+ node->layername = layer.isUndefined() ? "" : layer.toString();
+ node->convexity = (int)convexity.toDouble();
+ origin.getVec2(node->origin_x, node->origin_y);
+ node->scale = scale.toDouble();
if (node->convexity <= 0)
node->convexity = 1;
diff --git a/src/surface.cc b/src/surface.cc
index e927beb..756ad74 100644
--- a/src/surface.cc
+++ b/src/surface.cc
@@ -79,16 +79,17 @@ AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiat
Context c(ctx);
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
- node->filename = c.getAbsolutePath(c.lookup_variable("file").text);
+ Value fileval = c.lookup_variable("file");
+ node->filename = c.getAbsolutePath(fileval.isUndefined() ? "" : fileval.toString());
Value center = c.lookup_variable("center", true);
- if (center.type == Value::BOOL) {
- node->center = center.b;
+ 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.num;
+ if (convexity.type() == Value::NUMBER) {
+ node->convexity = (int)convexity.toDouble();
}
return node;
diff --git a/src/transform.cc b/src/transform.cc
index c2ac194..5b71346 100644
--- a/src/transform.cc
+++ b/src/transform.cc
@@ -87,29 +87,29 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
{
Vector3d scalevec(1,1,1);
Value v = c.lookup_variable("v");
- if (!v.getv3(scalevec[0], scalevec[1], scalevec[2], 1.0)) {
+ if (!v.getVec3(scalevec[0], scalevec[1], scalevec[2], 1.0)) {
double num;
- if (v.getnum(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)
+ if (val_a.type() == Value::VECTOR)
{
Eigen::AngleAxisd rotx, roty, rotz;
double a;
- if (val_a.vec.size() > 0) {
- val_a.vec[0]->getnum(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.vec.size() > 1) {
- val_a.vec[1]->getnum(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.vec.size() > 2) {
- val_a.vec[2]->getnum(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);
@@ -119,10 +119,10 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
Value val_v = c.lookup_variable("v");
double a = 0;
- val_a.getnum(a);
+ val_a.getDouble(a);
Vector3d axis(0,0,1);
- if (val_v.getv3(axis[0], axis[1], axis[2])) {
+ if (val_v.getVec3(axis[0], axis[1], axis[2])) {
if (axis.squaredNorm() > 0) axis.normalize();
}
@@ -136,7 +136,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
Value val_v = c.lookup_variable("v");
double x = 1, y = 0, z = 0;
- if (val_v.getv3(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;
@@ -157,17 +157,17 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
{
Value v = c.lookup_variable("v");
Vector3d translatevec(0,0,0);
- v.getv3(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) {
+ if (v.type() == Value::VECTOR) {
for (int i = 0; i < 16; i++) {
size_t x = i / 4, y = i % 4;
- if (y < v.vec.size() && v.vec[y]->type == Value::VECTOR && x < v.vec[y]->vec.size())
- v.vec[y]->vec[x]->getnum(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));
}
}
}
diff --git a/src/value.cc b/src/value.cc
index 93c4d5e..13b395d 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -25,507 +25,595 @@
*/
#include "value.h"
-#include "mathc99.h"
#include <assert.h>
#include <sstream>
-#include <QDir>
#include <boost/foreach.hpp>
-#include "printutils.h"
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/format.hpp>
-Value::Value()
+#include <QtCore/QDir>
+
+std::ostream &operator<<(std::ostream &stream, const Filename &filename)
{
- reset_undef();
+ stream << QuotedString(QDir::current().relativeFilePath(QString::fromStdString(filename)).toStdString());
+ return stream;
}
-Value::~Value()
+// FIXME: This could probably be done more elegantly using boost::regex
+std::ostream &operator<<(std::ostream &stream, const QuotedString &s)
{
- for (size_t i = 0; i < this->vec.size(); i++) delete this->vec[i];
- this->vec.clear();
+ stream << '"';
+ BOOST_FOREACH(char c, s) {
+ switch (c) {
+ case '\t':
+ stream << "\\t";
+ break;
+ case '\n':
+ stream << "\\n";
+ break;
+ case '"':
+ case '\\':
+ stream << '\\';
+ stream << c;
+ break;
+ default:
+ stream << c;
+ }
+ }
+ stream << '"';
+ return stream;
}
-Value::Value(bool v)
+Value Value::undefined;
+
+Value::Value() : value(boost::blank())
{
- reset_undef();
- this->type = BOOL;
- this->b = v;
+ // std::cout << "creating undef\n";
}
-Value::Value(double v)
+Value::Value(bool v) : value(v)
{
- reset_undef();
- this->type = NUMBER;
- this->num = v;
+ // std::cout << "creating bool\n";
}
-Value::Value(const std::string &t)
+Value::Value(int v) : value(double(v))
{
- reset_undef();
- this->type = STRING;
- this->text = t;
+ // std::cout << "creating int\n";
}
-Value::Value(const Value &v)
+Value::Value(double v) : value(v)
{
- *this = v;
+ // std::cout << "creating double " << v << "\n";
}
-Value& Value::operator = (const Value &v)
+Value::Value(const std::string &v) : value(v)
{
- reset_undef();
- this->type = v.type;
- this->b = v.b;
- this->num = v.num;
- for (size_t i = 0; i < v.vec.size(); i++) {
- this->vec.push_back(new Value(*v.vec[i]));
- }
- this->range_begin = v.range_begin;
- this->range_step = v.range_step;
- this->range_end = v.range_end;
- this->text = v.text;
- return *this;
+ // std::cout << "creating string\n";
}
-Value Value::operator ! () const
-{
- if (this->type == BOOL) {
- return Value(!this->b);
- }
- return Value();
-}
-
-Value Value::operator && (const Value &v) const
-{
- if (this->type == BOOL && v.type == BOOL) {
- return Value(this->b && v.b);
- }
- return Value();
-}
-
-Value Value::operator || (const Value &v) const
-{
- if (this->type == BOOL && v.type == BOOL) {
- return Value(this->b || v.b);
- }
- return Value();
-}
-
-Value Value::operator + (const Value &v) const
-{
- if (this->type == VECTOR && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size() && i < v.vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] + *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num + v.num);
- }
- return Value();
-}
-
-Value Value::operator - (const Value &v) const
-{
- if (this->type == VECTOR && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size() && i < v.vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] - *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num - v.num);
- }
- return Value();
-}
-
-Value Value::operator * (const Value &v) const
-{
- if (this->type == VECTOR && v.type == NUMBER) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] * v));
- return r;
- }
- if (this->type == NUMBER && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < v.vec.size(); i++)
- r.vec.push_back(new Value(*this * *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num * v.num);
- }
- if (this->type == VECTOR && v.type == VECTOR && this->vec.size() == v.vec.size() ) {
- if ( this->vec[0]->type == NUMBER && v.vec[0]->type == NUMBER ) {
- // Vector dot product.
- double r=0.0;
- for (size_t i=0; i <this->vec.size(); i++) {
- if ( this->vec[i]->type != NUMBER || v.vec[i]->type != NUMBER ) return Value();
- r = r + (this->vec[i]->num * v.vec[i]->num);
- }
- return Value(r);
- } else if ( this->vec[0]->type == VECTOR && v.vec[0]->type == NUMBER ) {
- // Matrix * Vector
- Value r;
- r.type = VECTOR;
- for ( size_t i=0; i < this->vec.size(); i++) {
- double r_e=0.0;
- if ( this->vec[i]->vec.size() != v.vec.size() ) return Value();
- for ( size_t j=0; j < this->vec[i]->vec.size(); j++) {
- if ( this->vec[i]->vec[j]->type != NUMBER || v.vec[i]->type != NUMBER ) return Value();
- r_e = r_e + (this->vec[i]->vec[j]->num * v.vec[j]->num);
- }
- r.vec.push_back(new Value(r_e));
- }
- return r;
- } else if (this->vec[0]->type == NUMBER && v.vec[0]->type == VECTOR ) {
- // Vector * Matrix
- Value r;
- r.type = VECTOR;
- for ( size_t i=0; i < v.vec[0]->vec.size(); i++) {
- double r_e=0.0;
- for ( size_t j=0; j < v.vec.size(); j++) {
- if ( v.vec[j]->vec.size() != v.vec[0]->vec.size() ) return Value();
- if ( this->vec[j]->type != NUMBER || v.vec[j]->vec[i]->type != NUMBER ) return Value();
- r_e = r_e + (this->vec[j]->num * v.vec[j]->vec[i]->num);
- }
- r.vec.push_back(new Value(r_e));
- }
- return r;
- }
- }
- if (this->type == VECTOR && v.type == VECTOR && this->vec[0]->type == VECTOR && v.vec[0]->type == VECTOR && this->vec[0]->vec.size() == v.vec.size() ) {
- // Matrix * Matrix
- Value rrow;
- rrow.type = VECTOR;
- for ( size_t i=0; i < this->vec.size(); i++ ) {
- Value * rcol=new Value();
- rcol->type = VECTOR;
- for ( size_t j=0; j < this->vec.size(); j++ ) {
- double r_e=0.0;
- for ( size_t k=0; k < v.vec.size(); k++ ) {
- r_e = r_e + (this->vec[i]->vec[k]->num * v.vec[k]->vec[j]->num);
- }
- // PRINTB(" r_e = %s",r_e);
- rcol->vec.push_back(new Value(r_e));
- }
- rrow.vec.push_back(rcol);
- }
- return rrow;
- }
- return Value();
-}
-
-Value Value::operator / (const Value &v) const
-{
- if (this->type == VECTOR && v.type == NUMBER) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size(); i++)
- r.vec.push_back(new Value(*this->vec[i] / v));
- return r;
- }
- if (this->type == NUMBER && v.type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < v.vec.size(); i++)
- r.vec.push_back(new Value(v / *v.vec[i]));
- return r;
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num / v.num);
- }
- return Value();
-}
-
-Value Value::operator % (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(fmod(this->num, v.num));
- }
- return Value();
-}
-
-Value Value::operator < (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num < v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text < v.text);
- }
- return Value();
-}
-
-Value Value::operator <= (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num <= v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text <= v.text);
- }
- return Value();
-}
-
-Value Value::operator == (const Value &v) const
-{
- if (this->type == BOOL && v.type == BOOL) {
- return Value(this->b == v.b);
- }
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num == v.num);
- }
- if (this->type == RANGE && v.type == RANGE) {
- return Value(this->range_begin == v.range_begin && this->range_step == v.range_step && this->range_end == v.range_end);
- }
- if (this->type == VECTOR && v.type == VECTOR) {
- if (this->vec.size() != v.vec.size())
- return Value(false);
- for (size_t i=0; i<this->vec.size(); i++)
- if (!(*this->vec[i] == *v.vec[i]).b)
- return Value(false);
- return Value(true);
- }
- if (this->type == STRING && v.type == STRING) {
- return Value(this->text == v.text);
- }
- return Value(false);
-}
-
-Value Value::operator != (const Value &v) const
-{
- Value eq = *this == v;
- return Value(!eq.b);
-}
-
-Value Value::operator >= (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num >= v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text >= v.text);
- }
- return Value();
-}
-
-Value Value::operator > (const Value &v) const
-{
- if (this->type == NUMBER && v.type == NUMBER) {
- return Value(this->num > v.num);
- }
- else if (this->type == STRING && v.type == STRING) {
- return Value(this->text > v.text);
- }
- return Value();
-}
-
-Value Value::inv() const
-{
- if (this->type == VECTOR) {
- Value r;
- r.type = VECTOR;
- for (size_t i = 0; i < this->vec.size(); i++)
- r.vec.push_back(new Value(this->vec[i]->inv()));
- return r;
- }
- if (this->type == NUMBER)
- return Value(-this->num);
- return Value();
-}
-
-bool Value::getnum(double &v) const
-{
- if (this->type != NUMBER)
- return false;
- v = this->num;
- return true;
-}
-
-bool Value::getv2(double &x, double &y) const
-{
- if (this->type != VECTOR || this->vec.size() != 2)
- return false;
- if (this->vec[0]->type != NUMBER)
- return false;
- if (this->vec[1]->type != NUMBER)
- return false;
- x = this->vec[0]->num;
- y = this->vec[1]->num;
- return true;
-}
-
-bool Value::getv3(double &x, double &y, double &z, double defaultval) const
-{
- if (this->type == VECTOR && this->vec.size() == 2) {
- if (getv2(x, y)) {
- z = defaultval;
- return true;
- }
- return false;
- }
- if (this->type != VECTOR || this->vec.size() != 3)
- return false;
- if (this->vec[0]->type != NUMBER)
- return false;
- if (this->vec[1]->type != NUMBER)
- return false;
- if (this->vec[2]->type != NUMBER)
- return false;
- x = this->vec[0]->num;
- y = this->vec[1]->num;
- z = this->vec[2]->num;
- return true;
-}
-
-void Value::reset_undef()
-{
- this->type = UNDEFINED;
- this->b = false;
- this->num = 0;
- for (size_t i = 0; i < this->vec.size(); i++) delete this->vec[i];
- this->vec.clear();
- this->range_begin = 0;
- this->range_step = 0;
- this->range_end = 0;
- this->text = "";
+Value::Value(const char *v) : value(std::string(v))
+{
+ // std::cout << "creating string from char *\n";
}
-std::string Value::toString() const
+Value::Value(char v) : value(std::string(1, v))
+{
+ // std::cout << "creating string from char\n";
+}
+
+Value::Value(const VectorType &v) : value(v)
+{
+ // std::cout << "creating vector\n";
+}
+
+Value::Value(const RangeType &v) : value(v)
+{
+ // std::cout << "creating range\n";
+}
+
+Value::Value(double begin, double step, double end) : value(RangeType(begin, step, end))
+{
+ // std::cout << "creating range from numbers\n";
+}
+
+Value::ValueType Value::type() const
+{
+ return static_cast<ValueType>(this->value.which());
+}
+
+bool Value::isUndefined() const
{
- std::stringstream stream;
- stream.precision(16);
-
- switch (this->type) {
- case STRING:
- stream << this->text;
- break;
- case VECTOR:
- stream << '[';
- for (size_t i = 0; i < this->vec.size(); i++) {
- if (i > 0) stream << ", ";
- stream << *(this->vec[i]);
- }
- stream << ']';
- break;
- case RANGE:
- stream << '['
- << this->range_begin
- << " : "
- << this->range_step
- << " : "
- << this->range_end
- << ']';
- break;
- case NUMBER:
+ return this->type() == UNDEFINED;
+}
+
+bool Value::toBool() const
+{
+ switch (this->type()) {
+ case BOOL:
+ return boost::get<bool>(this->value);
+ break;
+ case NUMBER:
+ return boost::get<double>(this->value)!= 0;
+ break;
+ case STRING:
+ return boost::get<std::string>(this->value).size() > 0;
+ break;
+ case VECTOR:
+ return boost::get<VectorType >(this->value).size() > 0;
+ break;
+ case RANGE:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+double Value::toDouble() const
+{
+ double d = 0;
+ getDouble(d);
+ return d;
+}
+
+bool Value::getDouble(double &v) const
+{
+ const double *d = boost::get<double>(&this->value);
+ if (d) {
+ v = *d;
+ return true;
+ }
+ return false;
+}
+
+class tostring_visitor : public boost::static_visitor<std::string>
+{
+public:
+ template <typename T> std::string operator()(const T &op1) const {
+ // std::cout << "[generic tostring_visitor]\n";
+ return boost::lexical_cast<std::string>(op1);
+ }
+
+ std::string operator()(const double &op1) const {
#ifdef OPENSCAD_TESTING
- // Quick and dirty hack to work around floating point rounding differences
- // across platforms for testing purposes.
- {
- if (this->num != this->num) { // Fix for avoiding nan vs. -nan across platforms
- stream << "nan";
- break;
- }
- std::stringstream tmp;
- tmp.precision(12);
- tmp.setf(std::ios_base::fixed);
- tmp << this->num;
- std::string tmpstr = tmp.str();
- size_t endpos = tmpstr.find_last_not_of('0');
- if (endpos >= 0 && tmpstr[endpos] == '.') endpos--;
- tmpstr = tmpstr.substr(0, endpos+1);
- size_t dotpos = tmpstr.find('.');
- if (dotpos != std::string::npos) {
- if (tmpstr.size() - dotpos > 12) tmpstr.erase(dotpos + 12);
- }
- stream << tmpstr;
- }
+ // Quick and dirty hack to work around floating point rounding differences
+ // across platforms for testing purposes.
+ if (op1 != op1) { // Fix for avoiding nan vs. -nan across platforms
+ return "nan";
+ }
+ std::stringstream tmp;
+ tmp.precision(12);
+ tmp.setf(std::ios_base::fixed);
+ tmp << op1;
+ std::string tmpstr = tmp.str();
+ size_t endpos = tmpstr.find_last_not_of('0');
+ if (endpos >= 0 && tmpstr[endpos] == '.') endpos--;
+ tmpstr = tmpstr.substr(0, endpos+1);
+ size_t dotpos = tmpstr.find('.');
+ if (dotpos != std::string::npos) {
+ if (tmpstr.size() - dotpos > 12) tmpstr.erase(dotpos + 12);
+ }
+ return tmpstr;
#else
- stream << this->num;
+ return boost::lexical_cast<std::string>(op1);
#endif
- break;
- case BOOL:
- stream << (this->b ? "true" : "false");
- break;
- default:
- stream << "undef";
- }
+ }
+
+ std::string operator()(const boost::blank &v) const {
+ return "undef";
+ }
+
+ std::string operator()(const bool &v) const {
+ return v ? "true" : "false";
+ }
+
+ std::string operator()(const Value::VectorType &v) const {
+ std::stringstream stream;
+ stream << '[';
+ for (size_t i = 0; i < v.size(); i++) {
+ if (i > 0) stream << ", ";
+ stream << v[i];
+ }
+ stream << ']';
+ return stream.str();
+ }
+
+ std::string operator()(const Value::RangeType &v) const {
+ return (boost::format("[%1% : %2% : %3%]") % v.begin % v.step % v.end).str();
+ }
+};
- return stream.str();
+std::string Value::toString() const
+{
+ return boost::apply_visitor(tostring_visitor(), this->value);
}
-bool Value::toBool() const
+const Value::VectorType &Value::toVector() const
{
- switch (this->type) {
- case STRING:
- return this->text.size() > 0;
- break;
- case VECTOR:
- return this->vec.size() > 0;
- break;
- case RANGE:
- return true;
- break;
- case NUMBER:
- return this->num != 0;
- break;
- case BOOL:
- return this->b;
- break;
- default:
- return false;
- break;
- }
+ static VectorType empty;
+
+ const VectorType *v = boost::get<VectorType>(&this->value);
+ if (v) return *v;
+ else return empty;
}
-/*!
- Append a value to this vector.
- This must be of type VECTOR.
-*/
-void Value::append(Value *val)
+bool Value::getVec2(double &x, double &y) const
+{
+ if (this->type() != VECTOR) return false;
+
+ const VectorType &v = toVector();
+
+ if (v.size() != 2) return false;
+ return (v[0].getDouble(x) && v[1].getDouble(y));
+}
+
+bool Value::getVec3(double &x, double &y, double &z, double defaultval) const
{
- assert(this->type == VECTOR);
- this->vec.push_back(val);
+ if (this->type() != VECTOR) return false;
+
+ const VectorType &v = toVector();
+
+ if (v.size() == 2) {
+ getVec2(x, y);
+ z = defaultval;
+ return true;
+ }
+ else {
+ if (v.size() != 3) return false;
+ }
+
+ return (v[0].getDouble(x) && v[1].getDouble(y) && v[2].getDouble(z));
}
-std::ostream &operator<<(std::ostream &stream, const Value &value)
+Value::RangeType Value::toRange() const
{
- if (value.type == Value::STRING) stream << QuotedString(value.toString());
- else stream << value.toString();
- return stream;
+ const RangeType *val = boost::get<RangeType>(&this->value);
+ if (val) {
+ return *val;
+ }
+ else return RangeType(0,0,0);
}
-std::ostream &operator<<(std::ostream &stream, const Filename &filename)
+Value &Value::operator=(const Value &v)
{
- stream << QuotedString(QDir::current().relativeFilePath(QString::fromStdString(filename)).toStdString());
- return stream;
+ if (this != &v) {
+ this->value = v.value;
+ }
+ return *this;
}
-// FIXME: This could probably be done more elegantly using boost::regex
-std::ostream &operator<<(std::ostream &stream, const QuotedString &s)
+Value Value::operator!() const
+{
+ return Value(!this->toBool());
+}
+
+class equals_visitor : public boost::static_visitor<bool>
{
- stream << '"';
- BOOST_FOREACH(char c, s) {
- switch (c) {
- case '\t':
- stream << "\\t";
- break;
- case '\n':
- stream << "\\n";
- break;
- case '"':
- case '\\':
- stream << '\\';
- stream << c;
- break;
- default:
- stream << c;
- }
- }
- stream << '"';
- return stream;
+public:
+ template <typename T, typename U> bool operator()(const T &op1, const U &op2) const {
+ return false;
+ }
+
+ template <typename T> bool operator()(const T &op1, const T &op2) const {
+ return op1 == op2;
+ }
+};
+
+bool Value::operator==(const Value &v) const
+{
+ return boost::apply_visitor(equals_visitor(), this->value, v.value);
+}
+
+bool Value::operator!=(const Value &v) const
+{
+ return !(*this == v);
+}
+
+bool Value::operator&&(const Value &v) const
+{
+ return this->toBool() && v.toBool();
+}
+
+bool Value::operator||(const Value &v) const
+{
+ return this->toBool() || v.toBool();
+}
+
+class less_visitor : public boost::static_visitor<bool>
+{
+public:
+ template <typename T, typename U> bool operator()(const T &op1, const U &op2) const {
+ return false;
+ }
+
+ bool operator()(const double &op1, const double &op2) const {
+ return op1 < op2;
+ }
+
+ bool operator()(const std::string &op1, const std::string &op2) const {
+ return op1 < op2;
+ }
+};
+
+class greater_visitor : public boost::static_visitor<bool>
+{
+public:
+ template <typename T, typename U> bool operator()(const T &op1, const U &op2) const {
+ return false;
+ }
+
+ bool operator()(const double &op1, const double &op2) const {
+ return op1 > op2;
+ }
+
+ bool operator()(const std::string &op1, const std::string &op2) const {
+ return op1 > op2;
+ }
+};
+
+bool Value::operator<(const Value &v) const
+{
+ return boost::apply_visitor(less_visitor(), this->value, v.value);
+}
+
+bool Value::operator>=(const Value &v) const
+{
+ return !(*this < v);
+}
+
+bool Value::operator>(const Value &v) const
+{
+ return boost::apply_visitor(greater_visitor(), this->value, v.value);
+}
+
+bool Value::operator<=(const Value &v) const
+{
+ return !(*this > v);
+}
+
+class plus_visitor : public boost::static_visitor<Value>
+{
+public:
+ template <typename T, typename U> Value operator()(const T &op1, const U &op2) const {
+ return Value::undefined;
+ }
+
+ Value operator()(const double &op1, const double &op2) const {
+ return Value(op1 + op2);
+ }
+
+ Value operator()(const Value::VectorType &op1, const Value::VectorType &op2) const {
+ Value::VectorType sum;
+ for (size_t i = 0; i < op1.size() && i < op2.size(); i++) {
+ sum.push_back(op1[i] + op2[i]);
+ }
+ return Value(sum);
+ }
+};
+
+Value Value::operator+(const Value &v) const
+{
+ return boost::apply_visitor(plus_visitor(), this->value, v.value);
+}
+
+class minus_visitor : public boost::static_visitor<Value>
+{
+public:
+ template <typename T, typename U> Value operator()(const T &op1, const U &op2) const {
+ return Value::undefined;
+ }
+
+ Value operator()(const double &op1, const double &op2) const {
+ return Value(op1 - op2);
+ }
+
+ Value operator()(const Value::VectorType &op1, const Value::VectorType &op2) const {
+ Value::VectorType sum;
+ for (size_t i = 0; i < op1.size() && i < op2.size(); i++) {
+ sum.push_back(op1[i] - op2[i]);
+ }
+ return Value(sum);
+ }
+};
+
+Value Value::operator-(const Value &v) const
+{
+ return boost::apply_visitor(minus_visitor(), this->value, v.value);
+}
+
+Value Value::operator*(const Value &v) const
+{
+ if (this->type() == NUMBER && v.type() == NUMBER) {
+ return Value(this->toDouble() * v.toDouble());
+ }
+ else if (this->type() == VECTOR && v.type() == NUMBER) {
+ const VectorType &vec = this->toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(vecval * v);
+ }
+ return result;
+ }
+ else if (this->type() == NUMBER && v.type() == VECTOR) {
+ const VectorType &vec = v.toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(*this * vecval);
+ }
+ return result;
+ }
+ else if (this->type() == VECTOR && v.type() == VECTOR &&
+ this->toVector().size() == v.toVector().size()) {
+ const VectorType &vec1 = this->toVector();
+ const VectorType &vec2 = v.toVector();
+ if (vec1[0].type() == NUMBER && vec2[0].type() == NUMBER) {
+ // Vector dot product.
+ double r = 0.0;
+ for (size_t i=0;i<vec1.size();i++) {
+ if (vec1[i].type() != NUMBER || vec2[i].type() != NUMBER) {
+ return Value::undefined;
+ }
+ r += (vec1[i].toDouble() * vec2[i].toDouble());
+ }
+ return Value(r);
+ // } else if ( this->vec[0]->type() == VECTOR && v.vec[0]->type() == NUMBER ) {
+ // // Matrix * Vector
+ // Value r;
+ // r.type() = VECTOR;
+ // for ( size_t i=0; i < this->vec.size(); i++) {
+ // double r_e=0.0;
+ // if ( this->vec[i]->vec.size() != v.vec.size() ) return Value();
+ // for ( size_t j=0; j < this->vec[i]->vec.size(); j++) {
+ // if ( this->vec[i]->vec[j]->type() != NUMBER || v.vec[i]->type() != NUMBER ) return Value();
+ // r_e = r_e + (this->vec[i]->vec[j]->num * v.vec[j]->num);
+ // }
+ // r.vec.push_back(new Value(r_e));
+ // }
+ // return r;
+ // } else if (this->vec[0]->type() == NUMBER && v.vec[0]->type() == VECTOR ) {
+ // // Vector * Matrix
+ // Value r;
+ // r.type() = VECTOR;
+ // for ( size_t i=0; i < v.vec[0]->vec.size(); i++) {
+ // double r_e=0.0;
+ // for ( size_t j=0; j < v.vec.size(); j++) {
+ // if ( v.vec[j]->vec.size() != v.vec[0]->vec.size() ) return Value();
+ // if ( this->vec[j]->type() != NUMBER || v.vec[j]->vec[i]->type() != NUMBER ) return Value();
+ // r_e = r_e + (this->vec[j]->num * v.vec[j]->vec[i]->num);
+ // }
+ // r.vec.push_back(new Value(r_e));
+ // }
+ // return r;
+ // }
+ }
+ // if (this->type() == VECTOR && v.type() == VECTOR && this->vec[0]->type() == VECTOR && v.vec[0]->type() == VECTOR && this->vec[0]->vec.size() == v.vec.size() ) {
+ // // Matrix * Matrix
+ // Value rrow;
+ // rrow.type() = VECTOR;
+ // for ( size_t i=0; i < this->vec.size(); i++ ) {
+ // Value * rcol=new Value();
+ // rcol->type() = VECTOR;
+ // for ( size_t j=0; j < this->vec.size(); j++ ) {
+ // double r_e=0.0;
+ // for ( size_t k=0; k < v.vec.size(); k++ ) {
+ // r_e = r_e + (this->vec[i]->vec[k]->num * v.vec[k]->vec[j]->num);
+ // }
+ // rcol->vec.push_back(new Value(r_e));
+ // }
+ // rrow.vec.push_back(rcol);
+ // }
+ // return rrow;
+ }
+ return Value::undefined;
+}
+
+Value Value::operator/(const Value &v) const
+{
+ if (this->type() == NUMBER && v.type() == NUMBER) {
+ return Value(this->toDouble() / v.toDouble());
+ }
+ else if (this->type() == VECTOR && v.type() == NUMBER) {
+ const VectorType &vec = this->toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(vecval / v);
+ }
+ return result;
+ }
+ else if (this->type() == NUMBER && v.type() == VECTOR) {
+ const VectorType &vec = v.toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(*this / vecval);
+ }
+ return result;
+ }
+ return Value::undefined;
+}
+
+Value Value::operator%(const Value &v) const
+{
+ if (this->type() == NUMBER && v.type() == NUMBER) {
+ return Value(fmod(boost::get<double>(this->value), boost::get<double>(v.value)));
+ }
+ return Value::undefined;
+}
+
+Value Value::operator-() const
+{
+ if (this->type() == NUMBER) {
+ return Value(-this->toDouble());
+ }
+ else if (this->type() == VECTOR) {
+ const VectorType &vec = this->toVector();
+ VectorType tmpv;
+ Value result(tmpv);
+ VectorType &dstv = boost::get<VectorType>(result.value);
+ BOOST_FOREACH(const Value &vecval, vec) {
+ dstv.push_back(-vecval);
+ }
+ return result;
+ }
+ return Value::undefined;
+}
+
+/*!
+ Append a value to this vector.
+ This must be of valtype VECTOR.
+*/
+/*
+ void Value::append(Value *val)
+ {
+ assert(this->type() == VECTOR);
+ this->vec.push_back(val);
+ }
+*/
+
+class bracket_visitor : public boost::static_visitor<Value>
+{
+public:
+ Value operator()(const std::string &str, const double &idx) const {
+ int i = int(idx);
+ Value v;
+ if (i >= 0 && i < str.size()) {
+ v = Value(str[int(idx)]);
+ // std::cout << "bracket_visitor: " << v << "\n";
+ }
+ return v;
+ }
+
+ Value operator()(const Value::VectorType &vec, const double &idx) const {
+ int i = int(idx);
+ if (i >= 0 && i < vec.size()) return vec[int(idx)];
+ return Value::undefined;
+ }
+
+ Value operator()(const Value::RangeType &range, const double &idx) const {
+ switch(int(idx)) {
+ case 0: return Value(range.begin);
+ case 1: return Value(range.step);
+ case 2: return Value(range.end);
+ }
+ return Value::undefined;
+ }
+
+ template <typename T, typename U> Value operator()(const T &op1, const U &op2) const {
+ // std::cout << "generic bracket_visitor\n";
+ return Value::undefined;
+ }
+};
+
+Value Value::operator[](const Value &v)
+{
+ return boost::apply_visitor(bracket_visitor(), this->value, v.value);
}
diff --git a/src/value.h b/src/value.h
index 4a67fbc..8534e62 100644
--- a/src/value.h
+++ b/src/value.h
@@ -3,6 +3,8 @@
#include <vector>
#include <string>
+#include <boost/variant.hpp>
+#include <boost/lexical_cast.hpp>
class QuotedString : public std::string
{
@@ -23,68 +25,95 @@ std::ostream &operator<<(std::ostream &stream, const Filename &filename);
class Value
{
public:
- enum type_e {
- UNDEFINED,
- BOOL,
- NUMBER,
- RANGE,
- VECTOR,
- STRING
- };
-
- enum type_e type;
-
- bool b;
- double num;
- std::vector<Value*> vec;
- double range_begin;
- double range_step;
- double range_end;
- std::string text;
-
- Value();
- ~Value();
-
- Value(bool v);
- Value(double v);
- Value(const std::string &t);
-
- Value(const Value &v);
- Value& operator = (const Value &v);
-
- Value operator ! () const;
- Value operator && (const Value &v) const;
- Value operator || (const Value &v) const;
-
- Value operator + (const Value &v) const;
- Value operator - (const Value &v) const;
- Value operator * (const Value &v) const;
- Value operator / (const Value &v) const;
- Value operator % (const Value &v) const;
-
- Value operator < (const Value &v) const;
- Value operator <= (const Value &v) const;
- Value operator == (const Value &v) const;
- Value operator != (const Value &v) const;
- Value operator >= (const Value &v) const;
- Value operator > (const Value &v) const;
-
- Value inv() const;
-
- bool getnum(double &v) const;
- bool getv2(double &x, double &y) const;
- bool getv3(double &x, double &y, double &z, double defaultval = 0.0) const;
-
- std::string toString() const;
-
- bool toBool() const;
-
- void append(Value *val);
+ struct RangeType {
+ RangeType(double begin, double step, double end)
+ : begin(begin), step(step), end(end) {}
+
+ bool operator==(const RangeType &other) const {
+ return this->begin == other.begin &&
+ this->step == other.step &&
+ this->end == other.end;
+ }
+
+ double begin;
+ double step;
+ double end;
+ };
+
+ typedef std::vector<Value> VectorType;
+
+ enum ValueType {
+ UNDEFINED,
+ BOOL,
+ NUMBER,
+ STRING,
+ VECTOR,
+ RANGE
+ };
+ static Value undefined;
+
+ Value();
+ Value(bool v);
+ Value(int v);
+ Value(double v);
+ Value(const std::string &v);
+ Value(const char *v);
+ Value(const char v);
+ Value(const VectorType &v);
+ Value(const RangeType &v);
+ Value(double begin, double step, double end);
+ ~Value() {}
+
+ ValueType type() const;
+ bool isUndefined() const;
+
+ double toDouble() const;
+ bool getDouble(double &v) const;
+ bool toBool() const;
+ std::string toString() const;
+ const VectorType &toVector() const;
+ bool getVec2(double &x, double &y) const;
+ bool getVec3(double &x, double &y, double &z, double defaultval = 0.0) const;
+ RangeType toRange() const;
+
+ Value &operator=(const Value &v);
+ Value operator!() const;
+ bool operator==(const Value &v) const;
+ bool operator!=(const Value &v) const;
+ bool operator&&(const Value &v) const;
+ bool operator||(const Value &v) const;
+ bool operator<(const Value &v) const;
+ bool operator<=(const Value &v) const;
+ bool operator>=(const Value &v) const;
+ bool operator>(const Value &v) const;
+ Value operator-() const;
+ Value operator[](const Value &v);
+ Value operator+(const Value &v) const;
+ Value operator-(const Value &v) const;
+ Value operator*(const Value &v) const;
+ Value operator/(const Value &v) const;
+ Value operator%(const Value &v) const;
+
+ /*
+ bool getnum(double &v) const;
+ bool getv2(double &x, double &y) const;
+ bool getv3(double &x, double &y, double &z, double defaultval = 0.0) const;
+
+ bool toBool() const;
+
+ void append(Value *val);
+ */
+
+ friend std::ostream &operator<<(std::ostream &stream, const Value &value) {
+ if (value.type() == Value::STRING) stream << QuotedString(value.toString());
+ else stream << value.toString();
+ return stream;
+ }
+
+ typedef boost::variant< boost::blank, bool, double, std::string, VectorType, RangeType > Variant;
private:
- void reset_undef();
+ Variant value;
};
-std::ostream &operator<<(std::ostream &stream, const Value &value);
-
#endif
contact: Jan Huwald // Impressum