diff options
Diffstat (limited to 'modules/gdscript/gdscript_analyzer.cpp')
-rw-r--r-- | modules/gdscript/gdscript_analyzer.cpp | 111 |
1 files changed, 36 insertions, 75 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index b32812a78f..3f2fdc04a5 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -978,7 +978,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { if (!call->arguments[i]->is_constant) { all_is_constant = false; - } else { + } else if (all_is_constant) { args.write[i] = call->arguments[i]->reduced_value; } @@ -1013,11 +1013,15 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { } } - GDScriptParser::DataType list_type; - list_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; - list_type.kind = GDScriptParser::DataType::BUILTIN; - list_type.builtin_type = Variant::ARRAY; - p_for->list->set_datatype(list_type); + if (p_for->list->is_constant) { + p_for->list->set_datatype(type_from_variant(p_for->list->reduced_value, p_for->list)); + } else { + GDScriptParser::DataType list_type; + list_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; + list_type.kind = GDScriptParser::DataType::BUILTIN; + list_type.builtin_type = Variant::ARRAY; + p_for->list->set_datatype(list_type); + } } } } @@ -2027,9 +2031,17 @@ void GDScriptAnalyzer::reduce_get_node(GDScriptParser::GetNodeNode *p_get_node) p_get_node->set_datatype(result); } -GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const StringName &p_class_name) { +GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const StringName &p_class_name, const GDScriptParser::Node *p_source) { Ref<GDScriptParserRef> ref = get_parser_for(ScriptServer::get_global_class_path(p_class_name)); - ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + Error err = ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED); + + if (err) { + push_error(vformat(R"(Could not resolve class "%s", because of a parser error.)", p_class_name), p_source); + GDScriptParser::DataType type; + type.type_source = GDScriptParser::DataType::UNDETECTED; + type.kind = GDScriptParser::DataType::VARIANT; + return type; + } GDScriptParser::DataType type; type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; @@ -2301,7 +2313,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident } if (ScriptServer::is_global_class(name)) { - p_identifier->set_datatype(make_global_class_meta_type(name)); + p_identifier->set_datatype(make_global_class_meta_type(name, p_identifier)); return; } @@ -2718,7 +2730,7 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op) mark_node_unsafe(p_unary_op); } else { bool valid = false; - result = get_operation_type(p_unary_op->variant_op, p_unary_op->operand->get_datatype(), p_unary_op->operand->get_datatype(), valid, p_unary_op); + result = get_operation_type(p_unary_op->variant_op, p_unary_op->operand->get_datatype(), valid, p_unary_op); if (!valid) { push_error(vformat(R"(Invalid operand of type "%s" for unary operator "%s".)", p_unary_op->operand->get_datatype().to_string(), Variant::get_operator_name(p_unary_op->variant_op)), p_unary_op->operand); @@ -3084,81 +3096,31 @@ bool GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_local, con } #endif -GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, const GDScriptParser::DataType &p_b, bool &r_valid, const GDScriptParser::Node *p_source) { - // This function creates dummy variant values and apply the operation to those. Less error-prone than keeping a table of valid operations. +GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, bool &r_valid, const GDScriptParser::Node *p_source) { + // Unary version. + GDScriptParser::DataType nil_type; + nil_type.builtin_type = Variant::NIL; + return get_operation_type(p_operation, p_a, nil_type, r_valid, p_source); +} +GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, const GDScriptParser::DataType &p_b, bool &r_valid, const GDScriptParser::Node *p_source) { GDScriptParser::DataType result; result.kind = GDScriptParser::DataType::VARIANT; Variant::Type a_type = p_a.builtin_type; Variant::Type b_type = p_b.builtin_type; - Variant a; - REF a_ref; - if (a_type == Variant::OBJECT) { - a_ref.instance(); - a = a_ref; - } else { - Callable::CallError err; - Variant::construct(a_type, a, nullptr, 0, err); - if (err.error != Callable::CallError::CALL_OK) { - r_valid = false; - ERR_FAIL_V_MSG(result, vformat("Could not construct value of type %s", Variant::get_type_name(a_type))); - } - } - Variant b; - REF b_ref; - if (b_type == Variant::OBJECT) { - b_ref.instance(); - b = b_ref; - } else { - Callable::CallError err; - Variant::construct(b_type, b, nullptr, 0, err); - if (err.error != Callable::CallError::CALL_OK) { - r_valid = false; - ERR_FAIL_V_MSG(result, vformat("Could not construct value of type %s", Variant::get_type_name(b_type))); - } - } - - // Avoid division by zero. - switch (b_type) { - case Variant::INT: - b = 1; - break; - case Variant::FLOAT: - b = 1.0; - break; - case Variant::VECTOR2: - b = Vector2(1.0, 1.0); - break; - case Variant::VECTOR2I: - b = Vector2i(1, 1); - break; - case Variant::VECTOR3: - b = Vector3(1.0, 1.0, 1.0); - break; - case Variant::VECTOR3I: - b = Vector3i(1, 1, 1); - break; - case Variant::COLOR: - b = Color(1.0, 1.0, 1.0, 1.0); - break; - default: - // No change needed. - break; - } + Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator(p_operation, a_type, b_type); - // Avoid error in formatting operator (%) where it doesn't find a placeholder. - if (a_type == Variant::STRING && b_type != Variant::ARRAY) { - a = String("%s"); + if (op_eval == nullptr) { + r_valid = false; + return result; } - Variant ret; - Variant::evaluate(p_operation, a, b, ret, r_valid); + r_valid = true; - if (r_valid) { - return type_from_variant(ret, p_source); - } + result.kind = GDScriptParser::DataType::BUILTIN; + result.builtin_type = Variant::get_operator_return_type(p_operation, a_type, b_type); return result; } @@ -3360,7 +3322,6 @@ Error GDScriptAnalyzer::resolve_program() { } depended_parsers[E->get()]->raise_status(GDScriptParserRef::FULLY_SOLVED); } - depended_parsers.clear(); return parser->errors.empty() ? OK : ERR_PARSE_ERROR; } |