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/gdscript/gdscript_parser.cpp') 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 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/gdscript/gdscript_parser.cpp') 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/gdscript/gdscript_parser.cpp') 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 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/gdscript/gdscript_parser.cpp') 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 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/gdscript/gdscript_parser.cpp') 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 7db7b43cb0452b02123eeeb8f4370646b31ba8e0 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 20:38:02 -0300 Subject: GDScript: Fix type detection for String formatting operator --- modules/gdscript/gdscript_parser.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'modules/gdscript/gdscript_parser.cpp') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 225c2736b8..ecaf79d6cd 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -5438,6 +5438,9 @@ GDScriptParser::DataType GDScriptParser::_get_operation_type(const Variant::Oper if (b_type == Variant::INT || b_type == Variant::REAL) { Variant::evaluate(Variant::OP_ADD, b, 1, b, r_valid); } + if (a_type == Variant::STRING) { + a = "%s"; // Work around for formatting operator (%) + } Variant ret; Variant::evaluate(p_op, a, b, ret, r_valid); -- cgit v1.2.3 From 0b78e4f9e3824361e4984eedd1c57996eb48c546 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 25 Jul 2018 20:48:22 -0300 Subject: GDScript: Add type inference syntax for function arguments --- modules/gdscript/gdscript_parser.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'modules/gdscript/gdscript_parser.cpp') diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index ecaf79d6cd..a0e58e3a37 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -3555,7 +3555,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { DataType argtype; if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) { - if (!_parse_type(argtype)) { + if (tokenizer->get_token(1) == GDScriptTokenizer::TK_OP_ASSIGN) { + argtype.infer_type = true; + tokenizer->advance(); + } else if (!_parse_type(argtype)) { _set_error("Expected type for argument."); return; } @@ -7140,11 +7143,9 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) { // Arguments int defaults_ofs = p_function->arguments.size() - p_function->default_values.size(); for (int i = 0; i < p_function->arguments.size(); i++) { - - // Resolve types - p_function->argument_types.write[i] = _resolve_type(p_function->argument_types[i], p_function->line); - - if (i >= defaults_ofs) { + if (i < defaults_ofs) { + p_function->argument_types.write[i] = _resolve_type(p_function->argument_types[i], p_function->line); + } else { if (p_function->default_values[i - defaults_ofs]->type != Node::TYPE_OPERATOR) { _set_error("Parser bug: invalid argument default value.", p_function->line, p_function->column); return; @@ -7159,11 +7160,18 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) { DataType def_type = _reduce_node_type(op->arguments[1]); - if (!_is_type_compatible(p_function->argument_types[i], def_type, true)) { - String arg_name = p_function->arguments[i]; - _set_error("Value type (" + def_type.to_string() + ") doesn't match the type of argument '" + - arg_name + "' (" + p_function->arguments[i] + ")", - p_function->line); + if (p_function->argument_types[i].infer_type) { + def_type.is_constant = false; + p_function->argument_types.write[i] = def_type; + } else { + p_function->return_type = _resolve_type(p_function->return_type, p_function->line); + + if (!_is_type_compatible(p_function->argument_types[i], def_type, true)) { + String arg_name = p_function->arguments[i]; + _set_error("Value type (" + def_type.to_string() + ") doesn't match the type of argument '" + + arg_name + "' (" + p_function->arguments[i] + ")", + p_function->line); + } } } } -- cgit v1.2.3