Commit 3fd47ec7 authored by twanvl's avatar twanvl

'ported' scripting code to work with unicode and the rest of MSE

parent 5a96fa68
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <data/game.hpp> #include <data/game.hpp>
#include <data/field.hpp> #include <data/field.hpp>
#include <util/error.hpp> #include <util/error.hpp>
#include <script/value.hpp>
DECLARE_TYPEOF_COLLECTION(FieldP); DECLARE_TYPEOF_COLLECTION(FieldP);
......
...@@ -7,10 +7,30 @@ ...@@ -7,10 +7,30 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <data/field.hpp> #include <data/field.hpp>
#include <data/field/text.hpp>
// ----------------------------------------------------------------------------- : Field // ----------------------------------------------------------------------------- : Field
Field::Field()
: index (0) // sensible default?
, editable (true)
, saveValue (true)
, showStatistics (true)
, identifying (false)
, cardListColumn (-1)
, cardListWidth (100)
, cardListAllow (true)
// , cardListAlign (ALIGN_LEFT)
, tabIndex (0)
{}
Field::~Field() {}
IMPLEMENT_REFLECTION(Field) { IMPLEMENT_REFLECTION(Field) {
if (!tag.reading()) {
String type = typeName();
REFLECT_N("type", type);
}
} }
template <> template <>
...@@ -18,10 +38,11 @@ shared_ptr<Field> read_new<Field>(Reader& reader) { ...@@ -18,10 +38,11 @@ shared_ptr<Field> read_new<Field>(Reader& reader) {
// there must be a type specified // there must be a type specified
String type; String type;
reader.handle(_("type"), type); reader.handle(_("type"), type);
// if (type == _("text")) { if (type == _("text")) {
// } else { return new_shared<TextField>();
} else {
throw "TODO"; throw "TODO";
// } }
} }
......
...@@ -41,14 +41,14 @@ class Field { ...@@ -41,14 +41,14 @@ class Field {
/// Creates a new Value corresponding to this Field /// Creates a new Value corresponding to this Field
/** thisP is a smart pointer to this */ /** thisP is a smart pointer to this */
virtual ValueP newValue(FieldP thisP) = 0; virtual ValueP newValue(const FieldP& thisP) const = 0;
/// Creates a new Style corresponding to this Field /// Creates a new Style corresponding to this Field
/** thisP is a smart pointer to this */ /** thisP is a smart pointer to this */
virtual StyleP newStyle(FieldP thisP) = 0; virtual StyleP newStyle(const FieldP& thisP) const = 0;
/// create a copy of this field /// create a copy of this field
virtual FieldP clone() = 0; virtual FieldP clone() const = 0;
/// Type of this field /// Type of this field
virtual String typeName() = 0; virtual String typeName() const = 0;
private: private:
DECLARE_REFLECTION_VIRTUAL(); DECLARE_REFLECTION_VIRTUAL();
...@@ -60,6 +60,7 @@ shared_ptr<Field> read_new<Field>(Reader& reader); ...@@ -60,6 +60,7 @@ shared_ptr<Field> read_new<Field>(Reader& reader);
// ----------------------------------------------------------------------------- : Style // ----------------------------------------------------------------------------- : Style
/// Style information needed to display a Value in a Field.
class Style { class Style {
public: public:
virtual ~Style(); virtual ~Style();
...@@ -72,13 +73,14 @@ void initObject(const FieldP&, StyleP&); ...@@ -72,13 +73,14 @@ void initObject(const FieldP&, StyleP&);
// ----------------------------------------------------------------------------- : Value // ----------------------------------------------------------------------------- : Value
/// A specific value 'in' a Field.
class Value { class Value {
public: public:
virtual ~Value(); virtual ~Value();
/// Create a copy of this value /// Create a copy of this value
virtual ValueP clone() = 0; virtual ValueP clone() const = 0;
private: private:
DECLARE_REFLECTION_VIRTUAL(); DECLARE_REFLECTION_VIRTUAL();
}; };
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <data/game.hpp> #include <data/game.hpp>
#include <data/field.hpp> #include <data/field.hpp>
#include <util/io/package_manager.hpp> #include <util/io/package_manager.hpp>
#include <script/value.hpp>
// ----------------------------------------------------------------------------- : Game // ----------------------------------------------------------------------------- : Game
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <data/set.hpp> #include <data/set.hpp>
#include <data/card.hpp> #include <data/card.hpp>
#include <script/value.hpp>
// ----------------------------------------------------------------------------- : Set // ----------------------------------------------------------------------------- : Set
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <util/io/writer.hpp> #include <util/io/writer.hpp>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/wfstream.h> #include <wx/wfstream.h>
#include <script/value.hpp>
// ----------------------------------------------------------------------------- : Extra types // ----------------------------------------------------------------------------- : Extra types
...@@ -105,7 +106,7 @@ IMPLEMENT_REFLECTION(Settings) { ...@@ -105,7 +106,7 @@ IMPLEMENT_REFLECTION(Settings) {
REFLECT_N("check updates", checkUpdates); REFLECT_N("check updates", checkUpdates);
// ioAll(io, "game settings", gameSettings); // ioAll(io, "game settings", gameSettings);
// ioStyleSettings(io); // ioStyleSettings(io);
REFLECT_N("default style settings", defaultStyleSettings); // REFLECT_N("default style settings", defaultStyleSettings);
} }
void Settings::read() { void Settings::read() {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <data/symbol.hpp> #include <data/symbol.hpp>
#include <gfx/bezier.hpp> #include <gfx/bezier.hpp>
#include <script/value.hpp>
DECLARE_TYPEOF_COLLECTION(SymbolPartP); DECLARE_TYPEOF_COLLECTION(SymbolPartP);
DECLARE_TYPEOF_COLLECTION(ControlPointP); DECLARE_TYPEOF_COLLECTION(ControlPointP);
......
...@@ -555,12 +555,6 @@ ...@@ -555,12 +555,6 @@
<File <File
RelativePath=".\data\card.hpp"> RelativePath=".\data\card.hpp">
</File> </File>
<File
RelativePath=".\data\field.cpp">
</File>
<File
RelativePath=".\data\field.hpp">
</File>
<File <File
RelativePath=".\data\game.cpp"> RelativePath=".\data\game.cpp">
</File> </File>
...@@ -674,6 +668,22 @@ ...@@ -674,6 +668,22 @@
RelativePath=".\data\format\mws.cpp"> RelativePath=".\data\format\mws.cpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="field"
Filter="">
<File
RelativePath=".\data\field.cpp">
</File>
<File
RelativePath=".\data\field.hpp">
</File>
<File
RelativePath=".\data\field\text.cpp">
</File>
<File
RelativePath=".\data\field\text.hpp">
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="util" Name="util"
...@@ -759,6 +769,12 @@ ...@@ -759,6 +769,12 @@
<Filter <Filter
Name="io" Name="io"
Filter=""> Filter="">
<File
RelativePath=".\util\io\get_member.cpp">
</File>
<File
RelativePath=".\util\io\get_member.hpp">
</File>
<File <File
RelativePath=".\util\io\package.cpp"> RelativePath=".\util\io\package.cpp">
<FileConfiguration <FileConfiguration
...@@ -900,6 +916,33 @@ ...@@ -900,6 +916,33 @@
<Filter <Filter
Name="script" Name="script"
Filter=""> Filter="">
<File
RelativePath=".\script\context.cpp">
</File>
<File
RelativePath=".\script\context.hpp">
</File>
<File
RelativePath=".\script\dependency.cpp">
</File>
<File
RelativePath=".\script\parser.cpp">
</File>
<File
RelativePath=".\script\parser.hpp">
</File>
<File
RelativePath=".\script\script.cpp">
</File>
<File
RelativePath=".\script\script.hpp">
</File>
<File
RelativePath=".\script\value.cpp">
</File>
<File
RelativePath=".\script\value.hpp">
</File>
</Filter> </Filter>
<File <File
RelativePath=".\code_template.cpp"> RelativePath=".\code_template.cpp">
......
...@@ -20,7 +20,7 @@ DECLARE_TYPEOF_COLLECTION(Context::Binding); ...@@ -20,7 +20,7 @@ DECLARE_TYPEOF_COLLECTION(Context::Binding);
class DependencyDummy : public ScriptIterator { class DependencyDummy : public ScriptIterator {
public: public:
virtual ScriptType type() const { return SCRIPT_DUMMY; } virtual ScriptType type() const { return SCRIPT_DUMMY; }
virtual String typeName() const { return "dummy"; } virtual String typeName() const { return _("dummy"); }
virtual ScriptValueP next() { return ScriptValueP(); } virtual ScriptValueP next() { return ScriptValueP(); }
}; };
...@@ -39,7 +39,7 @@ class DependencyUnion : public ScriptValue { ...@@ -39,7 +39,7 @@ class DependencyUnion : public ScriptValue {
{} {}
virtual ScriptType type() const { return SCRIPT_DUMMY; } virtual ScriptType type() const { return SCRIPT_DUMMY; }
virtual String typeName() const { return "union of " + a->typeName() + " and " + b->typeName(); } virtual String typeName() const { return _("union of ") + a->typeName() + _(" and ") + b->typeName(); }
virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const { virtual ScriptValueP dependencies(Context& ctx, const Dependency& dep) const {
return unified( a->dependencies(ctx,dep), b->dependencies(ctx,dep)); return unified( a->dependencies(ctx,dep), b->dependencies(ctx,dep));
...@@ -85,22 +85,25 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script) ...@@ -85,22 +85,25 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script)
// - member operator; and it signals a dependency. // - member operator; and it signals a dependency.
// - looper construction // - looper construction
// - + for function composition // - + for function composition
// Variable assignments are performed as normall.
// Jumps are tricky: // Jumps are tricky:
// - I_JUMP: Just follow them, but see below
// - I_JUMP_IF_NOT: We don't know the value of the condition, evaluate both branches.
// The simple solution would be to use recursion to fork off one of the cases.
// This could result in an exponential increase in execution time,
// because the analysis after an if statement is duplicated.
// A better solution is to evalutate branches 'in parallel'. After the if statement
// the net stack effect is +1, the top element will then be a DependencyUnion object.
// To detect the joining of the branches we look for I_JUMPs, the non jumping branch will have
// a I_JUMP at the end, when we encounter it we start evaluating the other if branch.
// - I_LOOP: We want to prevent infinite loops, the solution is that after the first // - I_LOOP: We want to prevent infinite loops, the solution is that after the first
// iteration we set the looper to a dummy value, so the loop is only executed once. // iteration we set the looper to a dummy value, so the loop is only executed once.
// TODO: This could result in false negatives when iterating over things like fields. // TODO: This could result in false negatives when iterating over things like fields.
// We ignore this, because loops are usually only used for exporting, where dependency // We ignore this, because loops are usually only used for exporting, where dependency
// analysis is not used anyway. // analysis is not used anyway.
// Variable assignments are performed as normall. // - I_JUMP_IF_NOT: We don't know the value of the condition, so we must evaluate both branches.
// The simple solution would be to use recursion to fork off one of the cases.
// This could result in an exponential increase in execution time,
// because the analysis after an if statement is duplicated.
// A better solution is to evalutate branches 'in parallel'.
// We create a jump record for taking the branch, and evaluate the fall through case.
// When later a jump record points to the current instruction the stack and variables of that
// record are unify with the current execution path.
// - I_JUMP: We must can not follow all jumps, because they may lead to a point beyond a jump record,
// we can then no longer hope to unify with that jump record.
// Instead we create a new jump record, and follow the jump record with the lowest target address.
// This story doesn't hold for backwards jumps, we can safely follow those (see I_LOOP above)
// Scope for evaluating this script. // Scope for evaluating this script.
size_t stack_size = stack.size(); size_t stack_size = stack.size();
......
...@@ -10,10 +10,13 @@ ...@@ -10,10 +10,13 @@
#include <script/parser.hpp> #include <script/parser.hpp>
#include <util/error.hpp> #include <util/error.hpp>
#include <stack> #include <stack>
#include <boost/lexical_cast.hpp> //%%
DECLARE_TYPEOF_COLLECTION(int); DECLARE_TYPEOF_COLLECTION(int);
#ifdef __WXMSW__
#define TokenType TokenType_ // some stupid windows header uses our name
#endif
// ----------------------------------------------------------------------------- : Tokenizing : class // ----------------------------------------------------------------------------- : Tokenizing : class
enum TokenType enum TokenType
...@@ -70,8 +73,6 @@ class TokenIterator { ...@@ -70,8 +73,6 @@ class TokenIterator {
// ----------------------------------------------------------------------------- : Characters // ----------------------------------------------------------------------------- : Characters
// TODO: isxx -> isXX!
bool isAlpha_(Char c) { return isAlpha(c) || c==_('_'); } bool isAlpha_(Char c) { return isAlpha(c) || c==_('_'); }
bool isAlnum_(Char c) { return isAlnum(c) || c==_('_'); } bool isAlnum_(Char c) { return isAlnum(c) || c==_('_'); }
bool isOper (Char c) { return c==_('+') || c==_('-') || c==_('*') || c==_('/') || c==_('!') || c==_('.') || bool isOper (Char c) { return c==_('+') || c==_('-') || c==_('*') || c==_('/') || c==_('!') || c==_('.') ||
...@@ -102,34 +103,34 @@ const Token& TokenIterator::read() { ...@@ -102,34 +103,34 @@ const Token& TokenIterator::read() {
} }
void TokenIterator::putBack() { void TokenIterator::putBack() {
Token t = {TOK_NEWLINE, "\n"}; Token t = {TOK_NEWLINE, _("\n")};
buffer.insert(buffer.begin(), t); buffer.insert(buffer.begin(), t);
} }
void TokenIterator::addToken() { void TokenIterator::addToken() {
if (pos >= input.size()) { if (pos >= input.size()) {
// EOF // EOF
Token t = {TOK_EOF, "end of input"}; Token t = {TOK_EOF, _("end of input")};
buffer.push_back(t); buffer.push_back(t);
return; return;
} }
// read a character from the input // read a character from the input
Char c = input[pos++]; //% input.GetChar(pos++); Char c = input.GetChar(pos++);
if (c == _('\n')) { if (c == _('\n')) {
Token t = { TOK_NEWLINE, "newline" }; Token t = {TOK_NEWLINE, _("newline")};
buffer.push_back(t); buffer.push_back(t);
} else if (isSpace(c)) { } else if (isSpace(c)) {
// ignore // ignore
} else if (isAlpha(c)) { } else if (isAlpha(c)) {
// name // name
size_t start = pos - 1; size_t start = pos - 1;
while (pos < input.size() && isalnum(input[pos])) ++pos; //%% isAlnum_(input.getChar(pos))) pos++; while (pos < input.size() && isAlnum_(input.GetChar(pos))) ++pos;
Token t = {TOK_NAME, cannocialNameForm(input.substr(start, pos-start)) }; // convert name to cannocial form Token t = {TOK_NAME, cannocialNameForm(input.substr(start, pos-start)) }; // convert name to cannocial form
buffer.push_back(t); buffer.push_back(t);
} else if (isDigit(c)) { } else if (isDigit(c)) {
// number // number
size_t start = pos - 1; size_t start = pos - 1;
while (pos < input.size() && isDigitOrDot(input[pos])) ++pos; while (pos < input.size() && isDigitOrDot(input.GetChar(pos))) ++pos;
String num = input.substr(start, pos-start); String num = input.substr(start, pos-start);
Token t = { Token t = {
num.find_first_of('.') == String::npos ? TOK_INT : TOK_DOUBLE, num.find_first_of('.') == String::npos ? TOK_INT : TOK_DOUBLE,
...@@ -172,7 +173,6 @@ void TokenIterator::addToken() { ...@@ -172,7 +173,6 @@ void TokenIterator::addToken() {
while (pos < input.size() && input[pos] != _('\n')) ++pos; while (pos < input.size() && input[pos] != _('\n')) ++pos;
} else { } else {
throw ScriptParseError(_("Unknown character in script: '") + String(1,c) + _("'")); throw ScriptParseError(_("Unknown character in script: '") + String(1,c) + _("'"));
assert(false);
} }
} }
...@@ -360,14 +360,14 @@ void parseExpr(TokenIterator& input, Script& script, Precedence minPrec) { ...@@ -360,14 +360,14 @@ void parseExpr(TokenIterator& input, Script& script, Precedence minPrec) {
script.addInstruction(I_GET_VAR, var); script.addInstruction(I_GET_VAR, var);
} }
} else if (token == TOK_INT) { } else if (token == TOK_INT) {
long l; long l = 0;
l = lexical_cast<long>(token.value); //l = lexical_cast<long>(token.value);
//token.value.toLong(l); token.value.ToLong(&l);
script.addInstruction(I_PUSH_CONST, toScript(l)); script.addInstruction(I_PUSH_CONST, toScript(l));
} else if (token == TOK_DOUBLE) { } else if (token == TOK_DOUBLE) {
double d; double d = 0;
d = lexical_cast<double>(token.value); //d = lexical_cast<double>(token.value);
//token.value.toDouble(d); token.value.ToDouble(&d);
script.addInstruction(I_PUSH_CONST, toScript(d)); script.addInstruction(I_PUSH_CONST, toScript(d));
} else if (token == TOK_STRING) { } else if (token == TOK_STRING) {
script.addInstruction(I_PUSH_CONST, toScript(token.value)); script.addInstruction(I_PUSH_CONST, toScript(token.value));
...@@ -404,7 +404,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc ...@@ -404,7 +404,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
// not an expression. Remove that instruction. // not an expression. Remove that instruction.
Instruction instr = script.getInstructions().back(); Instruction instr = script.getInstructions().back();
if (instr.instr != I_GET_VAR) { if (instr.instr != I_GET_VAR) {
throw ScriptParseError("Can only assign to variables"); throw ScriptParseError(_("Can only assign to variables"));
} else { } else {
script.getInstructions().pop_back(); script.getInstructions().pop_back();
parseOper(input, script, PREC_SET, I_SET_VAR, instr.data); parseOper(input, script, PREC_SET, I_SET_VAR, instr.data);
......
...@@ -8,17 +8,17 @@ ...@@ -8,17 +8,17 @@
#include <script/script.hpp> #include <script/script.hpp>
#include <script/context.hpp> #include <script/context.hpp>
#include <boost/lexical_cast.hpp> #include <util/error.hpp>
// ----------------------------------------------------------------------------- : Variables // ----------------------------------------------------------------------------- : Variables
typedef map<string, unsigned int> Variables; typedef map<String, unsigned int> Variables;
Variables variables; Variables variables;
DECLARE_TYPEOF(Variables); DECLARE_TYPEOF(Variables);
/// Return a unique name for a variable to allow for faster loopups /// Return a unique name for a variable to allow for faster loopups
unsigned int stringToVariable(const String& s) { unsigned int stringToVariable(const String& s) {
map<string, unsigned int>::iterator it = variables.find(s); map<String, unsigned int>::iterator it = variables.find(s);
if (it == variables.end()) { if (it == variables.end()) {
unsigned int v = (unsigned int)variables.size(); unsigned int v = (unsigned int)variables.size();
variables.insert(make_pair(s,v)); variables.insert(make_pair(s,v));
...@@ -35,7 +35,7 @@ String variableToString(unsigned int v) { ...@@ -35,7 +35,7 @@ String variableToString(unsigned int v) {
FOR_EACH(vi, variables) { FOR_EACH(vi, variables) {
if (vi.second == v) return vi.first; if (vi.second == v) return vi.first;
} }
throw "Variable not found: " + lexical_cast<String>(v); throw ScriptError(String(_("Variable not found: ")) << v);
} }
// ----------------------------------------------------------------------------- : Script // ----------------------------------------------------------------------------- : Script
...@@ -44,7 +44,7 @@ ScriptType Script::type() const { ...@@ -44,7 +44,7 @@ ScriptType Script::type() const {
return SCRIPT_SCRIPT_FUN; return SCRIPT_SCRIPT_FUN;
} }
String Script::typeName() const { String Script::typeName() const {
return "function"; return _("function");
} }
ScriptValueP Script::eval(Context& ctx) const { ScriptValueP Script::eval(Context& ctx) const {
return ctx.eval(*this); return ctx.eval(*this);
...@@ -90,6 +90,8 @@ unsigned int Script::getLabel() const { ...@@ -90,6 +90,8 @@ unsigned int Script::getLabel() const {
DECLARE_TYPEOF_COLLECTION(Instruction); DECLARE_TYPEOF_COLLECTION(Instruction);
#if 0 // debugging
String Script::dumpScript() const { String Script::dumpScript() const {
String ret; String ret;
int pos = 0; int pos = 0;
...@@ -163,3 +165,4 @@ String Script::dumpInstr(unsigned int pos, Instruction i) const { ...@@ -163,3 +165,4 @@ String Script::dumpInstr(unsigned int pos, Instruction i) const {
return ret; return ret;
} }
#endif
...@@ -8,22 +8,21 @@ ...@@ -8,22 +8,21 @@
#include <script/value.hpp> #include <script/value.hpp>
#include <util/error.hpp> #include <util/error.hpp>
#include <boost/lexical_cast.hpp> //%%
#include <boost/pool/singleton_pool.hpp> #include <boost/pool/singleton_pool.hpp>
// ----------------------------------------------------------------------------- : ScriptValue // ----------------------------------------------------------------------------- : ScriptValue
// Base cases // Base cases
ScriptValue::operator String() const { return "[[" + typeName() + "]]"; } ScriptValue::operator String() const { return _("[[") + typeName() + _("]]"); }
ScriptValue::operator int() const { throw ScriptError("Can't convert from "+typeName()+" to integer number"); } ScriptValue::operator int() const { throw ScriptError(_("Can't convert from ")+typeName()+_(" to integer number")); }
ScriptValue::operator double() const { throw ScriptError("Can't convert from "+typeName()+" to real number" ); } ScriptValue::operator double() const { throw ScriptError(_("Can't convert from ")+typeName()+_(" to real number" )); }
ScriptValue::operator Color() const { throw ScriptError("Can't convert from "+typeName()+" to color" ); } ScriptValue::operator Color() const { throw ScriptError(_("Can't convert from ")+typeName()+_(" to color" )); }
ScriptValueP ScriptValue::eval(Context&) const ScriptValueP ScriptValue::eval(Context&) const
{ throw ScriptError("Can't convert from "+typeName()+" to function" ); } { throw ScriptError(_("Can't convert from ")+typeName()+_(" to function" )); }
ScriptValueP ScriptValue::getMember(const String& name) const ScriptValueP ScriptValue::getMember(const String& name) const
{ throw (typeName() + " has no member '" + name + "'"); } { throw (typeName() + _(" has no member '") + name + _("'")); }
ScriptValueP ScriptValue::next() { throw InternalError("Can't convert from "+typeName()+" to iterator"); } ScriptValueP ScriptValue::next() { throw InternalError(_("Can't convert from ")+typeName()+_(" to iterator")); }
ScriptValueP ScriptValue::makeIterator() const { throw ScriptError("Can't convert from "+typeName()+" to collection"); } ScriptValueP ScriptValue::makeIterator() const { throw ScriptError( _("Can't convert from ")+typeName()+_(" to collection")); }
void ScriptValue::signalDependent(Context&, const Dependency&, const String& name) {} void ScriptValue::signalDependent(Context&, const Dependency&, const String& name) {}
ScriptValueP ScriptValue::dependencies( Context&, const Dependency&) const { return scriptNil; } ScriptValueP ScriptValue::dependencies( Context&, const Dependency&) const { return scriptNil; }
...@@ -32,7 +31,7 @@ ScriptValueP ScriptValue::dependencies( Context&, const Dependency&) const { r ...@@ -32,7 +31,7 @@ ScriptValueP ScriptValue::dependencies( Context&, const Dependency&) const { r
// ----------------------------------------------------------------------------- : Iterators // ----------------------------------------------------------------------------- : Iterators
ScriptType ScriptIterator::type() const { return SCRIPT_OBJECT; } ScriptType ScriptIterator::type() const { return SCRIPT_OBJECT; }
String ScriptIterator::typeName() const { return "iterator"; } String ScriptIterator::typeName() const { return _("iterator"); }
// Iterator over a range of integers // Iterator over a range of integers
class ScriptRangeIterator : public ScriptIterator { class ScriptRangeIterator : public ScriptIterator {
...@@ -62,8 +61,8 @@ class ScriptInt : public ScriptValue { ...@@ -62,8 +61,8 @@ class ScriptInt : public ScriptValue {
public: public:
ScriptInt(int v) : value(v) {} ScriptInt(int v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_INT; } virtual ScriptType type() const { return SCRIPT_INT; }
virtual String typeName() const { return "integer number"; } virtual String typeName() const { return _("integer number"); }
virtual operator String() const { return lexical_cast<String>(value); } virtual operator String() const { return String() << value; }
virtual operator double() const { return value; } virtual operator double() const { return value; }
virtual operator int() const { return value; } virtual operator int() const { return value; }
protected: protected:
...@@ -93,8 +92,8 @@ class ScriptDouble : public ScriptValue { ...@@ -93,8 +92,8 @@ class ScriptDouble : public ScriptValue {
public: public:
ScriptDouble(double v) : value(v) {} ScriptDouble(double v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_DOUBLE; } virtual ScriptType type() const { return SCRIPT_DOUBLE; }
virtual String typeName() const { return "real number"; } virtual String typeName() const { return _("real number"); }
virtual operator String() const { return lexical_cast<String>(value); } virtual operator String() const { return String() << value; }
virtual operator double() const { return value; } virtual operator double() const { return value; }
virtual operator int() const { return (int)value; } virtual operator int() const { return (int)value; }
private: private:
...@@ -112,10 +111,24 @@ class ScriptString : public ScriptValue { ...@@ -112,10 +111,24 @@ class ScriptString : public ScriptValue {
public: public:
ScriptString(const String& v) : value(v) {} ScriptString(const String& v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_STRING; } virtual ScriptType type() const { return SCRIPT_STRING; }
virtual String typeName() const { return "string"; } virtual String typeName() const { return _("string"); }
virtual operator String() const { return value; } virtual operator String() const { return value; }
virtual operator double() const { return lexical_cast<double>(value); } virtual operator double() const {
virtual operator int() const { return lexical_cast<int>(value); } double d;
if (value.ToDouble(&d)) {
return d;
} else {
throw ScriptError(_("Not a number: '") + value + _("'"));
}
}
virtual operator int() const {
long l;
if (value.ToLong(&l)) {
return l;
} else {
throw ScriptError(_("Not a number: '") + value + _("'"));
}
}
private: private:
String value; String value;
}; };
...@@ -132,7 +145,7 @@ class ScriptColor : public ScriptValue { ...@@ -132,7 +145,7 @@ class ScriptColor : public ScriptValue {
public: public:
ScriptColor(const Color& v) : value(v) {} ScriptColor(const Color& v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_COLOR; } virtual ScriptType type() const { return SCRIPT_COLOR; }
virtual String typeName() const { return "color"; } virtual String typeName() const { return _("color"); }
private: private:
Color value; Color value;
}; };
...@@ -148,8 +161,8 @@ ScriptValueP toScript(const Color& v) { ...@@ -148,8 +161,8 @@ ScriptValueP toScript(const Color& v) {
class ScriptNil : public ScriptValue { class ScriptNil : public ScriptValue {
public: public:
virtual ScriptType type() const { return SCRIPT_NIL; } virtual ScriptType type() const { return SCRIPT_NIL; }
virtual String typeName() const { return "nil"; } virtual String typeName() const { return _("nil"); }
virtual operator String() const { return ""; } virtual operator String() const { return wxEmptyString; }
virtual operator double() const { return 0.0; } virtual operator double() const { return 0.0; }
virtual operator int() const { return 0; } virtual operator int() const { return 0; }
}; };
......
...@@ -10,35 +10,22 @@ ...@@ -10,35 +10,22 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp> #include <util/prec.hpp>
#include <util/error.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/lexical_cast.hpp> //%%
//#ifndef WINVER
//#define WINVER 0x0501
//#endif
//#include <winresrc.h>
//#include <windef.h>
//#include <winbase.h> // Interlocked*crement
#include <windows.h>
#define TokenType TokenType_
extern "C" {
LONG __cdecl _InterlockedIncrement(LONG volatile *Addend);
LONG __cdecl _InterlockedDecrement(LONG volatile *Addend);
}
#pragma intrinsic (_InterlockedIncrement)
#define InterlockedIncrement _InterlockedIncrement
#pragma intrinsic (_InterlockedDecrement)
#define InterlockedDecrement _InterlockedDecrement
//long __declspec(dllimport) __stdcall InterlockedDecrement(long volatile* Addend);
//long __declspec(dllimport) __stdcall InterlockedIncrement(long volatile* Addend);
//#pragma intrinsic(_InterlockedIncrement)
//#pragma intrinsic( _InterlockedDecrement )
class Context; class Context;
class Dependency; class Dependency;
#ifdef _MSC_VER
extern "C" {
LONG __cdecl _InterlockedIncrement(LONG volatile *Addend);
LONG __cdecl _InterlockedDecrement(LONG volatile *Addend);
}
#pragma intrinsic (_InterlockedIncrement)
#define InterlockedIncrement _InterlockedIncrement
#pragma intrinsic (_InterlockedDecrement)
#define InterlockedDecrement _InterlockedDecrement
#endif
// ----------------------------------------------------------------------------- : ScriptValue // ----------------------------------------------------------------------------- : ScriptValue
//DECLARE_POINTER_TYPE(ScriptValue); //DECLARE_POINTER_TYPE(ScriptValue);
...@@ -161,10 +148,14 @@ class ScriptCollection : public ScriptValue { ...@@ -161,10 +148,14 @@ class ScriptCollection : public ScriptValue {
public: public:
inline ScriptCollection(const Collection* v) : value(v) {} inline ScriptCollection(const Collection* v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_OBJECT; } virtual ScriptType type() const { return SCRIPT_OBJECT; }
virtual String typeName() const { return "collection"; } virtual String typeName() const { return _("collection"); }
virtual ScriptValueP getMember(const String& name) const { virtual ScriptValueP getMember(const String& name) const {
int index = lexical_cast<int>(name); long index;
return toScript(value->at(index)); if (name.ToLong(&index)) {
return toScript(value->at(index));
} else {
throw ScriptError(_("Collection has no member ") + name);
}
} }
virtual ScriptValueP makeIterator() const { virtual ScriptValueP makeIterator() const {
return new_intrusive1<ScriptCollectionIterator<Collection> >(value); return new_intrusive1<ScriptCollectionIterator<Collection> >(value);
...@@ -182,7 +173,7 @@ class ScriptObject : public ScriptValue { ...@@ -182,7 +173,7 @@ class ScriptObject : public ScriptValue {
public: public:
inline ScriptObject(const shared_ptr<T>& v) : value(v) {} inline ScriptObject(const shared_ptr<T>& v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_OBJECT; } virtual ScriptType type() const { return SCRIPT_OBJECT; }
virtual String typeName() const { return "object"; } virtual String typeName() const { return _("object"); }
virtual ScriptValueP getMember(const String& name) const { virtual ScriptValueP getMember(const String& name) const {
GetMember gm(name); GetMember gm(name);
gm.handle(*value); gm.handle(*value);
...@@ -246,6 +237,7 @@ inline ScriptValueP toScript(const shared_ptr<T>& v) { return new_intrusive1<Scr ...@@ -246,6 +237,7 @@ inline ScriptValueP toScript(const shared_ptr<T>& v) { return new_intrusive1<Scr
* @code * @code
* SCRIPT_FUNCTION(my_function) { * SCRIPT_FUNCTION(my_function) {
* SCRIPT_PARAM(String, my_string_param); * SCRIPT_PARAM(String, my_string_param);
* ...
* } * }
* @endcode * @endcode
* Throws an error if the parameter is not found. * Throws an error if the parameter is not found.
......
...@@ -64,5 +64,21 @@ class ParseError : public Error { ...@@ -64,5 +64,21 @@ class ParseError : public Error {
inline ParseError(const String& str) : Error(str) {} inline ParseError(const String& str) : Error(str) {}
}; };
/// Parse error in a script
class ScriptParseError : public ParseError {
public:
inline ScriptParseError(const String& str) : ParseError(str) {}
inline ScriptParseError(const String& exp, const String& found)
: ParseError(_("Expected '") + exp + _("' instead of '") + found + _("'")) {}
};
// ----------------------------------------------------------------------------- : Script errors
/// A runtime error in a script
class ScriptError : public Error {
public:
inline ScriptError(const String& str) : Error(str) {}
};
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <util/io/get_member.hpp> #include <util/io/get_member.hpp>
#include <util/vector2d.hpp>
#include <script/value.hpp> #include <script/value.hpp>
// ----------------------------------------------------------------------------- : GetMember // ----------------------------------------------------------------------------- : GetMember
...@@ -20,3 +21,7 @@ void GetMember::store(const int v) { value = toScript(v); } ...@@ -20,3 +21,7 @@ void GetMember::store(const int v) { value = toScript(v); }
void GetMember::store(const unsigned int v) { value = toScript((int)v); } void GetMember::store(const unsigned int v) { value = toScript((int)v); }
void GetMember::store(const double v) { value = toScript(v); } void GetMember::store(const double v) { value = toScript(v); }
void GetMember::store(const bool v) { value = toScript(v); } void GetMember::store(const bool v) { value = toScript(v); }
void GetMember::store(const Vector2D& v) {
value = toScript(String::Format(_("(%.10lf,%.10lf)"), v.x, v.y));
}
...@@ -16,6 +16,8 @@ typedef boost::intrusive_ptr<ScriptValue> ScriptValueP; ...@@ -16,6 +16,8 @@ typedef boost::intrusive_ptr<ScriptValue> ScriptValueP;
inline void intrusive_ptr_add_ref(ScriptValue* p); inline void intrusive_ptr_add_ref(ScriptValue* p);
inline void intrusive_ptr_release(ScriptValue* p); inline void intrusive_ptr_release(ScriptValue* p);
class Vector2D;
// ----------------------------------------------------------------------------- : GetMember // ----------------------------------------------------------------------------- : GetMember
/// Find a member with a specific name using reflection /// Find a member with a specific name using reflection
...@@ -43,6 +45,7 @@ class GetMember { ...@@ -43,6 +45,7 @@ class GetMember {
/// Store something in the return value /// Store something in the return value
void store(const String& v); void store(const String& v);
void store(const Vector2D& v);
void store(const int v); void store(const int v);
void store(const unsigned int v); void store(const unsigned int v);
void store(const double v); void store(const double v);
...@@ -71,9 +74,9 @@ class GetMember { ...@@ -71,9 +74,9 @@ class GetMember {
// ----------------------------------------------------------------------------- : Reflection for enumerations // ----------------------------------------------------------------------------- : Reflection for enumerations
/// Implement enum reflection as used by Writer /// Implement enum reflection as used by GetMember
#define REFLECT_ENUM_WRITER(Enum) \ #define REFLECT_ENUM_GET_MEMBER(Enum) \
template<> void Writer::handle<Enum>(const Enum& enum_) { \ template<> void GetMember::handle<Enum>(const Enum& enum_) {\
EnumGetMember gm(*this); \ EnumGetMember gm(*this); \
reflect_ ## Enum(const_cast<Enum&>(enum_), gm); \ reflect_ ## Enum(const_cast<Enum&>(enum_), gm); \
} }
...@@ -88,7 +91,7 @@ class EnumGetMember { ...@@ -88,7 +91,7 @@ class EnumGetMember {
template <typename Enum> template <typename Enum>
inline void handle(const Char* name, Enum value, Enum enum_) { inline void handle(const Char* name, Enum value, Enum enum_) {
if (enum_ == value) { if (enum_ == value) {
writer.store(name); getMember.store(name);
} }
} }
......
...@@ -105,7 +105,5 @@ template <> void Writer::handle(const bool& value) { ...@@ -105,7 +105,5 @@ template <> void Writer::handle(const bool& value) {
// ----------------------------------------------------------------------------- : Handling less basic util types // ----------------------------------------------------------------------------- : Handling less basic util types
template <> void Writer::handle(const Vector2D& vec) { template <> void Writer::handle(const Vector2D& vec) {
String formated; handle(String::Format(_("(%.10lf,%.10lf)"), vec.x, vec.y));
formated.Printf(_("(%.10lf,%.10lf)"), vec.x, vec.y);
handle(formated);
} }
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "io/reader.hpp" #include "io/reader.hpp"
#include "io/writer.hpp" #include "io/writer.hpp"
#include "io/get_member.hpp"
// ----------------------------------------------------------------------------- : Declaring reflection // ----------------------------------------------------------------------------- : Declaring reflection
...@@ -27,8 +28,10 @@ ...@@ -27,8 +28,10 @@
template<class Tag> void reflect_impl(Tag& tag); \ template<class Tag> void reflect_impl(Tag& tag); \
friend class Reader; \ friend class Reader; \
friend class Writer; \ friend class Writer; \
friend class GetMember; \
void reflect(Reader& reader); \ void reflect(Reader& reader); \
void reflect(Writer& writer) void reflect(Writer& writer); \
void reflect(GetMember& getMember)
/// Declare that a class supports reflection, which can be overridden in derived classes /// Declare that a class supports reflection, which can be overridden in derived classes
#define DECLARE_REFLECTION_VIRTUAL() \ #define DECLARE_REFLECTION_VIRTUAL() \
...@@ -36,8 +39,10 @@ ...@@ -36,8 +39,10 @@
template<class Tag> void reflect_impl(Tag& tag); \ template<class Tag> void reflect_impl(Tag& tag); \
friend class Reader; \ friend class Reader; \
friend class Writer; \ friend class Writer; \
friend class GetMember; \
virtual void reflect(Reader& reader); \ virtual void reflect(Reader& reader); \
virtual void reflect(Writer& writer) virtual void reflect(Writer& writer); \
virtual void reflect(GetMember& getMember)
// ----------------------------------------------------------------------------- : Implementing reflection // ----------------------------------------------------------------------------- : Implementing reflection
...@@ -47,6 +52,7 @@ ...@@ -47,6 +52,7 @@
* Currently creates the methods: * Currently creates the methods:
* - Reader::handle(Cls&) * - Reader::handle(Cls&)
* - Writer::handle(Cls&) * - Writer::handle(Cls&)
* - GetMember::handle(Cls&)
* Usage: * Usage:
* @code * @code
* IMPLEMENT_REFLECTION(MyClass) { * IMPLEMENT_REFLECTION(MyClass) {
...@@ -58,6 +64,7 @@ ...@@ -58,6 +64,7 @@
#define IMPLEMENT_REFLECTION(Cls) \ #define IMPLEMENT_REFLECTION(Cls) \
REFLECT_OBJECT_READER(Cls) \ REFLECT_OBJECT_READER(Cls) \
REFLECT_OBJECT_WRITER(Cls) \ REFLECT_OBJECT_WRITER(Cls) \
REFLECT_OBJECT_GET_MEMBER(Cls) \
/* Extra level, so it can be declared virtual */ \ /* Extra level, so it can be declared virtual */ \
void Cls::reflect(Reader& reader) { \ void Cls::reflect(Reader& reader) { \
reflect_impl(reader); \ reflect_impl(reader); \
...@@ -65,6 +72,9 @@ ...@@ -65,6 +72,9 @@
void Cls::reflect(Writer& writer) { \ void Cls::reflect(Writer& writer) { \
reflect_impl(writer); \ reflect_impl(writer); \
} \ } \
void Cls::reflect(GetMember& getMember) { \
reflect_impl(getMember); \
} \
template <class Tag> \ template <class Tag> \
void Cls::reflect_impl(Tag& tag) void Cls::reflect_impl(Tag& tag)
...@@ -93,12 +103,14 @@ ...@@ -93,12 +103,14 @@
* Currently creates the methods: * Currently creates the methods:
* - Reader::handle(Enum& * - Reader::handle(Enum&
* - Writer::handle(const Enum&) * - Writer::handle(const Enum&)
* - GetMember::handle(const Enum&)
*/ */
#define IMPLEMENT_REFLECTION_ENUM(Enum) \ #define IMPLEMENT_REFLECTION_ENUM(Enum) \
template <class Tag> \ template <class Tag> \
void reflect_ ## Enum (Enum& enum_, Tag& tag); \ void reflect_ ## Enum (Enum& enum_, Tag& tag); \
REFLECT_ENUM_READER(Enum) \ REFLECT_ENUM_READER(Enum) \
REFLECT_ENUM_WRITER(Enum) \ REFLECT_ENUM_WRITER(Enum) \
REFLECT_ENUM_GET_MEMBER(Enum) \
template <class Tag> \ template <class Tag> \
void reflect_ ## Enum (Enum& enum_, Tag& tag) void reflect_ ## Enum (Enum& enum_, Tag& tag)
......
...@@ -14,7 +14,14 @@ ...@@ -14,7 +14,14 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
// MOVEME
/// Using intrusive_ptr where possible? (as opposed to smart_ptr)
#define USE_INTRUSIVE_PTR
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#ifdef USE_INTRUSIVE_PTR
#include <boost/intrusive_ptr.hpp>
#endif
using namespace boost; using namespace boost;
// ----------------------------------------------------------------------------- : Declaring // ----------------------------------------------------------------------------- : Declaring
...@@ -31,7 +38,6 @@ template <typename T> ...@@ -31,7 +38,6 @@ template <typename T>
inline shared_ptr<T> new_shared() { inline shared_ptr<T> new_shared() {
return shared_ptr<T>(new T()); return shared_ptr<T>(new T());
} }
/// Allocate a new shared-pointed object, given one argument to pass to the ctor of T /// Allocate a new shared-pointed object, given one argument to pass to the ctor of T
template <typename T, typename A0> template <typename T, typename A0>
inline shared_ptr<T> new_shared1(const A0& a0) { inline shared_ptr<T> new_shared1(const A0& a0) {
...@@ -58,5 +64,33 @@ inline shared_ptr<T> new_shared7(const A0& a0, const A1& a1, const A2& a2, const ...@@ -58,5 +64,33 @@ inline shared_ptr<T> new_shared7(const A0& a0, const A1& a1, const A2& a2, const
return shared_ptr<T>(new T(a0, a1, a2, a3, a4, a5, a6)); return shared_ptr<T>(new T(a0, a1, a2, a3, a4, a5, a6));
} }
// ----------------------------------------------------------------------------- : Intrusive pointers
#ifdef USE_INTRUSIVE_PTR
/// Allocate a new intrusive-pointed object
template <typename T>
inline intrusive_ptr<T> new_intrusive() {
return intrusive_ptr<T>(new T());
}
/// Allocate a new intrusive-pointed object, given one argument to pass to the ctor of T
template <typename T, typename A0>
inline intrusive_ptr<T> new_intrusive1(const A0& a0) {
return intrusive_ptr<T>(new T(a0));
}
/// Allocate a new intrusive-pointed object, given two arguments to pass to the ctor of T
template <typename T, typename A0, typename A1>
inline intrusive_ptr<T> new_intrusive2(const A0& a0, const A1& a1) {
return intrusive_ptr<T>(new T(a0, a1));
}
#else
#define intrusive_ptr smart_ptr
#define new_intrusive new_smart
#define new_intrusive1 new_smart1
#define new_intrusive2 new_smart2
#define new_intrusive3 new_smart3
#endif
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment