Script cleanup for standards-compliance (not going out of bounds on vectors).

I_POP is no longer considered a binary instruction because all other binary instructions expect the stack to have at least two elements - adding a manual check is kludgy
Added I_TAILCALL to accomodate indended optimizations



git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1417 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
coppro
2009-08-02 01:30:59 +00:00
parent 7af4cd4bd0
commit 79b18c1e72
5 changed files with 37 additions and 26 deletions
+16 -11
View File
@@ -44,12 +44,15 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
try {
// Instruction pointer
const Instruction* instr = &script.instructions[0];
const Instruction* end = &*script.instructions.end();
const Instruction* end = instr + script.instructions.size();
// Loop until we are done
while (instr < end) {
// Evaluate the current instruction
Instruction i = *instr++;
// If a scope is created, destroy it at end of block.
scoped_ptr<LocalScope> scope;
switch (i.instr) {
case I_NOP: break;
// Push a constant
@@ -59,7 +62,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
}
// Jump
case I_JUMP: {
instr = &script.instructions[i.data];
instr = &script.instructions[0] + i.data;
break;
}
// Conditional jump
@@ -67,7 +70,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
bool condition = *stack.back();
stack.pop_back();
if (!condition) {
instr = &script.instructions[i.data];
instr = &script.instructions[0] + i.data;
}
break;
}
@@ -98,7 +101,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
stack.push_back(val);
} else {
stack.erase(stack.end() - 2); // remove iterator
instr = &script.instructions[i.data];
instr = &script.instructions[0] + i.data;
}
break;
}
@@ -112,7 +115,7 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
stack.push_back(key);
} else {
stack.erase(stack.end() - 2); // remove iterator
instr = &script.instructions[i.data];
instr = &script.instructions[0] + i.data;
}
break;
}
@@ -123,9 +126,8 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
}
// Function call
case I_CALL: {
// new scope
LocalScope local_scope(*this);
case I_CALL: scope.reset(new LocalScope(*this)); //new scope
case I_TAILCALL: {
// prepare arguments
for (unsigned int j = 0 ; j < i.data ; ++j) {
setVariable((Variable)instr[i.data - j - 1].data, stack.back());
@@ -203,6 +205,12 @@ ScriptValueP Context::eval(const Script& script, bool useScope) {
instrQuaternary(i.instr4, a, b, c, d);
break;
}
// Pop off stack
case I_POP: {
stack.pop_back();
break;
}
// Duplicate stack
case I_DUP: {
stack.push_back(stack.at(stack.size() - i.data - 1));
@@ -419,9 +427,6 @@ class ScriptCompose : public ScriptValue {
void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP& b) {
switch (i) {
case I_POP:
// a = a;
break;
case I_MEMBER:
a = a->getMember(*b);
break;