summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gdscript.cpp13
-rw-r--r--modules/gdscript/gdscript.h1
-rw-r--r--modules/gdscript/gdscript_compiler.cpp16
-rw-r--r--modules/gdscript/gdscript_editor.cpp19
-rw-r--r--modules/gdscript/gdscript_functions.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.cpp64
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp10
-rw-r--r--modules/gdscript/gdscript_tokenizer.h3
8 files changed, 90 insertions, 38 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 4d5d8cedde..b0d5422afe 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -126,10 +126,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
GDScriptLanguage::singleton->lock->unlock();
#endif
- if (r_error.error != Variant::CallError::CALL_OK) {
- memdelete(instance);
- ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing
- }
+ ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing
}
//@TODO make thread safe
@@ -1779,10 +1776,11 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"remote",
"sync",
"master",
+ "puppet",
"slave",
"remotesync",
"mastersync",
- "slavesync",
+ "puppetsync",
0
};
@@ -1979,6 +1977,10 @@ String GDScriptWarning::get_message() const {
CHECK_SYMBOLS(4);
return "The argument '" + symbols[0] + "' of the function '" + symbols[1] + "' requires a the subtype '" + symbols[2] + "' but the supertype '" + symbols[3] + "' was provided";
} break;
+ case DEPRECATED_KEYWORD: {
+ CHECK_SYMBOLS(2);
+ return "The '" + symbols[0] + "' keyword is deprecated and will be removed in a future release, please replace its uses by '" + symbols[1] + "'.";
+ } break;
}
ERR_EXPLAIN("Invalid GDScript warning code: " + get_name_from_code(code));
ERR_FAIL_V(String());
@@ -2018,6 +2020,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
"UNSAFE_METHOD_ACCESS",
"UNSAFE_CAST",
"UNSAFE_CALL_ARGUMENT",
+ "DEPRECATED_KEYWORD",
NULL
};
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 739d18569f..d795500265 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -289,6 +289,7 @@ struct GDScriptWarning {
UNSAFE_METHOD_ACCESS, // Function not found in the detected type (but can be in subtypes)
UNSAFE_CAST, // Cast used in an unknown type
UNSAFE_CALL_ARGUMENT, // Function call argument is of a supertype of the require argument
+ DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced
WARNING_MAX,
} code;
Vector<String> symbols;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 741b837b05..310c4e21f2 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -388,7 +388,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
int ret = _parse_expression(codegen, an->elements[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -419,7 +419,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
int ret = _parse_expression(codegen, dn->elements[i].key, slevel);
if (ret < 0)
return ret;
- if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -429,7 +429,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
ret = _parse_expression(codegen, dn->elements[i].value, slevel);
if (ret < 0)
return ret;
- if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -545,7 +545,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
int ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -578,7 +578,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
int ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -606,7 +606,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
if (ret < 0)
return ret;
- if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -655,7 +655,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
@@ -681,7 +681,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
int ret = _parse_expression(codegen, on->arguments[i], slevel);
if (ret < 0)
return ret;
- if (ret & (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)) {
+ if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
slevel++;
codegen.alloc_stack(slevel);
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index affb73a048..a9b641de50 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1189,6 +1189,7 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c
c.line = op->line;
c.block = blk;
if (_guess_expression_type(p_context, op->arguments[1], r_type)) {
+ r_type.type.is_meta_type = false;
return true;
}
}
@@ -1221,7 +1222,7 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c
int def_from = p_context.function->arguments.size() - p_context.function->default_values.size();
if (i >= def_from) {
- int def_idx = def_from - i;
+ int def_idx = i - def_from;
if (p_context.function->default_values[def_idx]->type == GDScriptParser::Node::TYPE_OPERATOR) {
const GDScriptParser::OperatorNode *op = static_cast<const GDScriptParser::OperatorNode *>(p_context.function->default_values[def_idx]);
if (op->arguments.size() < 2) {
@@ -1376,11 +1377,11 @@ static bool _guess_identifier_type_from_base(const GDScriptCompletionContext &p_
for (int i = 0; i < base_type.class_type->variables.size(); i++) {
GDScriptParser::ClassNode::Member m = base_type.class_type->variables[i];
if (m.identifier == p_identifier) {
- if (m.data_type.has_type) {
- r_type.type = m.data_type;
- return true;
- }
if (m.expression) {
+ if (p_context.line == m.expression->line) {
+ // Variable used in the same expression
+ return false;
+ }
if (_guess_expression_type(p_context, m.expression, r_type)) {
return true;
}
@@ -1389,6 +1390,10 @@ static bool _guess_identifier_type_from_base(const GDScriptCompletionContext &p_
return true;
}
}
+ if (m.data_type.has_type) {
+ r_type.type = m.data_type;
+ return true;
+ }
return false;
}
}
@@ -2109,8 +2114,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
"and", "in", "not", "or", "false", "PI", "TAU", "INF", "NAN", "self", "true", "as", "assert",
"breakpoint", "class", "extends", "is", "func", "preload", "setget", "signal", "tool", "yield",
"const", "enum", "export", "onready", "static", "var", "break", "continue", "if", "elif",
- "else", "for", "pass", "return", "match", "while", "remote", "sync", "master", "slave",
- "remotesync", "mastersync", "slavesync",
+ "else", "for", "pass", "return", "match", "while", "remote", "sync", "master", "puppet", "slave",
+ "remotesync", "mastersync", "puppetsync",
0
};
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index c469defb01..5af9bbc05f 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -1458,7 +1458,7 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_ATAN2: {
- MethodInfo mi("atan2", PropertyInfo(Variant::REAL, "x"), PropertyInfo(Variant::REAL, "y"));
+ MethodInfo mi("atan2", PropertyInfo(Variant::REAL, "y"), PropertyInfo(Variant::REAL, "x"));
mi.return_val.type = Variant::REAL;
return mi;
} break;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 7243690f94..ea1287374b 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -81,8 +81,11 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) {
}
tokenizer->advance();
- if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) {
+ return false;
+ }
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
// be more python-like
int current = tab_level.back()->get();
tab_level.push_back(current);
@@ -92,10 +95,11 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) {
}
while (true) {
-
if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) {
return false; //wtf
+ } else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_EOF) {
+ return false;
} else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) {
int indent = tokenizer->get_token_line_indent();
@@ -637,9 +641,21 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
expr = op;
} else {
-
- _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + ".");
- return NULL;
+ // Object is a special case
+ bool valid = false;
+ if (bi_type == Variant::OBJECT) {
+ int object_constant = ClassDB::get_integer_constant("Object", identifier, &valid);
+ if (valid) {
+ ConstantNode *cn = alloc_node<ConstantNode>();
+ cn->value = object_constant;
+ cn->datatype = _type_from_variant(cn->value);
+ expr = cn;
+ }
+ }
+ if (!valid) {
+ _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + ".");
+ return NULL;
+ }
}
} else {
@@ -4382,10 +4398,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
}
- if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVESYNC) {
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE) {
current_export = PropertyInfo();
- _set_error("Expected 'var', 'onready', 'remote', 'master', 'slave', 'sync', 'remotesync', 'mastersync', 'slavesync'.");
+ _set_error("Expected 'var', 'onready', 'remote', 'master', 'puppet', 'sync', 'remotesync', 'mastersync', 'puppetsync'.");
return;
}
@@ -4442,7 +4458,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
rpc_mode = MultiplayerAPI::RPC_MODE_MASTER;
continue;
} break;
- case GDScriptTokenizer::TK_PR_SLAVE: {
+ case GDScriptTokenizer::TK_PR_SLAVE:
+#ifdef DEBUG_ENABLED
+ _add_warning(GDScriptWarning::DEPRECATED_KEYWORD, tokenizer->get_token_line(), "slave", "puppet");
+#endif
+ case GDScriptTokenizer::TK_PR_PUPPET: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
@@ -4459,7 +4479,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}
- rpc_mode = MultiplayerAPI::RPC_MODE_SLAVE;
+ rpc_mode = MultiplayerAPI::RPC_MODE_PUPPET;
continue;
} break;
case GDScriptTokenizer::TK_PR_REMOTESYNC:
@@ -4475,7 +4495,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- rpc_mode = MultiplayerAPI::RPC_MODE_SYNC;
+ rpc_mode = MultiplayerAPI::RPC_MODE_REMOTESYNC;
continue;
} break;
case GDScriptTokenizer::TK_PR_MASTERSYNC: {
@@ -4493,7 +4513,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
rpc_mode = MultiplayerAPI::RPC_MODE_MASTERSYNC;
continue;
} break;
- case GDScriptTokenizer::TK_PR_SLAVESYNC: {
+ case GDScriptTokenizer::TK_PR_PUPPETSYNC: {
//may be fallthrough from export, ignore if so
tokenizer->advance();
@@ -4505,7 +4525,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- rpc_mode = MultiplayerAPI::RPC_MODE_SLAVESYNC;
+ rpc_mode = MultiplayerAPI::RPC_MODE_PUPPETSYNC;
continue;
} break;
case GDScriptTokenizer::TK_PR_VAR: {
@@ -4847,6 +4867,20 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
StringName const_id = tokenizer->get_token_literal();
+ if (current_class->constant_expressions.has(const_id)) {
+ _set_error("A constant named '" + String(const_id) + "' already exists in this class (at line: " +
+ itos(current_class->constant_expressions[const_id].expression->line) + ").");
+ return;
+ }
+
+ for (int i = 0; i < current_class->variables.size(); i++) {
+ if (current_class->variables[i].identifier == const_id) {
+ _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " +
+ itos(current_class->variables[i].line) + ").");
+ return;
+ }
+ }
+
tokenizer->advance();
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
@@ -7200,6 +7234,12 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
expr.is_constant = true;
c.type = expr;
c.expression->set_datatype(expr);
+
+ DataType tmp;
+ if (_get_member_type(p_class->base_type, E->key(), tmp)) {
+ _set_error("Member '" + String(E->key()) + "' already exists in parent class.", c.expression->line);
+ return;
+ }
}
// Function declarations
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 941f5dbecc..77e1b7290e 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -112,10 +112,11 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = {
"rpc",
"sync",
"master",
+ "puppet",
"slave",
"remotesync",
"mastersync",
- "slavesync",
+ "puppetsync",
"'['",
"']'",
"'{'",
@@ -210,10 +211,11 @@ static const _kws _keyword_list[] = {
{ GDScriptTokenizer::TK_PR_REMOTE, "remote" },
{ GDScriptTokenizer::TK_PR_MASTER, "master" },
{ GDScriptTokenizer::TK_PR_SLAVE, "slave" },
+ { GDScriptTokenizer::TK_PR_PUPPET, "puppet" },
{ GDScriptTokenizer::TK_PR_SYNC, "sync" },
{ GDScriptTokenizer::TK_PR_REMOTESYNC, "remotesync" },
{ GDScriptTokenizer::TK_PR_MASTERSYNC, "mastersync" },
- { GDScriptTokenizer::TK_PR_SLAVESYNC, "slavesync" },
+ { GDScriptTokenizer::TK_PR_PUPPETSYNC, "puppetsync" },
{ GDScriptTokenizer::TK_PR_CONST, "const" },
{ GDScriptTokenizer::TK_PR_ENUM, "enum" },
//controlflow
@@ -258,11 +260,11 @@ bool GDScriptTokenizer::is_token_literal(int p_offset, bool variable_safe) const
case TK_PR_SIGNAL:
case TK_PR_REMOTE:
case TK_PR_MASTER:
- case TK_PR_SLAVE:
+ case TK_PR_PUPPET:
case TK_PR_SYNC:
case TK_PR_REMOTESYNC:
case TK_PR_MASTERSYNC:
- case TK_PR_SLAVESYNC:
+ case TK_PR_PUPPETSYNC:
return true;
// Literal for non-variables only:
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 01b1ac5bf2..cc894fb101 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -119,9 +119,10 @@ public:
TK_PR_SYNC,
TK_PR_MASTER,
TK_PR_SLAVE,
+ TK_PR_PUPPET,
TK_PR_REMOTESYNC,
TK_PR_MASTERSYNC,
- TK_PR_SLAVESYNC,
+ TK_PR_PUPPETSYNC,
TK_BRACKET_OPEN,
TK_BRACKET_CLOSE,
TK_CURLY_BRACKET_OPEN,