diff --git a/src/Preferences.cc b/src/Preferences.cc index efbfdf17..c26b2c26 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -32,6 +32,7 @@ #include #include #include +#include #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) { diff --git a/src/builtin.cc b/src/builtin.cc index e495f4a5..d24836d5 100644 --- a/src/builtin.cc +++ b/src/builtin.cc @@ -101,9 +101,9 @@ Builtins::Builtins() this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr(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(new ExpressionConst(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr(new ExpressionConst(zero3val)))); diff --git a/src/cgaladv.cc b/src/cgaladv.cc index 20addb78..a69a7a48 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -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(); diff --git a/src/color.cc b/src/color.cc index 5909c6d7..69d9e249 100644 --- a/src/color.cc +++ b/src/color.cc @@ -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]); } diff --git a/src/control.cc b/src/control.cc index 1aeaea27..261d5105 100644 --- a/src/control.cc +++ b/src/control.cc @@ -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); } diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 8bcd1bc5..45f22a75 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -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); } } diff --git a/src/expr.cc b/src/expr.cc index 68a30891..687a3105 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -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)); diff --git a/src/func.cc b/src/func.cc index e6dfbccc..23d3d135 100644 --- a/src/func.cc +++ b/src/func.cc @@ -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); } diff --git a/src/mainwin.cc b/src/mainwin.cc index 2c163b11..29026b0d 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -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())); diff --git a/src/primitives.cc b/src/primitives.cc index 0727c7aa..0a445a0b 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -508,12 +508,12 @@ Geometry *PrimitiveNode::createGeometry() const for (size_t i=0; ifaces->toVector().size(); i++) { p->append_poly(); - const Value::VectorType &vec = this->faces->toVector()[i].toVector(); + const Value::VectorType &vec = this->faces->toVector()[i]->toVector(); for (size_t j=0; jtoDouble(); 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;iaddOutline(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]); } diff --git a/src/settings.cc b/src/settings.cc index 8fb77749..35197389 100644 --- a/src/settings.cc +++ b/src/settings.cc @@ -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")); diff --git a/src/settings.h b/src/settings.h index 2864bb2c..6222f280 100644 --- a/src/settings.h +++ b/src/settings.h @@ -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; }; -} \ No newline at end of file +} diff --git a/src/transform.cc b/src/transform.cc index 2f7a2a89..7400903f 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -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; diff --git a/src/value.cc b/src/value.cc index 85b61972..eaa91d93 100644 --- a/src/value.cc +++ b/src/value.cc @@ -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(&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;itype() != VECTOR || + matrixvec[i]->toVector().size() != vectorvec.size()) { return Value(); } double r_e = 0.0; - for (size_t j=0;jtoVector().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;itoVector().size();i++) { double r_e = 0.0; for (size_t j=0;jtype() != 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;itype() != 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::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(); +} diff --git a/src/value.h b/src/value.h index a1a058a9..ae1779c1 100644 --- a/src/value.h +++ b/src/value.h @@ -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 ⦥ + 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 ⦥ - 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 +{ +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 &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 VectorType; +private: +}; + +class Value +{ +public: + typedef std::vector VectorType; enum ValueType { UNDEFINED, @@ -169,40 +207,3 @@ private: Variant value; }; -class ValuePtr : public shared_ptr -{ -public: - static ValuePtr undefined; - - ValuePtr(); - explicit ValuePtr(const Value &v); - ValuePtr(bool v); - ValuePtr(int v); - ValuePtr(double v); - ValuePtr(const std::string &v); - ValuePtr(const char *v); - ValuePtr(const char v); - ValuePtr(const Value::VectorType &v); - ValuePtr(const Value::RangeType &v); - - operator bool() const { return **this; } - - bool operator==(const ValuePtr &v) const; - bool operator!=(const ValuePtr &v) const; - bool operator<(const ValuePtr &v) const; - bool operator<=(const ValuePtr &v) const; - bool operator>=(const ValuePtr &v) const; - bool operator>(const ValuePtr &v) const; - ValuePtr operator-() const; - ValuePtr operator!() const; - ValuePtr 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: -}; diff --git a/testdata/scad/misc/recursion-test-vector.scad b/testdata/scad/misc/recursion-test-vector.scad new file mode 100644 index 00000000..88fccb61 --- /dev/null +++ b/testdata/scad/misc/recursion-test-vector.scad @@ -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]); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c4f0c689..94c981fe 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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 diff --git a/tests/regression/echotest/recursion-test-vector-expected.echo b/tests/regression/echotest/recursion-test-vector-expected.echo new file mode 100644 index 00000000..890b19a4 --- /dev/null +++ b/tests/regression/echotest/recursion-test-vector-expected.echo @@ -0,0 +1 @@ +ERROR: Recursion detected calling module 'rec'