mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-12 21:47:00 -04:00
Added ^ power operator,
Added abs, random_int, random_real, random_shuffle, random_select script functions. Made == comparison of doubles use a small epsilon, so things like 3/2 == 1.5 are actually true. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1013 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -198,7 +198,7 @@ void ChoiceStyle::initImage() {
|
|||||||
// CALL 0
|
// CALL 0
|
||||||
// PUSH_CONST nil
|
// PUSH_CONST nil
|
||||||
// OR_ELSE
|
// OR_ELSE
|
||||||
intrusive_ptr<ScriptCustomCollection> lookup(new ScriptCustomCollection());
|
ScriptCustomCollectionP lookup(new ScriptCustomCollection());
|
||||||
FOR_EACH(ci, choice_images) {
|
FOR_EACH(ci, choice_images) {
|
||||||
lookup->key_value[ci.first] = ci.second.getScriptP();
|
lookup->key_value[ci.first] = ci.second.getScriptP();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -402,6 +402,13 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP&
|
|||||||
a = to_script((int)*a % (int)*b);
|
a = to_script((int)*a % (int)*b);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case I_POW:
|
||||||
|
if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) {
|
||||||
|
a = to_script(pow((double)*a, (double)*b));
|
||||||
|
} else {
|
||||||
|
a = to_script(pow((int)*a, (int)*b));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case I_AND: OPERATOR_B(&&);
|
case I_AND: OPERATOR_B(&&);
|
||||||
case I_OR: OPERATOR_B(||);
|
case I_OR: OPERATOR_B(||);
|
||||||
case I_XOR: OPERATOR_B(!=);
|
case I_XOR: OPERATOR_B(!=);
|
||||||
@@ -442,7 +449,7 @@ void instrQuaternary(QuaternaryInstructionType i, ScriptValueP& a, const ScriptV
|
|||||||
// ----------------------------------------------------------------------------- : Simple instructions : objects and closures
|
// ----------------------------------------------------------------------------- : Simple instructions : objects and closures
|
||||||
|
|
||||||
void Context::makeObject(size_t n) {
|
void Context::makeObject(size_t n) {
|
||||||
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection());
|
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
||||||
size_t begin = stack.size() - 2 * n;
|
size_t begin = stack.size() - 2 * n;
|
||||||
for (size_t i = 0 ; i < n ; ++i) {
|
for (size_t i = 0 ; i < n ; ++i) {
|
||||||
const ScriptValueP& key = stack[begin + 2 * i];
|
const ScriptValueP& key = stack[begin + 2 * i];
|
||||||
|
|||||||
@@ -89,6 +89,21 @@ SCRIPT_FUNCTION(to_real) {
|
|||||||
SCRIPT_RETURN(input);
|
SCRIPT_RETURN(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(to_number) {
|
||||||
|
ScriptValueP input = ctx.getVariable(SCRIPT_VAR_input);
|
||||||
|
ScriptType t = input->type();
|
||||||
|
if (t == SCRIPT_BOOL) {
|
||||||
|
SCRIPT_RETURN((bool)*input ? 1 : 0);
|
||||||
|
} else if (t == SCRIPT_COLOR) {
|
||||||
|
AColor c = (AColor)*input;
|
||||||
|
SCRIPT_RETURN( (c.Red() + c.Blue() + c.Green()) / 3 );
|
||||||
|
} else if (t == SCRIPT_DOUBLE) {
|
||||||
|
SCRIPT_RETURN((double)*input);
|
||||||
|
} else {
|
||||||
|
SCRIPT_RETURN((int)*input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(to_boolean) {
|
SCRIPT_FUNCTION(to_boolean) {
|
||||||
ScriptValueP input = ctx.getVariable(SCRIPT_VAR_input);
|
ScriptValueP input = ctx.getVariable(SCRIPT_VAR_input);
|
||||||
ScriptType t = input->type();
|
ScriptType t = input->type();
|
||||||
@@ -106,6 +121,30 @@ SCRIPT_FUNCTION(to_color) {
|
|||||||
SCRIPT_RETURN(input);
|
SCRIPT_RETURN(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Math
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(abs) {
|
||||||
|
ScriptValueP input = ctx.getVariable(SCRIPT_VAR_input);
|
||||||
|
ScriptType t = input->type();
|
||||||
|
if (t == SCRIPT_DOUBLE) {
|
||||||
|
SCRIPT_RETURN(fabs((double)*input));
|
||||||
|
} else {
|
||||||
|
SCRIPT_RETURN(abs((int)*input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(random_real) {
|
||||||
|
SCRIPT_PARAM_DEFAULT_C(double, begin, 0.0);
|
||||||
|
SCRIPT_PARAM_DEFAULT_C(double, end, 1.0);
|
||||||
|
SCRIPT_RETURN( (double)rand() / RAND_MAX * (end - begin) + begin );
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(random_int) {
|
||||||
|
SCRIPT_PARAM_DEFAULT_C(int, begin, 0);
|
||||||
|
SCRIPT_PARAM_C( int, end);
|
||||||
|
SCRIPT_RETURN( rand() % (end - begin) + begin );
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : String stuff
|
// ----------------------------------------------------------------------------- : String stuff
|
||||||
|
|
||||||
// convert a string to upper case
|
// convert a string to upper case
|
||||||
@@ -142,8 +181,8 @@ SCRIPT_FUNCTION(trim) {
|
|||||||
// extract a substring
|
// extract a substring
|
||||||
SCRIPT_FUNCTION(substring) {
|
SCRIPT_FUNCTION(substring) {
|
||||||
SCRIPT_PARAM_C(String, input);
|
SCRIPT_PARAM_C(String, input);
|
||||||
SCRIPT_PARAM_DEFAULT(int, begin, 0);
|
SCRIPT_PARAM_DEFAULT_C(int, begin, 0);
|
||||||
SCRIPT_PARAM_DEFAULT(int, end, INT_MAX);
|
SCRIPT_PARAM_DEFAULT_C(int, end, INT_MAX);
|
||||||
if (begin < 0) begin = 0;
|
if (begin < 0) begin = 0;
|
||||||
if (end < 0) end = 0;
|
if (end < 0) end = 0;
|
||||||
if (begin >= end || (size_t)begin >= input.size()) {
|
if (begin >= end || (size_t)begin >= input.size()) {
|
||||||
@@ -302,7 +341,7 @@ ScriptValueP sort_script(Context& ctx, const ScriptValueP& list, ScriptValue& or
|
|||||||
}
|
}
|
||||||
sort(values.begin(), values.end(), smart_less_first);
|
sort(values.begin(), values.end(), smart_less_first);
|
||||||
// return collection
|
// return collection
|
||||||
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection());
|
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
||||||
FOR_EACH(v, values) {
|
FOR_EACH(v, values) {
|
||||||
ret->value.push_back(v.second);
|
ret->value.push_back(v.second);
|
||||||
}
|
}
|
||||||
@@ -365,7 +404,7 @@ SCRIPT_FUNCTION(filter_list) {
|
|||||||
SCRIPT_PARAM_C(ScriptValueP, input);
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
SCRIPT_PARAM_C(ScriptValueP, filter);
|
SCRIPT_PARAM_C(ScriptValueP, filter);
|
||||||
// filter a collection
|
// filter a collection
|
||||||
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection());
|
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
||||||
ScriptValueP it = input->makeIterator(input);
|
ScriptValueP it = input->makeIterator(input);
|
||||||
while (ScriptValueP v = it->next()) {
|
while (ScriptValueP v = it->next()) {
|
||||||
ctx.setVariable(SCRIPT_VAR_input, v);
|
ctx.setVariable(SCRIPT_VAR_input, v);
|
||||||
@@ -383,6 +422,57 @@ SCRIPT_FUNCTION(sort_list) {
|
|||||||
return sort_script(ctx, input, *order_by);
|
return sort_script(ctx, input, *order_by);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(random_shuffle) {
|
||||||
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
|
// convert to CustomCollection
|
||||||
|
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
||||||
|
ScriptValueP it = input->makeIterator(input);
|
||||||
|
while (ScriptValueP v = it->next()) {
|
||||||
|
ret->value.push_back(v);
|
||||||
|
}
|
||||||
|
// shuffle
|
||||||
|
random_shuffle(ret->value.begin(), ret->value.end());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCRIPT_FUNCTION(random_select) {
|
||||||
|
SCRIPT_PARAM_C(ScriptValueP, input);
|
||||||
|
SCRIPT_OPTIONAL_PARAM(int, count) {
|
||||||
|
// pick a single one
|
||||||
|
int itemCount = input->itemCount();
|
||||||
|
if (itemCount == 0) {
|
||||||
|
throw ScriptError(String::Format(_("Can not select a random item from an empty collection"), count));
|
||||||
|
}
|
||||||
|
return input->getIndex( rand() % itemCount );
|
||||||
|
} else {
|
||||||
|
// pick many
|
||||||
|
SCRIPT_PARAM_DEFAULT_C(bool, replace, false);
|
||||||
|
ScriptCustomCollectionP ret(new ScriptCustomCollection);
|
||||||
|
int itemCount = input->itemCount();
|
||||||
|
if (replace) {
|
||||||
|
if (itemCount == 0) {
|
||||||
|
throw ScriptError(String::Format(_("Can not select %d items from an empty collection"), count));
|
||||||
|
}
|
||||||
|
for (int i = 0 ; i < count ; ++i) {
|
||||||
|
ret->value.push_back( input->getIndex( rand() % itemCount ) );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (count > itemCount) {
|
||||||
|
throw ScriptError(String::Format(_("Can not select %d items from a collection conaining only %d items"), count, input->itemCount()));
|
||||||
|
}
|
||||||
|
// transfer all to ret and shuffle
|
||||||
|
ScriptValueP it = input->makeIterator(input);
|
||||||
|
while (ScriptValueP v = it->next()) {
|
||||||
|
ret->value.push_back(v);
|
||||||
|
}
|
||||||
|
random_shuffle(ret->value.begin(), ret->value.end());
|
||||||
|
// keep only the first 'count'
|
||||||
|
ret->value.resize(count);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Keywords
|
// ----------------------------------------------------------------------------- : Keywords
|
||||||
|
|
||||||
|
|
||||||
@@ -454,8 +544,13 @@ void init_script_basic_functions(Context& ctx) {
|
|||||||
ctx.setVariable(_("to string"), script_to_string);
|
ctx.setVariable(_("to string"), script_to_string);
|
||||||
ctx.setVariable(_("to int"), script_to_int);
|
ctx.setVariable(_("to int"), script_to_int);
|
||||||
ctx.setVariable(_("to real"), script_to_real);
|
ctx.setVariable(_("to real"), script_to_real);
|
||||||
|
ctx.setVariable(_("to number"), script_to_number);
|
||||||
ctx.setVariable(_("to boolean"), script_to_boolean);
|
ctx.setVariable(_("to boolean"), script_to_boolean);
|
||||||
ctx.setVariable(_("to color"), script_to_color);
|
ctx.setVariable(_("to color"), script_to_color);
|
||||||
|
// math
|
||||||
|
ctx.setVariable(_("abs"), script_abs);
|
||||||
|
ctx.setVariable(_("random_real"), script_random_real);
|
||||||
|
ctx.setVariable(_("random_int"), script_random_int);
|
||||||
// string
|
// string
|
||||||
ctx.setVariable(_("to upper"), script_to_upper);
|
ctx.setVariable(_("to upper"), script_to_upper);
|
||||||
ctx.setVariable(_("to lower"), script_to_lower);
|
ctx.setVariable(_("to lower"), script_to_lower);
|
||||||
@@ -482,6 +577,8 @@ void init_script_basic_functions(Context& ctx) {
|
|||||||
ctx.setVariable(_("number of items"), script_number_of_items);
|
ctx.setVariable(_("number of items"), script_number_of_items);
|
||||||
ctx.setVariable(_("filter list"), script_filter_list);
|
ctx.setVariable(_("filter list"), script_filter_list);
|
||||||
ctx.setVariable(_("sort list"), script_sort_list);
|
ctx.setVariable(_("sort list"), script_sort_list);
|
||||||
|
ctx.setVariable(_("random shuffle"), script_random_shuffle);
|
||||||
|
ctx.setVariable(_("random select"), script_random_select);
|
||||||
// keyword
|
// keyword
|
||||||
ctx.setVariable(_("expand keywords"), script_expand_keywords);
|
ctx.setVariable(_("expand keywords"), script_expand_keywords);
|
||||||
ctx.setVariable(_("expand keywords rule"), new_intrusive1<ScriptRule>(script_expand_keywords));
|
ctx.setVariable(_("expand keywords rule"), new_intrusive1<ScriptRule>(script_expand_keywords));
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ class ScriptBreakRule : public ScriptValue {
|
|||||||
virtual String typeName() const { return _("break_rule"); }
|
virtual String typeName() const { return _("break_rule"); }
|
||||||
virtual ScriptValueP eval(Context& ctx) const {
|
virtual ScriptValueP eval(Context& ctx) const {
|
||||||
SCRIPT_PARAM_C(String, input);
|
SCRIPT_PARAM_C(String, input);
|
||||||
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection);
|
ScriptCustomCollectionP ret(new ScriptCustomCollection);
|
||||||
while (regex.Matches(input)) {
|
while (regex.Matches(input)) {
|
||||||
// match, append to result
|
// match, append to result
|
||||||
size_t start, len;
|
size_t start, len;
|
||||||
@@ -393,7 +393,7 @@ SCRIPT_FUNCTION_WITH_SIMPLIFY(break_text) {
|
|||||||
SCRIPT_PARAM_C(String, input);
|
SCRIPT_PARAM_C(String, input);
|
||||||
SCRIPT_PARAM_C(ScriptRegexP, match);
|
SCRIPT_PARAM_C(ScriptRegexP, match);
|
||||||
SCRIPT_OPTIONAL_PARAM_C_(ScriptRegexP, in_context);
|
SCRIPT_OPTIONAL_PARAM_C_(ScriptRegexP, in_context);
|
||||||
intrusive_ptr<ScriptCustomCollection> ret(new ScriptCustomCollection);
|
ScriptCustomCollectionP ret(new ScriptCustomCollection);
|
||||||
// find all matches
|
// find all matches
|
||||||
while (match->regex.Matches(input)) {
|
while (match->regex.Matches(input)) {
|
||||||
// match, append to result
|
// match, append to result
|
||||||
|
|||||||
@@ -119,8 +119,7 @@ class TokenIterator {
|
|||||||
|
|
||||||
bool isAlpha_(Char c) { return isAlpha(c) || c==_('_'); }
|
bool isAlpha_(Char c) { return isAlpha(c) || c==_('_'); }
|
||||||
bool isAlnum_(Char c) { return isAlnum(c) || c==_('_'); }
|
bool isAlnum_(Char c) { return isAlnum(c) || c==_('_'); }
|
||||||
bool isOper (Char c) { return c==_('+') || c==_('-') || c==_('*') || c==_('/') || c==_('!') || c==_('.') || c==_('@') ||
|
bool isOper (Char c) { return wxStrchr(_("+-*/!.@%^&:=<>;,"),c) != nullptr; }
|
||||||
c==_(':') || c==_('=') || c==_('<') || c==_('>') || c==_(';') || c==_(','); }
|
|
||||||
bool isLparen(Char c) { return c==_('(') || c==_('[') || c==_('{'); }
|
bool isLparen(Char c) { return c==_('(') || c==_('[') || c==_('{'); }
|
||||||
bool isRparen(Char c) { return c==_(')') || c==_(']') || c==_('}'); }
|
bool isRparen(Char c) { return c==_(')') || c==_(']') || c==_('}'); }
|
||||||
bool isDigitOrDot(Char c) { return isDigit(c) || c==_('.'); }
|
bool isDigitOrDot(Char c) { return isDigit(c) || c==_('.'); }
|
||||||
@@ -347,6 +346,7 @@ enum Precedence
|
|||||||
, PREC_CMP // == != < > <= >=
|
, PREC_CMP // == != < > <= >=
|
||||||
, PREC_ADD // + -
|
, PREC_ADD // + -
|
||||||
, PREC_MUL // * / mod
|
, PREC_MUL // * / mod
|
||||||
|
, PREC_POW // ^ (right associative)
|
||||||
, PREC_UNARY // - not (unary operators)
|
, PREC_UNARY // - not (unary operators)
|
||||||
, PREC_FUN // [] () . (function call, member)
|
, PREC_FUN // [] () . (function call, member)
|
||||||
, PREC_STRING // +{ }+ (smart string operators)
|
, PREC_STRING // +{ }+ (smart string operators)
|
||||||
@@ -680,10 +680,11 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
|||||||
else if (minPrec <= PREC_CMP && token==_(">=")) parseOper(input, script, PREC_ADD, I_BINARY, I_GE);
|
else if (minPrec <= PREC_CMP && token==_(">=")) parseOper(input, script, PREC_ADD, I_BINARY, I_GE);
|
||||||
else if (minPrec <= PREC_ADD && token==_("+")) parseOper(input, script, PREC_MUL, I_BINARY, I_ADD);
|
else if (minPrec <= PREC_ADD && token==_("+")) parseOper(input, script, PREC_MUL, I_BINARY, I_ADD);
|
||||||
else if (minPrec <= PREC_ADD && token==_("-")) parseOper(input, script, PREC_MUL, I_BINARY, I_SUB);
|
else if (minPrec <= PREC_ADD && token==_("-")) parseOper(input, script, PREC_MUL, I_BINARY, I_SUB);
|
||||||
else if (minPrec <= PREC_MUL && token==_("*")) parseOper(input, script, PREC_UNARY, I_BINARY, I_MUL);
|
else if (minPrec <= PREC_MUL && token==_("*")) parseOper(input, script, PREC_POW, I_BINARY, I_MUL);
|
||||||
else if (minPrec <= PREC_MUL && token==_("/")) parseOper(input, script, PREC_UNARY, I_BINARY, I_FDIV);
|
else if (minPrec <= PREC_MUL && token==_("/")) parseOper(input, script, PREC_POW, I_BINARY, I_FDIV);
|
||||||
else if (minPrec <= PREC_MUL && token==_("div")) parseOper(input, script, PREC_UNARY, I_BINARY, I_DIV);
|
else if (minPrec <= PREC_MUL && token==_("div")) parseOper(input, script, PREC_POW, I_BINARY, I_DIV);
|
||||||
else if (minPrec <= PREC_MUL && token==_("mod")) parseOper(input, script, PREC_UNARY, I_BINARY, I_MOD);
|
else if (minPrec <= PREC_MUL && token==_("mod")) parseOper(input, script, PREC_POW, I_BINARY, I_MOD);
|
||||||
|
else if (minPrec <= PREC_POW && token==_("^")) parseOper(input, script, PREC_POW, I_BINARY, I_POW);
|
||||||
else if (minPrec <= PREC_FUN && token==_(".")) { // get member by name
|
else if (minPrec <= PREC_FUN && token==_(".")) { // get member by name
|
||||||
const Token& token = input.read();
|
const Token& token = input.read();
|
||||||
if (token == TOK_NAME || token == TOK_INT || token == TOK_DOUBLE || token == TOK_STRING) {
|
if (token == TOK_NAME || token == TOK_INT || token == TOK_DOUBLE || token == TOK_STRING) {
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ void init_script_variables() {
|
|||||||
VarN(in_context,_("in context"));
|
VarN(in_context,_("in context"));
|
||||||
Var(recursive);
|
Var(recursive);
|
||||||
Var(order);
|
Var(order);
|
||||||
|
Var(begin);
|
||||||
|
Var(end);
|
||||||
Var(filter);
|
Var(filter);
|
||||||
Var(choice);
|
Var(choice);
|
||||||
Var(choices);
|
Var(choices);
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ enum BinaryInstructionType
|
|||||||
, I_FDIV ///< floating point division
|
, I_FDIV ///< floating point division
|
||||||
, I_DIV ///< integer division
|
, I_DIV ///< integer division
|
||||||
, I_MOD ///< modulus
|
, I_MOD ///< modulus
|
||||||
|
, I_POW ///< power
|
||||||
// Logical
|
// Logical
|
||||||
, I_AND ///< logical and
|
, I_AND ///< logical and
|
||||||
, I_OR ///< logical or
|
, I_OR ///< logical or
|
||||||
@@ -116,6 +117,8 @@ enum Variable
|
|||||||
, SCRIPT_VAR_in_context
|
, SCRIPT_VAR_in_context
|
||||||
, SCRIPT_VAR_recursive
|
, SCRIPT_VAR_recursive
|
||||||
, SCRIPT_VAR_order
|
, SCRIPT_VAR_order
|
||||||
|
, SCRIPT_VAR_begin
|
||||||
|
, SCRIPT_VAR_end
|
||||||
, SCRIPT_VAR_filter
|
, SCRIPT_VAR_filter
|
||||||
, SCRIPT_VAR_choice
|
, SCRIPT_VAR_choice
|
||||||
, SCRIPT_VAR_choices
|
, SCRIPT_VAR_choices
|
||||||
|
|||||||
@@ -119,12 +119,11 @@ class ScriptCollection : public ScriptValue {
|
|||||||
inline ScriptCollection(const Collection* v) : value(v) {}
|
inline ScriptCollection(const Collection* v) : value(v) {}
|
||||||
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||||
virtual String typeName() const { return _TYPE_1_("collection of", type_name(*value->begin())); }
|
virtual String typeName() const { return _TYPE_1_("collection of", type_name(*value->begin())); }
|
||||||
virtual ScriptValueP getMember(const String& name) const {
|
virtual ScriptValueP getIndex(int index) const {
|
||||||
long index;
|
if (index >= 0 && index < (int)value->size()) {
|
||||||
if (name.ToLong(&index) && index >= 0 && (size_t)index < value->size()) {
|
|
||||||
return to_script(value->at(index));
|
return to_script(value->at(index));
|
||||||
} else {
|
} else {
|
||||||
return ScriptValue::getMember(name);
|
return ScriptValue::getIndex(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const {
|
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const {
|
||||||
@@ -196,6 +195,7 @@ class ScriptCustomCollection : public ScriptValue {
|
|||||||
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||||
virtual String typeName() const { return _TYPE_("collection"); }
|
virtual String typeName() const { return _TYPE_("collection"); }
|
||||||
virtual ScriptValueP getMember(const String& name) const;
|
virtual ScriptValueP getMember(const String& name) const;
|
||||||
|
virtual ScriptValueP getIndex(int index) const;
|
||||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
|
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
|
||||||
virtual int itemCount() const { return (int)value.size(); }
|
virtual int itemCount() const { return (int)value.size(); }
|
||||||
/// Collections can be compared by comparing pointers
|
/// Collections can be compared by comparing pointers
|
||||||
@@ -210,6 +210,8 @@ class ScriptCustomCollection : public ScriptValue {
|
|||||||
map<String,ScriptValueP> key_value;
|
map<String,ScriptValueP> key_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECLARE_POINTER_TYPE(ScriptCustomCollection);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Collections : concatenation
|
// ----------------------------------------------------------------------------- : Collections : concatenation
|
||||||
|
|
||||||
/// Script value containing the concatenation of two collections
|
/// Script value containing the concatenation of two collections
|
||||||
@@ -219,6 +221,7 @@ class ScriptConcatCollection : public ScriptValue {
|
|||||||
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||||
virtual String typeName() const { return _TYPE_("collection"); }
|
virtual String typeName() const { return _TYPE_("collection"); }
|
||||||
virtual ScriptValueP getMember(const String& name) const;
|
virtual ScriptValueP getMember(const String& name) const;
|
||||||
|
virtual ScriptValueP getIndex(int index) const;
|
||||||
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
|
virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const;
|
||||||
virtual int itemCount() const { return a->itemCount() + b->itemCount(); }
|
virtual int itemCount() const { return a->itemCount() + b->itemCount(); }
|
||||||
/// Collections can be compared by comparing pointers
|
/// Collections can be compared by comparing pointers
|
||||||
@@ -260,6 +263,7 @@ class ScriptObject : public ScriptValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual ScriptValueP getIndex(int index) const { ScriptValueP d = getDefault(); return d ? d->getIndex(index) : ScriptValue::getIndex(index); }
|
||||||
virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const {
|
virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const {
|
||||||
mark_dependency_member(*value, name, dep);
|
mark_dependency_member(*value, name, dep);
|
||||||
return getMember(name);
|
return getMember(name);
|
||||||
|
|||||||
+33
-8
@@ -24,7 +24,6 @@ ScriptValue::operator bool() const { throw Script
|
|||||||
ScriptValue::operator double() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("double" ))); }
|
ScriptValue::operator double() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("double" ))); }
|
||||||
ScriptValue::operator AColor() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("color" ))); }
|
ScriptValue::operator AColor() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("color" ))); }
|
||||||
ScriptValueP ScriptValue::eval(Context&) const { return delayError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); }
|
ScriptValueP ScriptValue::eval(Context&) const { return delayError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); }
|
||||||
ScriptValueP ScriptValue::getMember(const String& name) const { return delayError(_ERROR_2_("has no member", typeName(), name)); }
|
|
||||||
ScriptValueP ScriptValue::next() { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); }
|
ScriptValueP ScriptValue::next() { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); }
|
||||||
ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { return delayError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { return delayError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||||
int ScriptValue::itemCount() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
int ScriptValue::itemCount() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("collection"))); }
|
||||||
@@ -32,12 +31,28 @@ CompareWhat ScriptValue::compareAs(String& compare_str, void const*& compare_pt
|
|||||||
compare_str = toString();
|
compare_str = toString();
|
||||||
return COMPARE_AS_STRING;
|
return COMPARE_AS_STRING;
|
||||||
}
|
}
|
||||||
|
ScriptValueP ScriptValue::getMember(const String& name) const {
|
||||||
|
long index;
|
||||||
|
if (name.ToLong(&index)) {
|
||||||
|
return getIndex(index);
|
||||||
|
} else {
|
||||||
|
return delayError(_ERROR_2_("has no member", typeName(), name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ScriptValueP ScriptValue::getIndex(int index) const {
|
||||||
|
return delayError(_ERROR_2_("has no member", typeName(), String()<<index));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ScriptValueP ScriptValue::simplifyClosure(ScriptClosure&) const { return ScriptValueP(); }
|
ScriptValueP ScriptValue::simplifyClosure(ScriptClosure&) const { return ScriptValueP(); }
|
||||||
|
|
||||||
ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&) const { return dependency_dummy; }
|
ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&) const { return dependency_dummy; }
|
||||||
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
|
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
|
||||||
|
|
||||||
|
bool approx_equal(double a, double b) {
|
||||||
|
return a == b || fabs(a - b) < 1e-14;
|
||||||
|
}
|
||||||
|
|
||||||
/// compare script values for equallity
|
/// compare script values for equallity
|
||||||
bool equal(const ScriptValueP& a, const ScriptValueP& b) {
|
bool equal(const ScriptValueP& a, const ScriptValueP& b) {
|
||||||
if (a == b) return true;
|
if (a == b) return true;
|
||||||
@@ -48,7 +63,7 @@ bool equal(const ScriptValueP& a, const ScriptValueP& b) {
|
|||||||
return (bool)*a == (bool)*b;
|
return (bool)*a == (bool)*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 approx_equal( (double)*a, (double)*b);
|
||||||
} else if (at == SCRIPT_COLLECTION && bt == SCRIPT_COLLECTION) {
|
} else if (at == SCRIPT_COLLECTION && bt == SCRIPT_COLLECTION) {
|
||||||
// compare each element
|
// compare each element
|
||||||
if (a->itemCount() != b->itemCount()) return false;
|
if (a->itemCount() != b->itemCount()) return false;
|
||||||
@@ -338,12 +353,14 @@ ScriptValueP ScriptCustomCollection::getMember(const String& name) const {
|
|||||||
if (it != key_value.end()) {
|
if (it != key_value.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
} else {
|
} else {
|
||||||
long index;
|
return ScriptValue::getMember(name);
|
||||||
if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) {
|
}
|
||||||
return value.at(index);
|
}
|
||||||
} else {
|
ScriptValueP ScriptCustomCollection::getIndex(int index) const {
|
||||||
return ScriptValue::getMember(name);
|
if (index >= 0 && (size_t)index < value.size()) {
|
||||||
}
|
return value.at(index);
|
||||||
|
} else {
|
||||||
|
return ScriptValue::getIndex(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ScriptValueP ScriptCustomCollection::makeIterator(const ScriptValueP& thisP) const {
|
ScriptValueP ScriptCustomCollection::makeIterator(const ScriptValueP& thisP) const {
|
||||||
@@ -381,6 +398,14 @@ ScriptValueP ScriptConcatCollection::getMember(const String& name) const {
|
|||||||
return b->getMember(name);
|
return b->getMember(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ScriptValueP ScriptConcatCollection::getIndex(int index) const {
|
||||||
|
int itemsInA = a->itemCount();
|
||||||
|
if (index < itemsInA) {
|
||||||
|
return a->getIndex(index);
|
||||||
|
} else {
|
||||||
|
return b->getIndex(index - itemsInA);
|
||||||
|
}
|
||||||
|
}
|
||||||
ScriptValueP ScriptConcatCollection::makeIterator(const ScriptValueP& thisP) const {
|
ScriptValueP ScriptConcatCollection::makeIterator(const ScriptValueP& thisP) const {
|
||||||
return new_intrusive2<ScriptConcatCollectionIterator>(a->makeIterator(a), b->makeIterator(b));
|
return new_intrusive2<ScriptConcatCollectionIterator>(a->makeIterator(a), b->makeIterator(b));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ class ScriptValue : public IntrusivePtrBaseWithDelete {
|
|||||||
virtual ScriptValueP next();
|
virtual ScriptValueP next();
|
||||||
/// Return the number of items in this value (assuming it is a collection)
|
/// Return the number of items in this value (assuming it is a collection)
|
||||||
virtual int itemCount() const;
|
virtual int itemCount() const;
|
||||||
|
/// Get a member at the given index
|
||||||
|
virtual ScriptValueP getIndex(int index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ScriptValueP script_nil; ///< The preallocated nil value
|
extern ScriptValueP script_nil; ///< The preallocated nil value
|
||||||
|
|||||||
Reference in New Issue
Block a user