summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gd_compiler.cpp
diff options
context:
space:
mode:
authorKarroffel <therzog@mail.de>2016-10-16 13:20:28 +0200
committerkarroffel <therzog@mail.de>2017-01-11 04:40:28 +0100
commite781a7e07ec7388deccd372899ecbea8af7b67f4 (patch)
treed3a999554c027d8b443a91c7d9fcc6960228a134 /modules/gdscript/gd_compiler.cpp
parentd445f0639fa9eccc44f1f9c153108f9e90981077 (diff)
downloadredot-engine-e781a7e07ec7388deccd372899ecbea8af7b67f4.tar.gz
pattern matcher: Implemented backend
changed comments
Diffstat (limited to 'modules/gdscript/gd_compiler.cpp')
-rw-r--r--modules/gdscript/gd_compiler.cpp67
1 files changed, 63 insertions, 4 deletions
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp
index f7765200b9..139fdaad0d 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gd_compiler.cpp
@@ -980,7 +980,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
} break;
//TYPE_TYPE,
default: {
-
+
ERR_EXPLAIN("Bug in bytecode compiler, unexpected node in parse tree while parsing expression.");
ERR_FAIL_V(-1); //unreachable code
} break;
@@ -1020,9 +1020,68 @@ Error GDCompiler::_parse_block(CodeGen& codegen,const GDParser::BlockNode *p_blo
switch(cf->cf_type) {
case GDParser::ControlFlowNode::CF_MATCH: {
- Error err = _parse_block(codegen,cf->match->compiled_block,p_stack_level,p_break_addr,p_continue_addr);
- if (err)
- return err;
+ GDParser::MatchNode *match = cf->match;
+
+ GDParser::IdentifierNode *id = memnew(GDParser::IdentifierNode);
+ id->name = "#match_value";
+
+ // var #match_value
+ // copied because there is no _parse_statement :(
+ codegen.add_stack_identifier(id->name, p_stack_level++);
+ codegen.alloc_stack(p_stack_level);
+ new_identifiers++;
+
+ GDParser::OperatorNode *op = memnew(GDParser::OperatorNode);
+ op->op=GDParser::OperatorNode::OP_ASSIGN;
+ op->arguments.push_back(id);
+ op->arguments.push_back(match->val_to_match);
+
+ int ret = _parse_expression(codegen, op, p_stack_level);
+ if (ret < 0) {
+ return ERR_PARSE_ERROR;
+ }
+
+ // break address
+ codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(codegen.opcodes.size() + 3);
+ int break_addr = codegen.opcodes.size();
+ codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(0); // break addr
+
+ for (int j = 0; j < match->compiled_pattern_branches.size(); j++) {
+ GDParser::MatchNode::CompiledPatternBranch branch = match->compiled_pattern_branches[j];
+
+ // jump over continue
+ // jump unconditionally
+ // continue address
+ // compile the condition
+ int ret = _parse_expression(codegen, branch.compiled_pattern, p_stack_level);
+ if (ret < 0) {
+ return ERR_PARSE_ERROR;
+ }
+
+ codegen.opcodes.push_back(GDFunction::OPCODE_JUMP_IF);
+ codegen.opcodes.push_back(ret);
+ codegen.opcodes.push_back(codegen.opcodes.size() + 3);
+ int continue_addr = codegen.opcodes.size();
+ codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(0);
+
+
+
+ Error err = _parse_block(codegen, branch.body, p_stack_level, p_break_addr, continue_addr);
+ if (err) {
+ return ERR_PARSE_ERROR;
+ }
+
+ codegen.opcodes.push_back(GDFunction::OPCODE_JUMP);
+ codegen.opcodes.push_back(break_addr);
+
+ codegen.opcodes[continue_addr + 1] = codegen.opcodes.size();
+ }
+
+ codegen.opcodes[break_addr + 1] = codegen.opcodes.size();
+
} break;