Merge pull request #1432 from openscad/issue1407

Fix #1407 by storing vector values as heap objects (ValuePtr) rather than stack objects(Value)
This commit is contained in:
Marius Kintel 2015-09-14 00:53:16 -04:00
commit 7f9e7f9c83
18 changed files with 324 additions and 292 deletions

View file

@ -32,6 +32,7 @@
#include <QSettings>
#include <QStatusBar>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include "GeometryCache.h"
#include "AutoUpdater.h"
#include "feature.h"
@ -49,7 +50,7 @@ Q_DECLARE_METATYPE(Feature *);
class SettingsReader : public Settings::Visitor
{
QSettings settings;
const Value getValue(const Settings::SettingsEntry& entry, const std::string& value) const {
Value getValue(const Settings::SettingsEntry& entry, const std::string& value) const {
std::string trimmed_value(value);
boost::trim(trimmed_value);
@ -101,7 +102,7 @@ class SettingsWriter : public Settings::Visitor
settings.remove(key);
PRINTDB("SettingsWriter D: %s", key.toStdString().c_str());
} else {
Value value = s->get(entry);
const Value &value = s->get(entry);
settings.setValue(key, QString::fromStdString(value.toString()));
PRINTDB("SettingsWriter W: %s = '%s'", key.toStdString().c_str() % value.toString().c_str());
}
@ -689,18 +690,17 @@ void Preferences::updateGUI()
void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry)
{
comboBox->clear();
Value::VectorType vector = entry.range().toVector();
for (Value::VectorType::iterator it = vector.begin();it != vector.end();it++) {
QString val = QString::fromStdString((*it)[0].toString());
std::string text((*it)[1].toString());
QString qtext = QString::fromStdString(gettext(text.c_str()));
// Range is a vector of 2D vectors: [[name, value], ...]
BOOST_FOREACH(const ValuePtr &v, entry.range().toVector()) {
QString val = QString::fromStdString(v[0]->toString());
QString qtext = QString::fromStdString(gettext(v[1]->toString().c_str()));
comboBox->addItem(qtext, val);
}
}
void Preferences::initSpinBox(QSpinBox *spinBox, const Settings::SettingsEntry& entry)
{
Value::RangeType range = entry.range().toRange();
RangeType range = entry.range().toRange();
spinBox->setMinimum(range.begin_value());
spinBox->setMaximum(range.end_value());
}
@ -709,13 +709,13 @@ void Preferences::updateComboBox(QComboBox *comboBox, const Settings::SettingsEn
{
Settings::Settings *s = Settings::Settings::inst();
Value value = s->get(entry);
const Value &value = s->get(entry);
QString text = QString::fromStdString(value.toString());
int idx = comboBox->findData(text);
if (idx >= 0) {
comboBox->setCurrentIndex(idx);
} else {
Value defaultValue = entry.defaultValue();
const Value &defaultValue = entry.defaultValue();
QString defaultText = QString::fromStdString(defaultValue.toString());
int defIdx = comboBox->findData(defaultText);
if (defIdx >= 0) {

View file

@ -101,9 +101,9 @@ Builtins::Builtins()
this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0)))));
Value::VectorType zero3;
zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0));
zero3.push_back(Value(0.0));
zero3.push_back(ValuePtr(0.0));
zero3.push_back(ValuePtr(0.0));
zero3.push_back(ValuePtr(0.0));
ValuePtr zero3val(zero3);
this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new ExpressionConst(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new ExpressionConst(zero3val))));

View file

@ -89,17 +89,17 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
node->newsize << 0,0,0;
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();
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();
}
ValuePtr autosize = c.lookup_variable("auto");
node->autosize << false, false, false;
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();
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();

View file

@ -229,7 +229,7 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
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]);
}

View file

@ -63,7 +63,7 @@ public: // methods
static const EvalContext* getLastModuleCtx(const EvalContext *evalctx);
static AbstractNode* getChild(const Value &value, const EvalContext* modulectx);
static AbstractNode* getChild(const ValuePtr &value, const EvalContext* modulectx);
private: // data
Type type;
@ -78,15 +78,15 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst
ValuePtr it_values = evalctx->getArgValue(l, ctx);
Context c(ctx);
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, ValuePtr(*it));
for_eval(node, inst, l+1, &c, evalctx);
}
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 (RangeType::iterator it = range.begin();it != range.end();it++) {
c.set_variable(it_name, ValuePtr(*it));
for_eval(node, inst, l+1, &c, evalctx);
}
}
}
else if (it_values->type() == Value::VECTOR) {
@ -133,17 +133,17 @@ const EvalContext* ControlModule::getLastModuleCtx(const EvalContext *evalctx)
}
// static
AbstractNode* ControlModule::getChild(const Value& value, const EvalContext* modulectx)
AbstractNode* ControlModule::getChild(const ValuePtr &value, const EvalContext* modulectx)
{
if (value.type()!=Value::NUMBER) {
if (value->type()!=Value::NUMBER) {
// 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;
}
double v;
if (!value.getDouble(v)) {
PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value.toString());
if (!value->getDouble(v)) {
PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value->toString());
return NULL;
}
@ -223,12 +223,12 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
// one (or more ignored) parameter
ValuePtr value = evalctx->getArgValue(0);
if (value->type() == Value::NUMBER) {
return getChild(*value, modulectx);
return getChild(value, modulectx);
}
else if (value->type() == Value::VECTOR) {
AbstractNode* node = new AbstractNode(inst);
const Value::VectorType& vect = value->toVector();
foreach (const Value::VectorType::value_type& vectvalue, vect) {
foreach (const ValuePtr &vectvalue, vect) {
AbstractNode* childnode = getChild(vectvalue,modulectx);
if (childnode==NULL) continue; // error
node->children.push_back(childnode);
@ -236,15 +236,15 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
return node;
}
else if (value->type() == Value::RANGE) {
Value::RangeType range = value->toRange();
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);
return NULL;
}
AbstractNode* node = new AbstractNode(inst);
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
AbstractNode* childnode = getChild(Value(*it),modulectx); // with error cases
for (RangeType::iterator it = range.begin();it != range.end();it++) {
AbstractNode* childnode = getChild(ValuePtr(*it),modulectx); // with error cases
if (childnode==NULL) continue; // error
node->children.push_back(childnode);
}

View file

@ -200,8 +200,8 @@ ValuePtr builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
double x = x1 + ua*(x2 - x1);
double y = y1 + ua*(y2 - y1);
Value::VectorType ret;
ret.push_back(Value(x));
ret.push_back(Value(y));
ret.push_back(ValuePtr(x));
ret.push_back(ValuePtr(y));
return dxf_cross_cache[key] = ValuePtr(ret);
}
}

