summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gd_functions.cpp43
-rw-r--r--modules/gdscript/gd_functions.h1
-rw-r--r--modules/gdscript/gd_parser.cpp16
-rw-r--r--modules/gdscript/gd_parser.h1
-rw-r--r--modules/gdscript/gd_script.cpp13
-rw-r--r--modules/gdscript/gd_tokenizer.cpp18
6 files changed, 90 insertions, 2 deletions
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index 2930d9322c..f789493ae8 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -31,6 +31,7 @@
#include "object_type_db.h"
#include "reference.h"
#include "gd_script.h"
+#include "func_ref.h"
#include "os/os.h"
const char *GDFunctions::get_func_name(Function p_func) {
@@ -80,6 +81,7 @@ const char *GDFunctions::get_func_name(Function p_func) {
"clamp",
"nearest_po2",
"weakref",
+ "funcref",
"convert",
"typeof",
"str",
@@ -452,6 +454,36 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
} break;
+ case FUNC_FUNCREF: {
+ VALIDATE_ARG_COUNT(2);
+ if (p_args[0]->get_type()!=Variant::OBJECT) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=0;
+ r_error.expected=Variant::OBJECT;
+ r_ret=Variant();
+ return;
+
+ }
+ if (p_args[1]->get_type()!=Variant::STRING && p_args[1]->get_type()!=Variant::NODE_PATH) {
+
+ r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument=1;
+ r_error.expected=Variant::STRING;
+ r_ret=Variant();
+ return;
+
+ }
+
+ Ref<FuncRef> fr = memnew( FuncRef);
+
+ Object *obj = *p_args[0];
+ fr->set_instance(*p_args[0]);
+ fr->set_function(*p_args[1]);
+
+ r_ret=fr;
+
+ } break;
case TYPE_CONVERT: {
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(1);
@@ -678,7 +710,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
}
r_ret=ResourceLoader::load(*p_args[0]);
- }
+ } break;
case INST2DICT: {
VALIDATE_ARG_COUNT(1);
@@ -1063,7 +1095,7 @@ MethodInfo GDFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_RAND: {
- MethodInfo mi("rand");
+ MethodInfo mi("randi");
mi.return_val.type=Variant::INT;
return mi;
} break;
@@ -1130,6 +1162,13 @@ MethodInfo GDFunctions::get_info(Function p_func) {
return mi;
} break;
+ case FUNC_FUNCREF: {
+
+ MethodInfo mi("funcref",PropertyInfo(Variant::OBJECT,"instance"),PropertyInfo(Variant::STRING,"funcname"));
+ mi.return_val.type=Variant::OBJECT;
+ return mi;
+
+ } break;
case TYPE_CONVERT: {
MethodInfo mi("convert",PropertyInfo(Variant::NIL,"what"),PropertyInfo(Variant::INT,"type"));
diff --git a/modules/gdscript/gd_functions.h b/modules/gdscript/gd_functions.h
index 2ab397d18a..9255e5e2c5 100644
--- a/modules/gdscript/gd_functions.h
+++ b/modules/gdscript/gd_functions.h
@@ -77,6 +77,7 @@ public:
LOGIC_CLAMP,
LOGIC_NEAREST_PO2,
OBJ_WEAKREF,
+ FUNC_FUNCREF,
TYPE_CONVERT,
TYPE_OF,
TEXT_STR,
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index f962f8c5fb..f540660cd3 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -174,10 +174,19 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
/* Parse Operand */
/*****************/
+ if (parenthesis>0) {
+ //remove empty space (only allowed if inside parenthesis
+ while(tokenizer->get_token()==GDTokenizer::TK_NEWLINE) {
+ tokenizer->advance();
+ }
+ }
+
if (tokenizer->get_token()==GDTokenizer::TK_PARENTHESIS_OPEN) {
//subexpression ()
tokenizer->advance();
+ parenthesis++;
Node* subexpr = _parse_expression(p_parent,p_static);
+ parenthesis--;
if (!subexpr)
return NULL;
@@ -629,6 +638,12 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
/* Parse Operator */
/******************/
+ if (parenthesis>0) {
+ //remove empty space (only allowed if inside parenthesis
+ while(tokenizer->get_token()==GDTokenizer::TK_NEWLINE) {
+ tokenizer->advance();
+ }
+ }
Expression e;
e.is_op=false;
@@ -2475,6 +2490,7 @@ void GDParser::clear() {
tab_level.push_back(0);
error_line=0;
error_column=0;
+ parenthesis=0;
current_export.type=Variant::NIL;
error="";
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index 1925808cac..278e5f543d 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -356,6 +356,7 @@ private:
template<class T>
T* alloc_node();
+ int parenthesis;
bool error_set;
String error;
int error_line;
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 29857e6be6..75bb47ceab 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -635,6 +635,19 @@ Variant GDFunction::call(GDInstance *p_instance,const Variant **p_args, int p_ar
err.argument-=1;
}
}
+ } if (methodstr=="free") {
+
+ if (err.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+
+ if (base->is_ref()) {
+ err_text="Attempted to free a reference.";
+ break;
+ } else if (base->get_type()==Variant::OBJECT) {
+
+ err_text="Attempted to free a locked object (calling or emitting).";
+ break;
+ }
+ }
}
err_text=_get_call_error(err,"function '"+methodstr+"' in base '"+basestr+"'",(const Variant**)argptrs);
break;
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index ff9be7926b..aeee1f6667 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -242,6 +242,24 @@ void GDTokenizerText::_advance() {
case 0:
_make_token(TK_EOF);
break;
+ case '\\':
+ INCPOS(1);
+ if (GETCHAR(0)=='\r') {
+ INCPOS(1);
+ }
+
+ if (GETCHAR(0)!='\n') {
+ _make_error("Expected newline after '\\'.");
+ return;
+ }
+
+ INCPOS(1);
+
+ while(GETCHAR(0)==' ' || GETCHAR(0)=='\t') {
+ INCPOS(1);
+ }
+
+ continue;
case '\t':
case '\r':
case ' ':