diff options
Diffstat (limited to 'modules/gdscript/gdscript_parser.cpp')
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 417 |
1 files changed, 303 insertions, 114 deletions
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 17077567c7..b03d041aaf 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -72,6 +72,16 @@ bool GDScriptParser::_end_statement() { return false; } +void GDScriptParser::_set_end_statement_error(String p_name) { + String error_msg; + if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER) { + error_msg = vformat("Expected end of statement (\"%s\"), got %s (\"%s\") instead.", p_name, tokenizer->get_token_name(tokenizer->get_token()), tokenizer->get_token_identifier()); + } else { + error_msg = vformat("Expected end of statement (\"%s\"), got %s instead.", p_name, tokenizer->get_token_name(tokenizer->get_token())); + } + _set_error(error_msg); +} + bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { if (tokenizer->get_token() != GDScriptTokenizer::TK_COLON) { @@ -910,10 +920,18 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s e.is_op = true; switch (tokenizer->get_token()) { - case GDScriptTokenizer::TK_OP_ADD: e.op = OperatorNode::OP_POS; break; - case GDScriptTokenizer::TK_OP_SUB: e.op = OperatorNode::OP_NEG; break; - case GDScriptTokenizer::TK_OP_NOT: e.op = OperatorNode::OP_NOT; break; - case GDScriptTokenizer::TK_OP_BIT_INVERT: e.op = OperatorNode::OP_BIT_INVERT; break; + case GDScriptTokenizer::TK_OP_ADD: + e.op = OperatorNode::OP_POS; + break; + case GDScriptTokenizer::TK_OP_SUB: + e.op = OperatorNode::OP_NEG; + break; + case GDScriptTokenizer::TK_OP_NOT: + e.op = OperatorNode::OP_NOT; + break; + case GDScriptTokenizer::TK_OP_BIT_INVERT: + e.op = OperatorNode::OP_BIT_INVERT; + break; default: { } } @@ -1329,25 +1347,55 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s switch (tokenizer->get_token()) { //see operator - case GDScriptTokenizer::TK_OP_IN: op = OperatorNode::OP_IN; break; - case GDScriptTokenizer::TK_OP_EQUAL: op = OperatorNode::OP_EQUAL; break; - case GDScriptTokenizer::TK_OP_NOT_EQUAL: op = OperatorNode::OP_NOT_EQUAL; break; - case GDScriptTokenizer::TK_OP_LESS: op = OperatorNode::OP_LESS; break; - case GDScriptTokenizer::TK_OP_LESS_EQUAL: op = OperatorNode::OP_LESS_EQUAL; break; - case GDScriptTokenizer::TK_OP_GREATER: op = OperatorNode::OP_GREATER; break; - case GDScriptTokenizer::TK_OP_GREATER_EQUAL: op = OperatorNode::OP_GREATER_EQUAL; break; - case GDScriptTokenizer::TK_OP_AND: op = OperatorNode::OP_AND; break; - case GDScriptTokenizer::TK_OP_OR: op = OperatorNode::OP_OR; break; - case GDScriptTokenizer::TK_OP_ADD: op = OperatorNode::OP_ADD; break; - case GDScriptTokenizer::TK_OP_SUB: op = OperatorNode::OP_SUB; break; - case GDScriptTokenizer::TK_OP_MUL: op = OperatorNode::OP_MUL; break; - case GDScriptTokenizer::TK_OP_DIV: op = OperatorNode::OP_DIV; break; + case GDScriptTokenizer::TK_OP_IN: + op = OperatorNode::OP_IN; + break; + case GDScriptTokenizer::TK_OP_EQUAL: + op = OperatorNode::OP_EQUAL; + break; + case GDScriptTokenizer::TK_OP_NOT_EQUAL: + op = OperatorNode::OP_NOT_EQUAL; + break; + case GDScriptTokenizer::TK_OP_LESS: + op = OperatorNode::OP_LESS; + break; + case GDScriptTokenizer::TK_OP_LESS_EQUAL: + op = OperatorNode::OP_LESS_EQUAL; + break; + case GDScriptTokenizer::TK_OP_GREATER: + op = OperatorNode::OP_GREATER; + break; + case GDScriptTokenizer::TK_OP_GREATER_EQUAL: + op = OperatorNode::OP_GREATER_EQUAL; + break; + case GDScriptTokenizer::TK_OP_AND: + op = OperatorNode::OP_AND; + break; + case GDScriptTokenizer::TK_OP_OR: + op = OperatorNode::OP_OR; + break; + case GDScriptTokenizer::TK_OP_ADD: + op = OperatorNode::OP_ADD; + break; + case GDScriptTokenizer::TK_OP_SUB: + op = OperatorNode::OP_SUB; + break; + case GDScriptTokenizer::TK_OP_MUL: + op = OperatorNode::OP_MUL; + break; + case GDScriptTokenizer::TK_OP_DIV: + op = OperatorNode::OP_DIV; + break; case GDScriptTokenizer::TK_OP_MOD: op = OperatorNode::OP_MOD; break; //case GDScriptTokenizer::TK_OP_NEG: op=OperatorNode::OP_NEG ; break; - case GDScriptTokenizer::TK_OP_SHIFT_LEFT: op = OperatorNode::OP_SHIFT_LEFT; break; - case GDScriptTokenizer::TK_OP_SHIFT_RIGHT: op = OperatorNode::OP_SHIFT_RIGHT; break; + case GDScriptTokenizer::TK_OP_SHIFT_LEFT: + op = OperatorNode::OP_SHIFT_LEFT; + break; + case GDScriptTokenizer::TK_OP_SHIFT_RIGHT: + op = OperatorNode::OP_SHIFT_RIGHT; + break; case GDScriptTokenizer::TK_OP_ASSIGN: { _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN; @@ -1364,23 +1412,57 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s } } break; - case GDScriptTokenizer::TK_OP_ASSIGN_ADD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; break; - case GDScriptTokenizer::TK_OP_ASSIGN_SUB: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; break; - case GDScriptTokenizer::TK_OP_ASSIGN_MUL: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; break; - case GDScriptTokenizer::TK_OP_ASSIGN_DIV: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_DIV; break; - case GDScriptTokenizer::TK_OP_ASSIGN_MOD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MOD; break; - case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_LEFT; break; - case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_RIGHT; break; - case GDScriptTokenizer::TK_OP_ASSIGN_BIT_AND: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_AND; break; - case GDScriptTokenizer::TK_OP_ASSIGN_BIT_OR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_OR; break; - case GDScriptTokenizer::TK_OP_ASSIGN_BIT_XOR: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_XOR; break; - case GDScriptTokenizer::TK_OP_BIT_AND: op = OperatorNode::OP_BIT_AND; break; - case GDScriptTokenizer::TK_OP_BIT_OR: op = OperatorNode::OP_BIT_OR; break; - case GDScriptTokenizer::TK_OP_BIT_XOR: op = OperatorNode::OP_BIT_XOR; break; - case GDScriptTokenizer::TK_PR_IS: op = OperatorNode::OP_IS; break; - case GDScriptTokenizer::TK_CF_IF: op = OperatorNode::OP_TERNARY_IF; break; - case GDScriptTokenizer::TK_CF_ELSE: op = OperatorNode::OP_TERNARY_ELSE; break; - default: valid = false; break; + case GDScriptTokenizer::TK_OP_ASSIGN_ADD: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_SUB: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_MUL: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_DIV: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_DIV; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_MOD: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MOD; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_LEFT: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_LEFT; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_SHIFT_RIGHT: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SHIFT_RIGHT; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_AND: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_AND; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_OR: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_OR; + break; + case GDScriptTokenizer::TK_OP_ASSIGN_BIT_XOR: + _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_BIT_XOR; + break; + case GDScriptTokenizer::TK_OP_BIT_AND: + op = OperatorNode::OP_BIT_AND; + break; + case GDScriptTokenizer::TK_OP_BIT_OR: + op = OperatorNode::OP_BIT_OR; + break; + case GDScriptTokenizer::TK_OP_BIT_XOR: + op = OperatorNode::OP_BIT_XOR; + break; + case GDScriptTokenizer::TK_PR_IS: + op = OperatorNode::OP_IS; + break; + case GDScriptTokenizer::TK_CF_IF: + op = OperatorNode::OP_TERNARY_IF; + break; + case GDScriptTokenizer::TK_CF_ELSE: + op = OperatorNode::OP_TERNARY_ELSE; + break; + default: + valid = false; + break; } if (valid) { @@ -1433,36 +1515,74 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s unary = true; break; - case OperatorNode::OP_MUL: priority = 2; break; - case OperatorNode::OP_DIV: priority = 2; break; - case OperatorNode::OP_MOD: priority = 2; break; + case OperatorNode::OP_MUL: + priority = 2; + break; + case OperatorNode::OP_DIV: + priority = 2; + break; + case OperatorNode::OP_MOD: + priority = 2; + break; - case OperatorNode::OP_ADD: priority = 3; break; - case OperatorNode::OP_SUB: priority = 3; break; + case OperatorNode::OP_ADD: + priority = 3; + break; + case OperatorNode::OP_SUB: + priority = 3; + break; - case OperatorNode::OP_SHIFT_LEFT: priority = 4; break; - case OperatorNode::OP_SHIFT_RIGHT: priority = 4; break; + case OperatorNode::OP_SHIFT_LEFT: + priority = 4; + break; + case OperatorNode::OP_SHIFT_RIGHT: + priority = 4; + break; - case OperatorNode::OP_BIT_AND: priority = 5; break; - case OperatorNode::OP_BIT_XOR: priority = 6; break; - case OperatorNode::OP_BIT_OR: priority = 7; break; + case OperatorNode::OP_BIT_AND: + priority = 5; + break; + case OperatorNode::OP_BIT_XOR: + priority = 6; + break; + case OperatorNode::OP_BIT_OR: + priority = 7; + break; - case OperatorNode::OP_LESS: priority = 8; break; - case OperatorNode::OP_LESS_EQUAL: priority = 8; break; - case OperatorNode::OP_GREATER: priority = 8; break; - case OperatorNode::OP_GREATER_EQUAL: priority = 8; break; + case OperatorNode::OP_LESS: + priority = 8; + break; + case OperatorNode::OP_LESS_EQUAL: + priority = 8; + break; + case OperatorNode::OP_GREATER: + priority = 8; + break; + case OperatorNode::OP_GREATER_EQUAL: + priority = 8; + break; - case OperatorNode::OP_EQUAL: priority = 8; break; - case OperatorNode::OP_NOT_EQUAL: priority = 8; break; + case OperatorNode::OP_EQUAL: + priority = 8; + break; + case OperatorNode::OP_NOT_EQUAL: + priority = 8; + break; - case OperatorNode::OP_IN: priority = 10; break; + case OperatorNode::OP_IN: + priority = 10; + break; case OperatorNode::OP_NOT: priority = 11; unary = true; break; - case OperatorNode::OP_AND: priority = 12; break; - case OperatorNode::OP_OR: priority = 13; break; + case OperatorNode::OP_AND: + priority = 12; + break; + case OperatorNode::OP_OR: + priority = 13; + break; case OperatorNode::OP_TERNARY_IF: priority = 14; @@ -1475,17 +1595,39 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s // Rigth-to-left should be false in this case, otherwise it would always error. break; - case OperatorNode::OP_ASSIGN: priority = 15; break; - case OperatorNode::OP_ASSIGN_ADD: priority = 15; break; - case OperatorNode::OP_ASSIGN_SUB: priority = 15; break; - case OperatorNode::OP_ASSIGN_MUL: priority = 15; break; - case OperatorNode::OP_ASSIGN_DIV: priority = 15; break; - case OperatorNode::OP_ASSIGN_MOD: priority = 15; break; - case OperatorNode::OP_ASSIGN_SHIFT_LEFT: priority = 15; break; - case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: priority = 15; break; - case OperatorNode::OP_ASSIGN_BIT_AND: priority = 15; break; - case OperatorNode::OP_ASSIGN_BIT_OR: priority = 15; break; - case OperatorNode::OP_ASSIGN_BIT_XOR: priority = 15; break; + case OperatorNode::OP_ASSIGN: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_ADD: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_SUB: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_MUL: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_DIV: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_MOD: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_SHIFT_LEFT: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_SHIFT_RIGHT: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_BIT_AND: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_BIT_OR: + priority = 15; + break; + case OperatorNode::OP_ASSIGN_BIT_XOR: + priority = 15; + break; default: { _set_error("GDScriptParser bug, invalid operator in expression: " + itos(expression[i].op)); @@ -2037,7 +2179,8 @@ bool GDScriptParser::_reduce_export_var_type(Variant &p_value, int p_line) { if (p_value.get_type() == Variant::ARRAY) { Array arr = p_value; for (int i = 0; i < arr.size(); i++) { - if (!_reduce_export_var_type(arr[i], p_line)) return false; + if (!_reduce_export_var_type(arr[i], p_line)) + return false; } return true; } @@ -2046,7 +2189,8 @@ bool GDScriptParser::_reduce_export_var_type(Variant &p_value, int p_line) { Dictionary dict = p_value; for (int i = 0; i < dict.size(); i++) { Variant value = dict.get_value_at_index(i); - if (!_reduce_export_var_type(value, p_line)) return false; + if (!_reduce_export_var_type(value, p_line)) + return false; } return true; } @@ -2734,6 +2878,7 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) { IdentifierNode *id2 = alloc_node<IdentifierNode>(); id2->name = local_var->name; + id2->datatype = local_var->datatype; id2->declared_block = branch->body; id2->set_datatype(local_var->assign->get_datatype()); @@ -2937,7 +3082,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { lv->assign = assigned; if (!_end_statement()) { - _set_error("Expected end of statement (\"var\")."); + _set_end_statement_error("var"); return; } @@ -3171,9 +3316,15 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { ConstantNode *cn = alloc_node<ConstantNode>(); switch (args.size()) { - case 1: cn->value = (int)constants[0]; break; - case 2: cn->value = Vector2(constants[0], constants[1]); break; - case 3: cn->value = Vector3(constants[0], constants[1], constants[2]); break; + case 1: + cn->value = (int64_t)constants[0]; + break; + case 2: + cn->value = Vector2i(constants[0], constants[1]); + break; + case 3: + cn->value = Vector3i(constants[0], constants[1], constants[2]); + break; } cn->datatype = _type_from_variant(cn->value); container = cn; @@ -3185,9 +3336,15 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { on->arguments.push_back(tn); switch (args.size()) { - case 1: tn->vtype = Variant::INT; break; - case 2: tn->vtype = Variant::VECTOR2; break; - case 3: tn->vtype = Variant::VECTOR3; break; + case 1: + tn->vtype = Variant::INT; + break; + case 2: + tn->vtype = Variant::VECTOR2I; + break; + case 3: + tn->vtype = Variant::VECTOR3I; + break; } for (int i = 0; i < args.size(); i++) { @@ -3248,7 +3405,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_continue->cf_type = ControlFlowNode::CF_CONTINUE; p_block->statements.push_back(cf_continue); if (!_end_statement()) { - _set_error("Expected end of statement (\"continue\")."); + _set_end_statement_error("continue"); return; } } break; @@ -3260,7 +3417,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_break->cf_type = ControlFlowNode::CF_BREAK; p_block->statements.push_back(cf_break); if (!_end_statement()) { - _set_error("Expected end of statement (\"break\")."); + _set_end_statement_error("break"); return; } } break; @@ -3289,7 +3446,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { cf_return->arguments.push_back(retexpr); p_block->statements.push_back(cf_return); if (!_end_statement()) { - _set_error("Expected end of statement after return expression."); + _set_end_statement_error("return"); return; } } @@ -3326,7 +3483,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { _parse_pattern_block(compiled_branches, match_node->branches, p_static); - if (error_set) return; + if (error_set) + return; ControlFlowNode *match_cf_node = alloc_node<ControlFlowNode>(); match_cf_node->cf_type = ControlFlowNode::CF_MATCH; @@ -3378,7 +3536,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { p_block->statements.push_back(an); if (!_end_statement()) { - _set_error("Expected end of statement after \"assert\".", assert_line); + _set_end_statement_error("assert"); return; } } break; @@ -3389,7 +3547,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { p_block->statements.push_back(bn); if (!_end_statement()) { - _set_error("Expected end of statement after \"breakpoint\"."); + _set_end_statement_error("breakpoint"); return; } } break; @@ -3408,7 +3566,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON && tokenizer->get_token(1) == GDScriptTokenizer::TK_OP_ASSIGN) { _set_error("Unexpected ':=', use '=' instead. Expected end of statement after expression."); } else { - _set_error(String() + "Expected end of statement after expression, got " + tokenizer->get_token_name(tokenizer->get_token()) + " instead"); + _set_error(vformat("Expected end of statement after expression, got %s instead.", tokenizer->get_token_name(tokenizer->get_token()))); } return; } @@ -3598,7 +3756,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { if (error_set) return; if (!_end_statement()) { - _set_error("Expected end of statement after \"extends\"."); + _set_end_statement_error("extends"); return; } @@ -4103,7 +4261,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { p_class->_signals.push_back(sig); if (!_end_statement()) { - _set_error("Expected end of statement (\"signal\")."); + _set_end_statement_error("signal"); return; } } break; @@ -4923,7 +5081,8 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - if (!_reduce_export_var_type(cn->value, member.line)) return; + if (!_reduce_export_var_type(cn->value, member.line)) + return; member._export.type = cn->value.get_type(); member._export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; @@ -4960,6 +5119,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = member.identifier; + id->datatype = member.data_type; OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_INIT_ASSIGN; @@ -5002,6 +5162,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = member.identifier; + id->datatype = member.data_type; OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_INIT_ASSIGN; @@ -5044,7 +5205,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { p_class->variables.push_back(member); if (!_end_statement()) { - _set_error("Expected end of statement (\"continue\")."); + _set_end_statement_error("var"); return; } } break; @@ -5124,7 +5285,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { p_class->constant_expressions.insert(const_id, constant); if (!_end_statement()) { - _set_error("Expected end of statement (constant).", line); + _set_end_statement_error("const"); return; } @@ -5278,7 +5439,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (!_end_statement()) { - _set_error("Expected end of statement (\"enum\")."); + _set_end_statement_error("enum"); return; } @@ -5438,8 +5599,10 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive } } - if (base_class) break; - if (found) continue; + if (base_class) + break; + if (found) + continue; if (p->constant_expressions.has(base)) { if (p->constant_expressions[base].expression->type != Node::TYPE_CONSTANT) { @@ -5541,10 +5704,12 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive } String GDScriptParser::DataType::to_string() const { - if (!has_type) return "var"; + if (!has_type) + return "var"; switch (kind) { case BUILTIN: { - if (builtin_type == Variant::NIL) return "null"; + if (builtin_type == Variant::NIL) + return "null"; return Variant::get_type_name(builtin_type); } break; case NATIVE: { @@ -5708,8 +5873,10 @@ bool GDScriptParser::_parse_type(DataType &r_type, bool p_can_be_void) { } GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source, int p_line) { - if (!p_source.has_type) return p_source; - if (p_source.kind != DataType::UNRESOLVED) return p_source; + if (!p_source.has_type) + return p_source; + if (p_source.kind != DataType::UNRESOLVED) + return p_source; Vector<String> full_name = p_source.native_type.operator String().split(".", false); int name_part = 0; @@ -6647,6 +6814,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = cn->value.operator StringName(); + id->datatype = cn->datatype; op->op = OperatorNode::OP_INDEX_NAMED; op->arguments.write[1] = id; @@ -6948,7 +7116,8 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String native = "_" + native.operator String(); } if (!ClassDB::class_exists(native)) { - if (!check_types) return false; + if (!check_types) + return false; ERR_FAIL_V_MSG(false, "Parser bug: Class '" + String(native) + "' not found."); } @@ -7039,7 +7208,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat par_types.write[i - 1] = _reduce_node_type(p_call->arguments[i]); } - if (error_set) return DataType(); + if (error_set) + return DataType(); // Special case: check copy constructor. Those are defined implicitly in Variant. if (par_types.size() == 1) { @@ -7107,7 +7277,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat err += "' matches the signature '"; err += Variant::get_type_name(tn->vtype) + "("; for (int i = 0; i < par_types.size(); i++) { - if (i > 0) err += ", "; + if (i > 0) + err += ", "; err += par_types[i].to_string(); } err += ")'."; @@ -7465,7 +7636,8 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN native = "_" + native.operator String(); } if (!ClassDB::class_exists(native)) { - if (!check_types) return false; + if (!check_types) + return false; ERR_FAIL_V_MSG(false, "Parser bug: Class \"" + String(native) + "\" not found."); } @@ -7571,6 +7743,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType } if (_get_member_type(base_type, p_identifier, member_type)) { + if (!p_base_type && current_function && current_function->_static) { + _set_error("Can't access member variable (\"" + p_identifier.operator String() + "\") from a static function.", p_line); + return DataType(); + } return member_type; } @@ -7758,12 +7934,14 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { // Function declarations for (int i = 0; i < p_class->static_functions.size(); i++) { _check_function_types(p_class->static_functions[i]); - if (error_set) return; + if (error_set) + return; } for (int i = 0; i < p_class->functions.size(); i++) { _check_function_types(p_class->functions[i]); - if (error_set) return; + if (error_set) + return; } // Class variables @@ -7802,7 +7980,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { ConstantNode *tgt_type = alloc_node<ConstantNode>(); tgt_type->line = v.line; - tgt_type->value = (int)v.data_type.builtin_type; + tgt_type->value = (int64_t)v.data_type.builtin_type; OperatorNode *convert_call = alloc_node<OperatorNode>(); convert_call->line = v.line; @@ -7838,7 +8016,8 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { } // Setter and getter - if (v.setter == StringName() && v.getter == StringName()) continue; + if (v.setter == StringName() && v.getter == StringName()) + continue; bool found_getter = false; bool found_setter = false; @@ -7881,10 +8060,12 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { return; } } - if (found_getter && found_setter) break; + if (found_getter && found_setter) + break; } - if ((found_getter || v.getter == StringName()) && (found_setter || v.setter == StringName())) continue; + if ((found_getter || v.getter == StringName()) && (found_setter || v.setter == StringName())) + continue; // Check for static functions for (int j = 0; j < p_class->static_functions.size(); j++) { @@ -7915,7 +8096,8 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { for (int i = 0; i < p_class->subclasses.size(); i++) { current_class = p_class->subclasses[i]; _check_class_level_types(current_class); - if (error_set) return; + if (error_set) + return; current_class = p_class; } } @@ -8063,7 +8245,8 @@ void GDScriptParser::_check_class_blocks_types(ClassNode *p_class) { _check_block_types(current_block); current_block = nullptr; current_function = nullptr; - if (error_set) return; + if (error_set) + return; } for (int i = 0; i < p_class->functions.size(); i++) { @@ -8073,7 +8256,8 @@ void GDScriptParser::_check_class_blocks_types(ClassNode *p_class) { _check_block_types(current_block); current_block = nullptr; current_function = nullptr; - if (error_set) return; + if (error_set) + return; } #ifdef DEBUG_ENABLED @@ -8094,7 +8278,8 @@ void GDScriptParser::_check_class_blocks_types(ClassNode *p_class) { for (int i = 0; i < p_class->subclasses.size(); i++) { current_class = p_class->subclasses[i]; _check_class_blocks_types(current_class); - if (error_set) return; + if (error_set) + return; current_class = p_class; } } @@ -8179,7 +8364,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { ConstantNode *tgt_type = alloc_node<ConstantNode>(); tgt_type->line = lv->line; - tgt_type->value = (int)lv->datatype.builtin_type; + tgt_type->value = (int64_t)lv->datatype.builtin_type; tgt_type->datatype = _type_from_variant(tgt_type->value); OperatorNode *convert_call = alloc_node<OperatorNode>(); @@ -8357,7 +8542,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { _add_warning(GDScriptWarning::RETURN_VALUE_DISCARDED, op->line, func_name); } #endif // DEBUG_ENABLED - if (error_set) return; + if (error_set) + return; } break; case OperatorNode::OP_YIELD: { _mark_line_as_safe(op->line); @@ -8392,7 +8578,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { } } - if (!function_type.has_type) break; + if (!function_type.has_type) + break; if (function_type.kind == DataType::BUILTIN && function_type.builtin_type == Variant::NIL) { // Return void, should not have arguments @@ -8452,7 +8639,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { current_block = p_block->sub_blocks[i]; _check_block_types(current_block); current_block = p_block; - if (error_set) return; + if (error_set) + return; } #ifdef DEBUG_ENABLED @@ -8595,7 +8783,8 @@ Error GDScriptParser::_parse(const String &p_base_path) { current_function = nullptr; current_block = nullptr; - if (for_completion) check_types = false; + if (for_completion) + check_types = false; // Resolve all class-level stuff before getting into function blocks _check_class_level_types(main_class); @@ -8784,7 +8973,7 @@ int GDScriptParser::get_completion_argument_index() { return completion_argument; } -int GDScriptParser::get_completion_identifier_is_function() { +bool GDScriptParser::get_completion_identifier_is_function() { return completion_ident_is_call; } |