View file

@ -41,12 +41,12 @@ namespace {
Value::VectorType flatten(Value::VectorType const& vec) {
int n = 0;
for (unsigned int i = 0; i < vec.size(); i++) {
assert(vec[i].type() == Value::VECTOR);
n += vec[i].toVector().size();
assert(vec[i]->type() == Value::VECTOR);
n += vec[i]->toVector().size();
}
Value::VectorType ret; ret.reserve(n);
for (unsigned int i = 0; i < vec.size(); i++) {
std::copy(vec[i].toVector().begin(),vec[i].toVector().end(),std::back_inserter(ret));
std::copy(vec[i]->toVector().begin(),vec[i]->toVector().end(),std::back_inserter(ret));
}
return ret;
}
@ -357,7 +357,7 @@ ExpressionConst::ExpressionConst(const ValuePtr &val) : const_value(val)
ValuePtr ExpressionConst::evaluate(const class Context *) const
{
return ValuePtr(this->const_value);
return this->const_value;
}
void ExpressionConst::print(std::ostream &stream) const
@ -380,12 +380,12 @@ ValuePtr ExpressionRange::evaluate(const Context *context) const
ValuePtr v2 = this->second->evaluate(context);
if (v2->type() == Value::NUMBER) {
if (this->children.size() == 2) {
Value::RangeType range(v1->toDouble(), v2->toDouble());
RangeType range(v1->toDouble(), v2->toDouble());
return ValuePtr(range);
} else {
ValuePtr v3 = this->third->evaluate(context);
if (v3->type() == Value::NUMBER) {
Value::RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
return ValuePtr(range);
}
}
@ -409,7 +409,8 @@ ValuePtr ExpressionVector::evaluate(const Context *context) const
{
Value::VectorType vec;
BOOST_FOREACH(const Expression *e, this->children) {
vec.push_back(*(e->evaluate(context)));
ValuePtr tmpval = e->evaluate(context);
vec.push_back(tmpval);
}
return ValuePtr(vec);
}
@ -545,7 +546,7 @@ ValuePtr ExpressionLc::evaluate(const Context *context) const
if (this->second->isListComprehension()) {
return this->second->evaluate(context);
} else {
vec.push_back((*this->second->evaluate(context)));
vec.push_back(this->second->evaluate(context));
}
}
return ValuePtr(vec);
@ -561,26 +562,26 @@ ValuePtr ExpressionLc::evaluate(const Context *context) const
Context c(context);
if (it_values->type() == Value::RANGE) {
Value::RangeType range = it_values->toRange();
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++) {
for (RangeType::iterator it = range.begin();it != range.end();it++) {
c.set_variable(it_name, ValuePtr(*it));
vec.push_back((*this->first->evaluate(&c)));
vec.push_back(this->first->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->first->evaluate(&c)));
vec.push_back(this->first->evaluate(&c));
}
}
else if (it_values->type() != Value::UNDEFINED) {
c.set_variable(it_name, it_values);
vec.push_back((*this->first->evaluate(&c)));
vec.push_back(this->first->evaluate(&c));
}
if (this->first->isListComprehension()) {
return ValuePtr(flatten(vec));

View file

@ -258,14 +258,14 @@ ValuePtr builtin_rands(const Context *, const EvalContext *evalctx)
Value::VectorType vec;
if (min==max) { // Boost doesn't allow min == max
for (size_t i=0; i < numresults; i++)
vec.push_back( Value( min ) );
vec.push_back(ValuePtr(min));
} else {
boost::uniform_real<> distributor( min, max );
for (size_t i=0; i < numresults; i++) {
if ( deterministic ) {
vec.push_back(Value(distributor(deterministic_rng)));
vec.push_back(ValuePtr(distributor(deterministic_rng)));
} else {
vec.push_back(Value(distributor(lessdeterministic_rng)));
vec.push_back(ValuePtr(distributor(lessdeterministic_rng)));
}
}
}
@ -285,11 +285,11 @@ ValuePtr builtin_min(const Context *, const EvalContext *evalctx)
ValuePtr v0 = evalctx->getArgValue(0);
if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
Value min = v0->toVector()[0];
ValuePtr min = v0->toVector()[0];
for (size_t i = 1; i < v0->toVector().size(); i++) {
if (v0->toVector()[i] < min) min = v0->toVector()[i];
}
return ValuePtr(min);
return min;
}
if (v0->type() == Value::NUMBER) {
double val = v0->toDouble();
@ -317,11 +317,11 @@ ValuePtr builtin_max(const Context *, const EvalContext *evalctx)
ValuePtr v0 = evalctx->getArgValue(0);
if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
Value max = v0->toVector()[0];
ValuePtr max = v0->toVector()[0];
for (size_t i = 1; i < v0->toVector().size(); i++) {
if (v0->toVector()[i] > max) max = v0->toVector()[i];
}
return ValuePtr(max);
return max;
}
if (v0->type() == Value::NUMBER) {
double val = v0->toDouble();
@ -614,14 +614,13 @@ ValuePtr builtin_concat(const Context *, const EvalContext *evalctx)
Value::VectorType result;
for (size_t i = 0; i < evalctx->numArgs(); i++) {
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);
ValuePtr val = evalctx->getArgValue(i);
if (val->type() == Value::VECTOR) {
BOOST_FOREACH(const ValuePtr &v, val->toVector()) {
result.push_back(v);
}
} else {
result.push_back(*v);
result.push_back(val);
}
}
return ValuePtr(result);
@ -636,13 +635,13 @@ ValuePtr builtin_lookup(const Context *, const EvalContext *evalctx)
ValuePtr v1 = evalctx->getArgValue(1);
const Value::VectorType &vec = v1->toVector();
if (vec[0].toVector().size() < 2) // Second must be a vector of vectors
if (vec[0]->toVector().size() < 2) // Second must be a vector of vectors
return ValuePtr::undefined;
if (!vec[0].getVec2(low_p, low_v) || !vec[0].getVec2(high_p, high_v))
if (!vec[0]->getVec2(low_p, low_v) || !vec[0]->getVec2(high_p, high_v))
return ValuePtr::undefined;
for (size_t i = 1; i < vec.size(); i++) {
double this_p, this_v;
if (vec[i].getVec2(this_p, this_v)) {
if (vec[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;
@ -727,10 +726,10 @@ static Value::VectorType search(const std::string &find, const std::string &tabl
if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) {
matchCount++;
if (num_returns_per_match == 1) {
returnvec.push_back(Value(double(j)));
returnvec.push_back(ValuePtr(double(j)));
break;
} else {
resultvec.push_back(Value(double(j)));
resultvec.push_back(ValuePtr(double(j)));
}
if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) {
break;
@ -742,7 +741,7 @@ static Value::VectorType search(const std::string &find, const std::string &tabl
if (ptr_ft) g_utf8_strncpy(utf8_of_cp, ptr_ft, 1);
}
if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(Value(resultvec));
returnvec.push_back(ValuePtr(resultvec));
}
}
return returnvec;
@ -760,19 +759,19 @@ static Value::VectorType search(const std::string &find, const Value::VectorType
Value::VectorType resultvec;
const gchar *ptr_ft = g_utf8_offset_to_pointer(find.c_str(), i);
for (size_t j = 0; j < searchTableSize; j++) {
Value::VectorType entryVec = table[j].toVector();
const Value::VectorType &entryVec = table[j]->toVector();
if (entryVec.size() <= index_col_num) {
PRINTB("WARNING: Invalid entry in search vector at index %d, required number of values in the entry: %d. Invalid entry: %s", j % (index_col_num + 1) % table[j]);
return Value::VectorType();
}
const gchar *ptr_st = g_utf8_offset_to_pointer(entryVec[index_col_num].toString().c_str(), 0);
const gchar *ptr_st = g_utf8_offset_to_pointer(entryVec[index_col_num]->toString().c_str(), 0);
if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) {
matchCount++;
if (num_returns_per_match == 1) {
returnvec.push_back(Value(double(j)));
returnvec.push_back(ValuePtr(double(j)));
break;
} else {
resultvec.push_back(Value(double(j)));
resultvec.push_back(ValuePtr(double(j)));
}
if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) {
break;
@ -785,7 +784,7 @@ static Value::VectorType search(const std::string &find, const Value::VectorType
PRINTB(" WARNING: search term not found: \"%s\"", utf8_of_cp);
}
if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(Value(resultvec));
returnvec.push_back(ValuePtr(resultvec));
}
}
return returnvec;
@ -806,12 +805,12 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx)
unsigned int matchCount = 0;
for (size_t j = 0; j < searchTable->toVector().size(); j++) {
const Value &search_element = searchTable->toVector()[j];
const ValuePtr &search_element = searchTable->toVector()[j];
if ((index_col_num == 0 && *findThis == search_element) ||
(index_col_num < search_element.toVector().size() &&
*findThis == search_element.toVector()[index_col_num])) {
returnvec.push_back(Value(double(j)));
if ((index_col_num == 0 && findThis == search_element) ||
(index_col_num < search_element->toVector().size() &&
findThis == search_element->toVector()[index_col_num])) {
returnvec.push_back(ValuePtr(double(j)));
matchCount++;
if (num_returns_per_match != 0 && matchCount >= num_returns_per_match) break;
}
@ -828,16 +827,16 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx)
unsigned int matchCount = 0;
Value::VectorType resultvec;
Value const& find_value = findThis->toVector()[i];
const ValuePtr &find_value = findThis->toVector()[i];
for (size_t j = 0; j < searchTable->toVector().size(); j++) {
Value const& search_element = searchTable->toVector()[j];
const ValuePtr &search_element = searchTable->toVector()[j];
if ((index_col_num == 0 && find_value == search_element) ||
(index_col_num < search_element.toVector().size() &&
find_value == search_element.toVector()[index_col_num])) {
Value resultValue((double(j)));
(index_col_num < search_element->toVector().size() &&
find_value == search_element->toVector()[index_col_num])) {
ValuePtr resultValue((double(j)));
matchCount++;
if (num_returns_per_match == 1) {
returnvec.push_back(resultValue);
@ -849,10 +848,10 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx)
}
}
if (num_returns_per_match == 1 && matchCount == 0) {
returnvec.push_back(resultvec);
returnvec.push_back(ValuePtr(resultvec));
}
if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(resultvec);
returnvec.push_back(ValuePtr(resultvec));
}
}
} else {
@ -919,12 +918,12 @@ ValuePtr builtin_norm(const Context *, const EvalContext *evalctx)
ValuePtr val = evalctx->getArgValue(0);
if (val->type() == Value::VECTOR) {
double sum = 0;
Value::VectorType v = val->toVector();
const Value::VectorType &v = val->toVector();
size_t n = v.size();
for (size_t i = 0; i < n; i++)
if (v[i].type() == Value::NUMBER) {
if (v[i]->type() == Value::NUMBER) {
// sum += pow(v[i].toDouble(),2);
register double x = v[i].toDouble();
register double x = v[i]->toDouble();
sum += x*x;
} else {
PRINT("WARNING: Incorrect arguments to norm()");
@ -950,10 +949,10 @@ ValuePtr builtin_cross(const Context *, const EvalContext *evalctx)
return ValuePtr::undefined;
}
Value::VectorType v0 = arg0->toVector();
Value::VectorType v1 = arg1->toVector();
const Value::VectorType &v0 = arg0->toVector();
const Value::VectorType &v1 = arg1->toVector();
if ((v0.size() == 2) && (v1.size() == 2)) {
return ValuePtr(Value(v0[0].toDouble() * v1[1].toDouble() - v0[1].toDouble() * v1[0].toDouble()));
return ValuePtr(v0[0]->toDouble() * v1[1]->toDouble() - v0[1]->toDouble() * v1[0]->toDouble());
}
if ((v0.size() != 3) || (v1.size() != 3)) {
@ -961,12 +960,12 @@ ValuePtr builtin_cross(const Context *, const EvalContext *evalctx)
return ValuePtr::undefined;
}
for (unsigned int a = 0;a < 3;a++) {
if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) {
if ((v0[a]->type() != Value::NUMBER) || (v1[a]->type() != Value::NUMBER)) {
PRINT("WARNING: Invalid value in parameter vector for cross()");
return ValuePtr::undefined;
}
double d0 = v0[a].toDouble();
double d1 = v1[a].toDouble();
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 ValuePtr::undefined;
@ -977,14 +976,14 @@ ValuePtr builtin_cross(const Context *, const EvalContext *evalctx)
}
}
double x = v0[1].toDouble() * v1[2].toDouble() - v0[2].toDouble() * v1[1].toDouble();
double y = v0[2].toDouble() * v1[0].toDouble() - v0[0].toDouble() * v1[2].toDouble();
double z = v0[0].toDouble() * v1[1].toDouble() - v0[1].toDouble() * v1[0].toDouble();
double x = v0[1]->toDouble() * v1[2]->toDouble() - v0[2]->toDouble() * v1[1]->toDouble();
double y = v0[2]->toDouble() * v1[0]->toDouble() - v0[0]->toDouble() * v1[2]->toDouble();
double z = v0[0]->toDouble() * v1[1]->toDouble() - v0[1]->toDouble() * v1[0]->toDouble();
Value::VectorType result;
result.push_back(Value(x));
result.push_back(Value(y));
result.push_back(Value(z));
result.push_back(ValuePtr(x));
result.push_back(ValuePtr(y));
result.push_back(ValuePtr(z));
return ValuePtr(result);
}

View file

@ -1604,15 +1604,15 @@ void MainWindow::updateTemporalVariables()
this->top_ctx.set_variable("$t", ValuePtr(this->anim_tval));
Value::VectorType vpt;
vpt.push_back(Value(-qglview->cam.object_trans.x()));
vpt.push_back(Value(-qglview->cam.object_trans.y()));
vpt.push_back(Value(-qglview->cam.object_trans.z()));
this->top_ctx.set_variable("$vpt", Value(vpt));
vpt.push_back(ValuePtr(-qglview->cam.object_trans.x()));
vpt.push_back(ValuePtr(-qglview->cam.object_trans.y()));
vpt.push_back(ValuePtr(-qglview->cam.object_trans.z()));
this->top_ctx.set_variable("$vpt", ValuePtr(vpt));
Value::VectorType vpr;
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)));
vpr.push_back(ValuePtr(fmodf(360 - qglview->cam.object_rot.x() + 90, 360)));
vpr.push_back(ValuePtr(fmodf(360 - qglview->cam.object_rot.y(), 360)));
vpr.push_back(ValuePtr(fmodf(360 - qglview->cam.object_rot.z(), 360)));
top_ctx.set_variable("$vpr", ValuePtr(vpr));
top_ctx.set_variable("$vpd", ValuePtr(qglview->cam.zoomValue()));

