|
@@ -1389,25 +1389,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
|
|
|
|
- // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
|
|
|
|
- if (p_is_nested) {
|
|
|
|
- // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
- codegen.generator->write_and_right_operand(result_addr);
|
|
|
|
- codegen.generator->write_end_and(p_previous_test);
|
|
|
|
- } else if (!p_is_first) {
|
|
|
|
- // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
- codegen.generator->write_or_right_operand(result_addr);
|
|
|
|
- codegen.generator->write_end_or(p_previous_test);
|
|
|
|
- } else {
|
|
|
|
- // Just assign this value to the accumulator temporary.
|
|
|
|
- codegen.generator->write_assign(p_previous_test, result_addr);
|
|
|
|
- }
|
|
|
|
- codegen.generator->pop_temporary(); // Remove temp result addr.
|
|
|
|
-
|
|
|
|
// Create temporaries outside the loop so they can be reused.
|
|
// Create temporaries outside the loop so they can be reused.
|
|
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
|
|
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
|
|
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
|
|
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
|
|
- GDScriptCodeGenerator::Address test_addr = p_previous_test;
|
|
|
|
|
|
|
|
// Evaluate element by element.
|
|
// Evaluate element by element.
|
|
for (int i = 0; i < p_pattern->array.size(); i++) {
|
|
for (int i = 0; i < p_pattern->array.size(); i++) {
|
|
@@ -1417,7 +1401,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
}
|
|
}
|
|
|
|
|
|
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
|
|
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
|
|
- codegen.generator->write_and_left_operand(test_addr);
|
|
|
|
|
|
+ codegen.generator->write_and_left_operand(result_addr);
|
|
|
|
|
|
// Add index to constant map.
|
|
// Add index to constant map.
|
|
GDScriptCodeGenerator::Address index_addr = codegen.add_constant(i);
|
|
GDScriptCodeGenerator::Address index_addr = codegen.add_constant(i);
|
|
@@ -1431,19 +1415,34 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
codegen.generator->write_call_utility(element_type_addr, "typeof", typeof_args);
|
|
codegen.generator->write_call_utility(element_type_addr, "typeof", typeof_args);
|
|
|
|
|
|
// Try the pattern inside the element.
|
|
// Try the pattern inside the element.
|
|
- test_addr = _parse_match_pattern(codegen, r_error, p_pattern->array[i], element_addr, element_type_addr, p_previous_test, false, true);
|
|
|
|
|
|
+ result_addr = _parse_match_pattern(codegen, r_error, p_pattern->array[i], element_addr, element_type_addr, result_addr, false, true);
|
|
if (r_error != OK) {
|
|
if (r_error != OK) {
|
|
return GDScriptCodeGenerator::Address();
|
|
return GDScriptCodeGenerator::Address();
|
|
}
|
|
}
|
|
|
|
|
|
- codegen.generator->write_and_right_operand(test_addr);
|
|
|
|
- codegen.generator->write_end_and(test_addr);
|
|
|
|
|
|
+ codegen.generator->write_and_right_operand(result_addr);
|
|
|
|
+ codegen.generator->write_end_and(result_addr);
|
|
}
|
|
}
|
|
// Remove element temporaries.
|
|
// Remove element temporaries.
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
|
|
|
|
- return test_addr;
|
|
|
|
|
|
+ // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
|
|
|
|
+ if (p_is_nested) {
|
|
|
|
+ // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
+ codegen.generator->write_and_right_operand(result_addr);
|
|
|
|
+ codegen.generator->write_end_and(p_previous_test);
|
|
|
|
+ } else if (!p_is_first) {
|
|
|
|
+ // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
+ codegen.generator->write_or_right_operand(result_addr);
|
|
|
|
+ codegen.generator->write_end_or(p_previous_test);
|
|
|
|
+ } else {
|
|
|
|
+ // Just assign this value to the accumulator temporary.
|
|
|
|
+ codegen.generator->write_assign(p_previous_test, result_addr);
|
|
|
|
+ }
|
|
|
|
+ codegen.generator->pop_temporary(); // Remove temp result addr.
|
|
|
|
+
|
|
|
|
+ return p_previous_test;
|
|
} break;
|
|
} break;
|
|
case GDScriptParser::PatternNode::PT_DICTIONARY: {
|
|
case GDScriptParser::PatternNode::PT_DICTIONARY: {
|
|
if (p_is_nested) {
|
|
if (p_is_nested) {
|
|
@@ -1488,27 +1487,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
|
|
|
|
- // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
|
|
|
|
- if (p_is_nested) {
|
|
|
|
- // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
- codegen.generator->write_and_right_operand(result_addr);
|
|
|
|
- codegen.generator->write_end_and(p_previous_test);
|
|
|
|
- } else if (!p_is_first) {
|
|
|
|
- // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
- codegen.generator->write_or_right_operand(result_addr);
|
|
|
|
- codegen.generator->write_end_or(p_previous_test);
|
|
|
|
- } else {
|
|
|
|
- // Just assign this value to the accumulator temporary.
|
|
|
|
- codegen.generator->write_assign(p_previous_test, result_addr);
|
|
|
|
- }
|
|
|
|
- codegen.generator->pop_temporary(); // Remove temp result addr.
|
|
|
|
-
|
|
|
|
// Create temporaries outside the loop so they can be reused.
|
|
// Create temporaries outside the loop so they can be reused.
|
|
- temp_type.builtin_type = Variant::BOOL;
|
|
|
|
- GDScriptCodeGenerator::Address test_result = codegen.add_temporary(temp_type);
|
|
|
|
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
|
|
GDScriptCodeGenerator::Address element_addr = codegen.add_temporary();
|
|
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
|
|
GDScriptCodeGenerator::Address element_type_addr = codegen.add_temporary();
|
|
- GDScriptCodeGenerator::Address test_addr = p_previous_test;
|
|
|
|
|
|
|
|
// Evaluate element by element.
|
|
// Evaluate element by element.
|
|
for (int i = 0; i < p_pattern->dictionary.size(); i++) {
|
|
for (int i = 0; i < p_pattern->dictionary.size(); i++) {
|
|
@@ -1519,7 +1500,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
}
|
|
}
|
|
|
|
|
|
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
|
|
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
|
|
- codegen.generator->write_and_left_operand(test_addr);
|
|
|
|
|
|
+ codegen.generator->write_and_left_operand(result_addr);
|
|
|
|
|
|
// Get the pattern key.
|
|
// Get the pattern key.
|
|
GDScriptCodeGenerator::Address pattern_key_addr = _parse_expression(codegen, r_error, element.key);
|
|
GDScriptCodeGenerator::Address pattern_key_addr = _parse_expression(codegen, r_error, element.key);
|
|
@@ -1530,11 +1511,11 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
// Check if pattern key exists in user's dictionary. This will be AND-ed with next result.
|
|
// Check if pattern key exists in user's dictionary. This will be AND-ed with next result.
|
|
func_args.clear();
|
|
func_args.clear();
|
|
func_args.push_back(pattern_key_addr);
|
|
func_args.push_back(pattern_key_addr);
|
|
- codegen.generator->write_call(test_result, p_value_addr, "has", func_args);
|
|
|
|
|
|
+ codegen.generator->write_call(result_addr, p_value_addr, "has", func_args);
|
|
|
|
|
|
if (element.value_pattern != nullptr) {
|
|
if (element.value_pattern != nullptr) {
|
|
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
|
|
// Use AND here too, as we don't want to be checking elements if previous test failed (which means this might be an invalid get).
|
|
- codegen.generator->write_and_left_operand(test_result);
|
|
|
|
|
|
+ codegen.generator->write_and_left_operand(result_addr);
|
|
|
|
|
|
// Get actual value from user dictionary.
|
|
// Get actual value from user dictionary.
|
|
codegen.generator->write_get(element_addr, pattern_key_addr, p_value_addr);
|
|
codegen.generator->write_get(element_addr, pattern_key_addr, p_value_addr);
|
|
@@ -1545,16 +1526,16 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
codegen.generator->write_call_utility(element_type_addr, "typeof", func_args);
|
|
codegen.generator->write_call_utility(element_type_addr, "typeof", func_args);
|
|
|
|
|
|
// Try the pattern inside the value.
|
|
// Try the pattern inside the value.
|
|
- test_addr = _parse_match_pattern(codegen, r_error, element.value_pattern, element_addr, element_type_addr, test_addr, false, true);
|
|
|
|
|
|
+ result_addr = _parse_match_pattern(codegen, r_error, element.value_pattern, element_addr, element_type_addr, result_addr, false, true);
|
|
if (r_error != OK) {
|
|
if (r_error != OK) {
|
|
return GDScriptCodeGenerator::Address();
|
|
return GDScriptCodeGenerator::Address();
|
|
}
|
|
}
|
|
- codegen.generator->write_and_right_operand(test_addr);
|
|
|
|
- codegen.generator->write_end_and(test_addr);
|
|
|
|
|
|
+ codegen.generator->write_and_right_operand(result_addr);
|
|
|
|
+ codegen.generator->write_end_and(result_addr);
|
|
}
|
|
}
|
|
|
|
|
|
- codegen.generator->write_and_right_operand(test_addr);
|
|
|
|
- codegen.generator->write_end_and(test_addr);
|
|
|
|
|
|
+ codegen.generator->write_and_right_operand(result_addr);
|
|
|
|
+ codegen.generator->write_end_and(result_addr);
|
|
|
|
|
|
// Remove pattern key temporary.
|
|
// Remove pattern key temporary.
|
|
if (pattern_key_addr.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
|
|
if (pattern_key_addr.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
|
|
@@ -1565,9 +1546,23 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
|
|
// Remove element temporaries.
|
|
// Remove element temporaries.
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
codegen.generator->pop_temporary();
|
|
- codegen.generator->pop_temporary();
|
|
|
|
|
|
|
|
- return test_addr;
|
|
|
|
|
|
+ // If this isn't the first, we need to OR with the previous pattern. If it's nested, we use AND instead.
|
|
|
|
+ if (p_is_nested) {
|
|
|
|
+ // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
+ codegen.generator->write_and_right_operand(result_addr);
|
|
|
|
+ codegen.generator->write_end_and(p_previous_test);
|
|
|
|
+ } else if (!p_is_first) {
|
|
|
|
+ // Use the previous value as target, since we only need one temporary variable.
|
|
|
|
+ codegen.generator->write_or_right_operand(result_addr);
|
|
|
|
+ codegen.generator->write_end_or(p_previous_test);
|
|
|
|
+ } else {
|
|
|
|
+ // Just assign this value to the accumulator temporary.
|
|
|
|
+ codegen.generator->write_assign(p_previous_test, result_addr);
|
|
|
|
+ }
|
|
|
|
+ codegen.generator->pop_temporary(); // Remove temp result addr.
|
|
|
|
+
|
|
|
|
+ return p_previous_test;
|
|
} break;
|
|
} break;
|
|
case GDScriptParser::PatternNode::PT_REST:
|
|
case GDScriptParser::PatternNode::PT_REST:
|
|
// Do nothing.
|
|
// Do nothing.
|