summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gdscript_compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_compiler.cpp')
-rw-r--r--modules/gdscript/gdscript_compiler.cpp84
1 files changed, 70 insertions, 14 deletions
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index fae7861539..f417d323db 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -60,7 +60,7 @@ bool GDScriptCompiler::_is_class_member_property(GDScript *owner, const StringNa
scr = scr->_base;
}
- ERR_FAIL_COND_V(!nc, false);
+ ERR_FAIL_NULL_V(nc, false);
return ClassDB::has_property(nc->get_name(), p_name);
}
@@ -84,7 +84,7 @@ void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::N
}
}
-GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner) {
+GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner, bool p_handle_metatype) {
if (!p_datatype.is_set() || !p_datatype.is_hard_type() || p_datatype.is_coroutine) {
return GDScriptDataType();
}
@@ -101,11 +101,36 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.builtin_type = p_datatype.builtin_type;
} break;
case GDScriptParser::DataType::NATIVE: {
+ if (p_handle_metatype && p_datatype.is_meta_type) {
+ result.kind = GDScriptDataType::NATIVE;
+ result.builtin_type = Variant::OBJECT;
+ // Fixes GH-82255. `GDScriptNativeClass` is obtainable in GDScript,
+ // but is not a registered and exposed class, so `GDScriptNativeClass`
+ // is missing from `GDScriptLanguage::get_singleton()->get_global_map()`.
+ //result.native_type = GDScriptNativeClass::get_class_static();
+ result.native_type = Object::get_class_static();
+ break;
+ }
+
result.kind = GDScriptDataType::NATIVE;
- result.native_type = p_datatype.native_type;
result.builtin_type = p_datatype.builtin_type;
+ result.native_type = p_datatype.native_type;
+
+#ifdef DEBUG_ENABLED
+ if (unlikely(!GDScriptLanguage::get_singleton()->get_global_map().has(result.native_type))) {
+ ERR_PRINT(vformat(R"(GDScript bug: Native class "%s" not found.)", result.native_type));
+ result.native_type = Object::get_class_static();
+ }
+#endif
} break;
case GDScriptParser::DataType::SCRIPT: {
+ if (p_handle_metatype && p_datatype.is_meta_type) {
+ result.kind = GDScriptDataType::NATIVE;
+ result.builtin_type = Variant::OBJECT;
+ result.native_type = p_datatype.script_type.is_valid() ? p_datatype.script_type->get_class() : Script::get_class_static();
+ break;
+ }
+
result.kind = GDScriptDataType::SCRIPT;
result.builtin_type = p_datatype.builtin_type;
result.script_type_ref = p_datatype.script_type;
@@ -113,6 +138,13 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.native_type = p_datatype.native_type;
} break;
case GDScriptParser::DataType::CLASS: {
+ if (p_handle_metatype && p_datatype.is_meta_type) {
+ result.kind = GDScriptDataType::NATIVE;
+ result.builtin_type = Variant::OBJECT;
+ result.native_type = GDScript::get_class_static();
+ break;
+ }
+
result.kind = GDScriptDataType::GDSCRIPT;
result.builtin_type = p_datatype.builtin_type;
result.native_type = p_datatype.native_type;
@@ -148,6 +180,12 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
}
} break;
case GDScriptParser::DataType::ENUM:
+ if (p_handle_metatype && p_datatype.is_meta_type) {
+ result.kind = GDScriptDataType::BUILTIN;
+ result.builtin_type = Variant::DICTIONARY;
+ break;
+ }
+
result.kind = GDScriptDataType::BUILTIN;
result.builtin_type = p_datatype.builtin_type;
break;
@@ -159,7 +197,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
}
if (p_datatype.has_container_element_type()) {
- result.set_container_element_type(_gdtype_from_datatype(p_datatype.get_container_element_type(), p_owner));
+ result.set_container_element_type(_gdtype_from_datatype(p_datatype.get_container_element_type(), p_owner, false));
}
return result;
@@ -402,7 +440,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
String global_class_path = ScriptServer::get_global_class_path(identifier);
if (ResourceLoader::get_resource_type(global_class_path) == "GDScript") {
Error err = OK;
- res = GDScriptCache::get_full_script(global_class_path, err);
+ // Should not need to pass p_owner since analyzer will already have done it.
+ res = GDScriptCache::get_shallow_script(global_class_path, err);
if (err != OK) {
_set_error("Can't load global class " + String(identifier), p_expression);
r_error = ERR_COMPILATION_FAILED;
@@ -533,7 +572,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
} break;
case GDScriptParser::Node::CAST: {
const GDScriptParser::CastNode *cn = static_cast<const GDScriptParser::CastNode *>(p_expression);
- GDScriptDataType cast_type = _gdtype_from_datatype(cn->get_datatype(), codegen.script);
+ GDScriptDataType cast_type = _gdtype_from_datatype(cn->get_datatype(), codegen.script, false);
GDScriptCodeGenerator::Address result;
if (cast_type.has_type) {
@@ -573,11 +612,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
arguments.push_back(arg);
}
- if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(call->function_name) != Variant::VARIANT_MAX) {
- // Construct a built-in type.
- Variant::Type vtype = GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(call->callee)->name);
-
- gen->write_construct(result, vtype, arguments);
+ if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(call->function_name) < Variant::VARIANT_MAX) {
+ gen->write_construct(result, GDScriptParser::get_builtin_type(call->function_name), arguments);
} else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && Variant::has_utility_function(call->function_name)) {
// Variant utility function.
gen->write_call_utility(result, call->function_name, arguments);
@@ -911,7 +947,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(type_test->get_datatype(), codegen.script));
GDScriptCodeGenerator::Address operand = _parse_expression(codegen, r_error, type_test->operand);
- GDScriptDataType test_type = _gdtype_from_datatype(type_test->test_datatype, codegen.script);
+ GDScriptDataType test_type = _gdtype_from_datatype(type_test->test_datatype, codegen.script, false);
if (r_error) {
return GDScriptCodeGenerator::Address();
}
@@ -1889,6 +1925,26 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
}
}
+ // If there's a guard, check its condition too.
+ if (branch->guard_body != nullptr) {
+ // Do this first so the guard does not run unless the pattern matched.
+ gen->write_and_left_operand(pattern_result);
+
+ // Don't actually use the block for the guard.
+ // The binds are already in the locals and we don't want to clear the result of the guard condition before we check the actual match.
+ GDScriptCodeGenerator::Address guard_result = _parse_expression(codegen, err, static_cast<GDScriptParser::ExpressionNode *>(branch->guard_body->statements[0]));
+ if (err) {
+ return err;
+ }
+
+ gen->write_and_right_operand(guard_result);
+ gen->write_end_and(pattern_result);
+
+ if (guard_result.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+ codegen.generator->pop_temporary();
+ }
+ }
+
// Check if pattern did match.
gen->write_if(pattern_result);
@@ -2587,7 +2643,7 @@ Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptP
}
}
- GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type, p_script);
+ GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type, p_script, false);
int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[base_type.native_type];
p_script->native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
@@ -2755,7 +2811,7 @@ Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptP
minfo.property_info = prop_info;
p_script->member_indices[name] = minfo;
- p_script->members.insert(Variant());
+ p_script->members.insert(name);
} break;
case GDScriptParser::ClassNode::Member::FUNCTION: {