Be more strict about type conversion:

* numbers are no longer auto converted to booleans, use to_boolean or != 0
  * booleans are no longer auto converted to numbers, use to_int
  * strings will soon no longer be auto converted to numbers, use to_int

Added version information ("since 0.3.7") to documentation

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1006 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2008-06-28 13:34:57 +00:00
parent ba2665eb49
commit fe2e3fb9c8
29 changed files with 693 additions and 33 deletions
+9 -4
View File
@@ -63,7 +63,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
}
// Conditional jump
case I_JUMP_IF_NOT: {
int condition = *stack.back();
bool condition = *stack.back();
stack.pop_back();
if (!condition) {
instr = &script.instructions[i.data];
@@ -322,6 +322,11 @@ class ScriptCompose : public ScriptValue {
a = to_script((int)*a OP (int)*b); \
break
// operator on bools
#define OPERATOR_B(OP) \
a = to_script((bool)*a OP (bool)*b); \
break
// operator on doubles or ints
#define OPERATOR_DI(OP) \
if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) { \
@@ -392,9 +397,9 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP&
a = to_script((int)*a % (int)*b);
}
break;
case I_AND: OPERATOR_I(&&);
case I_OR: OPERATOR_I(||);
case I_XOR: a = to_script((bool)*a != (bool)*b); break;
case I_AND: OPERATOR_B(&&);
case I_OR: OPERATOR_B(||);
case I_XOR: OPERATOR_B(!=);
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(<);
+1
View File
@@ -78,6 +78,7 @@ class ScriptMissingVariable : public ScriptValue {
virtual operator String() const { return wxEmptyString; }
virtual operator double() const { return 0.0; }
virtual operator int() const { return 0; }
virtual operator bool() const { return false; }
virtual ScriptValueP eval(Context&) const { return script_nil; } // nil() == nil
private:
String name; ///< Name of the variable
+76 -14
View File
@@ -37,6 +37,75 @@ SCRIPT_FUNCTION(warning) {
return script_nil;
}
// ----------------------------------------------------------------------------- : Conversion
/// Format the input variable based on a printf like style specification
String format_input(const String& format, Context& ctx) {
String fmt = _("%") + replace_all(format, _("%"), _(""));
// determine type expected by format string
if (format.find_first_of(_("DdIiOoXx")) != String::npos) {
SCRIPT_PARAM_C(int, input);
return String::Format(fmt, input);
} else if (format.find_first_of(_("EeFfGg")) != String::npos) {
SCRIPT_PARAM_C(double, input);
return String::Format(fmt, input);
} else if (format.find_first_of(_("Ss")) != String::npos) {
SCRIPT_PARAM_C(String, input);
return format_string(fmt, input);
} else {
throw ScriptError(_ERROR_1_("unsupported format", format));
}
}
SCRIPT_FUNCTION(to_string) {
ScriptValueP format = ctx.getVariable(SCRIPT_VAR_format);
if (format && format->type() == SCRIPT_STRING) {
// format specifier. Be careful, the built in function 'format' has the same name
SCRIPT_RETURN(format_input(*format, ctx));
} else {
// simple conversion
SCRIPT_PARAM_C(String, input);
SCRIPT_RETURN(input);
}
}
SCRIPT_FUNCTION(to_int) {
ScriptValueP input = ctx.getVariable(SCRIPT_VAR_input);
ScriptType t = input->type();
int result;
if (t == SCRIPT_BOOL) {
result = (bool)*input ? 1 : 0;
} else if (t == SCRIPT_COLOR) {
AColor c = (AColor)*input;
result = (c.Red() + c.Blue() + c.Green()) / 3;
} else {
result = (int)*input;
}
SCRIPT_RETURN(result);
}
SCRIPT_FUNCTION(to_real) {
SCRIPT_PARAM_C(double, input);
SCRIPT_RETURN(input);
}
SCRIPT_FUNCTION(to_boolean) {
ScriptValueP input = ctx.getVariable(SCRIPT_VAR_input);
ScriptType t = input->type();
bool result;
if (t == SCRIPT_INT) {
result = (int)*input != 0;
} else {
result = (bool)*input;
}
SCRIPT_RETURN(result);
}
SCRIPT_FUNCTION(to_color) {
SCRIPT_PARAM_C(AColor, input);
SCRIPT_RETURN(input);
}
// ----------------------------------------------------------------------------- : String stuff
// convert a string to upper case
@@ -95,20 +164,7 @@ SCRIPT_FUNCTION(contains) {
SCRIPT_FUNCTION(format) {
SCRIPT_PARAM_C(String, format);
String fmt = _("%") + replace_all(format, _("%"), _(""));
// determine type expected by format string
if (format.find_first_of(_("DdIiOoXx")) != String::npos) {
SCRIPT_PARAM_C(int, input);
SCRIPT_RETURN(String::Format(fmt, input));
} else if (format.find_first_of(_("EeFfGg")) != String::npos) {
SCRIPT_PARAM_C(double, input);
SCRIPT_RETURN(String::Format(fmt, input));
} else if (format.find_first_of(_("Ss")) != String::npos) {
SCRIPT_PARAM_C(String, input);
SCRIPT_RETURN(format_string(fmt, input));
} else {
throw ScriptError(_ERROR_1_("unsupported format", format));
}
SCRIPT_RETURN(format_input(format,ctx));
}
SCRIPT_FUNCTION(curly_quotes) {
@@ -394,6 +450,12 @@ SCRIPT_FUNCTION(rule) {
void init_script_basic_functions(Context& ctx) {
// debugging
ctx.setVariable(_("trace"), script_trace);
// conversion
ctx.setVariable(_("to string"), script_to_string);
ctx.setVariable(_("to int"), script_to_int);
ctx.setVariable(_("to real"), script_to_real);
ctx.setVariable(_("to boolean"), script_to_boolean);
ctx.setVariable(_("to color"), script_to_color);
// string
ctx.setVariable(_("to upper"), script_to_upper);
ctx.setVariable(_("to lower"), script_to_lower);
+1
View File
@@ -419,4 +419,5 @@ void init_script_export_functions(Context& ctx) {
ctx.setVariable(_("copy file"), script_copy_file);
ctx.setVariable(_("write text file"), script_write_text_file);
ctx.setVariable(_("write image file"), script_write_image_file);
//ctx.setVariable(_("write set file"), script_write_set_file);//TODO
}
+6
View File
@@ -29,6 +29,11 @@ template <> inline GeneratedImageP from_script<GeneratedImageP>(const ScriptValu
return image_from_script(value);
}
SCRIPT_FUNCTION(to_image) {
SCRIPT_PARAM_C(GeneratedImageP, input);
return input;
}
// ----------------------------------------------------------------------------- : Image functions
SCRIPT_FUNCTION(linear_blend) {
@@ -181,6 +186,7 @@ SCRIPT_FUNCTION(built_in_image) {
// ----------------------------------------------------------------------------- : Init
void init_script_image_functions(Context& ctx) {
ctx.setVariable(_("to image"), script_to_image);
ctx.setVariable(_("linear blend"), script_linear_blend);
ctx.setVariable(_("masked blend"), script_masked_blend);
ctx.setVariable(_("combine blend"), script_combine_blend);
+1 -1
View File
@@ -23,7 +23,7 @@ DECLARE_TYPEOF_COLLECTION(ScriptParseError);
void store(const ScriptValueP& val, String& var) { var = val->toString(); }
void store(const ScriptValueP& val, int& var) { var = *val; }
void store(const ScriptValueP& val, double& var) { var = *val; }
void store(const ScriptValueP& val, bool& var) { var = static_cast<int>(*val); }
void store(const ScriptValueP& val, bool& var) { var = *val; }
void store(const ScriptValueP& val, Color& var) { var = (AColor)*val; }
void store(const ScriptValueP& val, AColor& var) { var = *val; }
void store(const ScriptValueP& val, Defaultable<String>& var) { var.assign(*val); }
+2
View File
@@ -60,6 +60,7 @@ class ScriptDelayedError : public ScriptValue {
virtual operator String() const;
virtual operator double() const;
virtual operator int() const;
virtual operator bool() const;
virtual operator AColor() const;
virtual int itemCount() const;
virtual CompareWhat compareAs(String&, void const*&) const;
@@ -243,6 +244,7 @@ class ScriptObject : public ScriptValue {
virtual operator String() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator String(); }
virtual operator double() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator double(); }
virtual operator int() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator int(); }
virtual operator bool() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator bool(); }
virtual operator AColor() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator AColor(); }
virtual ScriptValueP getMember(const String& name) const {
GetMember gm(name);
+16 -5
View File
@@ -20,6 +20,7 @@ DECLARE_TYPEOF_COLLECTION(pair<Variable COMMA ScriptValueP>);
ScriptValue::operator String() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("string" ))); }
ScriptValue::operator int() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("integer" ))); }
ScriptValue::operator bool() const { throw ScriptError(_ERROR_2_("can't convert", typeName(), _TYPE_("boolean" ))); }
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" ))); }
ScriptValueP ScriptValue::eval(Context&) const { return delayError(_ERROR_2_("can't convert", typeName(), _TYPE_("function"))); }
@@ -43,6 +44,8 @@ bool equal(const ScriptValueP& a, const ScriptValueP& b) {
ScriptType at = a->type(), bt = b->type();
if (at == bt && at == SCRIPT_INT) {
return (int)*a == (int)*b;
} else if (at == bt && at == SCRIPT_BOOL) {
return (bool)*a == (bool)*b;
} else if ((at == SCRIPT_INT || at == SCRIPT_DOUBLE) &&
(bt == SCRIPT_INT || bt == SCRIPT_DOUBLE)) {
return (double)*a == (double)*b;
@@ -81,6 +84,7 @@ String ScriptDelayedError::typeName() const { throw error; }
ScriptDelayedError::operator String() const { throw error; }
ScriptDelayedError::operator double() const { throw error; }
ScriptDelayedError::operator int() const { throw error; }
ScriptDelayedError::operator bool() const { throw error; }
ScriptDelayedError::operator AColor() const { throw error; }
int ScriptDelayedError::itemCount() const { throw error; }
CompareWhat ScriptDelayedError::compareAs(String&, void const*&) const { throw error; }
@@ -171,10 +175,11 @@ ScriptValueP to_script(int v) {
class ScriptBool : public ScriptValue {
public:
ScriptBool(bool v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_INT; }
virtual ScriptType type() const { return SCRIPT_BOOL; }
virtual String typeName() const { return _TYPE_("boolean"); }
virtual operator String() const { return value ? _("true") : _("false"); }
virtual operator int() const { return value; }
// bools don't autoconvert to int
virtual operator bool() const { return value; }
private:
bool value;
};
@@ -227,12 +232,17 @@ class ScriptString : public ScriptValue {
long l;
if (value.ToLong(&l)) {
return l;
} else if (value == _("yes") || value == _("true")) {
} else {
throw ScriptError(_ERROR_3_("can't convert value", value, typeName(), _TYPE_("integer")));
}
}
virtual operator bool() const {
if (value == _("yes") || value == _("true")) {
return true;
} else if (value == _("no") || value == _("false") || value.empty()) {
return false;
} else {
throw ScriptError(_ERROR_3_("can't convert value", value, typeName(), _TYPE_("integer")));
throw ScriptError(_ERROR_3_("can't convert value", value, typeName(), _TYPE_("boolean")));
}
}
virtual operator AColor() const {
@@ -270,7 +280,7 @@ class ScriptAColor : public ScriptValue {
virtual ScriptType type() const { return SCRIPT_COLOR; }
virtual String typeName() const { return _TYPE_("color"); }
virtual operator AColor() const { return value; }
virtual operator int() const { return (value.Red() + value.Blue() + value.Green()) / 3; }
// colors don't auto convert to int, use to_int to force
virtual operator String() const {
return format_acolor(value);
}
@@ -296,6 +306,7 @@ class ScriptNil : public ScriptValue {
virtual operator String() const { return wxEmptyString; }
virtual operator double() const { return 0.0; }
virtual operator int() const { return 0; }
virtual operator bool() const { return false; }
virtual ScriptValueP eval(Context&) const { return script_nil; } // nil() == nil
};
+2 -1
View File
@@ -22,6 +22,7 @@ DECLARE_POINTER_TYPE(ScriptValue);
enum ScriptType
{ SCRIPT_NIL
, SCRIPT_INT
, SCRIPT_BOOL
, SCRIPT_DOUBLE
, SCRIPT_STRING
, SCRIPT_COLOR
@@ -62,7 +63,7 @@ class ScriptValue : public IntrusivePtrBaseWithDelete {
/// Convert this value to an integer
virtual operator int() const;
/// Convert this value to a boolean
inline operator bool() const { return (int)*this; }
virtual operator bool() const;
/// Convert this value to a color
virtual operator AColor() const;