mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Simplified script VM:
- removed I_RET instruction, return is now implicit at end of script - I_POP is not a binary instruction. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@963 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+39
-32
@@ -346,19 +346,22 @@ void parseExpr(TokenIterator& input, Script& script, Precedence min_prec);
|
||||
/** @param input Read tokens from the input
|
||||
* @param script Add resulting instructions to the script
|
||||
* @param min_prec Minimum precedence level for operators
|
||||
* @param close_with Add this instruction at the end
|
||||
* @param close_with Add this instruction at the end, or I_NOP for no instruction
|
||||
* @param close_with_data Data for the instruction at the end
|
||||
* NOTE: The net stack effect of an expression should be +1
|
||||
*/
|
||||
void parseOper(TokenIterator& input, Script& script, Precedence min_prec, InstructionType close_with = I_NOP, int close_with_data = 0);
|
||||
|
||||
/// Parse call arguments, "(...)"
|
||||
void parseCallArguments(TokenIterator& input, Script& script, vector<Variable>& arguments);
|
||||
|
||||
|
||||
ScriptP parse(const String& s, Packaged* package, bool string_mode, vector<ScriptParseError>& errors_out) {
|
||||
errors_out.clear();
|
||||
// parse
|
||||
TokenIterator input(s, package, string_mode, errors_out);
|
||||
ScriptP script(new Script);
|
||||
parseOper(input, *script, PREC_ALL, I_RET);
|
||||
parseOper(input, *script, PREC_ALL);
|
||||
Token eof = input.read();
|
||||
if (eof != TOK_EOF) {
|
||||
input.expected(_("end of input"));
|
||||
@@ -403,7 +406,7 @@ void parseExpr(TokenIterator& input, Script& script, Precedence minPrec) {
|
||||
} else if (token == _("{")) {
|
||||
// {} = function block. Parse a new Script
|
||||
intrusive_ptr<Script> subScript(new Script);
|
||||
parseOper(input, *subScript, PREC_ALL, I_RET);
|
||||
parseOper(input, *subScript, PREC_ALL);
|
||||
expectToken(input, _("}"));
|
||||
script.addInstruction(I_PUSH_CONST, subScript);
|
||||
} else if (token == _("[")) {
|
||||
@@ -447,11 +450,11 @@ void parseExpr(TokenIterator& input, Script& script, Precedence minPrec) {
|
||||
unsigned int jmpElse, jmpEnd;
|
||||
parseOper(input, script, PREC_AND); // AAA
|
||||
jmpElse = script.getLabel(); // jmp_else:
|
||||
script.addInstruction(I_JUMP_IF_NOT, 0xFFFFFFFF); // jnz lbl_else
|
||||
script.addInstruction(I_JUMP_IF_NOT, INVALID_ADDRESS); // jnz lbl_else
|
||||
expectToken(input, _("then")); // then
|
||||
parseOper(input, script, PREC_SET); // BBB
|
||||
jmpEnd = script.getLabel(); // jmp_end:
|
||||
script.addInstruction(I_JUMP, 0xFFFFFFFF); // jump lbl_end
|
||||
script.addInstruction(I_JUMP, INVALID_ADDRESS); // jump lbl_end
|
||||
script.comeFrom(jmpElse); // lbl_else:
|
||||
if (input.peek() == _("else")) { // else
|
||||
input.read();
|
||||
@@ -476,11 +479,11 @@ void parseExpr(TokenIterator& input, Script& script, Precedence minPrec) {
|
||||
script.addInstruction(I_UNARY, I_ITERATOR_C); // iterator_collection
|
||||
script.addInstruction(I_PUSH_CONST, script_nil); // push nil
|
||||
lblStart = script.getLabel(); // lbl_start:
|
||||
script.addInstruction(I_LOOP, 0xFFFFFFFF); // loop
|
||||
script.addInstruction(I_LOOP, INVALID_ADDRESS); // loop
|
||||
expectToken(input, _("do")); // do
|
||||
script.addInstruction(I_SET_VAR,
|
||||
string_to_variable(name.value));// set name
|
||||
script.addInstruction(I_POP); // pop
|
||||
script.addInstruction(I_BINARY, I_POP); // pop
|
||||
parseOper(input, script, PREC_SET, I_BINARY, I_ADD);// CCC; add
|
||||
script.addInstruction(I_JUMP, lblStart); // jump lbl_start
|
||||
script.comeFrom(lblStart); // lbl_end:
|
||||
@@ -494,11 +497,11 @@ void parseExpr(TokenIterator& input, Script& script, Precedence minPrec) {
|
||||
script.addInstruction(I_BINARY, I_ITERATOR_R); // iterator_range
|
||||
script.addInstruction(I_PUSH_CONST, script_nil); // push nil
|
||||
lblStart = script.getLabel(); // lbl_start:
|
||||
script.addInstruction(I_LOOP, 0xFFFFFFFF); // loop
|
||||
script.addInstruction(I_LOOP, INVALID_ADDRESS); // loop
|
||||
expectToken(input, _("do")); // do
|
||||
script.addInstruction(I_SET_VAR,
|
||||
string_to_variable(name.value));// set name
|
||||
script.addInstruction(I_POP); // pop
|
||||
script.addInstruction(I_BINARY, I_POP); // pop
|
||||
parseOper(input, script, PREC_SET, I_BINARY, I_ADD);// DDD; add
|
||||
script.addInstruction(I_JUMP, lblStart); // jump lbl_start
|
||||
script.comeFrom(lblStart); // lbl_end:
|
||||
@@ -582,7 +585,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
||||
// allow ; at end of expression without errors
|
||||
break;
|
||||
}
|
||||
script.addInstruction(I_POP); // discard result of first expression
|
||||
script.addInstruction(I_BINARY, I_POP); // discard result of first expression
|
||||
parseOper(input, script, PREC_SET);
|
||||
} else if (minPrec <= PREC_SET && token==_(":=")) {
|
||||
// We made a mistake, the part before the := should be a variable name,
|
||||
@@ -646,27 +649,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
||||
} else if (minPrec <= PREC_FUN && token==_("(")) {
|
||||
// function call, read arguments
|
||||
vector<Variable> arguments;
|
||||
Token t = input.peek();
|
||||
while (t != _(")") && t != TOK_EOF) {
|
||||
if (input.peek(2) == _(":") && t.type == TOK_NAME) {
|
||||
// name: ...
|
||||
arguments.push_back(string_to_variable(t.value));
|
||||
input.read(); // skip the name
|
||||
input.read(); // and the :
|
||||
parseOper(input, script, PREC_SEQ);
|
||||
} else {
|
||||
// implicit "input" argument
|
||||
arguments.push_back(SCRIPT_VAR_input);
|
||||
parseOper(input, script, PREC_SEQ);
|
||||
}
|
||||
t = input.peek();
|
||||
if (t == _(",")) {
|
||||
// Comma separating the arguments
|
||||
input.read();
|
||||
t = input.peek();
|
||||
}
|
||||
}
|
||||
expectToken(input, _(")"));
|
||||
parseCallArguments(input, script, arguments);
|
||||
// generate instruction
|
||||
script.addInstruction(I_CALL, (unsigned int)arguments.size());
|
||||
FOR_EACH(arg,arguments) {
|
||||
@@ -696,7 +679,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
||||
// newline functions as ;
|
||||
// only if we don't match another token!
|
||||
input.putBack();
|
||||
script.addInstruction(I_POP);
|
||||
script.addInstruction(I_BINARY, I_POP);
|
||||
parseOper(input, script, PREC_SET);
|
||||
} else {
|
||||
input.putBack();
|
||||
@@ -708,3 +691,27 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
|
||||
script.addInstruction(closeWith, closeWithData);
|
||||
}
|
||||
}
|
||||
|
||||
void parseCallArguments(TokenIterator& input, Script& script, vector<Variable>& arguments) {
|
||||
Token t = input.peek();
|
||||
while (t != _(")") && t != TOK_EOF) {
|
||||
if (input.peek(2) == _(":") && t.type == TOK_NAME) {
|
||||
// name: ...
|
||||
arguments.push_back(string_to_variable(t.value));
|
||||
input.read(); // skip the name
|
||||
input.read(); // and the :
|
||||
parseOper(input, script, PREC_SEQ);
|
||||
} else {
|
||||
// implicit "input" argument
|
||||
arguments.push_back(SCRIPT_VAR_input);
|
||||
parseOper(input, script, PREC_SEQ);
|
||||
}
|
||||
t = input.peek();
|
||||
if (t == _(",")) {
|
||||
// Comma separating the arguments
|
||||
input.read();
|
||||
t = input.peek();
|
||||
}
|
||||
}
|
||||
expectToken(input, _(")"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user