From 2e897edbbfb348151ad801943047350e50ad710a Mon Sep 17 00:00:00 2001 From: Twan van Laarhoven Date: Sun, 26 Apr 2020 17:03:43 +0200 Subject: [PATCH] Use toSomeType() instead of operator SomeType in ScriptValue. This means that we are more explicit about type conversions. Also use override specifiers for overriden virtual functions in ScriptValue. --- src/data/keyword.cpp | 21 ++- src/data/keyword.hpp | 18 +- src/data/pack.cpp | 2 +- src/data/set.cpp | 6 +- src/gfx/generated_image.hpp | 194 ++++++++++---------- src/gui/control/card_list.cpp | 2 +- src/gui/set/console_panel.cpp | 2 +- src/gui/value/choice.cpp | 2 +- src/gui/value/color.cpp | 2 +- src/script/context.cpp | 81 ++++----- src/script/dependency.cpp | 20 +- src/script/functions/basic.cpp | 38 ++-- src/script/functions/construction.cpp | 2 +- src/script/functions/regex.cpp | 2 +- src/script/functions/spelling.cpp | 4 +- src/script/functions/util.hpp | 46 ++--- src/script/script.cpp | 2 +- src/script/script.hpp | 13 +- src/script/scriptable.cpp | 12 +- src/script/to_value.hpp | 253 +++++++++++++------------- src/script/value.cpp | 250 +++++++++++++++---------- src/script/value.hpp | 42 ++--- 22 files changed, 524 insertions(+), 490 deletions(-) diff --git a/src/data/keyword.cpp b/src/data/keyword.cpp index 331e123d..4fd31ee4 100644 --- a/src/data/keyword.cpp +++ b/src/data/keyword.cpp @@ -665,7 +665,7 @@ bool KeywordDatabase::tryExpand(const Keyword& kw, ctx.setVariable(_("used_placeholders"), to_script(used_placeholders)); // Final check whether the keyword matches - if (match_condition && (bool)*match_condition->eval(ctx) == false) { + if (match_condition && match_condition->eval(ctx)->toBool() == false) { return false; } @@ -673,7 +673,7 @@ bool KeywordDatabase::tryExpand(const Keyword& kw, bool expand = expand_type == _('1'); if (!expand && expand_type != _('0')) { // default expand, determined by script - expand = expand_default ? (bool)*expand_default->eval(ctx) : true; + expand = expand_default ? expand_default->eval(ctx)->toBool() : true; expand_type = expand ? _('A') : _('a'); } @@ -711,7 +711,7 @@ bool KeywordDatabase::tryExpand(const Keyword& kw, ScriptType KeywordParamValue::type() const { return SCRIPT_STRING; } String KeywordParamValue::typeName() const { return _("keyword parameter"); } -KeywordParamValue::operator String() const { +String KeywordParamValue::toString() const { String safe_type = replace_all(replace_all(replace_all(type_name, _("("),_("-")), _(")"),_("-")), @@ -719,16 +719,17 @@ KeywordParamValue::operator String() const { return _("") + value + _(""); } -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 Color() const { return *to_script(value); } -int KeywordParamValue::itemCount() const { return to_script(value)->itemCount(); } +// a bit of a hack: use the ScriptString implementation +int KeywordParamValue::toInt() const { return to_script(value)->toInt(); } +double KeywordParamValue::toDouble() const { return to_script(value)->toDouble(); } +bool KeywordParamValue::toBool() const { return to_script(value)->toBool(); } +Color KeywordParamValue::toColor() const { return to_script(value)->toColor(); } +int KeywordParamValue::itemCount() const { return to_script(value)->itemCount(); } ScriptValueP KeywordParamValue::getMember(const String& name) const { if (name == _("type")) return to_script(type_name); - if (name == _("separator before")) return to_script(separator_before); - if (name == _("separator after")) return to_script(separator_after); + if (name == _("separator_before")) return to_script(separator_before); + if (name == _("separator_after")) return to_script(separator_after); if (name == _("value")) return to_script(value); if (name == _("param")) return to_script(value); return ScriptValue::getMember(name); diff --git a/src/data/keyword.hpp b/src/data/keyword.hpp index 0a63550b..86db69c7 100644 --- a/src/data/keyword.hpp +++ b/src/data/keyword.hpp @@ -190,14 +190,14 @@ class KeywordParamValue : public ScriptValue { String separator_before, separator_after; String value; - virtual ScriptType type() const; - virtual String typeName() const; - virtual operator String() const; - virtual operator int() const; - virtual operator bool() const; - virtual operator double() const; - virtual operator Color() const; - virtual int itemCount() const; - virtual ScriptValueP getMember(const String& name) const; + ScriptType type() const override; + String typeName() const override; + String toString() const override; + int toInt() const override; + bool toBool() const override; + double toDouble() const override; + Color toColor() const override; + int itemCount() const override; + ScriptValueP getMember(const String& name) const override; }; diff --git a/src/data/pack.cpp b/src/data/pack.cpp index 1cdd3a4e..755e5478 100644 --- a/src/data/pack.cpp +++ b/src/data/pack.cpp @@ -111,7 +111,7 @@ PackInstance::PackInstance(const PackType& pack_type, PackGenerator& parent) if (pack_type.filter) { FOR_EACH(card, parent.set->cards) { Context& ctx = parent.set->getContext(card); - bool keep = *pack_type.filter.invoke(ctx); + bool keep = pack_type.filter.invoke(ctx)->toBool(); if (keep) { cards.push_back(card); } diff --git a/src/data/set.cpp b/src/data/set.cpp index c9739ee3..baee1cd7 100644 --- a/src/data/set.cpp +++ b/src/data/set.cpp @@ -267,9 +267,9 @@ int Set::positionOfCard(const CardP& card, const ScriptValueP& order_by, const S vector keep; if(filter) keep.reserve(cards.size()); FOR_EACH_CONST(c, cards) { Context& ctx = getContext(c); - values.push_back(*order_by->eval(ctx)); + values.push_back(order_by->eval(ctx)->toString()); if (filter) { - keep.push_back((bool)*filter->eval(ctx)); + keep.push_back(filter->eval(ctx)->toBool()); } } #if USE_SCRIPT_PROFILING @@ -289,7 +289,7 @@ int Set::numberOfCards(const ScriptValueP& filter) { } else { int n = 0; FOR_EACH_CONST(c, cards) { - if (*filter->eval(getContext(c))) ++n; + if (filter->eval(getContext(c))->toBool()) ++n; } filter_cache.insert(make_pair(filter,n)); return n; diff --git a/src/gfx/generated_image.hpp b/src/gfx/generated_image.hpp index cf8b1bd9..e76e5fbb 100644 --- a/src/gfx/generated_image.hpp +++ b/src/gfx/generated_image.hpp @@ -59,9 +59,9 @@ class GeneratedImage : public ScriptValue { /// Is this image blank? virtual bool isBlank() const { return false; } - virtual ScriptType type() const; - virtual String typeName() const; - virtual GeneratedImageP toImage(const ScriptValueP& thisP) const; + ScriptType type() const override; + String typeName() const override; + GeneratedImageP toImage(const ScriptValueP& thisP) const override; }; /// Resize an image to conform to the options @@ -71,13 +71,13 @@ Image conform_image(const Image&, const GeneratedImage::Options&); /// Apply some filter to a single image class SimpleFilterImage : public GeneratedImage { - public: +public: inline SimpleFilterImage(const GeneratedImageP& image) : image(image) {} - virtual ImageCombine combine() const { return image->combine(); } - virtual bool local() const { return image->local(); } - protected: + ImageCombine combine() const override { return image->combine(); } + bool local() const override { return image->local(); } +protected: GeneratedImageP image; }; @@ -85,14 +85,14 @@ class SimpleFilterImage : public GeneratedImage { /// An image generator that returns a blank image class BlankImage : public GeneratedImage { - public: - virtual Image generate(const Options&) const; - virtual bool operator == (const GeneratedImage& that) const; - virtual bool isBlank() const { return true; } +public: + Image generate(const Options&) const override; + bool operator == (const GeneratedImage& that) const override; + bool isBlank() const override { return true; } // Why is this not thread safe? What is GTK smoking? #ifdef __WXGTK__ - virtual bool threadSafe() const { return false; } + bool threadSafe() const override { return false; } #endif }; @@ -100,15 +100,15 @@ class BlankImage : public GeneratedImage { /// An image generator that linearly blends two other images class LinearBlendImage : public GeneratedImage { - public: +public: inline LinearBlendImage(const GeneratedImageP& image1, const GeneratedImageP& image2, double x1, double y1, double x2, double y2) : image1(image1), image2(image2), x1(x1), y1(y1), x2(x2), y2(y2) {} - virtual Image generate(const Options& opt) const; - virtual ImageCombine combine() const; - virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return image1->local() && image2->local(); } - private: + Image generate(const Options& opt) const override; + ImageCombine combine() const override; + bool operator == (const GeneratedImage& that) const override; + bool local() const override { return image1->local() && image2->local(); } +private: GeneratedImageP image1, image2; double x1, y1, x2, y2; }; @@ -117,15 +117,15 @@ class LinearBlendImage : public GeneratedImage { /// An image generator that blends two other images using a third as a mask class MaskedBlendImage : public GeneratedImage { - public: +public: inline MaskedBlendImage(const GeneratedImageP& light, const GeneratedImageP& dark, const GeneratedImageP& mask) : light(light), dark(dark), mask(mask) {} - virtual Image generate(const Options& opt) const; - virtual ImageCombine combine() const; - virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return light->local() && dark->local() && mask->local(); } - private: + Image generate(const Options& opt) const override; + ImageCombine combine() const override; + bool operator == (const GeneratedImage& that) const override; + bool local() const override { return light->local() && dark->local() && mask->local(); } +private: GeneratedImageP light, dark, mask; }; @@ -133,15 +133,15 @@ class MaskedBlendImage : public GeneratedImage { /// An image generator that blends two other images using an ImageCombine function class CombineBlendImage : public GeneratedImage { - public: +public: inline CombineBlendImage(const GeneratedImageP& image1, const GeneratedImageP& image2, ImageCombine image_combine) : image1(image1), image2(image2), image_combine(image_combine) {} - virtual Image generate(const Options& opt) const; - virtual ImageCombine combine() const; - virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return image1->local() && image2->local(); } - private: + Image generate(const Options& opt) const override; + ImageCombine combine() const override; + bool operator == (const GeneratedImage& that) const override; + bool local() const override { return image1->local() && image2->local(); } +private: GeneratedImageP image1, image2; ImageCombine image_combine; }; @@ -150,25 +150,25 @@ class CombineBlendImage : public GeneratedImage { /// Change the alpha channel of an image class SetMaskImage : public SimpleFilterImage { - public: +public: inline SetMaskImage(const GeneratedImageP& image, const GeneratedImageP& mask) : SimpleFilterImage(image), mask(mask) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: GeneratedImageP mask; }; /// Change the alpha channel of an image class SetAlphaImage : public SimpleFilterImage { - public: +public: inline SetAlphaImage(const GeneratedImageP& image, double alpha) : SimpleFilterImage(image), alpha(alpha) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: double alpha; }; @@ -176,14 +176,14 @@ class SetAlphaImage : public SimpleFilterImage { /// Change the combine mode class SetCombineImage : public SimpleFilterImage { - public: +public: inline SetCombineImage(const GeneratedImageP& image, ImageCombine image_combine) : SimpleFilterImage(image), image_combine(image_combine) {} - virtual Image generate(const Options& opt) const; - virtual ImageCombine combine() const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + ImageCombine combine() const override; + bool operator == (const GeneratedImage& that) const override; +private: ImageCombine image_combine; }; @@ -191,13 +191,13 @@ class SetCombineImage : public SimpleFilterImage { /// Saturate/desaturate an image class SaturateImage : public SimpleFilterImage { - public: +public: inline SaturateImage(const GeneratedImageP& image, double amount) : SimpleFilterImage(image), amount(amount) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: double amount; }; @@ -205,36 +205,36 @@ class SaturateImage : public SimpleFilterImage { /// Invert an image class InvertImage : public SimpleFilterImage { - public: +public: inline InvertImage(const GeneratedImageP& image) : SimpleFilterImage(image) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; }; // ----------------------------------------------------------------------------- : RecolorImage /// Recolor an image class RecolorImage : public SimpleFilterImage { - public: +public: inline RecolorImage(const GeneratedImageP& image, Color color) : SimpleFilterImage(image), color(color) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: Color color; }; /// Recolor an image, with custom colors class RecolorImage2 : public SimpleFilterImage { - public: +public: inline RecolorImage2(const GeneratedImageP& image, Color red, Color green, Color blue, Color white) : SimpleFilterImage(image), red(red), green(green), blue(blue), white(white) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: Color red,green,blue,white; }; @@ -246,29 +246,29 @@ class FlipImageHorizontal : public SimpleFilterImage { inline FlipImageHorizontal(const GeneratedImageP& image) : SimpleFilterImage(image) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; }; /// Flip an image vertically class FlipImageVertical : public SimpleFilterImage { - public: +public: inline FlipImageVertical(const GeneratedImageP& image) : SimpleFilterImage(image) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; }; /// Rotate an image class RotateImage : public SimpleFilterImage { - public: +public: inline RotateImage(const GeneratedImageP& image, Radians angle) : SimpleFilterImage(image), angle(angle) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: Radians angle; }; @@ -276,13 +276,13 @@ class RotateImage : public SimpleFilterImage { /// Enlarge an image by adding a border around it class EnlargeImage : public SimpleFilterImage { - public: +public: inline EnlargeImage(const GeneratedImageP& image, double border_size) : SimpleFilterImage(image), border_size(fabs(border_size)) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: double border_size; }; @@ -290,13 +290,13 @@ class EnlargeImage : public SimpleFilterImage { /// Crop an image at a certain point, to a certain size class CropImage : public SimpleFilterImage { - public: +public: inline CropImage(const GeneratedImageP& image, double width, double height, double offset_x, double offset_y) : SimpleFilterImage(image), width(width), height(height), offset_x(offset_x), offset_y(offset_y) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: double width, height; double offset_x, offset_y; }; @@ -305,14 +305,14 @@ class CropImage : public SimpleFilterImage { /// Add a drop shadow to an image class DropShadowImage : public SimpleFilterImage { - public: +public: inline DropShadowImage(const GeneratedImageP& image, double offset_x, double offset_y, double shadow_alpha, double shadow_blur_radius, Color shadow_color) : SimpleFilterImage(image), offset_x(offset_x), offset_y(offset_y) , shadow_alpha(shadow_alpha), shadow_blur_radius(shadow_blur_radius), shadow_color(shadow_color) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: double offset_x, offset_y; double shadow_alpha; double shadow_blur_radius; @@ -323,13 +323,13 @@ class DropShadowImage : public SimpleFilterImage { /// Load an image from a file in a package class PackagedImage : public GeneratedImage { - public: +public: inline PackagedImage(const String& filename) : filename(filename) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: String filename; }; @@ -341,9 +341,9 @@ class BuiltInImage : public GeneratedImage { inline BuiltInImage(const String& name) : name(name) {} - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; +private: String name; }; @@ -351,17 +351,17 @@ class BuiltInImage : public GeneratedImage { /// Use a symbol as an image class SymbolToImage : public GeneratedImage { - public: +public: SymbolToImage(bool is_local, const String& filename, Age age, const SymbolVariationP& variation); ~SymbolToImage(); - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return is_local; } + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; + bool local() const override { return is_local; } #ifdef __WXGTK__ - virtual bool threadSafe() const { return false; } + bool threadSafe() const override { return false; } #endif - private: +private: SymbolToImage(const SymbolToImage&); // copy ctor bool is_local; ///< Use local package? String filename; @@ -373,13 +373,13 @@ class SymbolToImage : public GeneratedImage { /// Use an image from an ImageValue as an image class ImageValueToImage : public GeneratedImage { - public: +public: ImageValueToImage(const String& filename, Age age); ~ImageValueToImage(); - virtual Image generate(const Options& opt) const; - virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return true; } - private: + Image generate(const Options& opt) const override; + bool operator == (const GeneratedImage& that) const override; + bool local() const override { return true; } +private: ImageValueToImage(const ImageValueToImage&); // copy ctor String filename; Age age; ///< Age the symbol was last updated diff --git a/src/gui/control/card_list.cpp b/src/gui/control/card_list.cpp index 4b4c41d1..37d34073 100644 --- a/src/gui/control/card_list.cpp +++ b/src/gui/control/card_list.cpp @@ -319,7 +319,7 @@ int CardListBase::OnGetItemImage(long pos) const { wxListItemAttr* CardListBase::OnGetItemAttr(long pos) const { if (!set->game->card_list_color_script) return nullptr; Context& ctx = set->getContext(getCard(pos)); - item_attr.SetTextColour(*set->game->card_list_color_script.invoke(ctx)); + item_attr.SetTextColour(set->game->card_list_color_script.invoke(ctx)->toColor()); return &item_attr; } diff --git a/src/gui/set/console_panel.cpp b/src/gui/set/console_panel.cpp index d18eb063..93de5023 100644 --- a/src/gui/set/console_panel.cpp +++ b/src/gui/set/console_panel.cpp @@ -508,7 +508,7 @@ void ConsolePanel::exec(String const& command) { message->bitmap = wxBitmap(image); } else if (type == SCRIPT_COLOR) { message->text = result->toCode(); - Color color = result->operator Color(); + Color color = result->toColor(); wxImage image(30,20); fill_image(image,color); set_alpha(image, color.Alpha() / 255.0); diff --git a/src/gui/value/choice.cpp b/src/gui/value/choice.cpp index a830a33e..b7a8e5cd 100644 --- a/src/gui/value/choice.cpp +++ b/src/gui/value/choice.cpp @@ -253,7 +253,7 @@ size_t DropDownChoiceList::selection() const { return 0; } else { // run default script to find out what the default choice would be - String default_choice = *field().default_script.invoke( cve.viewer.getContext() ); + String default_choice = field().default_script.invoke( cve.viewer.getContext() )->toString(); default_id = group->choiceId(default_choice); } } diff --git a/src/gui/value/color.cpp b/src/gui/value/color.cpp index 6dcb0558..f5e67a6a 100644 --- a/src/gui/value/color.cpp +++ b/src/gui/value/color.cpp @@ -107,7 +107,7 @@ size_t DropDownColorList::selection() const { return 0; } else if (hasDefault()) { // evaluate script to find default color - default_color = *field().default_script.invoke(cve.viewer.getContext()); + default_color = field().default_script.invoke(cve.viewer.getContext())->toColor(); } return selection; } diff --git a/src/script/context.cpp b/src/script/context.cpp index 844e9264..a5d1f557 100644 --- a/src/script/context.cpp +++ b/src/script/context.cpp @@ -67,7 +67,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) { } // Conditional jump case I_JUMP_IF_NOT: { - bool condition = *stack.back(); + bool condition = stack.back()->toBool(); stack.pop_back(); if (!condition) { instr = &script.instructions[0] + i.data; @@ -76,7 +76,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) { } // Short-circuiting and/or = conditional jump without pop case I_JUMP_SC_AND: { - bool condition = *stack.back(); + bool condition = stack.back()->toBool(); if (!condition) { instr = &script.instructions[0] + i.data; } else { @@ -85,7 +85,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) { break; } case I_JUMP_SC_OR: { - bool condition = *stack.back(); + bool condition = stack.back()->toBool(); if (condition) { instr = &script.instructions[0] + i.data; } else { @@ -109,7 +109,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) { // Get an object member case I_MEMBER_C: { - stack.back() = stack.back()->getMember(*script.constants[i.data]); + stack.back() = stack.back()->getMember(script.constants[i.data]->toString()); break; } // Loop over a container, push next value or jump @@ -367,13 +367,13 @@ void instrUnary(UnaryInstructionType i, ScriptValueP& a) { case I_NEGATE: { ScriptType at = a->type(); if (at == SCRIPT_DOUBLE) { - a = to_script(-(double)*a); + a = to_script(-a->toDouble()); } else { - a = to_script(-(int)*a); + a = to_script(-a->toInt()); } break; } case I_NOT: - a = to_script(!(bool)*a); + a = to_script(!a->toBool()); break; } } @@ -382,19 +382,18 @@ void instrUnary(UnaryInstructionType i, ScriptValueP& a) { /// Composition of two functions class ScriptCompose : public ScriptValue { - public: +public: ScriptCompose(ScriptValueP a, ScriptValueP b) : a(a), b(b) {} - virtual ScriptType type() const { return SCRIPT_FUNCTION; } - virtual String typeName() const { return _("function composition"); } + ScriptType type() const override { return SCRIPT_FUNCTION; } + String typeName() const override { return _("function composition"); } - virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const { + ScriptValueP dependencies(Context& ctx, const Dependency& dep) const override { ctx.setVariable(SCRIPT_VAR_input, a->dependencies(ctx, dep)); return b->dependencies(ctx, dep); } - protected: - virtual ScriptValueP do_eval(Context& ctx, bool openScope) const { + ScriptValueP eval(Context& ctx, bool openScope) const override { #if USE_SCRIPT_PROFILING Timer timer; { @@ -417,7 +416,7 @@ class ScriptCompose : public ScriptValue { #endif } - private: +private: ScriptValueP a,b; }; @@ -425,29 +424,29 @@ class ScriptCompose : public ScriptValue { // operator on ints #define OPERATOR_I(OP) \ - a = to_script((int)*a OP (int)*b); \ + a = to_script(a->toInt() OP b->toInt()); \ break // operator on bools #define OPERATOR_B(OP) \ - a = to_script((bool)*a OP (bool)*b); \ + a = to_script(a->toBool() OP b->toBool()); \ break // operator on doubles or ints #define OPERATOR_DI(OP) \ if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) { \ - a = to_script((double)*a OP (double)*b); \ + a = to_script(a->toDouble() OP b->toDouble()); \ } else { \ - a = to_script((int)*a OP (int)*b); \ + a = to_script(a->toInt() OP b->toInt()); \ } \ break // operator on doubles or ints, defined as a function #define OPERATOR_FUN_DI(OP) \ if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) { \ - a = to_script(OP((double)*a, (double)*b)); \ + a = to_script(OP(a->toDouble(), b->toDouble())); \ } else { \ - a = to_script(OP((int)*a, (int)*b)); \ + a = to_script(OP(a->toInt(), b->toInt())); \ } \ break @@ -455,10 +454,10 @@ class ScriptCompose : public ScriptValue { void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP& b) { switch (i) { case I_MEMBER: - a = a->getMember(*b); + a = a->getMember(b->toString()); break; case I_ITERATOR_R: - a = rangeIterator(*a, *b); + a = rangeIterator(a->toInt(), b->toInt()); break; default: ScriptType at = a->type(), bt = b->type(); @@ -473,45 +472,45 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP& } else if (at == SCRIPT_COLLECTION && bt == SCRIPT_COLLECTION) { a = make_intrusive(a, b); } else if (at == SCRIPT_INT && bt == SCRIPT_INT) { - a = to_script((int)*a + (int)*b); + a = to_script(a->toInt() + b->toInt()); } else if ((at == SCRIPT_INT || at == SCRIPT_DOUBLE) && (bt == SCRIPT_INT || bt == SCRIPT_DOUBLE)) { - a = to_script((double)*a + (double)*b); + a = to_script(a->toDouble() + b->toDouble()); } else { - a = to_script(a->toString() + b->toString()); + a = to_script(a->toString() + b->toString()); } break; case I_SUB: OPERATOR_DI(-); case I_MUL: OPERATOR_DI(*); case I_FDIV: - a = to_script((double)*a / (double)*b); + a = to_script(a->toDouble() / b->toDouble()); break; case I_DIV: if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) { - a = to_script((int)((double)*a / (double)*b)); + a = to_script((int)(a->toDouble() / b->toDouble())); } else { - a = to_script((int)*a / (int)*b); + a = to_script(a->toInt() / b->toInt()); } break; case I_MOD: if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) { - a = to_script(fmod((double)*a, (double)*b)); + a = to_script(fmod(a->toDouble(), b->toDouble())); } else { - a = to_script((int)*a % (int)*b); + a = to_script(a->toInt() % b->toInt()); } break; case I_POW: if (bt == SCRIPT_INT) { - int bi = *b; + int bi = b->toInt(); if (at == SCRIPT_DOUBLE) { - double aa = *a; + double aa = a->toDouble(); if (bi == 0) a = to_script(1); else if (bi == 1) a = to_script(aa); else if (bi == 2) a = to_script(aa * aa); else if (bi == 3) a = to_script(aa * aa * aa); else a = to_script(pow(aa,bi)); } else { - int aa = *a; + int aa = a->toInt(); if (bi == 0) a = to_script(1); else if (bi == 1) a = to_script(aa); else if (bi == 2) a = to_script(aa * aa); @@ -519,20 +518,20 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP& else a = to_script(pow((double)aa,bi)); } } else { - a = to_script(pow((double)*a, (double)*b)); + a = to_script(pow(a->toDouble(), b->toDouble())); } break; - case I_AND: OPERATOR_B(&&); + case I_AND: OPERATOR_B(&&); case I_OR: OPERATOR_B(||); - case I_XOR: 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_NEQ: a = to_script(!equal(a,b)); break; case I_LT: OPERATOR_DI(<); case I_GT: OPERATOR_DI(>); case I_LE: OPERATOR_DI(<=); case I_GE: OPERATOR_DI(>=); - case I_MIN: OPERATOR_FUN_DI(min); - case I_MAX: OPERATOR_FUN_DI(max); + case I_MIN: OPERATOR_FUN_DI(min); + case I_MAX: OPERATOR_FUN_DI(max); case I_OR_ELSE: if (at == SCRIPT_ERROR) a = b; break; @@ -546,7 +545,7 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP& void instrTernary(TernaryInstructionType i, ScriptValueP& a, const ScriptValueP& b, const ScriptValueP& c) { switch (i) { case I_RGB: - a = to_script(Color((int)*a, (int)*b, (int)*c)); + a = to_script(Color(a->toInt(), b->toInt(), c->toInt())); break; } } @@ -556,7 +555,7 @@ void instrTernary(TernaryInstructionType i, ScriptValueP& a, const ScriptValueP& void instrQuaternary(QuaternaryInstructionType i, ScriptValueP& a, const ScriptValueP& b, const ScriptValueP& c, const ScriptValueP& d) { switch (i) { case I_RGBA: - a = to_script(Color((int)*a, (int)*b, (int)*c, (int)*d)); + a = to_script(Color(a->toInt(), b->toInt(), c->toInt(), d->toInt())); break; } } diff --git a/src/script/dependency.cpp b/src/script/dependency.cpp index 9ce96119..911dda1a 100644 --- a/src/script/dependency.cpp +++ b/src/script/dependency.cpp @@ -76,16 +76,16 @@ ScriptValueP unified(const ScriptValueP& a, const ScriptValueP& b) { /// Behaves like script_nil, but with a name class ScriptMissingVariable : public ScriptValue { - public: +public: ScriptMissingVariable(const String& name) : name(name) {} - virtual ScriptType type() const { return SCRIPT_NIL; } - virtual String typeName() const { return _("missing variable '") + name + _("'"); } - 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: + ScriptType type() const override { return SCRIPT_NIL; } + String typeName() const override { return _("missing variable '") + name + _("'"); } + String toString() const override { return String(); } + double toDouble() const override { return 0.0; } + int toInt() const override { return 0; } + bool toBool() const override { return false; } + ScriptValueP eval(Context&, bool) const override { return script_nil; } // nil() == nil +private: String name; ///< Name of the variable }; @@ -224,7 +224,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script) // Get an object member (almost as normal) case I_MEMBER_C: { - String name = *script.constants[i.data]; + String name = script.constants[i.data]->toString(); stack.back() = stack.back()->dependencyMember(name, dep); // dependency on member break; } diff --git a/src/script/functions/basic.cpp b/src/script/functions/basic.cpp index 9e258264..e235499d 100644 --- a/src/script/functions/basic.cpp +++ b/src/script/functions/basic.cpp @@ -76,9 +76,9 @@ String format_input(const String& format, const ScriptValue& input) { // determine type expected by format string String fmt = _("%") + replace_all(format, _("%"), _("")); if (format.find_first_of(_("DdIiOoXx")) != String::npos) { - return String::Format(fmt, (int)input); + return String::Format(fmt, input.toInt()); } else if (format.find_first_of(_("EeFfGg")) != String::npos) { - return String::Format(fmt, (double)input); + return String::Format(fmt, input.toDouble()); } else if (format.find_first_of(_("Ss")) != String::npos) { return format_string(fmt, input.toString()); } else { @@ -93,13 +93,13 @@ SCRIPT_FUNCTION(to_string) { try { if (format && format->type() == SCRIPT_STRING) { // format specifier. Be careful, the built in function 'format' has the same name - SCRIPT_RETURN(format_input(*format, *input)); + SCRIPT_RETURN(format_input(format->toString(), *input)); } else { // simple conversion SCRIPT_RETURN(input->toString()); } } catch (const ScriptError& e) { - return make_intrusive(e); + return delay_error(e); } } @@ -109,9 +109,9 @@ SCRIPT_FUNCTION(to_int) { try { int result; if (t == SCRIPT_BOOL) { - result = (bool)*input ? 1 : 0; + result = input->toBool() ? 1 : 0; } else if (t == SCRIPT_COLOR) { - Color c = input->operator Color(); + Color c = input->toColor(); result = (c.Red() + c.Blue() + c.Green()) / 3; } else if (t == SCRIPT_STRING) { long l; @@ -124,7 +124,7 @@ SCRIPT_FUNCTION(to_int) { return delay_error(ScriptErrorConversion(str, input->typeName(), _TYPE_("integer"))); } } else { - result = (int)*input; + result = input->toInt(); } SCRIPT_RETURN(result); } catch (const ScriptError& e) { @@ -138,9 +138,9 @@ SCRIPT_FUNCTION(to_real) { try { double result; if (t == SCRIPT_BOOL) { - result = (bool)*input ? 1.0 : 0.0; + result = input->toBool() ? 1.0 : 0.0; } else if (t == SCRIPT_COLOR) { - Color c = input->operator Color(); + Color c = input->toColor(); result = (c.Red() + c.Blue() + c.Green()) / 3.0; } else if (t == SCRIPT_STRING) { String str = input->toString(); @@ -150,7 +150,7 @@ SCRIPT_FUNCTION(to_real) { return delay_error(ScriptErrorConversion(str, input->typeName(), _TYPE_("double"))); } } else { - result = (double)*input; + result = input->toDouble(); } SCRIPT_RETURN(result); } catch (const ScriptError& e) { @@ -163,12 +163,12 @@ SCRIPT_FUNCTION(to_number) { ScriptType t = input->type(); try { if (t == SCRIPT_BOOL) { - SCRIPT_RETURN((bool)*input ? 1 : 0); + SCRIPT_RETURN(input->toBool() ? 1 : 0); } else if (t == SCRIPT_COLOR) { - Color c = input->operator Color(); + Color c = input->toColor(); SCRIPT_RETURN( (c.Red() + c.Blue() + c.Green()) / 3 ); } else if (t == SCRIPT_DOUBLE) { - SCRIPT_RETURN((double)*input); + SCRIPT_RETURN(input->toDouble()); } else if (t == SCRIPT_NIL) { SCRIPT_RETURN(0); } else { @@ -195,9 +195,9 @@ SCRIPT_FUNCTION(to_boolean) { ScriptType t = input->type(); bool result; if (t == SCRIPT_INT) { - result = (int)*input != 0; + result = input->toInt() != 0; } else { - result = (bool)*input; + result = input->toBool(); } SCRIPT_RETURN(result); } catch (const ScriptError& e) { @@ -239,9 +239,9 @@ SCRIPT_FUNCTION(abs) { ScriptValueP input = ctx.getVariable(SCRIPT_VAR_input); ScriptType t = input->type(); if (t == SCRIPT_DOUBLE) { - SCRIPT_RETURN(fabs((double)*input)); + SCRIPT_RETURN(fabs(input->toDouble())); } else { - SCRIPT_RETURN(abs((int)*input)); + SCRIPT_RETURN(abs(input->toInt())); } } @@ -579,7 +579,7 @@ SCRIPT_FUNCTION(filter_list) { ScriptValueP it = input->makeIterator(); while (ScriptValueP v = it->next()) { ctx.setVariable(SCRIPT_VAR_input, v); - if (*filter->eval(ctx)) { + if (filter->eval(ctx)->toBool()) { ret->value.push_back(v); } } @@ -628,7 +628,7 @@ SCRIPT_FUNCTION(random_select_many) { SCRIPT_PARAM_C(ScriptValueP, input); SCRIPT_PARAM(int, count) ; SCRIPT_OPTIONAL_PARAM_C_(ScriptValueP, replace); - bool with_replace = replace && replace->type() != SCRIPT_FUNCTION && (bool)*replace; + bool with_replace = replace && replace->type() != SCRIPT_FUNCTION && replace->toBool(); // pick many ScriptCustomCollectionP ret(new ScriptCustomCollection); int itemCount = input->itemCount(); diff --git a/src/script/functions/construction.cpp b/src/script/functions/construction.cpp index 41ffe687..d876d579 100644 --- a/src/script/functions/construction.cpp +++ b/src/script/functions/construction.cpp @@ -44,7 +44,7 @@ SCRIPT_FUNCTION(new_card) { } else if (PackageChoiceValue* pvalue = dynamic_cast(value)) { pvalue->package_name = v->toString(); } else if (ColorValue* cvalue = dynamic_cast(value)) { - cvalue->value = v->operator Color(); + cvalue->value = v->toColor(); } else { throw ScriptError(format_string(_("Can not set value '%s', it is not of the right type"),name)); } diff --git a/src/script/functions/regex.cpp b/src/script/functions/regex.cpp index 9d529e90..242ef488 100644 --- a/src/script/functions/regex.cpp +++ b/src/script/functions/regex.cpp @@ -52,7 +52,7 @@ ScriptRegexP regex_from_script(const ScriptValueP& value) { ScriptRegexP regex = dynamic_pointer_cast(value); if (!regex) { // TODO: introduce some kind of caching? - regex = make_intrusive(*value); + regex = make_intrusive(value->toString()); } return regex; } diff --git a/src/script/functions/spelling.cpp b/src/script/functions/spelling.cpp index 6b6a56a1..f59422bd 100644 --- a/src/script/functions/spelling.cpp +++ b/src/script/functions/spelling.cpp @@ -37,12 +37,12 @@ inline size_t spelled_correctly(const String& input, size_t start, size_t end, S if (extra_test) { // try on untagged ctx.setVariable(SCRIPT_VAR_input, to_script(word)); - if (*extra_test->eval(ctx)) { + if (extra_test->eval(ctx)->toBool()) { return true; } // try on tagged ctx.setVariable(SCRIPT_VAR_input, to_script(input.substr(start,end-start))); - if (*extra_test->eval(ctx)) { + if (extra_test->eval(ctx)->toBool()) { return true; } } diff --git a/src/script/functions/util.hpp b/src/script/functions/util.hpp index 44c09f9a..3d0c9f3c 100644 --- a/src/script/functions/util.hpp +++ b/src/script/functions/util.hpp @@ -37,31 +37,31 @@ #define SCRIPT_FUNCTION(name) SCRIPT_FUNCTION_AUX(name,;) /// Macro to declare a new script function with custom dependency handling -#define SCRIPT_FUNCTION_WITH_DEP(name) \ - SCRIPT_FUNCTION_AUX(name, virtual ScriptValueP dependencies(Context&, const Dependency&) const;) +#define SCRIPT_FUNCTION_WITH_DEP(name) \ + SCRIPT_FUNCTION_AUX(name, ScriptValueP dependencies(Context&, const Dependency&) const override;) -#define SCRIPT_FUNCTION_DEPENDENCIES(name) \ +#define SCRIPT_FUNCTION_DEPENDENCIES(name) \ ScriptValueP ScriptBuiltIn_##name::dependencies(Context& ctx, const Dependency& dep) const /// Macro to declare a new script function with custom closure simplification -#define SCRIPT_FUNCTION_WITH_SIMPLIFY(name) \ - SCRIPT_FUNCTION_AUX(name, virtual ScriptValueP simplifyClosure(ScriptClosure&) const;) +#define SCRIPT_FUNCTION_WITH_SIMPLIFY(name) \ + SCRIPT_FUNCTION_AUX(name, ScriptValueP simplifyClosure(ScriptClosure&) const override;) -#define SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(name) \ +#define SCRIPT_FUNCTION_SIMPLIFY_CLOSURE(name) \ ScriptValueP ScriptBuiltIn_##name::simplifyClosure(ScriptClosure& closure) const // helper for SCRIPT_FUNCTION and SCRIPT_FUNCTION_DEP -#define SCRIPT_FUNCTION_AUX(name,dep) \ - class ScriptBuiltIn_##name : public ScriptValue { \ - dep \ - virtual ScriptType type() const \ - { return SCRIPT_FUNCTION; } \ - virtual String typeName() const \ +#define SCRIPT_FUNCTION_AUX(name,dep) \ + class ScriptBuiltIn_##name : public ScriptValue { \ + dep \ + ScriptType type() const override \ + { return SCRIPT_FUNCTION; } \ + String typeName() const override \ { return _("built-in function '") _(#name) _("'"); } \ - virtual ScriptValueP do_eval(Context&, bool) const; \ + ScriptValueP eval(Context&, bool) const override; \ }; \ ScriptValueP script_##name(new ScriptBuiltIn_##name); \ - ScriptValueP ScriptBuiltIn_##name::do_eval(Context& ctx, bool) const + ScriptValueP ScriptBuiltIn_##name::eval(Context& ctx, bool) const /// Return a value from a SCRIPT_FUNCTION #define SCRIPT_RETURN(value) return to_script(value) @@ -157,10 +157,10 @@ inline Type from_script(const ScriptValueP& v, Variable var) { class ScriptRule_##funname: public ScriptValue { \ public: \ inline ScriptRule_##funname(const type1& name1) : name1(name1) {} \ - virtual ScriptType type() const { return SCRIPT_FUNCTION; } \ - virtual String typeName() const { return _(#funname)_("_rule"); } \ + ScriptType type() const override { return SCRIPT_FUNCTION; } \ + String typeName() const override { return _(#funname)_("_rule"); } \ protected: \ - virtual ScriptValueP do_eval(Context& ctx, bool) const; \ + ScriptValueP eval(Context& ctx, bool) const override; \ private: \ type1 name1; \ }; \ @@ -172,7 +172,7 @@ inline Type from_script(const ScriptValueP& v, Variable var) { SCRIPT_PARAM_N(type1, str1, name1); \ return ScriptRule_##funname(name1).eval(ctx); \ } \ - ScriptValueP ScriptRule_##funname::do_eval(Context& ctx, bool) const + ScriptValueP ScriptRule_##funname::eval(Context& ctx, bool) const /// Utility for defining a script rule with two parameters #define SCRIPT_RULE_2(funname, type1, name1, type2, name2) \ @@ -185,7 +185,7 @@ inline Type from_script(const ScriptValueP& v, Variable var) { /// Utility for defining a script rule with two named parameters, with dependencies #define SCRIPT_RULE_2_N_DEP(funname, type1, str1, name1, type2, str2, name2) \ SCRIPT_RULE_2_N_AUX( funname, type1, str1, name1, type2, str2, name2, \ - virtual ScriptValueP dependencies(Context&, const Dependency&) const; \ + ScriptValueP dependencies(Context&, const Dependency&) const override; \ SCRIPT_FUNCTION_DEPENDENCIES(funname) { \ SCRIPT_PARAM_N(type1, str1, name1); \ SCRIPT_PARAM_N(type2, str2, name2); \ @@ -197,11 +197,11 @@ inline Type from_script(const ScriptValueP& v, Variable var) { public: \ inline ScriptRule_##funname(const type1& name1, const type2& name2) \ : name1(name1), name2(name2) {} \ - virtual ScriptType type() const { return SCRIPT_FUNCTION; } \ - virtual String typeName() const { return _(#funname)_("_rule"); } \ + ScriptType type() const override { return SCRIPT_FUNCTION; } \ + String typeName() const override { return _(#funname)_("_rule"); } \ dep \ protected: \ - virtual ScriptValueP do_eval(Context& ctx, bool) const; \ + ScriptValueP eval(Context& ctx, bool) const override; \ private: \ type1 name1; \ type2 name2; \ @@ -217,7 +217,7 @@ inline Type from_script(const ScriptValueP& v, Variable var) { return ScriptRule_##funname(name1, name2).eval(ctx); \ } \ more \ - ScriptValueP ScriptRule_##funname::do_eval(Context& ctx, bool) const + ScriptValueP ScriptRule_##funname::eval(Context& ctx, bool) const #define SCRIPT_RULE_2_DEPENDENCIES(name) \ ScriptValueP ScriptRule_##name::dependencies(Context& ctx, const Dependency& dep) const diff --git a/src/script/script.cpp b/src/script/script.cpp index 83b34900..ea0c9ee7 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -88,7 +88,7 @@ ScriptType Script::type() const { String Script::typeName() const { return _("function"); } -ScriptValueP Script::do_eval(Context& ctx, bool openScope) const { +ScriptValueP Script::eval(Context& ctx, bool openScope) const { return ctx.eval(*this, openScope); } ScriptValueP Script::dependencies(Context& ctx, const Dependency& dep) const { diff --git a/src/script/script.hpp b/src/script/script.hpp index e873eb96..43f6cc55 100644 --- a/src/script/script.hpp +++ b/src/script/script.hpp @@ -163,11 +163,11 @@ void init_script_variables(); * The script is itself a ScriptValue */ class Script : public ScriptValue { - public: +public: - virtual ScriptType type() const; - virtual String typeName() const; - virtual ScriptValueP dependencies(Context& ctx, const Dependency&) const; + ScriptType type() const override; + String typeName() const override; + ScriptValueP dependencies(Context& ctx, const Dependency&) const override; /// Add a jump instruction, later comeFrom should be called on the returned value unsigned int addInstruction(InstructionType t); @@ -196,10 +196,9 @@ class Script : public ScriptValue { /// Output an instruction in a human readable format String dumpInstr(unsigned int pos, Instruction i) const; - protected: - virtual ScriptValueP do_eval(Context& ctx, bool openScope) const; + ScriptValueP eval(Context& ctx, bool openScope = true) const override; - private: +private: /// Data of the instructions that make up this script vector instructions; /// Constant values that can be referred to from the script diff --git a/src/script/scriptable.cpp b/src/script/scriptable.cpp index af624767..596cf962 100644 --- a/src/script/scriptable.cpp +++ b/src/script/scriptable.cpp @@ -20,12 +20,12 @@ void parse_enum(const String&,Direction&); // ----------------------------------------------------------------------------- : Store 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 = *val; } -void store(const ScriptValueP& val, Color& var) { var = *val; } -void store(const ScriptValueP& val, Defaultable& var) { var.assign(*val); } -void store(const ScriptValueP& val, Defaultable& var) { var.assign(*val); } +void store(const ScriptValueP& val, int& var) { var = val->toInt(); } +void store(const ScriptValueP& val, double& var) { var = val->toDouble(); } +void store(const ScriptValueP& val, bool& var) { var = val->toBool(); } +void store(const ScriptValueP& val, Color& var) { var = val->toColor(); } +void store(const ScriptValueP& val, Defaultable& var) { var.assign(val->toString()); } +void store(const ScriptValueP& val, Defaultable& var) { var.assign(val->toColor()); } void store(const ScriptValueP& val, Alignment& var) { var = from_string(val->toString()); } void store(const ScriptValueP& val, Direction& var) { parse_enum(val->toString(),var); } diff --git a/src/script/to_value.hpp b/src/script/to_value.hpp index 8d6d49c9..2f1c1d87 100644 --- a/src/script/to_value.hpp +++ b/src/script/to_value.hpp @@ -61,56 +61,22 @@ template inline String to_code(const intrusive_ptr& p) { // ----------------------------------------------------------------------------- : Errors -/// A delayed error message. -/** Only when trying to use the object will the error be thrown. - * This can be 'caught' by the "or else" construct - */ -class ScriptDelayedError : public ScriptValue { - public: - inline ScriptDelayedError(const ScriptError& error) : error(error) {} - - virtual ScriptType type() const;// { return SCRIPT_ERROR; } - - // all of these throw - virtual String typeName() const; - virtual operator String() const; - virtual operator double() const; - virtual operator int() const; - virtual operator bool() const; - virtual operator Color() const; - virtual int itemCount() const; - virtual CompareWhat compareAs(String&, void const*&) const; - // these can propagate the error - virtual ScriptValueP getMember(const String& name) const; - virtual ScriptValueP dependencyMember(const String& name, const Dependency&) const; - virtual ScriptValueP dependencies(Context&, const Dependency&) const; - virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const; - - protected: - virtual ScriptValueP do_eval(Context&, bool openScope) const; - - private: - ScriptError error; // the error message -}; - +ScriptValueP delay_error(const ScriptError& error); inline ScriptValueP delay_error(const String& m) { - return make_intrusive(ScriptError(m)); -} -inline ScriptValueP delay_error(const ScriptError& error) { - return make_intrusive(error); + return delay_error(ScriptError(m)); } // ----------------------------------------------------------------------------- : Iterators // Iterator over a collection struct ScriptIterator : public ScriptValue { - virtual ScriptType type() const;// { return SCRIPT_ITERATOR; } - virtual String typeName() const;// { return "iterator"; } - virtual CompareWhat compareAs(String&, void const*&) const; // { return COMPARE_NO; } + ScriptType type() const override; + String typeName() const override; + CompareWhat compareAs(String&, void const*&) const override; /// Return the next item for this iterator, or ScriptValueP() if there is no such item - virtual ScriptValueP next(ScriptValueP* key_out = nullptr) = 0; - virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const; + ScriptValueP next(ScriptValueP* key_out = nullptr) override = 0; + ScriptValueP makeIterator(const ScriptValueP& thisP) const override; }; // make an iterator over a range @@ -121,18 +87,18 @@ ScriptValueP rangeIterator(int start, int end); ScriptValueP to_script(int); class ScriptCollectionBase : public ScriptValue { - public: - virtual ScriptType type() const { return SCRIPT_COLLECTION; } - virtual String typeName() const { return _TYPE_("collection"); } - virtual String toCode() const; +public: + ScriptType type() const override { return SCRIPT_COLLECTION; } + String typeName() const override { return _TYPE_("collection"); } + String toCode() const override; }; // Iterator over a collection template class ScriptCollectionIterator : public ScriptIterator { - public: +public: ScriptCollectionIterator(const Collection* col) : pos(0), col(col) {} - virtual ScriptValueP next(ScriptValueP* key_out) { + ScriptValueP next(ScriptValueP* key_out) override { if (pos < col->size()) { if (key_out) *key_out = to_script((int)pos); return to_script(col->at(pos++)); @@ -140,34 +106,38 @@ class ScriptCollectionIterator : public ScriptIterator { return ScriptValueP(); } } - private: +private: size_t pos; const Collection* col; }; -/// Script value containing a collection +/// Script value containing a collection (vector like) template class ScriptCollection : public ScriptCollectionBase { - public: +public: inline ScriptCollection(const Collection* v) : value(v) {} - virtual String typeName() const { return _TYPE_1_("collection of", type_name(*value->begin())); } - virtual ScriptValueP getIndex(int index) const { + String typeName() const override { + return _TYPE_1_("collection of", type_name(*value->begin())); + } + ScriptValueP getIndex(int index) const override { if (index >= 0 && index < (int)value->size()) { return to_script(value->at(index)); } else { return ScriptValue::getIndex(index); } } - virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const { + ScriptValueP makeIterator(const ScriptValueP& thisP) const override { return make_intrusive>(value); } - virtual int itemCount() const { return (int)value->size(); } + int itemCount() const override { + return (int)value->size(); + } /// Collections can be compared by comparing pointers - virtual CompareWhat compareAs(String&, void const*& compare_ptr) const { + CompareWhat compareAs(String&, void const*& compare_ptr) const override { compare_ptr = value; return COMPARE_AS_POINTER; } - private: +private: /// Store a pointer to a collection, collections are only ever used for structures owned outside the script const Collection* value; }; @@ -197,24 +167,24 @@ ScriptValueP get_member(const IndexMap& m, const String& name) { /// Script value containing a map-like collection template class ScriptMap : public ScriptValue { - public: +public: inline ScriptMap(const Collection* v) : value(v) {} - virtual ScriptType type() const { return SCRIPT_COLLECTION; } - virtual String typeName() const { return _TYPE_1_("collection of", type_name(value->begin())); } - virtual ScriptValueP getMember(const String& name) const { + ScriptType type() const override { return SCRIPT_COLLECTION; } + String typeName() const override { return _TYPE_1_("collection of", type_name(value->begin())); } + ScriptValueP getMember(const String& name) const override { return get_member(*value, name); } - virtual int itemCount() const { return (int)value->size(); } - virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const { + int itemCount() const override { return (int)value->size(); } + ScriptValueP dependencyMember(const String& name, const Dependency& dep) const override { mark_dependency_member(*value, name, dep); return getMember(name); } /// Collections can be compared by comparing pointers - virtual CompareWhat compareAs(String&, void const*& compare_ptr) const { + CompareWhat compareAs(String&, void const*& compare_ptr) const override { compare_ptr = value; return COMPARE_AS_POINTER; } - private: +private: /// Store a pointer to a collection, collections are only ever used for structures owned outside the script const Collection* value; }; @@ -223,7 +193,7 @@ class ScriptMap : public ScriptValue { /// Script value containing a custom collection, returned from script functions class ScriptCustomCollection : public ScriptCollectionBase { - public: +public: ScriptValueP getMember(const String& name) const override; ScriptValueP getIndex(int index) const override; ScriptValueP makeIterator(const ScriptValueP& thisP) const override; @@ -248,19 +218,19 @@ DECLARE_POINTER_TYPE(ScriptCustomCollection); /// Script value containing the concatenation of two collections class ScriptConcatCollection : public ScriptCollectionBase { - public: +public: inline ScriptConcatCollection(ScriptValueP a, ScriptValueP b) : a(a), b(b) {} - virtual ScriptValueP getMember(const String& name) const; - virtual ScriptValueP getIndex(int index) const; - virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const; - virtual int itemCount() const { return a->itemCount() + b->itemCount(); } + ScriptValueP getMember(const String& name) const override; + ScriptValueP getIndex(int index) const override; + ScriptValueP makeIterator(const ScriptValueP& thisP) const override; + int itemCount() const override { return a->itemCount() + b->itemCount(); } /// Collections can be compared by comparing pointers - virtual CompareWhat compareAs(String&, void const*& compare_ptr) const { + CompareWhat compareAs(String&, void const*& compare_ptr) const override { compare_ptr = this; return COMPARE_AS_POINTER; } - private: +private: ScriptValueP a,b; friend class ScriptConcatCollectionIterator; }; @@ -270,24 +240,37 @@ class ScriptConcatCollection : public ScriptCollectionBase { /// Script value containing an object (pointer) template class ScriptObject : public ScriptValue { - public: +public: inline ScriptObject(const T& v) : value(v) {} - virtual ScriptType type() const { ScriptValueP d = getDefault(); return d ? d->type() : SCRIPT_OBJECT; } - virtual String typeName() const { return type_name(*value); } - 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 Color() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator Color(); } - virtual String toCode() const { ScriptValueP d = getDefault(); return d ? d->toCode() : to_code(*value); } - virtual GeneratedImageP toImage(const ScriptValueP& thisP) const { + ScriptType type() const override { ScriptValueP d = getDefault(); return d ? d->type() : SCRIPT_OBJECT; } + String typeName() const override { return type_name(*value); } + String toString() const override { + ScriptValueP d = getDefault(); return d ? d->toString() : ScriptValue::toString(); + } + double toDouble() const override { + ScriptValueP d = getDefault(); return d ? d->toDouble() : ScriptValue::toDouble(); + } + int toInt() const override { + ScriptValueP d = getDefault(); return d ? d->toInt() : ScriptValue::toInt(); + } + bool toBool() const override { + ScriptValueP d = getDefault(); return d ? d->toBool() : ScriptValue::toBool(); + } + Color toColor() const override { + ScriptValueP d = getDefault(); return d ? d->toColor() : ScriptValue::toColor(); + } + String toCode() const override { + ScriptValueP d = getDefault(); return d ? d->toCode() : to_code(*value); + } + GeneratedImageP toImage(const ScriptValueP& thisP) const override { ScriptValueP d = getDefault(); return d ? d->toImage(d) : ScriptValue::toImage(thisP); } - virtual ScriptValueP getMember(const String& name) const { + ScriptValueP getMember(const String& name) const override { #if USE_SCRIPT_PROFILING Timer t; Profiler prof(t, (void*)mangled_name(typeid(T)), _("get member of ") + type_name(*value)); #endif + // Use reflection to find the member of the object GetMember gm(name); gm.handle(*value); if (gm.result()) return gm.result(); @@ -301,22 +284,24 @@ 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 { + ScriptValueP getIndex(int index) const override { + ScriptValueP d = getDefault(); return d ? d->getIndex(index) : ScriptValue::getIndex(index); + } + ScriptValueP dependencyMember(const String& name, const Dependency& dep) const override { mark_dependency_member(*value, name, dep); return getMember(name); } - virtual void dependencyThis(const Dependency& dep) { + void dependencyThis(const Dependency& dep) override { mark_dependency_value(*value, dep); } - virtual ScriptValueP makeIterator(const ScriptValueP& thisP) const { + ScriptValueP makeIterator(const ScriptValueP& thisP) const override { ScriptValueP it = make_iterator(*value); if (it) return it; ScriptValueP d = getDefault(); if (d) return d->makeIterator(d); return ScriptValue::makeIterator(thisP); } - virtual int itemCount() const { + int itemCount() const override { int i = item_count(*value); if (i >= 0) return i; ScriptValueP d = getDefault(); @@ -324,7 +309,7 @@ class ScriptObject : public ScriptValue { return ScriptValue::itemCount(); } /// Objects can be compared by comparing pointers - virtual CompareWhat compareAs(String& compare_str, void const*& compare_ptr) const { + CompareWhat compareAs(String& compare_str, void const*& compare_ptr) const override { ScriptValueP d = getDefault(); if (d) { return d->compareAs(compare_str, compare_ptr); @@ -335,7 +320,7 @@ class ScriptObject : public ScriptValue { } /// Get access to the value inline T getValue() const { return value; } - private: +private: T value; ///< The object ScriptValueP getDefault() const { GetDefaultMember gdm; @@ -348,12 +333,12 @@ class ScriptObject : public ScriptValue { /// A wrapper around a function that gives default arguments class ScriptClosure : public ScriptValue { - public: +public: ScriptClosure(ScriptValueP fun) : fun(fun) {} - virtual ScriptType type() const; - virtual String typeName() const; - virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const; + ScriptType type() const override; + String typeName() const override; + ScriptValueP dependencies(Context& ctx, const Dependency& dep) const override; /// Add a binding void addBinding(Variable v, const ScriptValueP& value); @@ -363,69 +348,87 @@ class ScriptClosure : public ScriptValue { /// Try to simplify this closure, returns a value if successful ScriptValueP simplify(); + ScriptValueP eval(Context& ctx, bool openScope) const override; + /// The wrapped function ScriptValueP fun; /// The default argument bindings vector > bindings; - protected: - virtual ScriptValueP do_eval(Context& ctx, bool openScope) const; - - private: +private: /// Apply the bindings in a context void applyBindings(Context& ctx) const; }; /// Turn a script function into a rule, a.k.a. a delayed closure class ScriptRule : public ScriptValue { - public: +public: inline ScriptRule(const ScriptValueP& fun) : fun(fun) {} - virtual ScriptType type() const; - virtual String typeName() const; + ScriptType type() const override; + String typeName() const override; + ScriptValueP eval(Context& ctx, bool openScope) const override; - protected: - virtual ScriptValueP do_eval(Context& ctx, bool openScope) const; - - private: +private: ScriptValueP fun; }; // ----------------------------------------------------------------------------- : Creating +extern ScriptValueP script_nil; ///< The preallocated nil value +extern ScriptValueP script_true; ///< The preallocated true value +extern ScriptValueP script_false; ///< The preallocated false value +extern ScriptValueP dependency_dummy; ///< Dummy value used during dependency analysis + /// Convert a value to a script value - ScriptValueP to_script(int v); -inline ScriptValueP to_script(long v) { return to_script((int) v); } - ScriptValueP to_script(double v); - ScriptValueP to_script(const String& v); - ScriptValueP to_script(Color v); - ScriptValueP to_script(wxDateTime v); -inline ScriptValueP to_script(bool v) { return v ? script_true : script_false; } +ScriptValueP to_script(int v); +ScriptValueP to_script(double v); +ScriptValueP to_script(const String& v); +ScriptValueP to_script(Color v); +ScriptValueP to_script(wxDateTime v); + +inline ScriptValueP to_script(long v) { + return to_script((int) v); +} +inline ScriptValueP to_script(bool v) { + return v ? script_true : script_false; +} + template -inline ScriptValueP to_script(const vector* v) { return make_intrusive>>(v); } +inline ScriptValueP to_script(const vector* v) { + return make_intrusive>>(v); +} template -inline ScriptValueP to_script(const map* v) { return make_intrusive>>(v); } +inline ScriptValueP to_script(const map* v) { + return make_intrusive>>(v); +} template -inline ScriptValueP to_script(const IndexMap* v) { return make_intrusive>>(v); } +inline ScriptValueP to_script(const IndexMap* v) { + return make_intrusive>>(v); +} template -inline ScriptValueP to_script(const intrusive_ptr& v) { return make_intrusive>>(v); } +inline ScriptValueP to_script(const intrusive_ptr& v) { + return make_intrusive>>(v); +} template -inline ScriptValueP to_script(const Defaultable& v) { return to_script(v()); } +inline ScriptValueP to_script(const Defaultable& v) { + return to_script(v()); +} // ----------------------------------------------------------------------------- : Destructing /// Convert a value from a script value to a normal value -template inline T from_script (const ScriptValueP& value) { +template inline T from_script(const ScriptValueP& value) { ScriptObject* o = dynamic_cast*>(value.get()); if (!o) { throw ScriptErrorConversion(value->typeName(), _TYPE_("object" )); } return o->getValue(); } -template <> inline ScriptValueP from_script(const ScriptValueP& value) { return value; } -template <> inline String from_script (const ScriptValueP& value) { return *value; } -template <> inline int from_script (const ScriptValueP& value) { return *value; } -template <> inline double from_script (const ScriptValueP& value) { return *value; } -template <> inline bool from_script (const ScriptValueP& value) { return *value; } -template <> inline Color from_script (const ScriptValueP& value) { return *value; } -template <> inline wxDateTime from_script (const ScriptValueP& value) { return *value; } +template <> inline ScriptValueP from_script(const ScriptValueP& value) { return value; } +template <> inline String from_script (const ScriptValueP& value) { return value->toString(); } +template <> inline int from_script (const ScriptValueP& value) { return value->toInt(); } +template <> inline double from_script (const ScriptValueP& value) { return value->toDouble(); } +template <> inline bool from_script (const ScriptValueP& value) { return value->toBool(); } +template <> inline Color from_script (const ScriptValueP& value) { return value->toColor(); } +template <> inline wxDateTime from_script (const ScriptValueP& value) { return value->toDateTime(); } diff --git a/src/script/value.cpp b/src/script/value.cpp index ded27c4e..a64f0ca1 100644 --- a/src/script/value.cpp +++ b/src/script/value.cpp @@ -17,18 +17,45 @@ // ----------------------------------------------------------------------------- : ScriptValue // Base cases -ScriptValue::operator String() const { throw ScriptErrorConversion(typeName(), _TYPE_("string" )); } -ScriptValue::operator int() const { throw ScriptErrorConversion(typeName(), _TYPE_("integer" )); } -ScriptValue::operator bool() const { throw ScriptErrorConversion(typeName(), _TYPE_("boolean" )); } -ScriptValue::operator double() const { throw ScriptErrorConversion(typeName(), _TYPE_("double" )); } -ScriptValue::operator Color() const { throw ScriptErrorConversion(typeName(), _TYPE_("color" )); } -ScriptValue::operator wxDateTime() const { throw ScriptErrorConversion(typeName(), _TYPE_("date" )); } -ScriptValueP ScriptValue::do_eval(Context&, bool) const { return delay_error(ScriptErrorConversion(typeName(), _TYPE_("function"))); } -ScriptValueP ScriptValue::next(ScriptValueP* key_out) { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); } -ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { return delay_error(ScriptErrorConversion(typeName(), _TYPE_("collection"))); } -int ScriptValue::itemCount() const { throw ScriptErrorConversion(typeName(), _TYPE_("collection")); } -GeneratedImageP ScriptValue::toImage(const ScriptValueP&) const { throw ScriptErrorConversion(typeName(), _TYPE_("image" )); } -String ScriptValue::toCode() const { return *this; } +String ScriptValue::toString() const { + throw ScriptErrorConversion(typeName(), _TYPE_("string")); +} +int ScriptValue::toInt() const { + throw ScriptErrorConversion(typeName(), _TYPE_("integer")); +} +bool ScriptValue::toBool() const { + throw ScriptErrorConversion(typeName(), _TYPE_("boolean")); +} +double ScriptValue::toDouble() const { + throw ScriptErrorConversion(typeName(), _TYPE_("double")); +} +Color ScriptValue::toColor() const { + throw ScriptErrorConversion(typeName(), _TYPE_("color")); +} +wxDateTime ScriptValue::toDateTime() const { + throw ScriptErrorConversion(typeName(), _TYPE_("date")); +} +GeneratedImageP ScriptValue::toImage(const ScriptValueP&) const { + throw ScriptErrorConversion(typeName(), _TYPE_("image" )); +} +String ScriptValue::toCode() const { + return toString(); +} + +ScriptValueP ScriptValue::eval(Context&, bool) const { + return delay_error(ScriptErrorConversion(typeName(), _TYPE_("function"))); +} + +ScriptValueP ScriptValue::next(ScriptValueP* key_out) { + throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); +} +ScriptValueP ScriptValue::makeIterator(const ScriptValueP&) const { + return delay_error(ScriptErrorConversion(typeName(), _TYPE_("collection"))); +} +int ScriptValue::itemCount() const { + throw ScriptErrorConversion(typeName(), _TYPE_("collection")); +} + CompareWhat ScriptValue::compareAs(String& compare_str, void const*& compare_ptr) const { compare_str = toCode(); return COMPARE_AS_STRING; @@ -46,13 +73,19 @@ ScriptValueP ScriptValue::getIndex(int index) const { } -ScriptValueP ScriptValue::simplifyClosure(ScriptClosure&) const { return ScriptValueP(); } +ScriptValueP ScriptValue::simplifyClosure(ScriptClosure&) const { + return nullptr; +} -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::dependencyName(const ScriptValue& container, const Dependency& dep) const { return container.dependencyMember(toString(),dep); } -ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; } +ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { + return dependency_dummy; +} void ScriptValue::dependencyThis(const Dependency& dep) {} bool approx_equal(double a, double b) { @@ -64,12 +97,12 @@ 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 a->toInt() == b->toInt(); } else if (at == bt && at == SCRIPT_BOOL) { - return (bool)*a == (bool)*b; + return a->toBool() == b->toBool(); } else if ((at == SCRIPT_INT || at == SCRIPT_DOUBLE) && (bt == SCRIPT_INT || bt == SCRIPT_DOUBLE)) { - return approx_equal( (double)*a, (double)*b); + return approx_equal(a->toDouble(), b->toDouble()); } else if (at == SCRIPT_COLLECTION && bt == SCRIPT_COLLECTION) { // compare each element if (a->itemCount() != b->itemCount()) return false; @@ -99,22 +132,42 @@ bool equal(const ScriptValueP& a, const ScriptValueP& b) { // ----------------------------------------------------------------------------- : Errors -ScriptType ScriptDelayedError::type() const { return SCRIPT_ERROR; } +/// A delayed error message. +/** Only when trying to use the object will the error be thrown. + * This can be 'caught' by the "or else" construct + */ +class ScriptDelayedError : public ScriptValue { +public: + inline ScriptDelayedError(const ScriptError& error) : error(error) {} -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 Color() const { throw error; } -int ScriptDelayedError::itemCount() const { throw error; } -CompareWhat ScriptDelayedError::compareAs(String&, void const*&) const { throw error; } -ScriptValueP ScriptDelayedError::getMember(const String&) const { return make_intrusive(error); } -ScriptValueP ScriptDelayedError::dependencyMember(const String&, const Dependency&) const { return make_intrusive(error); } -ScriptValueP ScriptDelayedError::do_eval(Context&, bool) const { return make_intrusive(error); } -ScriptValueP ScriptDelayedError::dependencies(Context&, const Dependency&) const { return make_intrusive(error); } -ScriptValueP ScriptDelayedError::makeIterator(const ScriptValueP& thisP) const { return thisP ? thisP : make_intrusive(error); } + ScriptType type() const override { return SCRIPT_ERROR; } + // all of these throw + String typeName() const override { throw error; } + String toString() const override { throw error; } + double toDouble() const override { throw error; } + int toInt() const override { throw error; } + bool toBool() const override { throw error; } + Color toColor() const override { throw error; } + wxDateTime toDateTime() const override { throw error; } + GeneratedImageP toImage(const ScriptValueP& thisP) const override { throw error; } + int itemCount() const override { throw error; } + CompareWhat compareAs(String&, void const*&) const override { throw error; } + + // these can propagate the error + ScriptValueP getMember(const String& name) const override { return delay_error(error); } + ScriptValueP dependencyMember(const String& name, const Dependency&) const override { return delay_error(error); } + ScriptValueP dependencies(Context&, const Dependency&) const override { return delay_error(error); } + ScriptValueP makeIterator(const ScriptValueP&) const override { return delay_error(error); } + ScriptValueP eval(Context&, bool openScope) const override { return delay_error(error); } + +private: + ScriptError error; // the error message +}; + +ScriptValueP delay_error(const ScriptError& error) { + return make_intrusive(error); +} // ----------------------------------------------------------------------------- : Iterators @@ -125,11 +178,12 @@ ScriptValueP ScriptIterator::makeIterator(const ScriptValueP& thisP) const { ret // Iterator over a range of integers class ScriptRangeIterator : public ScriptIterator { - public: +public: // Construct a range iterator with the given bounds (inclusive) ScriptRangeIterator(int start, int end) - : pos(start), start(start), end(end) {} - virtual ScriptValueP next(ScriptValueP* key_out) { + : pos(start), start(start), end(end) + {} + ScriptValueP next(ScriptValueP* key_out) override { if (pos <= end) { if (key_out) *key_out = to_script(pos-start); return to_script(pos++); @@ -137,7 +191,7 @@ class ScriptRangeIterator : public ScriptIterator { return ScriptValueP(); } } - private: +private: int pos, start, end; }; @@ -151,20 +205,20 @@ ScriptValueP rangeIterator(int start, int end) { // Integer values class ScriptInt : public ScriptValue { - public: +public: ScriptInt(int v) : value(v) {} - virtual ScriptType type() const { return SCRIPT_INT; } - virtual String typeName() const { return _TYPE_("integer"); } - virtual operator String() const { return String() << value; } - virtual operator double() const { return value; } - virtual operator int() const { return value; } - protected: + ScriptType type() const override { return SCRIPT_INT; } + String typeName() const override { return _TYPE_("integer"); } + String toString() const override { return String() << value; } + double toDouble() const override { return value; } + int toInt() const override { return value; } +protected: #ifdef USE_POOL_ALLOCATOR virtual void destroy() { boost::singleton_pool::free(this); } #endif - private: +private: int value; }; @@ -196,37 +250,35 @@ ScriptValueP to_script(int v) { // Boolean values class ScriptBool : public ScriptValue { - public: +public: ScriptBool(bool v) : value(v) {} - virtual ScriptType type() const { return SCRIPT_BOOL; } - virtual String typeName() const { return _TYPE_("boolean"); } - virtual operator String() const { return value ? _("true") : _("false"); } + ScriptType type() const override { return SCRIPT_BOOL; } + String typeName() const override { return _TYPE_("boolean"); } + String toString() const override { return value ? _("true") : _("false"); } + bool toBool() const override { return value; } // bools don't autoconvert to int - virtual operator bool() const { return value; } - private: +private: bool value; }; -// use integers to represent true/false /* NOTE: previous versions used ScriptInts as booleans, this gives problems * when we use a pool allocator for them, because the pool is destroyed before these globals. */ ScriptValueP script_true (new ScriptBool(true)); ScriptValueP script_false(new ScriptBool(false)); - // ----------------------------------------------------------------------------- : Doubles // Double values class ScriptDouble : public ScriptValue { - public: +public: ScriptDouble(double v) : value(v) {} - virtual ScriptType type() const { return SCRIPT_DOUBLE; } - virtual String typeName() const { return _TYPE_("double"); } - virtual operator String() const { return String() << value; } - virtual operator double() const { return value; } - virtual operator int() const { return (int)value; } - private: + ScriptType type() const override { return SCRIPT_DOUBLE; } + String typeName() const override { return _TYPE_("double"); } + String toString() const override { return String() << value; } + double toDouble() const override { return value; } + int toInt() const override { return (int)value; } +private: double value; }; @@ -238,12 +290,12 @@ ScriptValueP to_script(double v) { // String values class ScriptString : public ScriptValue { - public: +public: ScriptString(const String& v) : value(v) {} - virtual ScriptType type() const { return SCRIPT_STRING; } - virtual String typeName() const { return _TYPE_("string") + _(" (\"") + (value.size() < 30 ? value : value.substr(0,30) + _("...")) + _("\")"); } - virtual operator String() const { return value; } - virtual operator double() const { + ScriptType type() const override { return SCRIPT_STRING; } + String typeName() const override { return _TYPE_("string") + _(" (\"") + (value.size() < 30 ? value : value.substr(0,30) + _("...")) + _("\")"); } + String toString() const override { return value; } + double toDouble() const override { double d; if (value.ToDouble(&d)) { return d; @@ -251,7 +303,7 @@ class ScriptString : public ScriptValue { throw ScriptErrorConversion(value, typeName(), _TYPE_("double")); } } - virtual operator int() const { + int toInt() const override { long l; if (value.ToLong(&l)) { return l; @@ -259,7 +311,7 @@ class ScriptString : public ScriptValue { throw ScriptErrorConversion(value, typeName(), _TYPE_("integer")); } } - virtual operator bool() const { + bool toBool() const override { if (value == _("yes") || value == _("true")) { return true; } else if (value == _("no") || value == _("false") || value.empty()) { @@ -268,14 +320,14 @@ class ScriptString : public ScriptValue { throw ScriptErrorConversion(value, typeName(), _TYPE_("boolean")); } } - virtual operator Color() const { + Color toColor() const override { Color c = parse_color(value); if (!c.Ok()) { throw ScriptErrorConversion(value, typeName(), _TYPE_("color")); } return c; } - virtual operator wxDateTime() const { + wxDateTime toDateTime() const override { wxDateTime date; String::const_iterator end; if (!date.ParseDateTime(value,&end) || end != value.end()) { @@ -283,15 +335,15 @@ class ScriptString : public ScriptValue { } return date; } - virtual GeneratedImageP toImage(const ScriptValueP&) const { + GeneratedImageP toImage(const ScriptValueP&) const override { if (value.empty()) { return make_intrusive(); } else { return make_intrusive(value); } } - virtual int itemCount() const { return (int)value.size(); } - virtual ScriptValueP getMember(const String& name) const { + int itemCount() const override { return (int)value.size(); } + ScriptValueP getMember(const String& name) const override { // get member returns characters long index; if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) { @@ -300,7 +352,7 @@ class ScriptString : public ScriptValue { return delay_error(_ERROR_2_("has no member value", value, name)); } } - private: +private: String value; }; @@ -315,11 +367,11 @@ ScriptValueP to_script(const String& v) { class ScriptColor : public ScriptValue { public: ScriptColor(const Color& v) : value(v) {} - virtual ScriptType type() const { return SCRIPT_COLOR; } - virtual String typeName() const { return _TYPE_("color"); } - virtual operator Color() const { return value; } + ScriptType type() const override { return SCRIPT_COLOR; } + String typeName() const override { return _TYPE_("color"); } + Color toColor() const override { return value; } // colors don't auto convert to int, use to_int to force - virtual operator String() const { + String toString() const override { return format_color(value); } private: @@ -335,15 +387,15 @@ ScriptValueP to_script(Color v) { // wxDateTime values class ScriptDateTime : public ScriptValue { - public: +public: ScriptDateTime(const wxDateTime& v) : value(v) {} - virtual ScriptType type() const { return SCRIPT_DATETIME; } - virtual String typeName() const { return _TYPE_("date"); } - virtual operator wxDateTime() const { return value; } - virtual operator String() const { + ScriptType type() const override { return SCRIPT_DATETIME; } + String typeName() const override { return _TYPE_("date"); } + wxDateTime toDateTime() const override { return value; } + String toString() const override { return value.Format(_("%Y-%m-%d %H:%M:%S")); } - private: +private: wxDateTime value; }; @@ -359,27 +411,25 @@ class ScriptNil : public ScriptValue { public: ScriptType type() const override { return SCRIPT_NIL; } String typeName() const override { return _TYPE_("nil"); } - operator String() const override { return String(); } - operator double() const override { return 0.0; } - operator int() const override { return 0; } - operator bool() const override { return false; } - operator Color() const override { return wxTransparentColour; } + String toString() const override { return String(); } + double toDouble() const override { return 0.0; } + int toInt() const override { return 0; } + bool toBool() const override { return false; } + Color toColor() const override { return wxTransparentColour; } GeneratedImageP toImage(const ScriptValueP&) const { return make_intrusive(); } String toCode() const override { return "nil"; } - -protected: - virtual ScriptValueP do_eval(Context& ctx, bool) const { + ScriptValueP eval(Context& ctx, bool) const override { // nil(input) == input return ctx.getVariable(SCRIPT_VAR_input); } }; /// The preallocated nil value -ScriptValueP script_nil(new ScriptNil); +ScriptValueP script_nil = make_intrusive(); // ----------------------------------------------------------------------------- : Collection base @@ -401,10 +451,10 @@ String ScriptCollectionBase::toCode() const { // Iterator over a custom collection class ScriptCustomCollectionIterator : public ScriptIterator { -public: +public: ScriptCustomCollectionIterator(ScriptCustomCollection const* col, ScriptValueP const& col_owned) : col(col), col_owned(col_owned), pos(0), it(col->key_value.begin()) {} - virtual ScriptValueP next(ScriptValueP* key_out) { + ScriptValueP next(ScriptValueP* key_out) override { if (pos < col->value.size()) { if (key_out) *key_out = to_script((int)pos); return col->value.at(pos++); @@ -445,10 +495,10 @@ ScriptValueP ScriptCustomCollection::makeIterator(const ScriptValueP& thisP) con // Iterator over a concatenated collection class ScriptConcatCollectionIterator : public ScriptIterator { - public: +public: ScriptConcatCollectionIterator(const ScriptValueP& itA, const ScriptValueP& itB) : itA(itA), itB(itB) {} - virtual ScriptValueP next(ScriptValueP* key_out) { + ScriptValueP next(ScriptValueP* key_out) override { if (itA) { ScriptValueP v = itA->next(key_out); if (v) return v; @@ -457,7 +507,7 @@ class ScriptConcatCollectionIterator : public ScriptIterator { // TODO: somehow fix up the keys return itB->next(key_out); } - private: +private: ScriptValueP itA, itB; }; @@ -475,7 +525,7 @@ ScriptValueP ScriptConcatCollection::getMember(const String& name) const { } ScriptValueP ScriptConcatCollection::getIndex(int index) const { int itemsInA = a->itemCount(); - if (index < itemsInA) { + if (index < itemsInA) { return a->getIndex(index); } else { return b->getIndex(index - itemsInA); @@ -508,7 +558,7 @@ ScriptValueP ScriptClosure::simplify() { return fun->simplifyClosure(*this); } -ScriptValueP ScriptClosure::do_eval(Context& ctx, bool openScope) const { +ScriptValueP ScriptClosure::eval(Context& ctx, bool openScope) const { unique_ptr scope = openScope ? make_unique(ctx) : nullptr; applyBindings(ctx); return fun->eval(ctx, openScope); @@ -529,7 +579,7 @@ void ScriptClosure::applyBindings(Context& ctx) const { ScriptType ScriptRule::type() const { return SCRIPT_FUNCTION; } -String ScriptRule::typeName() const { return fun->typeName() + _(" rule"); } -ScriptValueP ScriptRule::do_eval(Context& ctx, bool openScope) const { +String ScriptRule::typeName() const { return fun->typeName() + _("_rule"); } +ScriptValueP ScriptRule::eval(Context& ctx, bool openScope) const { return ctx.makeClosure(fun); } diff --git a/src/script/value.hpp b/src/script/value.hpp index 52cec90b..281f9cb5 100644 --- a/src/script/value.hpp +++ b/src/script/value.hpp @@ -46,7 +46,7 @@ enum CompareWhat /// A value that can be handled by the scripting engine. /// Actual values are derived types class ScriptValue : public IntrusivePtrBaseWithDelete { - public: +public: virtual ~ScriptValue() {} /// Information on the type of this value @@ -58,31 +58,23 @@ class ScriptValue : public IntrusivePtrBaseWithDelete { virtual CompareWhat compareAs(String& compare_str, void const*& compare_ptr) const; /// Convert this value to a string - virtual operator String() const; + virtual String toString() const; /// Convert this value to a double - virtual operator double() const; + virtual double toDouble() const; /// Convert this value to an integer - virtual operator int() const; + virtual int toInt() const; /// Convert this value to a boolean - virtual operator bool() const; + virtual bool toBool() const; /// Convert this value to a color - virtual operator Color() const; + virtual Color toColor() const; /// Convert this value to a wxDateTime - virtual operator wxDateTime() const; + virtual wxDateTime toDateTime() const; + /// Convert this value to an image + virtual GeneratedImageP toImage(const ScriptValueP& thisP) const; /// Script code to generate this value virtual String toCode() const; - /// Explicit overload to convert to a string - /** This is sometimes necessary, because wxString has an int constructor, - * which confuses gcc. */ - inline String toString() const { return *this; } - /// Explicit overload to convert to a wxDateTime - /** Overload resolution is sometimes confused by other conversions */ - inline wxDateTime toDateTime() const { return *this; } - /// Convert this value to an image - virtual GeneratedImageP toImage(const ScriptValueP& thisP) const; - /// Get a member variable from this value virtual ScriptValueP getMember(const String& name) const; @@ -96,18 +88,16 @@ class ScriptValue : public IntrusivePtrBaseWithDelete { virtual ScriptValueP dependencyName(const ScriptValue& container, const Dependency&) const; /// Evaluate this value (if it is a function) - ScriptValueP eval(Context& ctx, bool openScope = true) const { - return do_eval(ctx, openScope); - } + virtual ScriptValueP eval(Context& ctx, bool openScope = true) const; /// Mark the scripts that this function depends on /** Return value is an abstract version of the return value of eval */ virtual ScriptValueP dependencies(Context&, const Dependency&) const; /// Simplify/optimize a default argument closure of this function. - /** Should return a simplification of the closure or null to keep the closure. + /** Should return a simplification of the closure or nullptr to keep the closure. * Alternatively, the closure may be modified in place. */ virtual ScriptValueP simplifyClosure(ScriptClosure&) const; - + /// Return an iterator for the current collection, an iterator is a value that has next() /** thisP is a shared_ptr for this collection, needed for the iterator to take ownership of it. * It can be null if the iterator always lives shorter than the collection. @@ -120,16 +110,8 @@ class ScriptValue : public IntrusivePtrBaseWithDelete { virtual int itemCount() const; /// Get a member at the given index virtual ScriptValueP getIndex(int index) const; - - protected: - virtual ScriptValueP do_eval(Context& ctx, bool openScope) const; }; -extern ScriptValueP script_nil; ///< The preallocated nil value -extern ScriptValueP script_true; ///< The preallocated true value -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 ScriptValueP& a, const ScriptValueP& b);