diff --git a/src/script/dependency.cpp b/src/script/dependency.cpp index 911dda1a..60edc8f1 100644 --- a/src/script/dependency.cpp +++ b/src/script/dependency.cpp @@ -22,11 +22,11 @@ extern ScriptValueP dependency_dummy; // A dummy type used during dependency analysis, // it simply supresses all error messages. class DependencyDummy : public ScriptIterator { - public: - virtual ScriptType type() const { return SCRIPT_DUMMY; } - virtual String typeName() const { return _("dummy"); } - virtual ScriptValueP next(ScriptValueP*) { return ScriptValueP(); } - virtual ScriptValueP dependencyName(const ScriptValue&, const Dependency&) const { return dependency_dummy; } +public: + ScriptType type() const override { return SCRIPT_DUMMY; } + String typeName() const override { return _("dummy"); } + ScriptValueP next(ScriptValueP*,int*) override { return ScriptValueP(); } + ScriptValueP dependencyName(const ScriptValue&, const Dependency&) const override { return dependency_dummy; } }; ScriptValueP dependency_dummy(new DependencyDummy); @@ -43,19 +43,19 @@ public: : a(a), b(b) {} - virtual ScriptType type() const { return SCRIPT_DUMMY; } - virtual String typeName() const { return _("union of ") + a->typeName() + _(" and ") + b->typeName(); } + ScriptType type() const override { return SCRIPT_DUMMY; } + String typeName() const override { return _("union of ") + a->typeName() + _(" and ") + b->typeName(); } - virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const { + ScriptValueP dependencies(Context& ctx, const Dependency& dep) const override { return unified( a->dependencies(ctx,dep), b->dependencies(ctx,dep)); } - virtual ScriptValueP makeIterator(ScriptValueP thisP) const { + ScriptValueP makeIterator(const ScriptValueP& thisP) const override { return unified(a->makeIterator(a), b->makeIterator(b)); } - virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const { + ScriptValueP dependencyMember(const String& name, const Dependency& dep) const override { return unified(a->dependencyMember(name,dep), b->dependencyMember(name,dep)); } - virtual ScriptValueP dependencyName(const ScriptValue& container, const Dependency& dep) const { + ScriptValueP dependencyName(const ScriptValue& container, const Dependency& dep) const override { return unified(a->dependencyName(container,dep), b->dependencyName(container,dep)); } private: diff --git a/src/script/to_value.hpp b/src/script/to_value.hpp index 2f1c1d87..82163aca 100644 --- a/src/script/to_value.hpp +++ b/src/script/to_value.hpp @@ -75,7 +75,7 @@ struct ScriptIterator : public ScriptValue { CompareWhat compareAs(String&, void const*&) const override; /// Return the next item for this iterator, or ScriptValueP() if there is no such item - ScriptValueP next(ScriptValueP* key_out = nullptr) override = 0; + ScriptValueP next(ScriptValueP* key_out = nullptr, int* index_out = nullptr) override = 0; ScriptValueP makeIterator(const ScriptValueP& thisP) const override; }; @@ -98,9 +98,10 @@ template class ScriptCollectionIterator : public ScriptIterator { public: ScriptCollectionIterator(const Collection* col) : pos(0), col(col) {} - ScriptValueP next(ScriptValueP* key_out) override { + ScriptValueP next(ScriptValueP* key_out, int* index_out) override { if (pos < col->size()) { if (key_out) *key_out = to_script((int)pos); + if (index_out) *index_out = (int)pos; return to_script(col->at(pos++)); } else { return ScriptValueP(); diff --git a/src/script/value.cpp b/src/script/value.cpp index a64f0ca1..1b8d9ece 100644 --- a/src/script/value.cpp +++ b/src/script/value.cpp @@ -46,7 +46,7 @@ ScriptValueP ScriptValue::eval(Context&, bool) const { return delay_error(ScriptErrorConversion(typeName(), _TYPE_("function"))); } -ScriptValueP ScriptValue::next(ScriptValueP* key_out) { +ScriptValueP ScriptValue::next(ScriptValueP* key_out, int* index_out) { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); } ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { @@ -183,9 +183,10 @@ public: ScriptRangeIterator(int start, int end) : pos(start), start(start), end(end) {} - ScriptValueP next(ScriptValueP* key_out) override { + ScriptValueP next(ScriptValueP* key_out, int* index_out) override { if (pos <= end) { if (key_out) *key_out = to_script(pos-start); + if (index_out) *index_out = (int)pos; return to_script(pos++); } else { return ScriptValueP(); @@ -288,6 +289,22 @@ ScriptValueP to_script(double v) { // ----------------------------------------------------------------------------- : String type +String quote_string(String const& str) { + String out; + out.reserve(str.size() + 2); + out += _('"'); + FOR_EACH_CONST(c, str) { + if (c == _('"') || c == _('\\')) { out += _('\\'); out += c; } + else if (c == _('\1')) out += _("\\<"); + else if (c == _('\n')) out += _("\\n"); + else if (c == _('\r')) out += _("\\r"); + else if (c == _('\t')) out += _("\\t"); + else out += c; + } + out += _('"'); + return out; +} + // String values class ScriptString : public ScriptValue { public: @@ -295,6 +312,9 @@ public: ScriptType type() const override { return SCRIPT_STRING; } String typeName() const override { return _TYPE_("string") + _(" (\"") + (value.size() < 30 ? value : value.substr(0,30) + _("...")) + _("\")"); } String toString() const override { return value; } + String toCode() const override { + return quote_string(value); + } double toDouble() const override { double d; if (value.ToDouble(&d)) { @@ -437,10 +457,15 @@ String ScriptCollectionBase::toCode() const { String ret = _("["); bool first = true; ScriptValueP it = makeIterator(); - while (ScriptValueP v = it->next()) { + ScriptValueP key; + int index = -1; + while (ScriptValueP v = it->next(&key,&index)) { if (!first) ret += _(","); first = false; - // todo: include keys + if (index == -1) { + ret += key->toCode(); + ret += _(":"); + } ret += v->toCode(); } ret += _("]"); @@ -454,12 +479,14 @@ class ScriptCustomCollectionIterator : public ScriptIterator { public: ScriptCustomCollectionIterator(ScriptCustomCollection const* col, ScriptValueP const& col_owned) : col(col), col_owned(col_owned), pos(0), it(col->key_value.begin()) {} - ScriptValueP next(ScriptValueP* key_out) override { + ScriptValueP next(ScriptValueP* key_out, int* index_out) override { if (pos < col->value.size()) { if (key_out) *key_out = to_script((int)pos); + if (index_out) *index_out = (int)pos; return col->value.at(pos++); } else if (it != col->key_value.end()) { if (key_out) *key_out = to_script(it->first); + if (index_out) *index_out = -1; return (it++)->second; } else { return ScriptValueP(); @@ -498,14 +525,14 @@ class ScriptConcatCollectionIterator : public ScriptIterator { public: ScriptConcatCollectionIterator(const ScriptValueP& itA, const ScriptValueP& itB) : itA(itA), itB(itB) {} - ScriptValueP next(ScriptValueP* key_out) override { + ScriptValueP next(ScriptValueP* key_out, int* index_out) override { if (itA) { - ScriptValueP v = itA->next(key_out); + ScriptValueP v = itA->next(key_out, index_out); if (v) return v; else itA = ScriptValueP(); } // TODO: somehow fix up the keys - return itB->next(key_out); + return itB->next(key_out, index_out); } private: ScriptValueP itA, itB; diff --git a/src/script/value.hpp b/src/script/value.hpp index 281f9cb5..268896ad 100644 --- a/src/script/value.hpp +++ b/src/script/value.hpp @@ -104,8 +104,10 @@ public: */ virtual ScriptValueP makeIterator(const ScriptValueP& thisP = ScriptValueP()) const; /// Return the next item for this iterator, or ScriptValueP() if there is no such item - /** If key_out != 0, then it will recieve the key of the item */ - virtual ScriptValueP next(ScriptValueP* key_out = nullptr); + /** If key_out != nullptr, then it will receive the key of the item + * If index_out != nullptr, then it will receive to index of the item if it is in an indexable container + */ + virtual ScriptValueP next(ScriptValueP* key_out = nullptr, int* index_out = nullptr); /// Return the number of items in this value (assuming it is a collection) virtual int itemCount() const; /// Get a member at the given index diff --git a/test/script/script-functions.mse-script b/test/script/script-functions.mse-script index 9d7287bc..f1602550 100644 --- a/test/script/script-functions.mse-script +++ b/test/script/script-functions.mse-script @@ -93,6 +93,7 @@ assert( length([]) == 0) assert( length([1]) == 1) assert( length([1,2]) == 2) assert( length([a:1,b:2]) == 2) +assert( length([1,2,3] + [4,5]) == 5) assert( length("") == 0) assert( length("1") == 1) assert( length("12") == 2) @@ -183,7 +184,7 @@ assert(to_code("abc") == "\"abc\"") assert(to_code("\\\<\n\r\t") == "\"\\\\\\<\\n\\r\\t\"") assert(to_code(1) == "1") assert(to_code([1,2,3]) == "[1,2,3]") -assert(to_code([x:"y"]) == "[x:\"y\"]") +assert(to_code([x:"y"]) == "[\"x\":\"y\"]") # count_chosen assert( count_chosen("") == 0 )