summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/doc_classes/GDScript.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptFunctionState.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptNativeClass.xml2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/gdscript_editor.cpp4
-rw-r--r--modules/gdscript/gdscript_function.cpp20
-rw-r--r--modules/gdscript/gdscript_function.h1
-rw-r--r--modules/gdscript/gdscript_functions.cpp10
-rw-r--r--modules/gdscript/gdscript_parser.cpp91
9 files changed, 83 insertions, 51 deletions
diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml
index 59cb00e3f6..40a435f459 100644
--- a/modules/gdscript/doc_classes/GDScript.xml
+++ b/modules/gdscript/doc_classes/GDScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScript" inherits="Script" category="Core" version="3.0-stable">
+<class name="GDScript" inherits="Script" category="Core" version="3.1">
<brief_description>
A script implemented in the GDScript programming language.
</brief_description>
diff --git a/modules/gdscript/doc_classes/GDScriptFunctionState.xml b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
index 8510136f68..c205cedef5 100644
--- a/modules/gdscript/doc_classes/GDScriptFunctionState.xml
+++ b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.0-stable">
+<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.1">
<brief_description>
State of a function call after yielding.
</brief_description>
diff --git a/modules/gdscript/doc_classes/GDScriptNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
index 48826ec1e0..90935b5c22 100644
--- a/modules/gdscript/doc_classes/GDScriptNativeClass.xml
+++ b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.0-stable">
+<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.1">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 1649fb52f2..048948dada 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -181,7 +181,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
//wait, identifier could be a local variable or something else... careful here, must reference properly
//as stack may be more interesting to work with
- //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases peformance a lot.
+ //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases performance a lot.
const GDScriptParser::IdentifierNode *in = static_cast<const GDScriptParser::IdentifierNode *>(p_expression);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 505562324f..5f72dca866 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -60,7 +60,7 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str
"# var a = 2\n" +
"# var b = \"textvar\"\n\n" +
"func _ready():\n" +
- "%TS%# Called every time the node is added to the scene.\n" +
+ "%TS%# Called when the node is added to the scene for the first time.\n" +
"%TS%# Initialization here\n" +
"%TS%pass\n\n" +
"#func _process(delta):\n" +
@@ -410,13 +410,11 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na
String s = "func " + p_name + "(";
if (p_args.size()) {
- s += " ";
for (int i = 0; i < p_args.size(); i++) {
if (i > 0)
s += ", ";
s += p_args[i].get_slice(":", 0);
}
- s += " ";
}
s += "):\n" + _get_indentation() + "pass # replace with function body\n";
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index a2f449909f..f83bec0c7f 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -1535,15 +1535,21 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar
// then the function did yield again after resuming.
if (ret.is_ref()) {
GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
- if (gdfs && gdfs->function == function)
+ if (gdfs && gdfs->function == function) {
completed = false;
+ gdfs->previous_state = Ref<GDScriptFunctionState>(this);
+ }
}
function = NULL; //cleaned up;
state.result = Variant();
if (completed) {
- emit_signal("completed", ret);
+ GDScriptFunctionState *state = this;
+ while (state != NULL) {
+ state->emit_signal("completed", ret);
+ state = *(state->previous_state);
+ }
}
return ret;
@@ -1591,15 +1597,21 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
// then the function did yield again after resuming.
if (ret.is_ref()) {
GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret);
- if (gdfs && gdfs->function == function)
+ if (gdfs && gdfs->function == function) {
completed = false;
+ gdfs->previous_state = Ref<GDScriptFunctionState>(this);
+ }
}
function = NULL; //cleaned up;
state.result = Variant();
if (completed) {
- emit_signal("completed", ret);
+ GDScriptFunctionState *state = this;
+ while (state != NULL) {
+ state->emit_signal("completed", ret);
+ state = *(state->previous_state);
+ }
}
return ret;
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 9310444c7a..dff4bdfaf2 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -234,6 +234,7 @@ class GDScriptFunctionState : public Reference {
GDScriptFunction *function;
GDScriptFunction::CallState state;
Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ Ref<GDScriptFunctionState> previous_state;
protected:
static void _bind_methods();
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index c067d5409f..278585cb01 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -358,13 +358,16 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
r_ret = Math::dectime((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]);
} break;
case MATH_RANDOMIZE: {
+ VALIDATE_ARG_COUNT(0);
Math::randomize();
r_ret = Variant();
} break;
case MATH_RAND: {
+ VALIDATE_ARG_COUNT(0);
r_ret = Math::rand();
} break;
case MATH_RANDF: {
+ VALIDATE_ARG_COUNT(0);
r_ret = Math::randf();
} break;
case MATH_RANDOM: {
@@ -593,7 +596,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
r_ret = String(result);
} break;
case TEXT_STR: {
+ if (p_arg_count < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ r_ret = Variant();
+ return;
+ }
String str;
for (int i = 0; i < p_arg_count; i++) {
@@ -1180,6 +1189,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
} break;
case PRINT_STACK: {
+ VALIDATE_ARG_COUNT(0);
ScriptLanguage *script = GDScriptLanguage::get_singleton();
for (int i = 0; i < script->debug_get_stack_level_count(); i++) {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 1392323d56..435bc327dc 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -456,23 +456,26 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (!validating) {
//this can be too slow for just validating code
- if (for_completion && ScriptCodeCompletionCache::get_singleton()) {
+ if (for_completion && ScriptCodeCompletionCache::get_singleton() && FileAccess::exists(path)) {
res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path);
- } else { // essential; see issue 15902
+ } else if (!for_completion || FileAccess::exists(path)) {
res = ResourceLoader::load(path);
}
- if (!res.is_valid()) {
- _set_error("Can't preload resource at path: " + path);
- return NULL;
- }
} else {
if (!FileAccess::exists(path)) {
_set_error("Can't preload resource at path: " + path);
return NULL;
+ } else if (ScriptCodeCompletionCache::get_singleton()) {
+ res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path);
}
}
+ if (!res.is_valid()) {
+ _set_error("Can't preload resource at path: " + path);
+ return NULL;
+ }
+
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' after 'preload' path");
return NULL;
@@ -576,18 +579,47 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (identifier == StringName()) {
- _set_error("Built-in type constant expected after '.'");
+ _set_error("Built-in type constant or static function expected after '.'");
return NULL;
}
if (!Variant::has_numeric_constant(bi_type, identifier)) {
- _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + ".");
- return NULL;
- }
+ if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN &&
+ Variant::is_method_const(bi_type, identifier) &&
+ Variant::get_method_return_type(bi_type, identifier) == bi_type) {
+
+ tokenizer->advance();
+
+ OperatorNode *construct = alloc_node<OperatorNode>();
+ construct->op = OperatorNode::OP_CALL;
+
+ TypeNode *tn = alloc_node<TypeNode>();
+ tn->vtype = bi_type;
+ construct->arguments.push_back(tn);
+
+ OperatorNode *op = alloc_node<OperatorNode>();
+ op->op = OperatorNode::OP_CALL;
+ op->arguments.push_back(construct);
+
+ IdentifierNode *id = alloc_node<IdentifierNode>();
+ id->name = identifier;
+ op->arguments.push_back(id);
+
+ if (!_parse_arguments(op, op->arguments, p_static, true))
+ return NULL;
+
+ expr = op;
+ } else {
+
+ _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + ".");
+ return NULL;
+ }
+ } else {
- ConstantNode *cn = alloc_node<ConstantNode>();
- cn->value = Variant::get_numeric_constant_value(bi_type, identifier);
- expr = cn;
+ ConstantNode *cn = alloc_node<ConstantNode>();
+ cn->value = Variant::get_numeric_constant_value(bi_type, identifier);
+ expr = cn;
+ }
} else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_PARENTHESIS_OPEN && tokenizer->is_token_literal()) {
// We check with is_token_literal, as this allows us to use match/sync/etc. as a name
@@ -1516,11 +1548,11 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to
String errwhere;
if (op->arguments[0]->type == Node::TYPE_TYPE) {
TypeNode *tn = static_cast<TypeNode *>(op->arguments[0]);
- errwhere = "'" + Variant::get_type_name(tn->vtype) + "'' constructor";
+ errwhere = "'" + Variant::get_type_name(tn->vtype) + "' constructor";
} else {
GDScriptFunctions::Function func = static_cast<BuiltInFunctionNode *>(op->arguments[0])->function;
- errwhere = String("'") + GDScriptFunctions::get_func_name(func) + "'' intrinsic function";
+ errwhere = String("'") + GDScriptFunctions::get_func_name(func) + "' intrinsic function";
}
switch (ce.error) {
@@ -4069,7 +4101,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
ConstantNode *cn = static_cast<ConstantNode *>(subexpr);
if (cn->value.get_type() == Variant::NIL) {
- _set_error("Can't accept a null constant expression for infering export type.");
+ _set_error("Can't accept a null constant expression for inferring export type.");
return;
}
member._export.type = cn->value.get_type();
@@ -4205,7 +4237,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
} break;
case GDScriptTokenizer::TK_PR_ENUM: {
- //mutiple constant declarations..
+ //multiple constant declarations..
int last_assign = -1; // Incremented by 1 right before the assingment.
String enum_name;
@@ -4356,8 +4388,6 @@ Error GDScriptParser::_parse(const String &p_base_path) {
base_path = p_base_path;
- clear();
-
//assume class
ClassNode *main_class = alloc_node<ClassNode>();
main_class->initializer = alloc_node<BlockNode>();
@@ -4382,17 +4412,7 @@ Error GDScriptParser::_parse(const String &p_base_path) {
Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path, const String &p_self_path) {
- for_completion = false;
- validating = false;
- completion_type = COMPLETION_NONE;
- completion_node = NULL;
- completion_class = NULL;
- completion_function = NULL;
- completion_block = NULL;
- completion_found = false;
- current_block = NULL;
- current_class = NULL;
- current_function = NULL;
+ clear();
self_path = p_self_path;
GDScriptTokenizerBuffer *tb = memnew(GDScriptTokenizerBuffer);
@@ -4406,16 +4426,7 @@ Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const St
Error GDScriptParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion) {
- completion_type = COMPLETION_NONE;
- completion_node = NULL;
- completion_class = NULL;
- completion_function = NULL;
- completion_block = NULL;
- completion_found = false;
- current_block = NULL;
- current_class = NULL;
-
- current_function = NULL;
+ clear();
self_path = p_self_path;
GDScriptTokenizerText *tt = memnew(GDScriptTokenizerText);