View file

@ -508,12 +508,12 @@ Geometry *PrimitiveNode::createGeometry() const
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();
size_t pt = vec[j]->toDouble();
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);
return p;
@ -572,7 +572,7 @@ Geometry *PrimitiveNode::createGeometry() const
double x,y;
const Value::VectorType &vec = this->points->toVector();
for (unsigned int i=0;i<vec.size();i++) {
const Value &val = vec[i];
const Value &val = *vec[i];
if (!val.getVec2(x, y) || isinf(x) || isinf(y)) {
PRINTB("ERROR: Unable to convert point %s at index %d to a vec2 of numbers",
val.toString() % i);
@ -585,10 +585,10 @@ Geometry *PrimitiveNode::createGeometry() const
p->addOutline(outline);
}
else {
BOOST_FOREACH(const Value &polygon, this->paths->toVector()) {
BOOST_FOREACH(const ValuePtr &polygon, this->paths->toVector()) {
Outline2d curroutline;
BOOST_FOREACH(const Value &index, polygon.toVector()) {
unsigned int idx = index.toDouble();
BOOST_FOREACH(const ValuePtr &index, polygon->toVector()) {
unsigned int idx = index->toDouble();
if (idx < outline.vertices.size()) {
curroutline.vertices.push_back(outline.vertices[idx]);
}

View file

@ -45,25 +45,25 @@ bool SettingsEntry::is_default() const
static Value value(std::string s1, std::string s2) {
Value::VectorType v;
v += Value(s1), Value(s2);
v += ValuePtr(s1), ValuePtr(s2);
return v;
}
static Value values(std::string s1, std::string s1disp, std::string s2, std::string s2disp) {
Value::VectorType v;
v += value(s1, s1disp), value(s2, s2disp);
v += ValuePtr(value(s1, s1disp)), ValuePtr(value(s2, s2disp));
return v;
}
static Value values(std::string s1, std::string s1disp, std::string s2, std::string s2disp, std::string s3, std::string s3disp) {
Value::VectorType v;
v += value(s1, s1disp), value(s2, s2disp), value(s3, s3disp);
v += ValuePtr(value(s1, s1disp)), ValuePtr(value(s2, s2disp)), ValuePtr(value(s3, s3disp));
return v;
}
static Value values(std::string s1, std::string s1disp, std::string s2, std::string s2disp, std::string s3, std::string s3disp, std::string s4, std::string s4disp) {
Value::VectorType v;
v += value(s1, s1disp), value(s2, s2disp), value(s3, s3disp), value(s4, s4disp);
v += ValuePtr(value(s1, s1disp)), ValuePtr(value(s2, s2disp)), ValuePtr(value(s3, s3disp)), ValuePtr(value(s4, s4disp));
return v;
}
@ -94,12 +94,17 @@ void Settings::visit(Visitor& visitor)
}
}
Value Settings::get(const SettingsEntry& entry)
const Value &Settings::defaultValue(const SettingsEntry& entry)
{
return entry._default;
}
const Value &Settings::get(const SettingsEntry& entry)
{
return entry._value;
}
void Settings::set(SettingsEntry& entry, const Value val)
void Settings::set(SettingsEntry& entry, const Value &val)
{
entry._value = val;
}
@ -122,15 +127,15 @@ Visitor::~Visitor()
* can be translated.
*/
SettingsEntry Settings::showWarningsIn3dView("3dview", "showWarningsIn3dView", Value(true), Value(true));
SettingsEntry Settings::indentationWidth("editor", "indentationWidth", Value(Value::RangeType(1, 16)), Value(4));
SettingsEntry Settings::tabWidth("editor", "tabWidth", Value(Value::RangeType(1, 16)), Value(4));
SettingsEntry Settings::indentationWidth("editor", "indentationWidth", Value(RangeType(1, 16)), Value(4));
SettingsEntry Settings::tabWidth("editor", "tabWidth", Value(RangeType(1, 16)), Value(4));
SettingsEntry Settings::lineWrap("editor", "lineWrap", values("None", _("None"), "Char", _("Wrap at character boundaries"), "Word", _("Wrap at word boundaries")), Value("Word"));
SettingsEntry Settings::lineWrapIndentationStyle("editor", "lineWrapIndentationStyle", values("Fixed", _("Fixed"), "Same", _("Same"), "Indented", _("Indented")), Value("Fixed"));
SettingsEntry Settings::lineWrapIndentation("editor", "lineWrapIndentation", Value(Value::RangeType(0, 999)), Value(4));
SettingsEntry Settings::lineWrapIndentation("editor", "lineWrapIndentation", Value(RangeType(0, 999)), Value(4));
SettingsEntry Settings::lineWrapVisualizationBegin("editor", "lineWrapVisualizationBegin", values("None", _("None"), "Text", _("Text"), "Border", _("Border"), "Margin", _("Margin")), Value("None"));
SettingsEntry Settings::lineWrapVisualizationEnd("editor", "lineWrapVisualizationEnd", values("None", _("None"), "Text", _("Text"), "Border", _("Border"), "Margin", _("Margin")), Value("Border"));
SettingsEntry Settings::showWhitespace("editor", "showWhitespaces", values("Never", _("Never"), "Always", _("Always"), "AfterIndentation", _("After indentation")), Value("Never"));
SettingsEntry Settings::showWhitespaceSize("editor", "showWhitespacesSize", Value(Value::RangeType(1, 16)), Value(2));
SettingsEntry Settings::showWhitespaceSize("editor", "showWhitespacesSize", Value(RangeType(1, 16)), Value(2));
SettingsEntry Settings::autoIndent("editor", "autoIndent", Value(true), Value(true));
SettingsEntry Settings::indentStyle("editor", "indentStyle", values("Spaces", _("Spaces"), "Tabs", _("Tabs")), Value("Spaces"));
SettingsEntry Settings::tabKeyFunction("editor", "tabKeyFunction", values("Indent", _("Indent"), "InsertTab", _("Insert Tab")), Value("Indent"));

View file

@ -55,9 +55,9 @@ public:
void visit(class Visitor& visitor);
Value defaultValue(const SettingsEntry& entry);
Value get(const SettingsEntry& entry);
void set(SettingsEntry& entry, const Value val);
const Value &defaultValue(const SettingsEntry& entry);
const Value &get(const SettingsEntry& entry);
void set(SettingsEntry& entry, const Value &val);
private:
Settings();
@ -73,4 +73,4 @@ public:
virtual void handle(SettingsEntry& entry) const = 0;
};
}
}

View file

@ -105,15 +105,15 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
Eigen::AngleAxisd rotz(0, Vector3d::UnitZ());
double a;
if (val_a->toVector().size() > 0) {
val_a->toVector()[0].getDouble(a);
val_a->toVector()[0]->getDouble(a);
rotx = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitX());
}
if (val_a->toVector().size() > 1) {
val_a->toVector()[1].getDouble(a);
val_a->toVector()[1]->getDouble(a);
roty = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitY());
}
if (val_a->toVector().size() > 2) {
val_a->toVector()[2].getDouble(a);
val_a->toVector()[2]->getDouble(a);
rotz = Eigen::AngleAxisd(a*M_PI/180, Vector3d::UnitZ());
}
node->matrix.rotate(rotz * roty * rotx);
@ -171,9 +171,9 @@ AbstractNode *TransformModule::instantiate(const Context *ctx, const ModuleInsta
Matrix4d rawmatrix = Matrix4d::Identity();
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(rawmatrix(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(rawmatrix(y, x));
}
double w = rawmatrix(3,3);
if (w != 1.0) node->matrix = rawmatrix / w;

View file

@ -250,15 +250,19 @@ public:
stream << '[';
for (size_t i = 0; i < v.size(); i++) {
if (i > 0) stream << ", ";
stream << v[i];
stream << *v[i];
}
stream << ']';
return stream.str();
}
std::string operator()(const Value::RangeType &v) const {
std::string operator()(const RangeType &v) const {
return (boost::format("[%1% : %2% : %3%]") % v.begin_val % v.step_val % v.end_val).str();
}
std::string operator()(const ValuePtr &v) const {
return v->toString();
}
};
std::string Value::toString() const
@ -290,12 +294,12 @@ public:
{
std::stringstream stream;
for (size_t i = 0; i < v.size(); i++) {
stream << v[i].chrString();
stream << v[i]->chrString();
}
return stream.str();
}
std::string operator()(const Value::RangeType &v) const
std::string operator()(const RangeType &v) const
{
const boost::uint32_t steps = v.nbsteps();
if (steps >= 10000) {
@ -304,8 +308,8 @@ public:
}
std::stringstream stream;
Value::RangeType range = v;
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
RangeType range = v;
for (RangeType::iterator it = range.begin();it != range.end();it++) {
const Value value(*it);
stream << value.chrString();
}
@ -337,8 +341,8 @@ bool Value::getVec2(double &x, double &y, bool ignoreInfinite) const
double rx, ry;
bool valid = ignoreInfinite
? v[0].getFiniteDouble(rx) && v[1].getFiniteDouble(ry)
: v[0].getDouble(rx) && v[1].getDouble(ry);
? v[0]->getFiniteDouble(rx) && v[1]->getFiniteDouble(ry)
: v[0]->getDouble(rx) && v[1]->getDouble(ry);
if (valid) {
x = rx;
@ -363,10 +367,10 @@ bool Value::getVec3(double &x, double &y, double &z, double defaultval) const
if (v.size() != 3) return false;
}
return (v[0].getDouble(x) && v[1].getDouble(y) && v[2].getDouble(z));
return (v[0]->getDouble(x) && v[1]->getDouble(y) && v[2]->getDouble(z));
}
Value::RangeType Value::toRange() const
RangeType Value::toRange() const
{
const RangeType *val = boost::get<RangeType>(&this->value);
if (val) {
@ -473,7 +477,7 @@ public:
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]);
sum.push_back(ValuePtr(*op1[i] + *op2[i]));
}
return Value(sum);
}
@ -498,7 +502,7 @@ public:
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]);
sum.push_back(ValuePtr(*op1[i] - *op2[i]));
}
return Value(sum);
}
@ -513,8 +517,8 @@ Value Value::multvecnum(const Value &vecval, const Value &numval)
{
// Vector * Number
VectorType dstv;
BOOST_FOREACH(const Value &val, vecval.toVector()) {
dstv.push_back(val * numval);
BOOST_FOREACH(const ValuePtr &val, vecval.toVector()) {
dstv.push_back(ValuePtr(*val * numval));
}
return Value(dstv);
}
@ -524,18 +528,18 @@ Value Value::multmatvec(const VectorType &matrixvec, const VectorType &vectorvec
// Matrix * Vector
VectorType dstv;
for (size_t i=0;i<matrixvec.size();i++) {
if (matrixvec[i].type() != VECTOR ||
matrixvec[i].toVector().size() != vectorvec.size()) {
if (matrixvec[i]->type() != VECTOR ||
matrixvec[i]->toVector().size() != vectorvec.size()) {
return Value();
}
double r_e = 0.0;
for (size_t j=0;j<matrixvec[i].toVector().size();j++) {
if (matrixvec[i].toVector()[j].type() != NUMBER || vectorvec[j].type() != NUMBER) {
for (size_t j=0;j<matrixvec[i]->toVector().size();j++) {
if (matrixvec[i]->toVector()[j]->type() != NUMBER || vectorvec[j]->type() != NUMBER) {
return Value();
}
r_e += matrixvec[i].toVector()[j].toDouble() * vectorvec[j].toDouble();
r_e += matrixvec[i]->toVector()[j]->toDouble() * vectorvec[j]->toDouble();
}
dstv.push_back(Value(r_e));
dstv.push_back(ValuePtr(r_e));
}
return Value(dstv);
}
@ -545,17 +549,17 @@ Value Value::multvecmat(const VectorType &vectorvec, const VectorType &matrixvec
assert(vectorvec.size() == matrixvec.size());
// Vector * Matrix
VectorType dstv;
for (size_t i=0;i<matrixvec[0].toVector().size();i++) {
for (size_t i=0;i<matrixvec[0]->toVector().size();i++) {
double r_e = 0.0;
for (size_t j=0;j<vectorvec.size();j++) {
if (matrixvec[j].type() != VECTOR ||
matrixvec[j].toVector()[i].type() != NUMBER ||
vectorvec[j].type() != NUMBER) {
if (matrixvec[j]->type() != VECTOR ||
matrixvec[j]->toVector()[i]->type() != NUMBER ||
vectorvec[j]->type() != NUMBER) {
return Value::undefined;
}
r_e += vectorvec[j].toDouble() * matrixvec[j].toVector()[i].toDouble();
r_e += vectorvec[j]->toDouble() * matrixvec[j]->toVector()[i]->toDouble();
}
dstv.push_back(Value(r_e));
dstv.push_back(ValuePtr(r_e));
}
return Value(dstv);
}
@ -574,31 +578,31 @@ Value Value::operator*(const Value &v) const
else if (this->type() == VECTOR && v.type() == VECTOR) {
const VectorType &vec1 = this->toVector();
const VectorType &vec2 = v.toVector();
if (vec1[0].type() == NUMBER && vec2[0].type() == NUMBER &&
if (vec1[0]->type() == NUMBER && vec2[0]->type() == NUMBER &&
vec1.size() == vec2.size()) {
// 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) {
if (vec1[i]->type() != NUMBER || vec2[i]->type() != NUMBER) {
return Value::undefined;
}
r += (vec1[i].toDouble() * vec2[i].toDouble());
r += (vec1[i]->toDouble() * vec2[i]->toDouble());
}
return Value(r);
} else if (vec1[0].type() == VECTOR && vec2[0].type() == NUMBER &&
vec1[0].toVector().size() == vec2.size()) {
} else if (vec1[0]->type() == VECTOR && vec2[0]->type() == NUMBER &&
vec1[0]->toVector().size() == vec2.size()) {
return multmatvec(vec1, vec2);
} else if (vec1[0].type() == NUMBER && vec2[0].type() == VECTOR &&
} else if (vec1[0]->type() == NUMBER && vec2[0]->type() == VECTOR &&
vec1.size() == vec2.size()) {
return multvecmat(vec1, vec2);
} else if (vec1[0].type() == VECTOR && vec2[0].type() == VECTOR &&
vec1[0].toVector().size() == vec2.size()) {
} else if (vec1[0]->type() == VECTOR && vec2[0]->type() == VECTOR &&
vec1[0]->toVector().size() == vec2.size()) {
// Matrix * Matrix
VectorType dstv;
BOOST_FOREACH(const Value &srcrow, vec1) {
const VectorType &srcrowvec = srcrow.toVector();
BOOST_FOREACH(const ValuePtr &srcrow, vec1) {
const VectorType &srcrowvec = srcrow->toVector();
if (srcrowvec.size() != vec2.size()) return Value::undefined;
dstv.push_back(multvecmat(srcrowvec, vec2));
dstv.push_back(ValuePtr(multvecmat(srcrowvec, vec2)));
}
return Value(dstv);
}
@ -614,16 +618,16 @@ Value Value::operator/(const Value &v) const
else if (this->type() == VECTOR && v.type() == NUMBER) {
const VectorType &vec = this->toVector();
VectorType dstv;
BOOST_FOREACH(const Value &vecval, vec) {
dstv.push_back(vecval / v);
BOOST_FOREACH(const ValuePtr &vecval, vec) {
dstv.push_back(ValuePtr(*vecval / v));
}
return Value(dstv);
}
else if (this->type() == NUMBER && v.type() == VECTOR) {
const VectorType &vec = v.toVector();
VectorType dstv;
BOOST_FOREACH(const Value &vecval, vec) {
dstv.push_back(*this / vecval);
BOOST_FOREACH(const ValuePtr &vecval, vec) {
dstv.push_back(ValuePtr(*this / *vecval));
}
return Value(dstv);
}
@ -646,8 +650,8 @@ Value Value::operator-() const
else if (this->type() == VECTOR) {
const VectorType &vec = this->toVector();
VectorType dstv;
BOOST_FOREACH(const Value &vecval, vec) {
dstv.push_back(-vecval);
BOOST_FOREACH(const ValuePtr &vecval, vec) {
dstv.push_back(ValuePtr(-*vecval));
}
return Value(dstv);
}
@ -694,11 +698,11 @@ public:
Value operator()(const Value::VectorType &vec, const double &idx) const {
const boost::uint32_t i = convert_to_uint32(idx);
if (i < vec.size()) return vec[i];
if (i < vec.size()) return *vec[i];
return Value::undefined;
}
Value operator()(const Value::RangeType &range, const double &idx) const {
Value operator()(const RangeType &range, const double &idx) const {
const boost::uint32_t i = convert_to_uint32(idx);
switch(i) {
case 0: return Value(range.begin_val);
@ -719,14 +723,14 @@ Value Value::operator[](const Value &v) const
return boost::apply_visitor(bracket_visitor(), this->value, v.value);
}
void Value::RangeType::normalize() {
void RangeType::normalize() {
if ((step_val>0) && (end_val < begin_val)) {
std::swap(begin_val,end_val);
printDeprecation("Using ranges of the form [begin:end] with begin value greater than the end value is deprecated.");
}
}
boost::uint32_t Value::RangeType::nbsteps() const {
boost::uint32_t RangeType::nbsteps() const {
if (boost::math::isnan(step_val) || boost::math::isinf(begin_val) || (boost::math::isinf(end_val))) {
return std::numeric_limits<boost::uint32_t>::max();
}
@ -755,13 +759,13 @@ boost::uint32_t Value::RangeType::nbsteps() const {
return steps;
}
Value::RangeType::iterator::iterator(Value::RangeType &range, type_t type) : range(range), val(range.begin_val)
RangeType::iterator::iterator(RangeType &range, type_t type) : range(range), val(range.begin_val)
{
this->type = type;
update_type();
}
void Value::RangeType::iterator::update_type()
void RangeType::iterator::update_type()
{
if (range.step_val == 0) {
type = RANGE_TYPE_END;
@ -776,17 +780,17 @@ void Value::RangeType::iterator::update_type()
}
}
Value::RangeType::iterator::reference Value::RangeType::iterator::operator*()
RangeType::iterator::reference RangeType::iterator::operator*()
{
return val;
}
Value::RangeType::iterator::pointer Value::RangeType::iterator::operator->()
RangeType::iterator::pointer RangeType::iterator::operator->()
{
return &(operator*());
}
Value::RangeType::iterator::self_type Value::RangeType::iterator::operator++()
RangeType::iterator::self_type RangeType::iterator::operator++()
{
if (type < 0) {
type = RANGE_TYPE_RUNNING;
@ -796,14 +800,14 @@ Value::RangeType::iterator::self_type Value::RangeType::iterator::operator++()
return *this;
}
Value::RangeType::iterator::self_type Value::RangeType::iterator::operator++(int)
RangeType::iterator::self_type RangeType::iterator::operator++(int)
{
self_type tmp(*this);
operator++();
return tmp;
}
bool Value::RangeType::iterator::operator==(const self_type &other) const
bool RangeType::iterator::operator==(const self_type &other) const
{
if (type == RANGE_TYPE_RUNNING) {
return (type == other.type) && (val == other.val) && (range == other.range);
@ -812,7 +816,7 @@ bool Value::RangeType::iterator::operator==(const self_type &other) const
}
}
bool Value::RangeType::iterator::operator!=(const self_type &other) const
bool RangeType::iterator::operator!=(const self_type &other) const
{
return !(*this == other);
}
@ -862,7 +866,7 @@ ValuePtr::ValuePtr(const Value::VectorType &v)
this->reset(new Value(v));
}
ValuePtr::ValuePtr(const Value::RangeType &v)
ValuePtr::ValuePtr(const RangeType &v)
{
this->reset(new Value(v));
}
@ -937,3 +941,12 @@ ValuePtr ValuePtr::operator%(const ValuePtr &v) const
return ValuePtr(**this % *v);
}
ValuePtr::operator bool() const
{
return **this;
}
const Value &ValuePtr::operator*() const
{
return *this->get();
}

View file

@ -29,75 +29,113 @@ public:
};
std::ostream &operator<<(std::ostream &stream, const Filename &filename);
class Value
{
class RangeType {
private:
double begin_val;
double step_val;
double end_val;
/// inverse begin/end if begin is upper than end
void normalize();
public:
class RangeType {
private:
double begin_val;
double step_val;
double end_val;
/// inverse begin/end if begin is upper than end
void normalize();
public:
typedef enum { RANGE_TYPE_BEGIN, RANGE_TYPE_RUNNING, RANGE_TYPE_END } type_t;
typedef enum { RANGE_TYPE_BEGIN, RANGE_TYPE_RUNNING, RANGE_TYPE_END } type_t;
class iterator {
public:
typedef iterator self_type;
typedef double value_type;
typedef double& reference;
typedef double* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef double difference_type;
iterator(RangeType &range, type_t type);
self_type operator++();
self_type operator++(int junk);
reference operator*();
pointer operator->();
bool operator==(const self_type& other) const;
bool operator!=(const self_type& other) const;
private:
RangeType &range;
double val;
type_t type;
class iterator {
public:
typedef iterator self_type;
typedef double value_type;
typedef double& reference;
typedef double* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef double difference_type;
iterator(RangeType &range, type_t type);
self_type operator++();
self_type operator++(int junk);
reference operator*();
pointer operator->();
bool operator==(const self_type& other) const;
bool operator!=(const self_type& other) const;
private:
RangeType &range;
double val;
type_t type;
void update_type();
};
RangeType(double begin, double end)
: begin_val(begin), step_val(1.0), end_val(end)
void update_type();
};
RangeType(double begin, double end)
: begin_val(begin), step_val(1.0), end_val(end)
{
normalize();
}
RangeType(double begin, double step, double end)
: begin_val(begin), step_val(step), end_val(end) {}
bool operator==(const RangeType &other) const {
return this->begin_val == other.begin_val &&
this->step_val == other.step_val &&
this->end_val == other.end_val;
}
double begin_value() { return begin_val; }
double step_value() { return step_val; }
double end_value() { return end_val; }
iterator begin() { return iterator(*this, RANGE_TYPE_BEGIN); }
iterator end() { return iterator(*this, RANGE_TYPE_END); }
/// return number of steps, max uint32_t value if step is 0
boost::uint32_t nbsteps() const;
friend class chr_visitor;
friend class tostring_visitor;
friend class bracket_visitor;
};
RangeType(double begin, double step, double end)
: begin_val(begin), step_val(step), end_val(end) {}
class ValuePtr : public shared_ptr<const class Value>
{
public:
static ValuePtr undefined;
bool operator==(const RangeType &other) const {
return this->begin_val == other.begin_val &&
this->step_val == other.step_val &&
this->end_val == other.end_val;
}
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 class std::vector<ValuePtr> &v);
ValuePtr(const class RangeType &v);
double begin_value() { return begin_val; }
double step_value() { return step_val; }
double end_value() { return end_val; }
operator bool() const;
iterator begin() { return iterator(*this, RANGE_TYPE_BEGIN); }
iterator end() { return iterator(*this, RANGE_TYPE_END); }
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 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;
/// return number of steps, max uint32_t value if step is 0
boost::uint32_t nbsteps() const;
friend class chr_visitor;
friend class tostring_visitor;
friend class bracket_visitor;
};
const Value &operator*() const;
typedef std::vector<Value> VectorType;
private:
};
class Value
{
public:
typedef std::vector<ValuePtr> VectorType;
enum ValueType {
UNDEFINED,
@ -169,40 +207,3 @@ 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 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:
};

View file

@ -0,0 +1,9 @@
// Test for recursion crashing when vectors are parameters to a module
// See github issue1407
rec();
module rec(a=1)
{
rec([a,10,10]);
}

View file

@ -839,7 +839,9 @@ endif()
#
# GUI binary tests
#
if(APPLE)
if(EXISTS "$ENV{OPENSCAD_BINARY}")
set(OPENSCAD_BINPATH "$ENV{OPENSCAD_BINARY}")
elseif(APPLE)
set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../OpenSCAD.app/Contents/MacOS/OpenSCAD")
elseif (MINGW_CROSS_ENV_DIR)
set(OPENSCAD_BINPATH "${CMAKE_CURRENT_SOURCE_DIR}/../mingw32/release/openscad.exe")
@ -1112,6 +1114,7 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES}
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-function.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-function2.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-module.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-vector.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/tail-recursion-tests.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad

View file

@ -0,0 +1 @@
ERROR: Recursion detected calling module 'rec'