mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Type name of ScriptObjects is now reported as the actual object type (card/set/value/etc.);
Back trace is slightly smarter Removed move_cursor_with_sort git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@542 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+1
-13
@@ -131,19 +131,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
|
||||
const Instruction* instr_bt = script.backtraceSkip(instr - i.data - 2, i.data);
|
||||
// have we have reached the name
|
||||
if (instr_bt) {
|
||||
if (instr_bt->instr == I_GET_VAR) {
|
||||
throw ScriptError(e.what() + _("\n in function: ") + variable_to_string(instr_bt->data));
|
||||
} else if (instr_bt->instr == I_MEMBER_C) {
|
||||
throw ScriptError(e.what() + _("\n in function: ??\?.") + script.constants[instr_bt->data]->operator String());
|
||||
} else if (instr_bt->instr == I_BINARY && instr_bt->instr2 == I_MEMBER) {
|
||||
throw ScriptError(e.what() + _("\n in function: ??\?[??\?]"));
|
||||
} else if (instr_bt->instr == I_BINARY && instr_bt->instr2 == I_ADD) {
|
||||
throw ScriptError(e.what() + _("\n in function: ??? + ???"));
|
||||
} else if (instr_bt->instr == I_NOP || instr_bt->instr == I_CALL) {
|
||||
throw ScriptError(e.what() + _("\n in function: ??\?(??\?)"));
|
||||
} else {
|
||||
throw ScriptError(e.what() + _("\n in function: ??\?"));
|
||||
}
|
||||
throw ScriptError(e.what() + _("\n in function: ") + script.instructionName(instr_bt));
|
||||
} else {
|
||||
throw e; // rethrow
|
||||
}
|
||||
|
||||
+30
-1
@@ -184,9 +184,13 @@ String Script::dumpInstr(unsigned int pos, Instruction i) const {
|
||||
// ----------------------------------------------------------------------------- : Backtracing
|
||||
|
||||
const Instruction* Script::backtraceSkip(const Instruction* instr, int to_skip) const {
|
||||
unsigned int initial = instr - &instructions[0];
|
||||
for (;instr >= &instructions[0] &&
|
||||
(to_skip || // we have something to skip
|
||||
instr >= &instructions[1] && (instr-1)->instr == I_JUMP // always look inside a jump
|
||||
instr >= &instructions[1] && (
|
||||
(instr-1)->instr == I_JUMP // always look inside a jump
|
||||
|| (instr-1)->instr == I_NOP // and skip nops
|
||||
)
|
||||
) ; --instr) {
|
||||
// skip an instruction
|
||||
switch (instr->instr) {
|
||||
@@ -205,6 +209,10 @@ const Instruction* Script::backtraceSkip(const Instruction* instr, int to_skip)
|
||||
to_skip += 2 * instr->data - 1;
|
||||
break;
|
||||
case I_JUMP: {
|
||||
if (instr->data > initial) {
|
||||
// we were in an else branch all along, ignore this jump
|
||||
return instr + 1;
|
||||
}
|
||||
// there will be a way not to take this jump
|
||||
// the part in between will have no significant stack effect
|
||||
unsigned int after_jump = instr + 1 - &instructions[0];
|
||||
@@ -248,3 +256,24 @@ const Instruction* Script::backtraceSkip(const Instruction* instr, int to_skip)
|
||||
}
|
||||
return instr >= &instructions[0] ? instr : nullptr;
|
||||
}
|
||||
|
||||
String Script::instructionName(const Instruction* instr) const {
|
||||
if (instr < &instructions[0] || instr >= &instructions[instructions.size()]) return _("??\?");
|
||||
if (instr->instr == I_GET_VAR) {
|
||||
return variable_to_string(instr->data);
|
||||
} else if (instr->instr == I_MEMBER_C) {
|
||||
return instructionName(backtraceSkip(instr - 1, 0))
|
||||
+ _(".")
|
||||
+ constants[instr->data]->toString();
|
||||
} else if (instr->instr == I_BINARY && instr->instr2 == I_MEMBER) {
|
||||
throw _("??\?[...]");
|
||||
} else if (instr->instr == I_BINARY && instr->instr2 == I_ADD) {
|
||||
return _("??? + ???");
|
||||
} else if (instr->instr == I_NOP) {
|
||||
return _("??\?(...)");
|
||||
} else if (instr->instr == I_CALL) {
|
||||
return instructionName(backtraceSkip(instr - 1, instr->data)) + _("(...)");
|
||||
} else {
|
||||
return _("??\?");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +162,8 @@ class Script : public ScriptValue {
|
||||
* If the backtrace fails, returns nullptr
|
||||
*/
|
||||
const Instruction* backtraceSkip(const Instruction* instr, int to_skip) const;
|
||||
/// Find the name of an instruction
|
||||
String instructionName(const Instruction* instr) const;
|
||||
|
||||
friend class Context;
|
||||
};
|
||||
|
||||
+11
-3
@@ -31,6 +31,14 @@ ScriptValueP make_iterator(const T& v) {
|
||||
template <typename T>
|
||||
void mark_dependency_member(const T& value, const String& name, const Dependency& dep) {}
|
||||
|
||||
/// Type name of an object, for error messages
|
||||
template <typename T> inline String type_name(const T&) {
|
||||
return _TYPE_("object");
|
||||
}
|
||||
template <typename K, typename V> inline String type_name(const pair<K,V>& p) {
|
||||
return type_name(p.second); // for maps
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Errors
|
||||
|
||||
/// A delayed error message.
|
||||
@@ -104,7 +112,7 @@ class ScriptCollection : public ScriptValue {
|
||||
public:
|
||||
inline ScriptCollection(const Collection* v) : value(v) {}
|
||||
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||
virtual String typeName() const { return _TYPE_("collection"); }
|
||||
virtual String typeName() const { return format_string(_TYPE_("collection"), type_name(*value->begin())); }
|
||||
virtual ScriptValueP getMember(const String& name) const {
|
||||
long index;
|
||||
if (name.ToLong(&index) && index >= 0 && (size_t)index < value->size()) {
|
||||
@@ -152,7 +160,7 @@ class ScriptMap : public ScriptValue {
|
||||
public:
|
||||
inline ScriptMap(const Collection* v) : value(v) {}
|
||||
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||
virtual String typeName() const { return _TYPE_("collection"); }
|
||||
virtual String typeName() const { return format_string(_TYPE_("collection"), type_name(value->begin())); }
|
||||
virtual ScriptValueP getMember(const String& name) const {
|
||||
return get_member(*value, name);
|
||||
}
|
||||
@@ -195,7 +203,7 @@ class ScriptObject : public ScriptValue {
|
||||
public:
|
||||
inline ScriptObject(const T& v) : value(v) {}
|
||||
virtual ScriptType type() const { return SCRIPT_OBJECT; }
|
||||
virtual String typeName() const { return _TYPE_("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(); }
|
||||
|
||||
Reference in New Issue
Block a user