feat: updated engine
This commit is contained in:
parent
cbe99774ff
commit
f4cf6b3999
6607 changed files with 910135 additions and 430025 deletions
|
|
@ -38,8 +38,8 @@
|
|||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/config/project_settings.h"
|
||||
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object/class_db.h"
|
||||
|
||||
bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
|
||||
if (codegen.function_node && codegen.function_node->is_static) {
|
||||
|
|
@ -252,7 +252,7 @@ static bool _can_use_validate_call(const MethodBind *p_method, const Vector<GDSc
|
|||
}
|
||||
|
||||
GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root, bool p_initializer) {
|
||||
if (p_expression->is_constant && !(p_expression->get_datatype().is_meta_type && p_expression->get_datatype().kind == GDScriptParser::DataType::CLASS)) {
|
||||
if (p_expression->is_constant && !(p_expression->type_constraint.is_meta_type && p_expression->type_constraint.kind == GDScriptParser::DataType::CLASS)) {
|
||||
return codegen.add_constant(p_expression->reduced_value);
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
// Try class members.
|
||||
if (_is_class_member_property(codegen, identifier)) {
|
||||
// Get property.
|
||||
GDScriptCodeGenerator::Address temp = codegen.add_temporary(_gdtype_from_datatype(p_expression->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address temp = codegen.add_temporary(_gdtype_from_datatype(p_expression->type_constraint, codegen.script));
|
||||
gen->write_get_member(temp, identifier);
|
||||
return temp;
|
||||
}
|
||||
|
|
@ -419,9 +419,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
|
||||
// If it's an autoload singleton, we postpone to load it at runtime.
|
||||
// This is so one autoload doesn't try to load another before it's compiled.
|
||||
HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
|
||||
HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads(ProjectSettings::get_singleton()->get_autoload_list());
|
||||
if (autoloads.has(identifier) && autoloads[identifier].is_singleton) {
|
||||
GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->type_constraint, codegen.script));
|
||||
int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
|
||||
gen->write_store_global(global, idx);
|
||||
return global;
|
||||
|
|
@ -503,7 +503,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
Vector<GDScriptCodeGenerator::Address> values;
|
||||
|
||||
// Create the result temporary first since it's the last to be killed.
|
||||
GDScriptDataType array_type = _gdtype_from_datatype(an->get_datatype(), codegen.script);
|
||||
GDScriptDataType array_type = _gdtype_from_datatype(an->type_constraint, codegen.script);
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(array_type);
|
||||
|
||||
for (int i = 0; i < an->elements.size(); i++) {
|
||||
|
|
@ -533,7 +533,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
Vector<GDScriptCodeGenerator::Address> elements;
|
||||
|
||||
// Create the result temporary first since it's the last to be killed.
|
||||
GDScriptDataType dict_type = _gdtype_from_datatype(dn->get_datatype(), codegen.script);
|
||||
GDScriptDataType dict_type = _gdtype_from_datatype(dn->type_constraint, codegen.script);
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(dict_type);
|
||||
|
||||
for (int i = 0; i < dn->elements.size(); i++) {
|
||||
|
|
@ -580,7 +580,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, false);
|
||||
GDScriptDataType cast_type = _gdtype_from_datatype(cn->type_constraint, codegen.script, false);
|
||||
|
||||
GDScriptCodeGenerator::Address result;
|
||||
if (cast_type.has_type()) {
|
||||
|
|
@ -603,12 +603,15 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::CALL: {
|
||||
const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(p_expression);
|
||||
bool is_awaited = p_expression == awaited_node;
|
||||
GDScriptDataType type = _gdtype_from_datatype(call->get_datatype(), codegen.script);
|
||||
GDScriptCodeGenerator::Address result;
|
||||
if (p_root) {
|
||||
result = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::NIL);
|
||||
} else if (is_awaited) {
|
||||
// When called with await, we need to use an untyped temporary regardless of whether the base
|
||||
// class function is a coroutine, because an inherited class could return a function state object.
|
||||
result = codegen.add_temporary();
|
||||
} else {
|
||||
result = codegen.add_temporary(type);
|
||||
result = codegen.add_temporary(_gdtype_from_datatype(call->type_constraint, codegen.script));
|
||||
}
|
||||
|
||||
Vector<GDScriptCodeGenerator::Address> arguments;
|
||||
|
|
@ -747,7 +750,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
Vector<GDScriptCodeGenerator::Address> args;
|
||||
args.push_back(codegen.add_constant(NodePath(get_node->full_path)));
|
||||
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->type_constraint, codegen.script));
|
||||
|
||||
MethodBind *get_node_method = ClassDB::get_method("Node", "get_node");
|
||||
gen->write_call_method_bind_validated(result, GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), get_node_method, args);
|
||||
|
|
@ -763,7 +766,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::AWAIT: {
|
||||
const GDScriptParser::AwaitNode *await = static_cast<const GDScriptParser::AwaitNode *>(p_expression);
|
||||
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(p_expression->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(p_expression->type_constraint, codegen.script));
|
||||
GDScriptParser::ExpressionNode *previous_awaited_node = awaited_node;
|
||||
awaited_node = await->to_await;
|
||||
GDScriptCodeGenerator::Address argument = _parse_expression(codegen, r_error, await->to_await);
|
||||
|
|
@ -783,7 +786,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
// Indexing operator.
|
||||
case GDScriptParser::Node::SUBSCRIPT: {
|
||||
const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(p_expression);
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(subscript->type_constraint, codegen.script));
|
||||
|
||||
GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
|
||||
if (r_error) {
|
||||
|
|
@ -811,7 +814,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
// Remove result temp as we don't need it.
|
||||
gen->pop_temporary();
|
||||
// Faster than indexing self (as if no self. had been used).
|
||||
return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->get_datatype(), codegen.script));
|
||||
return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::MEMBER, MI->value.index, _gdtype_from_datatype(subscript->type_constraint, codegen.script));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -849,7 +852,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::UNARY_OPERATOR: {
|
||||
const GDScriptParser::UnaryOpNode *unary = static_cast<const GDScriptParser::UnaryOpNode *>(p_expression);
|
||||
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(unary->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(unary->type_constraint, codegen.script));
|
||||
|
||||
GDScriptCodeGenerator::Address operand = _parse_expression(codegen, r_error, unary->operand);
|
||||
if (r_error) {
|
||||
|
|
@ -867,7 +870,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::BINARY_OPERATOR: {
|
||||
const GDScriptParser::BinaryOpNode *binary = static_cast<const GDScriptParser::BinaryOpNode *>(p_expression);
|
||||
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(binary->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(binary->type_constraint, codegen.script));
|
||||
|
||||
switch (binary->operation) {
|
||||
case GDScriptParser::BinaryOpNode::OP_LOGIC_AND: {
|
||||
|
|
@ -921,7 +924,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::TERNARY_OPERATOR: {
|
||||
// x IF a ELSE y operator with early out on failure.
|
||||
const GDScriptParser::TernaryOpNode *ternary = static_cast<const GDScriptParser::TernaryOpNode *>(p_expression);
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(ternary->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(ternary->type_constraint, codegen.script));
|
||||
|
||||
gen->write_start_ternary(result);
|
||||
|
||||
|
|
@ -959,7 +962,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
} break;
|
||||
case GDScriptParser::Node::TYPE_TEST: {
|
||||
const GDScriptParser::TypeTestNode *type_test = static_cast<const GDScriptParser::TypeTestNode *>(p_expression);
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(type_test->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(type_test->type_constraint, 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, false);
|
||||
|
|
@ -1100,7 +1103,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
break;
|
||||
}
|
||||
const GDScriptParser::SubscriptNode *subscript_elem = E->get();
|
||||
GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript_elem->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript_elem->type_constraint, codegen.script));
|
||||
GDScriptCodeGenerator::Address key;
|
||||
StringName name;
|
||||
|
||||
|
|
@ -1139,8 +1142,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
|
||||
// Perform operator if any.
|
||||
if (assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) {
|
||||
GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->type_constraint, codegen.script));
|
||||
GDScriptCodeGenerator::Address value = codegen.add_temporary(_gdtype_from_datatype(subscript->type_constraint, codegen.script));
|
||||
if (subscript->is_attribute) {
|
||||
gen->write_get_named(value, name, prev_base);
|
||||
} else {
|
||||
|
|
@ -1260,8 +1263,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
StringName name = static_cast<GDScriptParser::IdentifierNode *>(assignment->assignee)->name;
|
||||
|
||||
if (has_operation) {
|
||||
GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address member = codegen.add_temporary(_gdtype_from_datatype(assignment->assignee->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->type_constraint, codegen.script));
|
||||
GDScriptCodeGenerator::Address member = codegen.add_temporary(_gdtype_from_datatype(assignment->assignee->type_constraint, codegen.script));
|
||||
gen->write_get_member(member, name);
|
||||
gen->write_binary_operator(op_result, assignment->variant_op, member, assigned_value);
|
||||
gen->pop_temporary(); // Pop member temp.
|
||||
|
|
@ -1345,7 +1348,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
bool has_operation = assignment->operation != GDScriptParser::AssignmentNode::OP_NONE;
|
||||
if (has_operation) {
|
||||
// Perform operation.
|
||||
GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address op_result = codegen.add_temporary(_gdtype_from_datatype(assignment->type_constraint, codegen.script));
|
||||
GDScriptCodeGenerator::Address og_value = _parse_expression(codegen, r_error, assignment->assignee);
|
||||
gen->write_binary_operator(op_result, assignment->variant_op, og_value, assigned_value);
|
||||
to_assign = op_result;
|
||||
|
|
@ -1395,7 +1398,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
} break;
|
||||
case GDScriptParser::Node::LAMBDA: {
|
||||
const GDScriptParser::LambdaNode *lambda = static_cast<const GDScriptParser::LambdaNode *>(p_expression);
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(lambda->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(lambda->type_constraint, codegen.script));
|
||||
|
||||
Vector<GDScriptCodeGenerator::Address> captures;
|
||||
captures.resize(lambda->captures.size());
|
||||
|
|
@ -1909,7 +1912,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||
codegen.start_block(); // Add an extra block, since @special locals belong to the match scope.
|
||||
|
||||
// Evaluate the match expression.
|
||||
GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->type_constraint, codegen.script));
|
||||
GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, err, match->test);
|
||||
if (err) {
|
||||
return err;
|
||||
|
|
@ -2039,7 +2042,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||
// Also we use custom logic to clear block locals.
|
||||
codegen.start_block();
|
||||
|
||||
GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->get_datatype(), codegen.script));
|
||||
GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->type_constraint, codegen.script));
|
||||
|
||||
// Optimize `range()` call to not allocate an array.
|
||||
GDScriptParser::CallNode *range_call = nullptr;
|
||||
|
|
@ -2052,7 +2055,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||
}
|
||||
}
|
||||
|
||||
gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype(), codegen.script), range_call != nullptr);
|
||||
gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->type_constraint, codegen.script), range_call != nullptr);
|
||||
|
||||
if (range_call != nullptr) {
|
||||
Vector<GDScriptCodeGenerator::Address> args;
|
||||
|
|
@ -2169,10 +2172,10 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||
}
|
||||
|
||||
if (return_n->void_return) {
|
||||
// Always return "null", even if the expression is a call to a void function.
|
||||
gen->write_return(codegen.add_constant(Variant()));
|
||||
// Always return `null`, even if the expression is a call to a `void` function.
|
||||
gen->write_return(codegen.add_constant(Variant()), false);
|
||||
} else {
|
||||
gen->write_return(return_value);
|
||||
gen->write_return(return_value, return_n->use_conversion);
|
||||
}
|
||||
if (return_value.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
|
||||
codegen.generator->pop_temporary();
|
||||
|
|
@ -2214,7 +2217,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||
const GDScriptParser::VariableNode *lv = static_cast<const GDScriptParser::VariableNode *>(s);
|
||||
// Should be already in stack when the block began.
|
||||
GDScriptCodeGenerator::Address local = codegen.locals[lv->identifier->name];
|
||||
GDScriptDataType local_type = _gdtype_from_datatype(lv->get_datatype(), codegen.script);
|
||||
GDScriptDataType local_type = _gdtype_from_datatype(lv->type_constraint, codegen.script);
|
||||
|
||||
bool initialized = false;
|
||||
if (lv->initializer != nullptr) {
|
||||
|
|
@ -2310,7 +2313,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
|
|||
is_abstract = p_func->is_abstract;
|
||||
is_static = p_func->is_static;
|
||||
rpc_config = p_func->rpc_config;
|
||||
return_type = _gdtype_from_datatype(p_func->get_datatype(), p_script);
|
||||
return_type = _gdtype_from_datatype(p_func->return_type_constraint, p_script);
|
||||
} else {
|
||||
if (p_for_ready) {
|
||||
func_name = "@implicit_ready";
|
||||
|
|
@ -2338,11 +2341,11 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
|
|||
if (p_func) {
|
||||
for (int i = 0; i < p_func->parameters.size(); i++) {
|
||||
const GDScriptParser::ParameterNode *parameter = p_func->parameters[i];
|
||||
GDScriptDataType par_type = _gdtype_from_datatype(parameter->get_datatype(), p_script);
|
||||
GDScriptDataType par_type = _gdtype_from_datatype(parameter->type_constraint, p_script);
|
||||
uint32_t par_addr = codegen.generator->add_parameter(parameter->identifier->name, parameter->initializer != nullptr, par_type);
|
||||
codegen.parameters[parameter->identifier->name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::FUNCTION_PARAMETER, par_addr, par_type);
|
||||
|
||||
method_info.arguments.push_back(parameter->get_datatype().to_property_info(parameter->identifier->name));
|
||||
method_info.arguments.push_back(parameter->type_constraint.to_property_info(parameter->identifier->name));
|
||||
|
||||
if (parameter->initializer != nullptr) {
|
||||
optional_parameters++;
|
||||
|
|
@ -2350,7 +2353,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
|
|||
}
|
||||
|
||||
if (p_func->is_vararg()) {
|
||||
vararg_addr = codegen.add_local(p_func->rest_parameter->identifier->name, _gdtype_from_datatype(p_func->rest_parameter->get_datatype(), codegen.script));
|
||||
vararg_addr = codegen.add_local(p_func->rest_parameter->identifier->name, _gdtype_from_datatype(p_func->rest_parameter->type_constraint, codegen.script));
|
||||
method_info.flags |= METHOD_FLAG_VARARG;
|
||||
}
|
||||
|
||||
|
|
@ -2376,7 +2379,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
|
|||
continue;
|
||||
}
|
||||
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script);
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->type_constraint, codegen.script);
|
||||
if (field_type.has_type()) {
|
||||
codegen.generator->write_newline(field->start_line);
|
||||
|
||||
|
|
@ -2420,7 +2423,7 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script);
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->type_constraint, codegen.script);
|
||||
GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, field_type);
|
||||
|
||||
if (field->use_conversion_assign) {
|
||||
|
|
@ -2510,15 +2513,8 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
|
|||
}
|
||||
|
||||
if (p_func) {
|
||||
// If no `return` statement, then return type is `void`, not `Variant`.
|
||||
if (p_func->body->has_return) {
|
||||
gd_function->return_type = _gdtype_from_datatype(p_func->get_datatype(), p_script);
|
||||
method_info.return_val = p_func->get_datatype().to_property_info(String());
|
||||
} else {
|
||||
gd_function->return_type = GDScriptDataType();
|
||||
gd_function->return_type.kind = GDScriptDataType::BUILTIN;
|
||||
gd_function->return_type.builtin_type = Variant::NIL;
|
||||
}
|
||||
gd_function->return_type = _gdtype_from_datatype(p_func->return_type_constraint, p_script);
|
||||
method_info.return_val = p_func->return_type_constraint.to_property_info(String());
|
||||
|
||||
if (p_func->is_vararg()) {
|
||||
gd_function->_vararg_index = vararg_addr.address;
|
||||
|
|
@ -2572,7 +2568,7 @@ GDScriptFunction *GDScriptCompiler::_make_static_initializer(Error &r_error, GDS
|
|||
continue;
|
||||
}
|
||||
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script);
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->type_constraint, codegen.script);
|
||||
if (field_type.has_type()) {
|
||||
codegen.generator->write_newline(field->start_line);
|
||||
|
||||
|
|
@ -2616,7 +2612,7 @@ GDScriptFunction *GDScriptCompiler::_make_static_initializer(Error &r_error, GDS
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script);
|
||||
GDScriptDataType field_type = _gdtype_from_datatype(field->type_constraint, codegen.script);
|
||||
GDScriptCodeGenerator::Address temp = codegen.add_temporary(field_type);
|
||||
|
||||
if (field->use_conversion_assign) {
|
||||
|
|
@ -2795,24 +2791,27 @@ Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptP
|
|||
if (err) {
|
||||
return err;
|
||||
}
|
||||
} else if (!base->is_valid()) {
|
||||
} else if (!base->is_script_valid()) {
|
||||
String base_qualified_name = base->fully_qualified_name;
|
||||
String base_path = base->path;
|
||||
|
||||
Error err = OK;
|
||||
Ref<GDScript> base_root = GDScriptCache::get_shallow_script(base->path, err, p_script->path);
|
||||
Ref<GDScript> base_root = GDScriptCache::get_shallow_script(base_path, err, p_script->path);
|
||||
if (err) {
|
||||
_set_error(vformat(R"(Could not parse base class "%s" from "%s": %s)", base->fully_qualified_name, base->path, error_names[err]), nullptr);
|
||||
_set_error(vformat(R"(Could not parse base class "%s" from "%s": %s)", base_qualified_name, base_path, error_names[err]), nullptr);
|
||||
return err;
|
||||
}
|
||||
if (base_root.is_valid()) {
|
||||
base = Ref<GDScript>(base_root->find_class(base->fully_qualified_name));
|
||||
base = Ref<GDScript>(base_root->find_class(base_qualified_name));
|
||||
}
|
||||
if (base.is_null()) {
|
||||
_set_error(vformat(R"(Could not find class "%s" in "%s".)", base->fully_qualified_name, base->path), nullptr);
|
||||
_set_error(vformat(R"(Could not find class "%s" in "%s".)", base_qualified_name, base_path), nullptr);
|
||||
return ERR_COMPILATION_FAILED;
|
||||
}
|
||||
|
||||
err = _prepare_compilation(base.ptr(), p_class->base_type.class_type, p_keep_state);
|
||||
if (err) {
|
||||
_set_error(vformat(R"(Could not populate class members of base class "%s" in "%s".)", base->fully_qualified_name, base->path), nullptr);
|
||||
_set_error(vformat(R"(Could not populate class members of base class "%s" in "%s".)", base_qualified_name, base_path), nullptr);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
|
@ -2860,9 +2859,11 @@ Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptP
|
|||
}
|
||||
break;
|
||||
}
|
||||
minfo.data_type = _gdtype_from_datatype(variable->get_datatype(), p_script);
|
||||
|
||||
PropertyInfo prop_info = variable->get_datatype().to_property_info(name);
|
||||
const GDScriptParser::DataType variable_type = variable->type_constraint;
|
||||
minfo.data_type = _gdtype_from_datatype(variable_type, p_script);
|
||||
|
||||
PropertyInfo prop_info = variable_type.to_property_info(name);
|
||||
PropertyInfo export_info = variable->export_info;
|
||||
|
||||
if (variable->exported) {
|
||||
|
|
@ -2873,6 +2874,28 @@ Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptP
|
|||
prop_info.hint = export_info.hint;
|
||||
prop_info.hint_string = export_info.hint_string;
|
||||
prop_info.usage = export_info.usage;
|
||||
} else {
|
||||
// Enum hint doesn't really belong to the data type information, so we don't want to add it to
|
||||
// `GDScriptParser::DataType::to_property_info()`. However, we still want to add this metadata
|
||||
// for unexported properties so they display nicely in the Remote Tree Inspector.
|
||||
if (variable_type.kind == GDScriptParser::DataType::ENUM && !variable_type.is_meta_type) {
|
||||
prop_info.hint = PROPERTY_HINT_ENUM;
|
||||
|
||||
String enum_hint_string;
|
||||
bool first = true;
|
||||
for (const KeyValue<StringName, int64_t> &E : variable_type.enum_values) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
enum_hint_string += ",";
|
||||
}
|
||||
enum_hint_string += E.key.string().capitalize().xml_escape();
|
||||
enum_hint_string += ":";
|
||||
enum_hint_string += String::num_int64(E.value).xml_escape();
|
||||
}
|
||||
|
||||
prop_info.hint_string = enum_hint_string;
|
||||
}
|
||||
}
|
||||
prop_info.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
|
||||
minfo.property_info = prop_info;
|
||||
|
|
@ -3048,45 +3071,8 @@ Error GDScriptCompiler::_compile_class(GDScript *p_script, const GDScriptParser:
|
|||
//validate instances if keeping state
|
||||
|
||||
if (p_keep_state) {
|
||||
for (RBSet<Object *>::Element *E = p_script->instances.front(); E;) {
|
||||
RBSet<Object *>::Element *N = E->next();
|
||||
|
||||
ScriptInstance *si = E->get()->get_script_instance();
|
||||
if (si->is_placeholder()) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
PlaceHolderScriptInstance *psi = static_cast<PlaceHolderScriptInstance *>(si);
|
||||
|
||||
if (p_script->is_tool()) {
|
||||
//re-create as an instance
|
||||
p_script->placeholders.erase(psi); //remove placeholder
|
||||
|
||||
GDScriptInstance *instance = memnew(GDScriptInstance);
|
||||
instance->members.resize(p_script->member_indices.size());
|
||||
instance->script = Ref<GDScript>(p_script);
|
||||
instance->owner = E->get();
|
||||
|
||||
//needed for hot reloading
|
||||
for (const KeyValue<StringName, GDScript::MemberInfo> &F : p_script->member_indices) {
|
||||
instance->member_indices_cache[F.key] = F.value.index;
|
||||
}
|
||||
instance->owner->set_script_instance(instance);
|
||||
|
||||
/* STEP 2, INITIALIZE AND CONSTRUCT */
|
||||
|
||||
Callable::CallError ce;
|
||||
p_script->initializer->call(instance, nullptr, 0, ce);
|
||||
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
//well, tough luck, not gonna do anything here
|
||||
}
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
} else {
|
||||
GDScriptInstance *gi = static_cast<GDScriptInstance *>(si);
|
||||
gi->reload_members();
|
||||
}
|
||||
|
||||
E = N;
|
||||
for (SelfList<GDScriptInstance> *E = p_script->instances.first(); E; E = E->next()) {
|
||||
E->self()->reload_members();
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_ENABLED
|
||||
|
|
@ -3117,8 +3103,8 @@ Error GDScriptCompiler::_compile_class(GDScript *p_script, const GDScriptParser:
|
|||
|
||||
void GDScriptCompiler::convert_to_initializer_type(Variant &p_variant, const GDScriptParser::VariableNode *p_node) {
|
||||
// Set p_variant to the value of p_node's initializer, with the type of p_node's variable.
|
||||
GDScriptParser::DataType member_t = p_node->datatype;
|
||||
GDScriptParser::DataType init_t = p_node->initializer->datatype;
|
||||
GDScriptParser::DataType member_t = p_node->type_constraint;
|
||||
GDScriptParser::DataType init_t = p_node->initializer->type_constraint;
|
||||
if (member_t.is_hard_type() && init_t.is_hard_type() &&
|
||||
member_t.kind == GDScriptParser::DataType::BUILTIN && init_t.kind == GDScriptParser::DataType::BUILTIN) {
|
||||
if (Variant::can_convert_strict(init_t.builtin_type, member_t.builtin_type)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue