Merge pull request #81662 from Repiteo/container-type-vector
Change GDScriptDataType `container_element_type` to vector container
This commit is contained in:
commit
3b9347d5b2
9 changed files with 168 additions and 138 deletions
|
@ -64,8 +64,8 @@ void GDScriptDocGen::_doctype_from_gdtype(const GDType &p_gdtype, String &r_type
|
|||
r_type = p_is_return ? "void" : "null";
|
||||
return;
|
||||
}
|
||||
if (p_gdtype.builtin_type == Variant::ARRAY && p_gdtype.has_container_element_type()) {
|
||||
_doctype_from_gdtype(p_gdtype.get_container_element_type(), r_type, r_enum);
|
||||
if (p_gdtype.builtin_type == Variant::ARRAY && p_gdtype.has_container_element_type(0)) {
|
||||
_doctype_from_gdtype(p_gdtype.get_container_element_type(0), r_type, r_enum);
|
||||
if (!r_enum.is_empty()) {
|
||||
r_type = "int[]";
|
||||
r_enum += "[]";
|
||||
|
|
|
@ -494,7 +494,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
|
|||
in_function_arg_dicts = 0;
|
||||
}
|
||||
|
||||
if (expect_type && (prev_is_char || str[j] == '=') && str[j] != '[' && str[j] != '.') {
|
||||
if (expect_type && (prev_is_char || str[j] == '=') && str[j] != '[' && str[j] != ',' && str[j] != '.') {
|
||||
expect_type = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -685,10 +685,10 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
|
|||
result.builtin_type = GDScriptParser::get_builtin_type(first);
|
||||
|
||||
if (result.builtin_type == Variant::ARRAY) {
|
||||
GDScriptParser::DataType container_type = type_from_metatype(resolve_datatype(p_type->container_type));
|
||||
GDScriptParser::DataType container_type = type_from_metatype(resolve_datatype(p_type->get_container_type_or_null(0)));
|
||||
if (container_type.kind != GDScriptParser::DataType::VARIANT) {
|
||||
container_type.is_constant = false;
|
||||
result.set_container_element_type(container_type);
|
||||
result.set_container_element_type(0, container_type);
|
||||
}
|
||||
}
|
||||
} else if (class_exists(first)) {
|
||||
|
@ -829,8 +829,16 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
|
|||
}
|
||||
}
|
||||
|
||||
if (result.builtin_type != Variant::ARRAY && p_type->container_type != nullptr) {
|
||||
push_error("Only arrays can specify the collection element type.", p_type);
|
||||
if (!p_type->container_types.is_empty()) {
|
||||
if (result.builtin_type == Variant::ARRAY) {
|
||||
if (p_type->container_types.size() != 1) {
|
||||
push_error("Arrays require exactly one collection element type.", p_type);
|
||||
return bad_type;
|
||||
}
|
||||
} else {
|
||||
push_error("Only arrays can specify collection element types.", p_type);
|
||||
return bad_type;
|
||||
}
|
||||
}
|
||||
|
||||
p_type->set_datatype(result);
|
||||
|
@ -1891,8 +1899,8 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
|
|||
|
||||
if (p_assignable->initializer->type == GDScriptParser::Node::ARRAY) {
|
||||
GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(p_assignable->initializer);
|
||||
if (has_specified_type && specified_type.has_container_element_type()) {
|
||||
update_array_literal_element_type(array, specified_type.get_container_element_type());
|
||||
if (has_specified_type && specified_type.has_container_element_type(0)) {
|
||||
update_array_literal_element_type(array, specified_type.get_container_element_type(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1955,7 +1963,7 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi
|
|||
} else {
|
||||
push_error(vformat(R"(Cannot assign a value of type %s to %s "%s" with specified type %s.)", initializer_type.to_string(), p_kind, p_assignable->identifier->name, specified_type.to_string()), p_assignable->initializer);
|
||||
}
|
||||
} else if (specified_type.has_container_element_type() && !initializer_type.has_container_element_type()) {
|
||||
} else if (specified_type.has_container_element_type(0) && !initializer_type.has_container_element_type(0)) {
|
||||
mark_node_unsafe(p_assignable->initializer);
|
||||
#ifdef DEBUG_ENABLED
|
||||
} else if (specified_type.builtin_type == Variant::INT && initializer_type.builtin_type == Variant::FLOAT) {
|
||||
|
@ -2127,8 +2135,8 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
|
|||
if (list_type.is_variant()) {
|
||||
variable_type.kind = GDScriptParser::DataType::VARIANT;
|
||||
mark_node_unsafe(p_for->list);
|
||||
} else if (list_type.has_container_element_type()) {
|
||||
variable_type = list_type.get_container_element_type();
|
||||
} else if (list_type.has_container_element_type(0)) {
|
||||
variable_type = list_type.get_container_element_type(0);
|
||||
variable_type.type_source = list_type.type_source;
|
||||
} else if (list_type.is_typed_container_type()) {
|
||||
variable_type = list_type.get_typed_container_type();
|
||||
|
@ -2377,8 +2385,8 @@ void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) {
|
|||
result.builtin_type = Variant::NIL;
|
||||
result.is_constant = true;
|
||||
} else {
|
||||
if (p_return->return_value->type == GDScriptParser::Node::ARRAY && has_expected_type && expected_type.has_container_element_type()) {
|
||||
update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_return->return_value), expected_type.get_container_element_type());
|
||||
if (p_return->return_value->type == GDScriptParser::Node::ARRAY && has_expected_type && expected_type.has_container_element_type(0)) {
|
||||
update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_return->return_value), expected_type.get_container_element_type(0));
|
||||
}
|
||||
if (has_expected_type && expected_type.is_hard_type() && p_return->return_value->is_constant) {
|
||||
update_const_expression_builtin_type(p_return->return_value, expected_type, "return");
|
||||
|
@ -2598,7 +2606,7 @@ void GDScriptAnalyzer::update_const_expression_builtin_type(GDScriptParser::Expr
|
|||
// This function determines which type is that (if any).
|
||||
void GDScriptAnalyzer::update_array_literal_element_type(GDScriptParser::ArrayNode *p_array, const GDScriptParser::DataType &p_element_type) {
|
||||
GDScriptParser::DataType expected_type = p_element_type;
|
||||
expected_type.unset_container_element_type(); // Nested types (like `Array[Array[int]]`) are not currently supported.
|
||||
expected_type.container_element_types.clear(); // Nested types (like `Array[Array[int]]`) are not currently supported.
|
||||
|
||||
for (int i = 0; i < p_array->elements.size(); i++) {
|
||||
GDScriptParser::ExpressionNode *element_node = p_array->elements[i];
|
||||
|
@ -2621,7 +2629,7 @@ void GDScriptAnalyzer::update_array_literal_element_type(GDScriptParser::ArrayNo
|
|||
}
|
||||
|
||||
GDScriptParser::DataType array_type = p_array->get_datatype();
|
||||
array_type.set_container_element_type(expected_type);
|
||||
array_type.set_container_element_type(0, expected_type);
|
||||
p_array->set_datatype(array_type);
|
||||
}
|
||||
|
||||
|
@ -2668,8 +2676,8 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
|
|||
}
|
||||
|
||||
// Check if assigned value is an array literal, so we can make it a typed array too if appropriate.
|
||||
if (p_assignment->assigned_value->type == GDScriptParser::Node::ARRAY && assignee_type.is_hard_type() && assignee_type.has_container_element_type()) {
|
||||
update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_assignment->assigned_value), assignee_type.get_container_element_type());
|
||||
if (p_assignment->assigned_value->type == GDScriptParser::Node::ARRAY && assignee_type.is_hard_type() && assignee_type.has_container_element_type(0)) {
|
||||
update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_assignment->assigned_value), assignee_type.get_container_element_type(0));
|
||||
}
|
||||
|
||||
if (p_assignment->operation == GDScriptParser::AssignmentNode::OP_NONE && assignee_type.is_hard_type() && p_assignment->assigned_value->is_constant) {
|
||||
|
@ -2747,7 +2755,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
|
|||
// weak non-variant assignee and incompatible result
|
||||
downgrades_assignee = true;
|
||||
}
|
||||
} else if (assignee_type.has_container_element_type() && !op_type.has_container_element_type()) {
|
||||
} else if (assignee_type.has_container_element_type(0) && !op_type.has_container_element_type(0)) {
|
||||
// typed array assignee and untyped array result
|
||||
mark_node_unsafe(p_assignment);
|
||||
}
|
||||
|
@ -3311,8 +3319,8 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
|
|||
// If the function requires typed arrays we must make literals be typed.
|
||||
for (const KeyValue<int, GDScriptParser::ArrayNode *> &E : arrays) {
|
||||
int index = E.key;
|
||||
if (index < par_types.size() && par_types[index].is_hard_type() && par_types[index].has_container_element_type()) {
|
||||
update_array_literal_element_type(E.value, par_types[index].get_container_element_type());
|
||||
if (index < par_types.size() && par_types[index].is_hard_type() && par_types[index].has_container_element_type(0)) {
|
||||
update_array_literal_element_type(E.value, par_types[index].get_container_element_type(0));
|
||||
}
|
||||
}
|
||||
validate_call_arg(par_types, default_arg_count, method_flags.has_flag(METHOD_FLAG_VARARG), p_call);
|
||||
|
@ -3444,8 +3452,8 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
|
|||
}
|
||||
}
|
||||
|
||||
if (p_cast->operand->type == GDScriptParser::Node::ARRAY && cast_type.has_container_element_type()) {
|
||||
update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_cast->operand), cast_type.get_container_element_type());
|
||||
if (p_cast->operand->type == GDScriptParser::Node::ARRAY && cast_type.has_container_element_type(0)) {
|
||||
update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_cast->operand), cast_type.get_container_element_type(0));
|
||||
}
|
||||
|
||||
if (!cast_type.is_variant()) {
|
||||
|
@ -4432,8 +4440,8 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
|||
break;
|
||||
// Can have an element type.
|
||||
case Variant::ARRAY:
|
||||
if (base_type.has_container_element_type()) {
|
||||
result_type = base_type.get_container_element_type();
|
||||
if (base_type.has_container_element_type(0)) {
|
||||
result_type = base_type.get_container_element_type(0);
|
||||
result_type.type_source = base_type.type_source;
|
||||
} else {
|
||||
result_type.kind = GDScriptParser::DataType::VARIANT;
|
||||
|
@ -4597,7 +4605,7 @@ Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::Expressi
|
|||
}
|
||||
|
||||
Variant GDScriptAnalyzer::make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced) {
|
||||
Array array = p_array->get_datatype().has_container_element_type() ? make_array_from_element_datatype(p_array->get_datatype().get_container_element_type()) : Array();
|
||||
Array array = p_array->get_datatype().has_container_element_type(0) ? make_array_from_element_datatype(p_array->get_datatype().get_container_element_type(0)) : Array();
|
||||
|
||||
array.resize(p_array->elements.size());
|
||||
for (int i = 0; i < p_array->elements.size(); i++) {
|
||||
|
@ -4719,8 +4727,8 @@ Variant GDScriptAnalyzer::make_variable_default_value(GDScriptParser::VariableNo
|
|||
GDScriptParser::DataType datatype = p_variable->get_datatype();
|
||||
if (datatype.is_hard_type()) {
|
||||
if (datatype.kind == GDScriptParser::DataType::BUILTIN && datatype.builtin_type != Variant::OBJECT) {
|
||||
if (datatype.builtin_type == Variant::ARRAY && datatype.has_container_element_type()) {
|
||||
result = make_array_from_element_datatype(datatype.get_container_element_type());
|
||||
if (datatype.builtin_type == Variant::ARRAY && datatype.has_container_element_type(0)) {
|
||||
result = make_array_from_element_datatype(datatype.get_container_element_type(0));
|
||||
} else {
|
||||
VariantInternal::initialize(&result, datatype.builtin_type);
|
||||
}
|
||||
|
@ -4747,11 +4755,11 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
|
|||
if (p_value.get_type() == Variant::ARRAY) {
|
||||
const Array &array = p_value;
|
||||
if (array.get_typed_script()) {
|
||||
result.set_container_element_type(type_from_metatype(make_script_meta_type(array.get_typed_script())));
|
||||
result.set_container_element_type(0, type_from_metatype(make_script_meta_type(array.get_typed_script())));
|
||||
} else if (array.get_typed_class_name()) {
|
||||
result.set_container_element_type(type_from_metatype(make_native_meta_type(array.get_typed_class_name())));
|
||||
result.set_container_element_type(0, type_from_metatype(make_native_meta_type(array.get_typed_class_name())));
|
||||
} else if (array.get_typed_builtin() != Variant::NIL) {
|
||||
result.set_container_element_type(type_from_metatype(make_builtin_meta_type((Variant::Type)array.get_typed_builtin())));
|
||||
result.set_container_element_type(0, type_from_metatype(make_builtin_meta_type((Variant::Type)array.get_typed_builtin())));
|
||||
}
|
||||
} else if (p_value.get_type() == Variant::OBJECT) {
|
||||
// Object is treated as a native type, not a builtin type.
|
||||
|
@ -4873,7 +4881,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo
|
|||
ERR_FAIL_V_MSG(result, "Could not find element type from property hint of a typed array.");
|
||||
}
|
||||
elem_type.is_constant = false;
|
||||
result.set_container_element_type(elem_type);
|
||||
result.set_container_element_type(0, elem_type);
|
||||
} else if (p_property.type == Variant::INT) {
|
||||
// Check if it's enum.
|
||||
if ((p_property.usage & PROPERTY_USAGE_CLASS_IS_ENUM) && p_property.class_name != StringName()) {
|
||||
|
@ -5225,7 +5233,7 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator
|
|||
bool hard_operation = p_a.is_hard_type() && p_b.is_hard_type();
|
||||
|
||||
if (p_operation == Variant::OP_ADD && a_type == Variant::ARRAY && b_type == Variant::ARRAY) {
|
||||
if (p_a.has_container_element_type() && p_b.has_container_element_type() && p_a.get_container_element_type() == p_b.get_container_element_type()) {
|
||||
if (p_a.has_container_element_type(0) && p_b.has_container_element_type(0) && p_a.get_container_element_type(0) == p_b.get_container_element_type(0)) {
|
||||
r_valid = true;
|
||||
result = p_a;
|
||||
result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
|
||||
|
@ -5276,8 +5284,8 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
|
|||
}
|
||||
if (valid && p_target.builtin_type == Variant::ARRAY && p_source.builtin_type == Variant::ARRAY) {
|
||||
// Check the element type.
|
||||
if (p_target.has_container_element_type() && p_source.has_container_element_type()) {
|
||||
valid = p_target.get_container_element_type() == p_source.get_container_element_type();
|
||||
if (p_target.has_container_element_type(0) && p_source.has_container_element_type(0)) {
|
||||
valid = p_target.get_container_element_type(0) == p_source.get_container_element_type(0);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
|
|
|
@ -623,8 +623,8 @@ void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, V
|
|||
void GDScriptByteCodeGenerator::write_type_test(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
|
||||
switch (p_type.kind) {
|
||||
case GDScriptDataType::BUILTIN: {
|
||||
if (p_type.builtin_type == Variant::ARRAY && p_type.has_container_element_type()) {
|
||||
const GDScriptDataType &element_type = p_type.get_container_element_type();
|
||||
if (p_type.builtin_type == Variant::ARRAY && p_type.has_container_element_type(0)) {
|
||||
const GDScriptDataType &element_type = p_type.get_container_element_type(0);
|
||||
append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_ARRAY);
|
||||
append(p_target);
|
||||
append(p_source);
|
||||
|
@ -878,8 +878,8 @@ void GDScriptByteCodeGenerator::write_get_static_variable(const Address &p_targe
|
|||
void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_target, const Address &p_source) {
|
||||
switch (p_target.type.kind) {
|
||||
case GDScriptDataType::BUILTIN: {
|
||||
if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
|
||||
const GDScriptDataType &element_type = p_target.type.get_container_element_type();
|
||||
if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type(0)) {
|
||||
const GDScriptDataType &element_type = p_target.type.get_container_element_type(0);
|
||||
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY);
|
||||
append(p_target);
|
||||
append(p_source);
|
||||
|
@ -924,8 +924,8 @@ void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_ta
|
|||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) {
|
||||
if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
|
||||
const GDScriptDataType &element_type = p_target.type.get_container_element_type();
|
||||
if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type(0)) {
|
||||
const GDScriptDataType &element_type = p_target.type.get_container_element_type(0);
|
||||
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY);
|
||||
append(p_target);
|
||||
append(p_source);
|
||||
|
@ -1666,9 +1666,9 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
|
|||
|
||||
// If this is a typed function, then we need to check for potential conversions.
|
||||
if (function->return_type.has_type) {
|
||||
if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) {
|
||||
if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type(0)) {
|
||||
// Typed array.
|
||||
const GDScriptDataType &element_type = function->return_type.get_container_element_type();
|
||||
const GDScriptDataType &element_type = function->return_type.get_container_element_type(0);
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
|
||||
append(p_return_value);
|
||||
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
|
||||
|
@ -1691,8 +1691,8 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
|
|||
} else {
|
||||
switch (function->return_type.kind) {
|
||||
case GDScriptDataType::BUILTIN: {
|
||||
if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) {
|
||||
const GDScriptDataType &element_type = function->return_type.get_container_element_type();
|
||||
if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type(0)) {
|
||||
const GDScriptDataType &element_type = function->return_type.get_container_element_type(0);
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
|
||||
append(p_return_value);
|
||||
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
|
||||
|
|
|
@ -196,8 +196,8 @@ 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, false));
|
||||
for (int i = 0; i < p_datatype.container_element_types.size(); i++) {
|
||||
result.set_container_element_type(i, _gdtype_from_datatype(p_datatype.get_container_element_type_or_variant(i), p_owner, false));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -507,8 +507,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
values.push_back(val);
|
||||
}
|
||||
|
||||
if (array_type.has_container_element_type()) {
|
||||
gen->write_construct_typed_array(result, array_type.get_container_element_type(), values);
|
||||
if (array_type.has_container_element_type(0)) {
|
||||
gen->write_construct_typed_array(result, array_type.get_container_element_type(0), values);
|
||||
} else {
|
||||
gen->write_construct_array(result, values);
|
||||
}
|
||||
|
@ -2133,8 +2133,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||
initialized = true;
|
||||
} else if (local_type.has_type) {
|
||||
// Initialize with default for type.
|
||||
if (local_type.has_container_element_type()) {
|
||||
codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
|
||||
if (local_type.has_container_element_type(0)) {
|
||||
codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(0), Vector<GDScriptCodeGenerator::Address>());
|
||||
initialized = true;
|
||||
} else if (local_type.kind == GDScriptDataType::BUILTIN) {
|
||||
codegen.generator->write_construct(local, local_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
|
||||
|
@ -2276,8 +2276,8 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_
|
|||
|
||||
GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, field_type);
|
||||
|
||||
if (field_type.has_container_element_type()) {
|
||||
codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
|
||||
if (field_type.has_container_element_type(0)) {
|
||||
codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(0), Vector<GDScriptCodeGenerator::Address>());
|
||||
} else if (field_type.kind == GDScriptDataType::BUILTIN) {
|
||||
codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
|
||||
}
|
||||
|
@ -2466,9 +2466,9 @@ GDScriptFunction *GDScriptCompiler::_make_static_initializer(Error &r_error, GDS
|
|||
if (field_type.has_type) {
|
||||
codegen.generator->write_newline(field->start_line);
|
||||
|
||||
if (field_type.has_container_element_type()) {
|
||||
if (field_type.has_container_element_type(0)) {
|
||||
GDScriptCodeGenerator::Address temp = codegen.add_temporary(field_type);
|
||||
codegen.generator->write_construct_typed_array(temp, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>());
|
||||
codegen.generator->write_construct_typed_array(temp, field_type.get_container_element_type(0), Vector<GDScriptCodeGenerator::Address>());
|
||||
codegen.generator->write_set_static_variable(temp, class_addr, p_script->static_variables_indices[field->identifier->name].index);
|
||||
codegen.generator->pop_temporary();
|
||||
} else if (field_type.kind == GDScriptDataType::BUILTIN) {
|
||||
|
|
|
@ -45,10 +45,9 @@ class GDScriptInstance;
|
|||
class GDScript;
|
||||
|
||||
class GDScriptDataType {
|
||||
private:
|
||||
GDScriptDataType *container_element_type = nullptr;
|
||||
|
||||
public:
|
||||
Vector<GDScriptDataType> container_element_types;
|
||||
|
||||
enum Kind {
|
||||
UNINITIALIZED,
|
||||
BUILTIN,
|
||||
|
@ -76,19 +75,20 @@ public:
|
|||
case BUILTIN: {
|
||||
Variant::Type var_type = p_variant.get_type();
|
||||
bool valid = builtin_type == var_type;
|
||||
if (valid && builtin_type == Variant::ARRAY && has_container_element_type()) {
|
||||
if (valid && builtin_type == Variant::ARRAY && has_container_element_type(0)) {
|
||||
Array array = p_variant;
|
||||
if (array.is_typed()) {
|
||||
GDScriptDataType array_container_type = get_container_element_type(0);
|
||||
Variant::Type array_builtin_type = (Variant::Type)array.get_typed_builtin();
|
||||
StringName array_native_type = array.get_typed_class_name();
|
||||
Ref<Script> array_script_type_ref = array.get_typed_script();
|
||||
|
||||
if (array_script_type_ref.is_valid()) {
|
||||
valid = (container_element_type->kind == SCRIPT || container_element_type->kind == GDSCRIPT) && container_element_type->script_type == array_script_type_ref.ptr();
|
||||
valid = (array_container_type.kind == SCRIPT || array_container_type.kind == GDSCRIPT) && array_container_type.script_type == array_script_type_ref.ptr();
|
||||
} else if (array_native_type != StringName()) {
|
||||
valid = container_element_type->kind == NATIVE && container_element_type->native_type == array_native_type;
|
||||
valid = array_container_type.kind == NATIVE && array_container_type.native_type == array_native_type;
|
||||
} else {
|
||||
valid = container_element_type->kind == BUILTIN && container_element_type->builtin_type == array_builtin_type;
|
||||
valid = array_container_type.kind == BUILTIN && array_container_type.builtin_type == array_builtin_type;
|
||||
}
|
||||
} else {
|
||||
valid = false;
|
||||
|
@ -147,24 +147,32 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
void set_container_element_type(const GDScriptDataType &p_element_type) {
|
||||
container_element_type = memnew(GDScriptDataType(p_element_type));
|
||||
}
|
||||
|
||||
GDScriptDataType get_container_element_type() const {
|
||||
ERR_FAIL_NULL_V(container_element_type, GDScriptDataType());
|
||||
return *container_element_type;
|
||||
}
|
||||
|
||||
bool has_container_element_type() const {
|
||||
return container_element_type != nullptr;
|
||||
}
|
||||
|
||||
void unset_container_element_type() {
|
||||
if (container_element_type) {
|
||||
memdelete(container_element_type);
|
||||
void set_container_element_type(int p_index, const GDScriptDataType &p_element_type) {
|
||||
ERR_FAIL_COND(p_index < 0);
|
||||
while (p_index >= container_element_types.size()) {
|
||||
container_element_types.push_back(GDScriptDataType());
|
||||
}
|
||||
container_element_type = nullptr;
|
||||
container_element_types.write[p_index] = GDScriptDataType(p_element_type);
|
||||
}
|
||||
|
||||
GDScriptDataType get_container_element_type(int p_index) const {
|
||||
ERR_FAIL_INDEX_V(p_index, container_element_types.size(), GDScriptDataType());
|
||||
return container_element_types[p_index];
|
||||
}
|
||||
|
||||
GDScriptDataType get_container_element_type_or_variant(int p_index) const {
|
||||
if (p_index < 0 || p_index >= container_element_types.size()) {
|
||||
return GDScriptDataType();
|
||||
}
|
||||
return container_element_types[p_index];
|
||||
}
|
||||
|
||||
bool has_container_element_type(int p_index) const {
|
||||
return p_index >= 0 && p_index < container_element_types.size();
|
||||
}
|
||||
|
||||
bool has_container_element_types() const {
|
||||
return !container_element_types.is_empty();
|
||||
}
|
||||
|
||||
GDScriptDataType() = default;
|
||||
|
@ -176,19 +184,14 @@ public:
|
|||
native_type = p_other.native_type;
|
||||
script_type = p_other.script_type;
|
||||
script_type_ref = p_other.script_type_ref;
|
||||
unset_container_element_type();
|
||||
if (p_other.has_container_element_type()) {
|
||||
set_container_element_type(p_other.get_container_element_type());
|
||||
}
|
||||
container_element_types = p_other.container_element_types;
|
||||
}
|
||||
|
||||
GDScriptDataType(const GDScriptDataType &p_other) {
|
||||
*this = p_other;
|
||||
}
|
||||
|
||||
~GDScriptDataType() {
|
||||
unset_container_element_type();
|
||||
}
|
||||
~GDScriptDataType() {}
|
||||
};
|
||||
|
||||
class GDScriptFunction {
|
||||
|
|
|
@ -3337,14 +3337,21 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) {
|
|||
|
||||
if (match(GDScriptTokenizer::Token::BRACKET_OPEN)) {
|
||||
// Typed collection (like Array[int]).
|
||||
type->container_type = parse_type(false); // Don't allow void for array element type.
|
||||
if (type->container_type == nullptr) {
|
||||
push_error(R"(Expected type for collection after "[".)");
|
||||
complete_extents(type);
|
||||
type = nullptr;
|
||||
} else if (type->container_type->container_type != nullptr) {
|
||||
push_error("Nested typed collections are not supported.");
|
||||
}
|
||||
bool first_pass = true;
|
||||
do {
|
||||
TypeNode *container_type = parse_type(false); // Don't allow void for element type.
|
||||
if (container_type == nullptr) {
|
||||
push_error(vformat(R"(Expected type for collection after "%s".)", first_pass ? "[" : ","));
|
||||
complete_extents(type);
|
||||
type = nullptr;
|
||||
break;
|
||||
} else if (container_type->container_types.size() > 0) {
|
||||
push_error("Nested typed collections are not supported.");
|
||||
} else {
|
||||
type->container_types.append(container_type);
|
||||
}
|
||||
first_pass = false;
|
||||
} while (match(GDScriptTokenizer::Token::COMMA));
|
||||
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after collection type.)");
|
||||
if (type != nullptr) {
|
||||
complete_extents(type);
|
||||
|
@ -3996,8 +4003,8 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
|
|||
variable->export_info.type = Variant::INT;
|
||||
}
|
||||
} else if (p_annotation->name == SNAME("@export_multiline")) {
|
||||
if (export_type.builtin_type == Variant::ARRAY && export_type.has_container_element_type()) {
|
||||
DataType inner_type = export_type.get_container_element_type();
|
||||
if (export_type.builtin_type == Variant::ARRAY && export_type.has_container_element_type(0)) {
|
||||
DataType inner_type = export_type.get_container_element_type(0);
|
||||
if (inner_type.builtin_type != Variant::STRING) {
|
||||
push_error(vformat(R"("%s" annotation on arrays requires a string type but type "%s" was given instead.)", p_annotation->name.operator String(), inner_type.to_string()), variable);
|
||||
return false;
|
||||
|
@ -4033,8 +4040,8 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
|
|||
|
||||
bool is_array = false;
|
||||
|
||||
if (export_type.builtin_type == Variant::ARRAY && export_type.has_container_element_type()) {
|
||||
export_type = export_type.get_container_element_type(); // Use inner type for.
|
||||
if (export_type.builtin_type == Variant::ARRAY && export_type.has_container_element_type(0)) {
|
||||
export_type = export_type.get_container_element_type(0); // Use inner type for.
|
||||
is_array = true;
|
||||
}
|
||||
|
||||
|
@ -4344,8 +4351,8 @@ String GDScriptParser::DataType::to_string() const {
|
|||
if (builtin_type == Variant::NIL) {
|
||||
return "null";
|
||||
}
|
||||
if (builtin_type == Variant::ARRAY && has_container_element_type()) {
|
||||
return vformat("Array[%s]", container_element_type->to_string());
|
||||
if (builtin_type == Variant::ARRAY && has_container_element_type(0)) {
|
||||
return vformat("Array[%s]", container_element_types[0].to_string());
|
||||
}
|
||||
return Variant::get_type_name(builtin_type);
|
||||
case NATIVE:
|
||||
|
@ -4398,36 +4405,36 @@ PropertyInfo GDScriptParser::DataType::to_property_info(const String &p_name) co
|
|||
switch (kind) {
|
||||
case BUILTIN:
|
||||
result.type = builtin_type;
|
||||
if (builtin_type == Variant::ARRAY && has_container_element_type()) {
|
||||
const DataType *elem_type = container_element_type;
|
||||
switch (elem_type->kind) {
|
||||
if (builtin_type == Variant::ARRAY && has_container_element_type(0)) {
|
||||
const DataType elem_type = get_container_element_type(0);
|
||||
switch (elem_type.kind) {
|
||||
case BUILTIN:
|
||||
result.hint = PROPERTY_HINT_ARRAY_TYPE;
|
||||
result.hint_string = Variant::get_type_name(elem_type->builtin_type);
|
||||
result.hint_string = Variant::get_type_name(elem_type.builtin_type);
|
||||
break;
|
||||
case NATIVE:
|
||||
result.hint = PROPERTY_HINT_ARRAY_TYPE;
|
||||
result.hint_string = elem_type->native_type;
|
||||
result.hint_string = elem_type.native_type;
|
||||
break;
|
||||
case SCRIPT:
|
||||
result.hint = PROPERTY_HINT_ARRAY_TYPE;
|
||||
if (elem_type->script_type.is_valid() && elem_type->script_type->get_global_name() != StringName()) {
|
||||
result.hint_string = elem_type->script_type->get_global_name();
|
||||
if (elem_type.script_type.is_valid() && elem_type.script_type->get_global_name() != StringName()) {
|
||||
result.hint_string = elem_type.script_type->get_global_name();
|
||||
} else {
|
||||
result.hint_string = elem_type->native_type;
|
||||
result.hint_string = elem_type.native_type;
|
||||
}
|
||||
break;
|
||||
case CLASS:
|
||||
result.hint = PROPERTY_HINT_ARRAY_TYPE;
|
||||
if (elem_type->class_type != nullptr && elem_type->class_type->get_global_name() != StringName()) {
|
||||
result.hint_string = elem_type->class_type->get_global_name();
|
||||
if (elem_type.class_type != nullptr && elem_type.class_type->get_global_name() != StringName()) {
|
||||
result.hint_string = elem_type.class_type->get_global_name();
|
||||
} else {
|
||||
result.hint_string = elem_type->native_type;
|
||||
result.hint_string = elem_type.native_type;
|
||||
}
|
||||
break;
|
||||
case ENUM:
|
||||
result.hint = PROPERTY_HINT_ARRAY_TYPE;
|
||||
result.hint_string = String(elem_type->native_type).replace("::", ".");
|
||||
result.hint_string = String(elem_type.native_type).replace("::", ".");
|
||||
break;
|
||||
case VARIANT:
|
||||
case RESOLVING:
|
||||
|
|
|
@ -101,11 +101,9 @@ public:
|
|||
struct WhileNode;
|
||||
|
||||
class DataType {
|
||||
private:
|
||||
// Private access so we can control memory management.
|
||||
DataType *container_element_type = nullptr;
|
||||
|
||||
public:
|
||||
Vector<DataType> container_element_types;
|
||||
|
||||
enum Kind {
|
||||
BUILTIN,
|
||||
NATIVE,
|
||||
|
@ -152,24 +150,39 @@ public:
|
|||
_FORCE_INLINE_ String to_string_strict() const { return is_hard_type() ? to_string() : "Variant"; }
|
||||
PropertyInfo to_property_info(const String &p_name) const;
|
||||
|
||||
_FORCE_INLINE_ void set_container_element_type(const DataType &p_type) {
|
||||
container_element_type = memnew(DataType(p_type));
|
||||
_FORCE_INLINE_ static DataType get_variant_type() { // Default DataType for container elements.
|
||||
DataType datatype;
|
||||
datatype.kind = VARIANT;
|
||||
datatype.type_source = INFERRED;
|
||||
return datatype;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ DataType get_container_element_type() const {
|
||||
ERR_FAIL_NULL_V(container_element_type, DataType());
|
||||
return *container_element_type;
|
||||
_FORCE_INLINE_ void set_container_element_type(int p_index, const DataType &p_type) {
|
||||
ERR_FAIL_COND(p_index < 0);
|
||||
while (p_index >= container_element_types.size()) {
|
||||
container_element_types.push_back(get_variant_type());
|
||||
}
|
||||
container_element_types.write[p_index] = DataType(p_type);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool has_container_element_type() const {
|
||||
return container_element_type != nullptr;
|
||||
_FORCE_INLINE_ DataType get_container_element_type(int p_index) const {
|
||||
ERR_FAIL_INDEX_V(p_index, container_element_types.size(), get_variant_type());
|
||||
return container_element_types[p_index];
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void unset_container_element_type() {
|
||||
if (container_element_type) {
|
||||
memdelete(container_element_type);
|
||||
};
|
||||
container_element_type = nullptr;
|
||||
_FORCE_INLINE_ DataType get_container_element_type_or_variant(int p_index) const {
|
||||
if (p_index < 0 || p_index >= container_element_types.size()) {
|
||||
return get_variant_type();
|
||||
}
|
||||
return container_element_types[p_index];
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool has_container_element_type(int p_index) const {
|
||||
return p_index >= 0 && p_index < container_element_types.size();
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool has_container_element_types() const {
|
||||
return !container_element_types.is_empty();
|
||||
}
|
||||
|
||||
bool is_typed_container_type() const;
|
||||
|
@ -229,10 +242,7 @@ public:
|
|||
class_type = p_other.class_type;
|
||||
method_info = p_other.method_info;
|
||||
enum_values = p_other.enum_values;
|
||||
unset_container_element_type();
|
||||
if (p_other.has_container_element_type()) {
|
||||
set_container_element_type(p_other.get_container_element_type());
|
||||
}
|
||||
container_element_types = p_other.container_element_types;
|
||||
}
|
||||
|
||||
DataType() = default;
|
||||
|
@ -241,9 +251,7 @@ public:
|
|||
*this = p_other;
|
||||
}
|
||||
|
||||
~DataType() {
|
||||
unset_container_element_type();
|
||||
}
|
||||
~DataType() {}
|
||||
};
|
||||
|
||||
struct ParserError {
|
||||
|
@ -1183,7 +1191,11 @@ public:
|
|||
|
||||
struct TypeNode : public Node {
|
||||
Vector<IdentifierNode *> type_chain;
|
||||
TypeNode *container_type = nullptr;
|
||||
Vector<TypeNode *> container_types;
|
||||
|
||||
TypeNode *get_container_type_or_null(int p_index) const {
|
||||
return p_index >= 0 && p_index < container_types.size() ? container_types[p_index] : nullptr;
|
||||
}
|
||||
|
||||
TypeNode() {
|
||||
type = TYPE;
|
||||
|
|
|
@ -91,8 +91,8 @@ Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataT
|
|||
if (p_data_type.builtin_type == Variant::ARRAY) {
|
||||
Array array;
|
||||
// Typed array.
|
||||
if (p_data_type.has_container_element_type()) {
|
||||
const GDScriptDataType &element_type = p_data_type.get_container_element_type();
|
||||
if (p_data_type.has_container_element_type(0)) {
|
||||
const GDScriptDataType &element_type = p_data_type.get_container_element_type(0);
|
||||
array.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue