summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2021-08-14 05:44:22 +0200
committerPedro J. Estébanez <pedrojrulez@gmail.com>2021-09-11 11:35:25 +0200
commitd72f12a561179719d8a1228221ba13c7c029be17 (patch)
tree47f0486083e82e10f6efd0772a6d850961d2c407 /modules/gdscript
parent0a001afec53aa4caed7820b34db4d7d15686e24d (diff)
Implement iterator variable typing in GDScript
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp24
-rw-r--r--modules/gdscript/gdscript_parser.cpp33
-rw-r--r--modules/gdscript/gdscript_parser.h4
3 files changed, 57 insertions, 4 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 6b7403d854..f090e7db25 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -1089,12 +1089,28 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
}
}
- if (!list_resolved) {
+ GDScriptParser::DataType variable_type;
+ if (list_resolved) {
+ variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
+ variable_type.kind = GDScriptParser::DataType::BUILTIN;
+ variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else?
+ p_for->variable->set_datatype(variable_type);
+ } else {
resolve_node(p_for->list);
+ if (p_for->list->datatype.has_container_element_type()) {
+ variable_type = p_for->list->datatype.get_container_element_type();
+ variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
+ } else if (p_for->list->datatype.is_typed_container_type()) {
+ variable_type = p_for->list->datatype.get_typed_container_type();
+ variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
+ } else {
+ // Last resort
+ // TODO: Must other cases be handled? Must we mark as unsafe?
+ variable_type.type_source = GDScriptParser::DataType::UNDETECTED;
+ variable_type.kind = GDScriptParser::DataType::VARIANT;
+ }
}
-
- // TODO: If list is a typed array, the variable should be an element.
- // Also applicable for constant range() (so variable is int or float).
+ p_for->variable->set_datatype(variable_type);
resolve_suite(p_for->loop);
p_for->set_datatype(p_for->loop->get_datatype());
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index d21caf4389..1cbb4861bc 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3540,6 +3540,39 @@ String GDScriptParser::DataType::to_string() const {
ERR_FAIL_V_MSG("<unresolved type", "Kind set outside the enum range.");
}
+static Variant::Type _variant_type_to_typed_array_element_type(Variant::Type p_type) {
+ switch (p_type) {
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY:
+ return Variant::INT;
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ return Variant::FLOAT;
+ case Variant::PACKED_STRING_ARRAY:
+ return Variant::STRING;
+ case Variant::PACKED_VECTOR2_ARRAY:
+ return Variant::VECTOR2;
+ case Variant::PACKED_VECTOR3_ARRAY:
+ return Variant::VECTOR3;
+ case Variant::PACKED_COLOR_ARRAY:
+ return Variant::COLOR;
+ default:
+ return Variant::NIL;
+ }
+}
+
+bool GDScriptParser::DataType::is_typed_container_type() const {
+ return kind == GDScriptParser::DataType::BUILTIN && _variant_type_to_typed_array_element_type(builtin_type) != Variant::NIL;
+}
+
+GDScriptParser::DataType GDScriptParser::DataType::get_typed_container_type() const {
+ GDScriptParser::DataType type;
+ type.kind = GDScriptParser::DataType::BUILTIN;
+ type.builtin_type = _variant_type_to_typed_array_element_type(builtin_type);
+ return type;
+}
+
/*---------- PRETTY PRINT FOR DEBUG ----------*/
#ifdef DEBUG_ENABLED
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 0bce8d7ddd..ed5300eb59 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -161,6 +161,10 @@ public:
container_element_type = nullptr;
}
+ bool is_typed_container_type() const;
+
+ GDScriptParser::DataType get_typed_container_type() const;
+
bool operator==(const DataType &p_other) const {
if (type_source == UNDETECTED || p_other.type_source == UNDETECTED) {
return true; // Can be consireded equal for parsing purposes.