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
+1
View File
@@ -649,6 +649,7 @@ KeywordParamValue::operator String() const {
KeywordParamValue::operator int() const { return *to_script(value); } // a bit of a hack
KeywordParamValue::operator double() const { return *to_script(value); }
KeywordParamValue::operator bool() const { return *to_script(value); }
KeywordParamValue::operator AColor() const { return *to_script(value); }
int KeywordParamValue::itemCount() const { return to_script(value)->itemCount(); }
+1
View File
@@ -176,6 +176,7 @@ class KeywordParamValue : public ScriptValue {
virtual String typeName() const;
virtual operator String() const;
virtual operator int() const;
virtual operator bool() const;
virtual operator double() const;
virtual operator AColor() const;
virtual int itemCount() const;
+414
View File
@@ -3399,6 +3399,420 @@
</File>
</Filter>
</Filter>
<Filter
Name="doc"
Filter="">
<Filter
Name="about"
Filter="">
</Filter>
<Filter
Name="file"
Filter="">
<File
RelativePath="..\doc\file\format.txt">
</File>
<File
RelativePath="..\doc\file\index.txt">
</File>
<File
RelativePath="..\doc\file\package.txt">
</File>
<File
RelativePath="..\doc\file\style_triangle.txt">
</File>
</Filter>
<Filter
Name="script"
Filter="">
<File
RelativePath="..\doc\script\best_practices.txt">
</File>
<File
RelativePath="..\doc\script\control_structures.txt">
</File>
<File
RelativePath="..\doc\script\default_arguments.txt">
</File>
<File
RelativePath="..\doc\script\functions.txt">
</File>
<File
RelativePath="..\doc\script\index.txt">
</File>
<File
RelativePath="..\doc\script\introduction.txt">
</File>
<File
RelativePath="..\doc\script\operators.txt">
</File>
<File
RelativePath="..\doc\script\predefined_variables.txt">
</File>
<File
RelativePath="..\doc\script\variables.txt">
</File>
</Filter>
<Filter
Name="function"
Filter="">
<File
RelativePath="..\doc\function\assert.txt">
</File>
<File
RelativePath="..\doc\function\break_text.txt">
</File>
<File
RelativePath="..\doc\function\built_in_image.txt">
</File>
<File
RelativePath="..\doc\function\chosen.txt">
</File>
<File
RelativePath="..\doc\function\combine_blend.txt">
</File>
<File
RelativePath="..\doc\function\combined_editor.txt">
</File>
<File
RelativePath="..\doc\function\contains.txt">
</File>
<File
RelativePath="..\doc\function\copy_file.txt">
</File>
<File
RelativePath="..\doc\function\crop.txt">
</File>
<File
RelativePath="..\doc\function\curly_quotes.txt">
</File>
<File
RelativePath="..\doc\function\drop_shadow.txt">
</File>
<File
RelativePath="..\doc\function\english_number.txt">
</File>
<File
RelativePath="..\doc\function\english_plural.txt">
</File>
<File
RelativePath="..\doc\function\enlarge.txt">
</File>
<File
RelativePath="..\doc\function\exclusive_choice.txt">
</File>
<File
RelativePath="..\doc\function\expand_keywords.txt">
</File>
<File
RelativePath="..\doc\function\filter_list.txt">
</File>
<File
RelativePath="..\doc\function\filter_text.txt">
</File>
<File
RelativePath="..\doc\function\format.txt">
</File>
<File
RelativePath="..\doc\function\index.txt">
</File>
<File
RelativePath="..\doc\function\keyword_usage.txt">
</File>
<File
RelativePath="..\doc\function\length.txt">
</File>
<File
RelativePath="..\doc\function\linear_blend.txt">
</File>
<File
RelativePath="..\doc\function\masked_blend.txt">
</File>
<File
RelativePath="..\doc\function\match.txt">
</File>
<File
RelativePath="..\doc\function\number_of_items.txt">
</File>
<File
RelativePath="..\doc\function\position.txt">
</File>
<File
RelativePath="..\doc\function\primary_choice.txt">
</File>
<File
RelativePath="..\doc\function\process_english_hints.txt">
</File>
<File
RelativePath="..\doc\function\regex_escape.txt">
</File>
<File
RelativePath="..\doc\function\remove_choice.txt">
</File>
<File
RelativePath="..\doc\function\remove_tag.txt">
</File>
<File
RelativePath="..\doc\function\remove_tags.txt">
</File>
<File
RelativePath="..\doc\function\replace.txt">
</File>
<File
RelativePath="..\doc\function\require_choice.txt">
</File>
<File
RelativePath="..\doc\function\require_exclusive_choice.txt">
</File>
<File
RelativePath="..\doc\function\reverse.txt">
</File>
<File
RelativePath="..\doc\function\saturate.txt">
</File>
<File
RelativePath="..\doc\function\set_alpha.txt">
</File>
<File
RelativePath="..\doc\function\set_combine.txt">
</File>
<File
RelativePath="..\doc\function\set_mask.txt">
</File>
<File
RelativePath="..\doc\function\sort_list.txt">
</File>
<File
RelativePath="..\doc\function\sort_text.txt">
</File>
<File
RelativePath="..\doc\function\substring.txt">
</File>
<File
RelativePath="..\doc\function\symbol_variation.txt">
</File>
<File
RelativePath="..\doc\function\symbols_to_html.txt">
</File>
<File
RelativePath="..\doc\function\tag_contents.txt">
</File>
<File
RelativePath="..\doc\function\to_boolean.txt">
</File>
<File
RelativePath="..\doc\function\to_color.txt">
</File>
<File
RelativePath="..\doc\function\to_html.txt">
</File>
<File
RelativePath="..\doc\function\to_int.txt">
</File>
<File
RelativePath="..\doc\function\to_lower.txt">
</File>
<File
RelativePath="..\doc\function\to_real.txt">
</File>
<File
RelativePath="..\doc\function\to_string.txt">
</File>
<File
RelativePath="..\doc\function\to_text.txt">
</File>
<File
RelativePath="..\doc\function\to_title.txt">
</File>
<File
RelativePath="..\doc\function\to_upper.txt">
</File>
<File
RelativePath="..\doc\function\trace.txt">
</File>
<File
RelativePath="..\doc\function\trim.txt">
</File>
<File
RelativePath="..\doc\function\write_image_file.txt">
</File>
<File
RelativePath="..\doc\function\write_text_file.txt">
</File>
</Filter>
<Filter
Name="type"
Filter="">
<File
RelativePath="..\doc\type\alignment.txt">
</File>
<File
RelativePath="..\doc\type\boolean.txt">
</File>
<File
RelativePath="..\doc\type\card.txt">
</File>
<File
RelativePath="..\doc\type\choice.txt">
</File>
<File
RelativePath="..\doc\type\choice_render_style.txt">
</File>
<File
RelativePath="..\doc\type\color.txt">
</File>
<File
RelativePath="..\doc\type\color_choice.txt">
</File>
<File
RelativePath="..\doc\type\combine.txt">
</File>
<File
RelativePath="..\doc\type\control_point.txt">
</File>
<File
RelativePath="..\doc\type\dependency.txt">
</File>
<File
RelativePath="..\doc\type\direction.txt">
</File>
<File
RelativePath="..\doc\type\double.txt">
</File>
<File
RelativePath="..\doc\type\export_template.txt">
</File>
<File
RelativePath="..\doc\type\field.txt">
</File>
<File
RelativePath="..\doc\type\filename.txt">
</File>
<File
RelativePath="..\doc\type\font.txt">
</File>
<File
RelativePath="..\doc\type\function.txt">
</File>
<File
RelativePath="..\doc\type\game.txt">
</File>
<File
RelativePath="..\doc\type\graph_type.txt">
</File>
<File
RelativePath="..\doc\type\image.txt">
</File>
<File
RelativePath="..\doc\type\include.txt">
</File>
<File
RelativePath="..\doc\type\index.txt">
</File>
<File
RelativePath="..\doc\type\indexmap.txt">
</File>
<File
RelativePath="..\doc\type\insert_symbol_menu.txt">
</File>
<File
RelativePath="..\doc\type\installer.txt">
</File>
<File
RelativePath="..\doc\type\int.txt">
</File>
<File
RelativePath="..\doc\type\keyword.txt">
</File>
<File
RelativePath="..\doc\type\keyword_mode.txt">
</File>
<File
RelativePath="..\doc\type\keyword_param_reference_script.txt">
</File>
<File
RelativePath="..\doc\type\keyword_param_type.txt">
</File>
<File
RelativePath="..\doc\type\list.txt">
</File>
<File
RelativePath="..\doc\type\locale.txt">
</File>
<File
RelativePath="..\doc\type\map.txt">
</File>
<File
RelativePath="..\doc\type\regex.txt">
</File>
<File
RelativePath="..\doc\type\script.txt">
</File>
<File
RelativePath="..\doc\type\scriptable.txt">
</File>
<File
RelativePath="..\doc\type\set.txt">
</File>
<File
RelativePath="..\doc\type\settings.txt">
</File>
<File
RelativePath="..\doc\type\statistics_category.txt">
</File>
<File
RelativePath="..\doc\type\statistics_dimension.txt">
</File>
<File
RelativePath="..\doc\type\string.txt">
</File>
<File
RelativePath="..\doc\type\style.txt">
</File>
<File
RelativePath="..\doc\type\stylesheet.txt">
</File>
<File
RelativePath="..\doc\type\symbol.txt">
</File>
<File
RelativePath="..\doc\type\symbol_combine.txt">
</File>
<File
RelativePath="..\doc\type\symbol_font.txt">
</File>
<File
RelativePath="..\doc\type\symbol_font_reference.txt">
</File>
<File
RelativePath="..\doc\type\symbol_font_symbol.txt">
</File>
<File
RelativePath="..\doc\type\symbol_part.txt">
</File>
<File
RelativePath="..\doc\type\symbol_variation.txt">
</File>
<File
RelativePath="..\doc\type\tagged_string.txt">
</File>
<File
RelativePath="..\doc\type\value.txt">
</File>
<File
RelativePath="..\doc\type\vector2d.txt">
</File>
<File
RelativePath="..\doc\type\version.txt">
</File>
<File
RelativePath="..\doc\type\word_list.txt">
</File>
<File
RelativePath="..\doc\type\word_list_word.txt">
</File>
</Filter>
</Filter>
<File
RelativePath=".\code_template.cpp">
<FileConfiguration
+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;