Commit 53175119 authored by twanvl's avatar twanvl

Make == script operator to work correctly on collections (lists)

parent 1209425e
...@@ -251,7 +251,10 @@ ScriptValueP Context::makeClosure(const ScriptValueP& fun) { ...@@ -251,7 +251,10 @@ ScriptValueP Context::makeClosure(const ScriptValueP& fun) {
if (variables[var].level < level) break; if (variables[var].level < level) break;
closure->addBinding(var, variables[var].value); 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& ...@@ -392,8 +395,8 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP&
case I_AND: OPERATOR_I(&&); case I_AND: OPERATOR_I(&&);
case I_OR: OPERATOR_I(||); case I_OR: OPERATOR_I(||);
case I_XOR: a = to_script((bool)*a != (bool)*b); break; case I_XOR: a = to_script((bool)*a != (bool)*b); break;
case I_EQ: 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_NEQ: a = to_script(!equal(a,b)); break;
case I_LT: OPERATOR_DI(<); case I_LT: OPERATOR_DI(<);
case I_GT: OPERATOR_DI(>); case I_GT: OPERATOR_DI(>);
case I_LE: OPERATOR_DI(<=); case I_LE: OPERATOR_DI(<=);
......
...@@ -215,7 +215,7 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr ...@@ -215,7 +215,7 @@ int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const Scr
ScriptValueP it = in->makeIterator(in); ScriptValueP it = in->makeIterator(in);
int i = 0; int i = 0;
while (ScriptValueP v = it->next()) { while (ScriptValueP v = it->next()) {
if (equal(*of, *v)) return i; if (equal(of, v)) return i;
i++; i++;
} }
} }
...@@ -384,17 +384,10 @@ SCRIPT_FUNCTION(keyword_usage) { ...@@ -384,17 +384,10 @@ SCRIPT_FUNCTION(keyword_usage) {
// ----------------------------------------------------------------------------- : Rule form // ----------------------------------------------------------------------------- : Rule form
/// Turn a script function into a rule, a.k.a. a delayed closure /// Turn a script function into a rule, a.k.a. a delayed closure
class ScriptRule : public ScriptValue { SCRIPT_FUNCTION(rule) {
public: SCRIPT_PARAM(ScriptValueP, input);
inline ScriptRule(const ScriptValueP& fun) : fun(fun) {} return new_intrusive1<ScriptRule>(input);
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;
};
// ----------------------------------------------------------------------------- : Init // ----------------------------------------------------------------------------- : Init
......
...@@ -321,6 +321,17 @@ class ScriptClosure : public ScriptValue { ...@@ -321,6 +321,17 @@ class ScriptClosure : public ScriptValue {
void applyBindings(Context& ctx) const; 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 // ----------------------------------------------------------------------------- : Creating
/// Convert a value to a script value /// Convert a value to a script value
...@@ -360,7 +371,5 @@ template <> inline bool from_script<bool> (const ScriptValueP& va ...@@ -360,7 +371,5 @@ template <> inline bool from_script<bool> (const ScriptValueP& va
template <> inline Color from_script<Color> (const ScriptValueP& value) { return (AColor)*value; } template <> inline Color from_script<Color> (const ScriptValueP& value) { return (AColor)*value; }
template <> inline AColor from_script<AColor> (const ScriptValueP& value) { return *value; } template <> inline AColor from_script<AColor> (const ScriptValueP& value) { return *value; }
void from_script(const ScriptValueP& value, wxRegEx& out);
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -38,19 +38,30 @@ ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency& ...@@ -38,19 +38,30 @@ ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; } ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
/// compare script values for equallity /// compare script values for equallity
bool equal(const ScriptValue& a, const ScriptValue& b) { bool equal(const ScriptValueP& a, const ScriptValueP& b) {
if (&a == &b) return true; if (a == b) return true;
ScriptType at = a.type(), bt = b.type(); ScriptType at = a->type(), bt = b->type();
if (at == bt && at == SCRIPT_INT) { if (at == bt && at == SCRIPT_INT) {
return (int)a == (int)b; return (int)*a == (int)*b;
} else if ((at == SCRIPT_INT || at == SCRIPT_DOUBLE) && } else if ((at == SCRIPT_INT || at == SCRIPT_DOUBLE) &&
(bt == SCRIPT_INT || bt == 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 { } else {
String as, bs; String as, bs;
const void* ap, *bp; const void* ap, *bp;
CompareWhat aw = a.compareAs(as, ap); CompareWhat aw = a->compareAs(as, ap);
CompareWhat bw = b.compareAs(bs, bp); CompareWhat bw = b->compareAs(bs, bp);
// compare pointers or strings // compare pointers or strings
if (aw == COMPARE_AS_STRING || bw == COMPARE_AS_STRING) { if (aw == COMPARE_AS_STRING || bw == COMPARE_AS_STRING) {
return as == bs; return as == bs;
...@@ -402,10 +413,9 @@ void ScriptClosure::applyBindings(Context& ctx) const { ...@@ -402,10 +413,9 @@ void ScriptClosure::applyBindings(Context& ctx) const {
} }
} }
// ----------------------------------------------------------------------------- : Destructing
void from_script(const ScriptValueP& value, wxRegEx& regex) { ScriptType ScriptRule::type() const { return SCRIPT_FUNCTION; }
if (!regex.Compile(*value, wxRE_ADVANCED)) { String ScriptRule::typeName() const { return fun->typeName() + _(" rule"); }
throw ScriptError(_ERROR_2_("can't convert", value->typeName(), _TYPE_("regex"))); ScriptValueP ScriptRule::eval(Context& ctx) const {
} return ctx.makeClosure(fun);
} }
...@@ -29,6 +29,7 @@ enum ScriptType ...@@ -29,6 +29,7 @@ enum ScriptType
, SCRIPT_FUNCTION , SCRIPT_FUNCTION
, SCRIPT_OBJECT // Only ScriptObject , SCRIPT_OBJECT // Only ScriptObject
, SCRIPT_COLLECTION , SCRIPT_COLLECTION
, SCRIPT_REGEX
, SCRIPT_ITERATOR , SCRIPT_ITERATOR
, SCRIPT_DUMMY , SCRIPT_DUMMY
, SCRIPT_ERROR , SCRIPT_ERROR
...@@ -102,7 +103,7 @@ extern ScriptValueP script_false; ///< The preallocated false value ...@@ -102,7 +103,7 @@ extern ScriptValueP script_false; ///< The preallocated false value
extern ScriptValueP dependency_dummy; ///< Dummy value used during dependency analysis extern ScriptValueP dependency_dummy; ///< Dummy value used during dependency analysis
/// compare script values for equallity /// compare script values for equallity
bool equal(const ScriptValue& a, const ScriptValue& b); bool equal(const ScriptValueP& a, const ScriptValueP& b);
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment