Skip to content

Commit

Permalink
GDScript: Strings and StringNames match
Browse files Browse the repository at this point in the history
  • Loading branch information
rune-scape committed Jun 15, 2023
1 parent 33957ae commit fcdd926
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 39 deletions.
77 changes: 55 additions & 22 deletions modules/gdscript/gdscript_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1272,37 +1272,40 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
}

// Get literal type into constant map.
GDScriptCodeGenerator::Address literal_type_addr = codegen.add_constant((int)p_pattern->literal->value.get_type());
Variant::Type literal_type = p_pattern->literal->value.get_type();
GDScriptCodeGenerator::Address literal_type_addr = codegen.add_constant(literal_type);

// Equality is always a boolean.
GDScriptDataType equality_type;
equality_type.has_type = true;
equality_type.kind = GDScriptDataType::BUILTIN;
equality_type.builtin_type = Variant::BOOL;

GDScriptCodeGenerator::Address type_string_addr = codegen.add_constant(Variant::STRING);
GDScriptCodeGenerator::Address type_string_name_addr = codegen.add_constant(Variant::STRING_NAME);

// Check type equality.
GDScriptCodeGenerator::Address type_equality_addr = codegen.add_temporary(equality_type);
codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_EQUAL, p_type_addr, literal_type_addr);

// Check if StringName <-> String comparison is possible.
GDScriptCodeGenerator::Address type_comp_addr_1 = codegen.add_temporary(equality_type);
GDScriptCodeGenerator::Address type_comp_addr_2 = codegen.add_temporary(equality_type);
if (literal_type == Variant::STRING) {
GDScriptCodeGenerator::Address type_stringname_addr = codegen.add_constant(Variant::STRING_NAME);

// Check StringName <-> String type equality.
GDScriptCodeGenerator::Address tmp_comp_addr = codegen.add_temporary(equality_type);

codegen.generator->write_binary_operator(tmp_comp_addr, Variant::OP_EQUAL, p_type_addr, type_stringname_addr);
codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_OR, type_equality_addr, tmp_comp_addr);

codegen.generator->pop_temporary(); // Remove tmp_comp_addr from stack.
} else if (literal_type == Variant::STRING_NAME) {
GDScriptCodeGenerator::Address type_string_addr = codegen.add_constant(Variant::STRING);

codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_EQUAL, p_type_addr, type_string_addr);
codegen.generator->write_binary_operator(type_comp_addr_2, Variant::OP_EQUAL, literal_type_addr, type_string_name_addr);
codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_AND, type_comp_addr_1, type_comp_addr_2);
codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_OR, type_equality_addr, type_comp_addr_1);
// Check String <-> StringName type equality.
GDScriptCodeGenerator::Address tmp_comp_addr = codegen.add_temporary(equality_type);

codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_EQUAL, p_type_addr, type_string_name_addr);
codegen.generator->write_binary_operator(type_comp_addr_2, Variant::OP_EQUAL, literal_type_addr, type_string_addr);
codegen.generator->write_binary_operator(type_comp_addr_1, Variant::OP_AND, type_comp_addr_1, type_comp_addr_2);
codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_OR, type_equality_addr, type_comp_addr_1);
codegen.generator->write_binary_operator(tmp_comp_addr, Variant::OP_EQUAL, p_type_addr, type_string_addr);
codegen.generator->write_binary_operator(type_equality_addr, Variant::OP_OR, type_equality_addr, tmp_comp_addr);

codegen.generator->pop_temporary(); // Remove type_comp_addr_2 from stack.
codegen.generator->pop_temporary(); // Remove type_comp_addr_1 from stack.
codegen.generator->pop_temporary(); // Remove tmp_comp_addr from stack.
}

codegen.generator->write_and_left_operand(type_equality_addr);

Expand Down Expand Up @@ -1349,9 +1352,22 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
} else if (!p_is_first) {
codegen.generator->write_or_left_operand(p_previous_test);
}

GDScriptCodeGenerator::Address type_string_addr = codegen.add_constant(Variant::STRING);
GDScriptCodeGenerator::Address type_stringname_addr = codegen.add_constant(Variant::STRING_NAME);

// Equality is always a boolean.
GDScriptDataType equality_type;
equality_type.has_type = true;
equality_type.kind = GDScriptDataType::BUILTIN;
equality_type.builtin_type = Variant::BOOL;

// Create the result temps first since it's the last to go away.
GDScriptCodeGenerator::Address result_addr = codegen.add_temporary();
GDScriptCodeGenerator::Address equality_test_addr = codegen.add_temporary();
GDScriptCodeGenerator::Address result_addr = codegen.add_temporary(equality_type);
GDScriptCodeGenerator::Address equality_test_addr = codegen.add_temporary(equality_type);
GDScriptCodeGenerator::Address stringy_comp_addr = codegen.add_temporary(equality_type);
GDScriptCodeGenerator::Address stringy_comp_addr_2 = codegen.add_temporary(equality_type);
GDScriptCodeGenerator::Address expr_type_addr = codegen.add_temporary();

// Evaluate expression.
GDScriptCodeGenerator::Address expr_addr;
Expand All @@ -1363,10 +1379,27 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
// Evaluate expression type.
Vector<GDScriptCodeGenerator::Address> typeof_args;
typeof_args.push_back(expr_addr);
codegen.generator->write_call_utility(result_addr, "typeof", typeof_args);
codegen.generator->write_call_utility(expr_type_addr, "typeof", typeof_args);

// Check type equality.
codegen.generator->write_binary_operator(result_addr, Variant::OP_EQUAL, p_type_addr, result_addr);
codegen.generator->write_binary_operator(result_addr, Variant::OP_EQUAL, p_type_addr, expr_type_addr);

// Check for String <-> StringName comparison.
codegen.generator->write_binary_operator(stringy_comp_addr, Variant::OP_EQUAL, p_type_addr, type_string_addr);
codegen.generator->write_binary_operator(stringy_comp_addr_2, Variant::OP_EQUAL, expr_type_addr, type_stringname_addr);
codegen.generator->write_binary_operator(stringy_comp_addr, Variant::OP_AND, stringy_comp_addr, stringy_comp_addr_2);
codegen.generator->write_binary_operator(result_addr, Variant::OP_OR, result_addr, stringy_comp_addr);

// Check for StringName <-> String comparison.
codegen.generator->write_binary_operator(stringy_comp_addr, Variant::OP_EQUAL, p_type_addr, type_stringname_addr);
codegen.generator->write_binary_operator(stringy_comp_addr_2, Variant::OP_EQUAL, expr_type_addr, type_string_addr);
codegen.generator->write_binary_operator(stringy_comp_addr, Variant::OP_AND, stringy_comp_addr, stringy_comp_addr_2);
codegen.generator->write_binary_operator(result_addr, Variant::OP_OR, result_addr, stringy_comp_addr);

codegen.generator->pop_temporary(); // Remove expr_type_addr from stack.
codegen.generator->pop_temporary(); // Remove stringy_comp_addr_2 from stack.
codegen.generator->pop_temporary(); // Remove stringy_comp_addr from stack.

codegen.generator->write_and_left_operand(result_addr);

// Check value equality.
Expand All @@ -1380,7 +1413,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_match_pattern(CodeGen &c
if (expr_addr.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
codegen.generator->pop_temporary();
}
codegen.generator->pop_temporary(); // Remove type equality temporary.
codegen.generator->pop_temporary(); // Remove equality_test_addr from stack.

// 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) {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# https://github.com/godotengine/godot/issues/64171
# https://github.com/godotengine/godot/issues/60145

var s = "abc"
var sn = &"abc"

func test():
print("Compare ==: ", "abc" == &"abc")
Expand All @@ -9,3 +13,27 @@ func test():
print("Concat: ", "abc" + &"def")
print("Concat: ", &"abc" + "def")
print("Concat: ", &"abc" + &"def")

match "abc":
&"abc":
print("String matched StringName literal")
_:
print("no Match")

match &"abc":
"abc":
print("StringName matched String literal")
_:
print("no Match")

match "abc":
sn:
print("String matched StringName")
_:
print("no match")

match &"abc":
s:
print("StringName matched String")
_:
print("no match")
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ Compare !=: false
Concat: abcdef
Concat: abcdef
Concat: abcdef
String matched StringName literal
StringName matched String literal
String matched StringName
StringName matched String

0 comments on commit fcdd926

Please sign in to comment.