From b7bd85e70c40c6cdff61b1e057eafb9abd93a742 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 10:20:11 -0300 Subject: GDScript: Look up local scope first for detecting type --- modules/gdscript/gdscript_parser.cpp | 42 +++++++++++++++++------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'modules') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index d8ce6e7f17..bd1724e8bc 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -6770,7 +6770,26 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType // Check classes in current file ClassNode *base = NULL; if (!p_base_type) { - // Possibly this is a global, check first + base = current_class; + base_type.has_type = true; + base_type.is_constant = true; + base_type.kind = DataType::CLASS; + base_type.class_type = base; + } else { + base_type = DataType(*p_base_type); + if (base_type.kind == DataType::CLASS) { + base = base_type.class_type; + } + } + + DataType member_type; + + if (_get_member_type(base_type, p_identifier, member_type)) { + return member_type; + } + + if (!p_base_type) { + // Possibly this is a global, check before failing if (ClassDB::class_exists(p_identifier) || ClassDB::class_exists("_" + p_identifier.operator String())) { DataType result; @@ -6885,27 +6904,6 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType } } - // Nothing found, keep looking in local scope - - base = current_class; - base_type.has_type = true; - base_type.is_constant = true; - base_type.kind = DataType::CLASS; - base_type.class_type = base; - } else { - base_type = *p_base_type; - if (base_type.kind == DataType::CLASS) { - base = base_type.class_type; - } - } - - DataType member_type; - - if (_get_member_type(base_type, p_identifier, member_type)) { - return member_type; - } - - if (!p_base_type) { // This means looking in the current class, which type is always known _set_error("Identifier '" + p_identifier.operator String() + "' is not declared in the current scope.", p_line); } -- cgit v1.2.3 From 65c069c8d9925aab870f7778591eb60cca85b214 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 10:54:54 -0300 Subject: GDScript: Fix main script detection --- modules/gdscript/gdscript_compiler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'modules') diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 93585a5342..fe393957db 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -140,7 +140,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D } break; case GDScriptParser::DataType::CLASS: { result.kind = GDScriptDataType::GDSCRIPT; - if (p_datatype.class_type->name == StringName()) { + if (!p_datatype.class_type->owner) { result.script_type = Ref(main_script); } else { result.script_type = class_map[p_datatype.class_type->name]; @@ -482,7 +482,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: Variant script; int idx = -1; - if (cn->cast_type.class_type->name == StringName()) { + if (!cn->cast_type.class_type->owner) { script = codegen.script; } else { StringName name = cn->cast_type.class_type->name; @@ -1181,7 +1181,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: Variant script; int idx = -1; - if (assign_type.class_type->name == StringName()) { + if (!assign_type.class_type->owner) { script = codegen.script; } else { StringName name = assign_type.class_type->name; @@ -1994,7 +1994,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner p_script->_signals[name] = p_class->_signals[i].arguments; } - if (p_class->name != StringName()) { + if (!p_class->owner) { parsed_classes.insert(p_class->name); } -- cgit v1.2.3 From cd6ad5462c59a9f7545e252e0fecd65dd4c0eda7 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 11:41:27 -0300 Subject: GDScript: Fix returned value of get_default_argument_count() --- modules/gdscript/gdscript_function.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index ec346a6b46..6561071c5d 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1579,7 +1579,7 @@ StringName GDScriptFunction::get_global_name(int p_idx) const { int GDScriptFunction::get_default_argument_count() const { - return default_arguments.size(); + return _default_arg_count; } int GDScriptFunction::get_default_argument_addr(int p_idx) const { -- cgit v1.2.3 From 4cb17191b8e5a690889870bd03d83e71d62fb694 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 12:12:46 -0300 Subject: GDScript: Allow inherited method to add optional arguments Also show the parent method signature in the error message. --- modules/gdscript/gdscript_parser.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index bd1724e8bc..44851111d7 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -7159,6 +7159,7 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) { if (!(p_function->name == "_init")) { // Signature for the initializer may vary +#ifdef DEBUG_ENABLED DataType return_type; List arg_types; int default_arg_count = 0; @@ -7169,18 +7170,44 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) { if (_get_function_signature(base_type, p_function->name, return_type, arg_types, default_arg_count, _static, vararg)) { bool valid = _static == p_function->_static; valid = valid && return_type == p_function->return_type; - valid = valid && p_function->default_values.size() >= default_arg_count; - valid = valid && arg_types.size() == p_function->arguments.size(); + int argsize_diff = p_function->arguments.size() - arg_types.size(); + valid = valid && argsize_diff >= 0; + valid = valid && p_function->default_values.size() >= default_arg_count + argsize_diff; int i = 0; for (List::Element *E = arg_types.front(); valid && E; E = E->next()) { valid = valid && E->get() == p_function->argument_types[i++]; } if (!valid) { - _set_error("Function signature doesn't match the parent.", p_function->line); + String parent_signature = return_type.has_type ? return_type.to_string() : "Variant"; + if (parent_signature == "null") { + parent_signature = "void"; + } + parent_signature += " " + p_function->name + "("; + if (arg_types.size()) { + int i = 0; + for (List::Element *E = arg_types.front(); E; E = E->next()) { + if (E != arg_types.front()) { + parent_signature += ", "; + } + String arg = E->get().to_string(); + if (arg == "null" || arg == "var") { + arg = "Variant"; + } + parent_signature += arg; + if (i == arg_types.size() - default_arg_count) { + parent_signature += "=default"; + } + + i++; + } + } + parent_signature += ")"; + _set_error("Function signature doesn't match the parent. Parent signature is: '" + parent_signature + "'.", p_function->line); return; } } +#endif // DEBUG_ENABLED } else { if (p_function->return_type.has_type && (p_function->return_type.kind != DataType::BUILTIN || p_function->return_type.builtin_type != Variant::NIL)) { _set_error("Constructor cannot return a value.", p_function->line); -- cgit v1.2.3 From 96ee93e8c7638d8c0d8f1dd6567bbab2a24fd9e8 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 13:01:26 -0300 Subject: GDScript: Fix mismatching between export hint and type hint --- modules/gdscript/gdscript_parser.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'modules') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 44851111d7..9d8d08d40a 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -4187,6 +4187,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { current_export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; current_export.hint_string = native_class->get_name(); + current_export.class_name = native_class->get_name(); } else { current_export = PropertyInfo(); @@ -4546,6 +4547,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { member._export.type = Variant::OBJECT; member._export.hint = PROPERTY_HINT_RESOURCE_TYPE; member._export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; + member._export.hint_string = member.data_type.native_type; member._export.class_name = member.data_type.native_type; } else { _set_error("Invalid export type. Only built-in and native resource types can be exported.", member.line); -- cgit v1.2.3 From 1ac9c0fe3aa42458441cea9ca9df87bde30e676a Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 13:12:07 -0300 Subject: GDScript: Allow strict conversion when assigning typed variables --- modules/gdscript/gdscript_function.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'modules') diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 6561071c5d..1e0363c2df 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -743,13 +743,18 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX); if (src->get_type() != var_type) { - err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) + - "' to a variable of type '" + Variant::get_type_name(var_type) + "'."; - OPCODE_BREAK; + if (Variant::can_convert_strict(src->get_type(), var_type)) { + Variant::CallError ce; + *dst = Variant::construct(var_type, const_cast(&src), 1, ce); + } else { + err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) + + "' to a variable of type '" + Variant::get_type_name(var_type) + "'."; + OPCODE_BREAK; + } + } else { + *dst = *src; } - *dst = *src; - ip += 4; } DISPATCH_OPCODE; -- cgit v1.2.3 From 3d6609303bc2def39fb5b87b9325b94b2549ede8 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 13:39:05 -0300 Subject: GDScript: Fix bogus error when a cursor token is found on class --- modules/gdscript/gdscript_parser.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'modules') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 9d8d08d40a..2630e985d9 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3332,6 +3332,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { switch (token) { + case GDScriptTokenizer::TK_CURSOR: { + tokenizer->advance(); + } break; case GDScriptTokenizer::TK_EOF: p_class->end_line = tokenizer->get_token_line(); case GDScriptTokenizer::TK_ERROR: { -- cgit v1.2.3 From a62f4af7ba86f612e558ecf11c8d4070b4e3fdac Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 17:01:01 -0300 Subject: GDScript: Enable built-in function introspection in non-tools Only for debug builds. Fix problems in non-tools targets. --- modules/gdscript/gdscript_functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index 63286b2e91..f2e52d48dd 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -1412,7 +1412,7 @@ bool GDScriptFunctions::is_deterministic(Function p_func) { MethodInfo GDScriptFunctions::get_info(Function p_func) { -#ifdef TOOLS_ENABLED +#ifdef DEBUG_ENABLED //using a switch, so the compiler generates a jumptable switch (p_func) { -- cgit v1.2.3 From a3ae4a9510146433e725289770d7cf6ef9424de0 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 18:18:53 -0300 Subject: GDScript: Allow accessing constants of outer classes --- modules/gdscript/gdscript_parser.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'modules') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 2630e985d9..225c2736b8 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -6820,6 +6820,9 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType result.class_type = outer_class; return result; } + if (outer_class->constant_expressions.has(p_identifier)) { + return outer_class->constant_expressions[p_identifier].type; + } for (int i = 0; i < outer_class->subclasses.size(); i++) { if (outer_class->subclasses[i] == current_class) { continue; -- cgit v1.2.3 From aeb0b3114d336958e4e1ab7781022e583ef8fe1d Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 18:45:38 -0300 Subject: GDScript: Fix type detection on Object typed assign Also make typed assigns a debug-only thing, so release builds are more lenient on errors. --- modules/gdscript/gdscript_function.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 1e0363c2df..bae3f48923 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -742,6 +742,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX); +#ifdef DEBUG_ENABLED if (src->get_type() != var_type) { if (Variant::can_convert_strict(src->get_type(), var_type)) { Variant::CallError ce; @@ -752,8 +753,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } } else { +#endif // DEBUG_ENABLED *dst = *src; +#ifdef DEBUG_ENABLED } +#endif // DEBUG_ENABLED ip += 4; } @@ -766,17 +770,22 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GET_VARIANT_PTR(dst, 2); GET_VARIANT_PTR(src, 3); +#ifdef DEBUG_ENABLED GDScriptNativeClass *nc = Object::cast_to(type->operator Object *()); GD_ERR_BREAK(!nc); + if (!src->get_type() != Variant::OBJECT && !src->get_type() != Variant::NIL) { + err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) + + "' to a variable of type '" + nc->get_name() + "'."; + OPCODE_BREAK; + } Object *src_obj = src->operator Object *(); - GD_ERR_BREAK(!src_obj); - if (!ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) { + if (src_obj && !ClassDB::is_parent_class(src_obj->get_class_name(), nc->get_name())) { err_text = "Trying to assign value of type '" + src_obj->get_class_name() + "' to a variable of type '" + nc->get_name() + "'."; OPCODE_BREAK; } - +#endif // DEBUG_ENABLED *dst = *src; ip += 4; @@ -790,6 +799,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GET_VARIANT_PTR(dst, 2); GET_VARIANT_PTR(src, 3); +#ifdef DEBUG_ENABLED Script *base_type = Object::cast_to