From a9c5f72fdc41c1727ba4c88da7547b31c5b57249 Mon Sep 17 00:00:00 2001 From: twanvl Date: Wed, 18 Jun 2008 23:11:26 +0000 Subject: [PATCH] Make == script operator to work correctly on collections (lists) git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@992 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/script/context.cpp | 9 ++++++--- src/script/functions/basic.cpp | 17 +++++------------ src/script/to_value.hpp | 13 +++++++++++-- src/script/value.cpp | 34 ++++++++++++++++++++++------------ src/script/value.hpp | 3 ++- 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/script/context.cpp b/src/script/context.cpp index ed3c51cc..d0e01143 100644 --- a/src/script/context.cpp +++ b/src/script/context.cpp @@ -251,7 +251,10 @@ ScriptValueP Context::makeClosure(const ScriptValueP& fun) { if (variables[var].level < level) break; closure->addBinding(var, variables[var].value); } - return closure; + // can we simplify? + ScriptValueP better = closure->simplify(); + if (better) return better; + else return closure; } @@ -392,8 +395,8 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP& case I_AND: OPERATOR_I(&&); case I_OR: OPERATOR_I(||); case I_XOR: a = to_script((bool)*a != (bool)*b); break; - case I_EQ: a = to_script( equal(*a,*b)); break; - case I_NEQ: a = to_script(!equal(*a,*b)); break; + case I_EQ: a = to_script( equal(a,b)); break; + case I_NEQ: a = to_script(!equal(a,b)); break; case I_LT: OPERATOR_DI(<); case I_GT: OPERATOR_DI(>); case I_LE: OPERATOR_DI(<=); diff --git a/src/script/functions/basic.cpp b/src/script/functions/basic.cpp index fd3646aa..bde90ac9 100644 --- a/src/script/functions/basic.cpp +++ b/src/script/functions/basic.cpp @@ -215,7 +215,7 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr ScriptValueP it = in->makeIterator(in); int i = 0; while (ScriptValueP v = it->next()) { - if (equal(*of, *v)) return i; + if (equal(of, v)) return i; i++; } } @@ -384,17 +384,10 @@ SCRIPT_FUNCTION(keyword_usage) { // ----------------------------------------------------------------------------- : Rule form /// Turn a script function into a rule, a.k.a. a delayed closure -class ScriptRule : public ScriptValue { - public: - inline ScriptRule(const ScriptValueP& fun) : fun(fun) {} - virtual ScriptType type() const { return SCRIPT_FUNCTION; } - virtual String typeName() const { return fun->typeName() + _(" rule"); } - virtual ScriptValueP eval(Context& ctx) const { - return ctx.makeClosure(fun); - } - private: - ScriptValueP fun; -}; +SCRIPT_FUNCTION(rule) { + SCRIPT_PARAM(ScriptValueP, input); + return new_intrusive1(input); +} // ----------------------------------------------------------------------------- : Init diff --git a/src/script/to_value.hpp b/src/script/to_value.hpp index f5607d1d..2bacc783 100644 --- a/src/script/to_value.hpp +++ b/src/script/to_value.hpp @@ -321,6 +321,17 @@ class ScriptClosure : public ScriptValue { void applyBindings(Context& ctx) const; }; +/// Turn a script function into a rule, a.k.a. a delayed closure +class ScriptRule : public ScriptValue { + public: + inline ScriptRule(const ScriptValueP& fun) : fun(fun) {} + virtual ScriptType type() const; + virtual String typeName() const; + virtual ScriptValueP eval(Context& ctx) const; + private: + ScriptValueP fun; +}; + // ----------------------------------------------------------------------------- : Creating /// Convert a value to a script value @@ -360,7 +371,5 @@ template <> inline bool from_script (const ScriptValueP& va template <> inline Color from_script (const ScriptValueP& value) { return (AColor)*value; } template <> inline AColor from_script (const ScriptValueP& value) { return *value; } -void from_script(const ScriptValueP& value, wxRegEx& out); - // ----------------------------------------------------------------------------- : EOF #endif diff --git a/src/script/value.cpp b/src/script/value.cpp index 20893ec6..f0858bd9 100644 --- a/src/script/value.cpp +++ b/src/script/value.cpp @@ -38,19 +38,30 @@ ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency& ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; } /// compare script values for equallity -bool equal(const ScriptValue& a, const ScriptValue& b) { - if (&a == &b) return true; - ScriptType at = a.type(), bt = b.type(); +bool equal(const ScriptValueP& a, const ScriptValueP& b) { + if (a == b) return true; + ScriptType at = a->type(), bt = b->type(); if (at == bt && at == SCRIPT_INT) { - return (int)a == (int)b; + return (int)*a == (int)*b; } else if ((at == SCRIPT_INT || at == SCRIPT_DOUBLE) && (bt == SCRIPT_INT || bt == SCRIPT_DOUBLE)) { - return (double)a == (double)b; + return (double)*a == (double)*b; + } else if (at == SCRIPT_COLLECTION && bt == SCRIPT_COLLECTION) { + // compare each element + if (a->itemCount() != b->itemCount()) return false; + ScriptValueP a_it = a->makeIterator(a); + ScriptValueP b_it = b->makeIterator(b); + while (true) { + ScriptValueP a_v = a_it->next(); + ScriptValueP b_v = b_it->next(); + if (!a_v || !b_v) return a_v == b_v; + if (!equal(a_v, b_v)) return false; + } } else { String as, bs; const void* ap, *bp; - CompareWhat aw = a.compareAs(as, ap); - CompareWhat bw = b.compareAs(bs, bp); + CompareWhat aw = a->compareAs(as, ap); + CompareWhat bw = b->compareAs(bs, bp); // compare pointers or strings if (aw == COMPARE_AS_STRING || bw == COMPARE_AS_STRING) { return as == bs; @@ -402,10 +413,9 @@ void ScriptClosure::applyBindings(Context& ctx) const { } } -// ----------------------------------------------------------------------------- : Destructing -void from_script(const ScriptValueP& value, wxRegEx& regex) { - if (!regex.Compile(*value, wxRE_ADVANCED)) { - throw ScriptError(_ERROR_2_("can't convert", value->typeName(), _TYPE_("regex"))); - } +ScriptType ScriptRule::type() const { return SCRIPT_FUNCTION; } +String ScriptRule::typeName() const { return fun->typeName() + _(" rule"); } +ScriptValueP ScriptRule::eval(Context& ctx) const { + return ctx.makeClosure(fun); } diff --git a/src/script/value.hpp b/src/script/value.hpp index 8582f021..b36e550f 100644 --- a/src/script/value.hpp +++ b/src/script/value.hpp @@ -29,6 +29,7 @@ enum ScriptType , SCRIPT_FUNCTION , SCRIPT_OBJECT // Only ScriptObject , SCRIPT_COLLECTION +, SCRIPT_REGEX , SCRIPT_ITERATOR , SCRIPT_DUMMY , SCRIPT_ERROR @@ -102,7 +103,7 @@ extern ScriptValueP script_false; ///< The preallocated false value extern ScriptValueP dependency_dummy; ///< Dummy value used during dependency analysis /// compare script values for equallity -bool equal(const ScriptValue& a, const ScriptValue& b); +bool equal(const ScriptValueP& a, const ScriptValueP& b); // ----------------------------------------------------------------------------- : EOF #endif