summaryrefslogtreecommitdiff
path: root/modules/gdscript/gdscript_vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_vm.cpp')
-rw-r--r--modules/gdscript/gdscript_vm.cpp226
1 files changed, 213 insertions, 13 deletions
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 8bf6a8b08b..8a261a88e3 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -33,6 +33,7 @@
#include "core/core_string_names.h"
#include "core/os/os.h"
#include "gdscript.h"
+#include "gdscript_lambda_callable.h"
Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, Variant *p_stack, String &r_error) const {
int address = p_address & ADDR_MASK;
@@ -151,6 +152,44 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
return err_text;
}
+void (*type_init_function_table[])(Variant *) = {
+ nullptr, // NIL (shouldn't be called).
+ &VariantInitializer<bool>::init, // BOOL.
+ &VariantInitializer<int64_t>::init, // INT.
+ &VariantInitializer<double>::init, // FLOAT.
+ &VariantInitializer<String>::init, // STRING.
+ &VariantInitializer<Vector2>::init, // VECTOR2.
+ &VariantInitializer<Vector2i>::init, // VECTOR2I.
+ &VariantInitializer<Rect2>::init, // RECT2.
+ &VariantInitializer<Rect2i>::init, // RECT2I.
+ &VariantInitializer<Vector3>::init, // VECTOR3.
+ &VariantInitializer<Vector3i>::init, // VECTOR3I.
+ &VariantInitializer<Transform2D>::init, // TRANSFORM2D.
+ &VariantInitializer<Plane>::init, // PLANE.
+ &VariantInitializer<Quaternion>::init, // QUATERNION.
+ &VariantInitializer<AABB>::init, // AABB.
+ &VariantInitializer<Basis>::init, // BASIS.
+ &VariantInitializer<Transform3D>::init, // TRANSFORM3D.
+ &VariantInitializer<Color>::init, // COLOR.
+ &VariantInitializer<StringName>::init, // STRING_NAME.
+ &VariantInitializer<NodePath>::init, // NODE_PATH.
+ &VariantInitializer<RID>::init, // RID.
+ &VariantTypeAdjust<Object *>::adjust, // OBJECT.
+ &VariantInitializer<Callable>::init, // CALLABLE.
+ &VariantInitializer<Signal>::init, // SIGNAL.
+ &VariantInitializer<Dictionary>::init, // DICTIONARY.
+ &VariantInitializer<Array>::init, // ARRAY.
+ &VariantInitializer<PackedByteArray>::init, // PACKED_BYTE_ARRAY.
+ &VariantInitializer<PackedInt32Array>::init, // PACKED_INT32_ARRAY.
+ &VariantInitializer<PackedInt64Array>::init, // PACKED_INT64_ARRAY.
+ &VariantInitializer<PackedFloat32Array>::init, // PACKED_FLOAT32_ARRAY.
+ &VariantInitializer<PackedFloat64Array>::init, // PACKED_FLOAT64_ARRAY.
+ &VariantInitializer<PackedStringArray>::init, // PACKED_STRING_ARRAY.
+ &VariantInitializer<PackedVector2Array>::init, // PACKED_VECTOR2_ARRAY.
+ &VariantInitializer<PackedVector3Array>::init, // PACKED_VECTOR3_ARRAY.
+ &VariantInitializer<PackedColorArray>::init, // PACKED_COLOR_ARRAY.
+};
+
#if defined(__GNUC__)
#define OPCODES_TABLE \
static const void *switch_table_ops[] = { \
@@ -195,6 +234,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
&&OPCODE_CALL_SELF_BASE, \
&&OPCODE_CALL_METHOD_BIND, \
&&OPCODE_CALL_METHOD_BIND_RET, \
+ &&OPCODE_CALL_BUILTIN_STATIC, \
&&OPCODE_CALL_PTRCALL_NO_RETURN, \
&&OPCODE_CALL_PTRCALL_BOOL, \
&&OPCODE_CALL_PTRCALL_INT, \
@@ -208,10 +248,10 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
&&OPCODE_CALL_PTRCALL_VECTOR3I, \
&&OPCODE_CALL_PTRCALL_TRANSFORM2D, \
&&OPCODE_CALL_PTRCALL_PLANE, \
- &&OPCODE_CALL_PTRCALL_QUAT, \
+ &&OPCODE_CALL_PTRCALL_QUATERNION, \
&&OPCODE_CALL_PTRCALL_AABB, \
&&OPCODE_CALL_PTRCALL_BASIS, \
- &&OPCODE_CALL_PTRCALL_TRANSFORM, \
+ &&OPCODE_CALL_PTRCALL_TRANSFORM3D, \
&&OPCODE_CALL_PTRCALL_COLOR, \
&&OPCODE_CALL_PTRCALL_STRING_NAME, \
&&OPCODE_CALL_PTRCALL_NODE_PATH, \
@@ -232,6 +272,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
&&OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY, \
&&OPCODE_AWAIT, \
&&OPCODE_AWAIT_RESUME, \
+ &&OPCODE_CREATE_LAMBDA, \
&&OPCODE_JUMP, \
&&OPCODE_JUMP_IF, \
&&OPCODE_JUMP_IF_NOT, \
@@ -282,6 +323,40 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
&&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \
&&OPCODE_ITERATE_OBJECT, \
&&OPCODE_STORE_NAMED_GLOBAL, \
+ &&OPCODE_TYPE_ADJUST_BOOL, \
+ &&OPCODE_TYPE_ADJUST_INT, \
+ &&OPCODE_TYPE_ADJUST_FLOAT, \
+ &&OPCODE_TYPE_ADJUST_STRING, \
+ &&OPCODE_TYPE_ADJUST_VECTOR2, \
+ &&OPCODE_TYPE_ADJUST_VECTOR2I, \
+ &&OPCODE_TYPE_ADJUST_RECT2, \
+ &&OPCODE_TYPE_ADJUST_RECT2I, \
+ &&OPCODE_TYPE_ADJUST_VECTOR3, \
+ &&OPCODE_TYPE_ADJUST_VECTOR3I, \
+ &&OPCODE_TYPE_ADJUST_TRANSFORM2D, \
+ &&OPCODE_TYPE_ADJUST_PLANE, \
+ &&OPCODE_TYPE_ADJUST_QUATERNION, \
+ &&OPCODE_TYPE_ADJUST_AABB, \
+ &&OPCODE_TYPE_ADJUST_BASIS, \
+ &&OPCODE_TYPE_ADJUST_TRANSFORM, \
+ &&OPCODE_TYPE_ADJUST_COLOR, \
+ &&OPCODE_TYPE_ADJUST_STRING_NAME, \
+ &&OPCODE_TYPE_ADJUST_NODE_PATH, \
+ &&OPCODE_TYPE_ADJUST_RID, \
+ &&OPCODE_TYPE_ADJUST_OBJECT, \
+ &&OPCODE_TYPE_ADJUST_CALLABLE, \
+ &&OPCODE_TYPE_ADJUST_SIGNAL, \
+ &&OPCODE_TYPE_ADJUST_DICTIONARY, \
+ &&OPCODE_TYPE_ADJUST_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, \
+ &&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, \
&&OPCODE_ASSERT, \
&&OPCODE_BREAKPOINT, \
&&OPCODE_LINE, \
@@ -323,7 +398,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
#define OP_GET_VECTOR3I get_vector3i
#define OP_GET_RECT2 get_rect2
#define OP_GET_RECT2I get_rect2i
-#define OP_GET_QUAT get_quat
+#define OP_GET_QUATERNION get_quaternion
#define OP_GET_COLOR get_color
#define OP_GET_STRING get_string
#define OP_GET_STRING_NAME get_string_name
@@ -341,7 +416,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
#define OP_GET_PACKED_VECTOR2_ARRAY get_vector2_array
#define OP_GET_PACKED_VECTOR3_ARRAY get_vector3_array
#define OP_GET_PACKED_COLOR_ARRAY get_color_array
-#define OP_GET_TRANSFORM get_transform
+#define OP_GET_TRANSFORM3D get_transform
#define OP_GET_TRANSFORM2D get_transform2d
#define OP_GET_PLANE get_plane
#define OP_GET_AABB get_aabb
@@ -455,6 +530,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
+ for (const Map<int, Variant::Type>::Element *E = temporary_slots.front(); E; E = E->next()) {
+ type_init_function_table[E->get()](&stack[E->key()]);
+ }
+
String err_text;
#ifdef DEBUG_ENABLED
@@ -1418,13 +1497,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (err.error != Callable::CallError::CALL_OK) {
String methodstr = *methodname;
String basestr = _get_var_type(base);
+ bool is_callable = false;
if (methodstr == "call") {
- if (argc >= 1) {
+ if (argc >= 1 && base->get_type() != Variant::CALLABLE) {
methodstr = String(*argptrs[0]) + " (via call)";
if (err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
err.argument += 1;
}
+ } else {
+ methodstr = base->operator String() + " (Callable)";
+ is_callable = true;
}
} else if (methodstr == "free") {
if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
@@ -1444,7 +1527,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
}
}
- err_text = _get_call_error(err, "function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs);
+ err_text = _get_call_error(err, "function '" + methodstr + (is_callable ? "" : "' in base '" + basestr) + "'", (const Variant **)argptrs);
OPCODE_BREAK;
}
#endif
@@ -1533,6 +1616,51 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
DISPATCH_OPCODE;
+ OPCODE(OPCODE_CALL_BUILTIN_STATIC) {
+ CHECK_SPACE(4 + instr_arg_count);
+
+ ip += instr_arg_count;
+
+ GD_ERR_BREAK(_code_ptr[ip + 1] < 0 || _code_ptr[ip + 1] >= Variant::VARIANT_MAX);
+ Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 1];
+
+ int methodname_idx = _code_ptr[ip + 2];
+ GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count);
+ const StringName *methodname = &_global_names_ptr[methodname_idx];
+
+ int argc = _code_ptr[ip + 3];
+ GD_ERR_BREAK(argc < 0);
+
+ GET_INSTRUCTION_ARG(ret, argc);
+
+ const Variant **argptrs = const_cast<const Variant **>(instruction_args);
+
+#ifdef DEBUG_ENABLED
+ uint64_t call_time = 0;
+
+ if (GDScriptLanguage::get_singleton()->profiling) {
+ call_time = OS::get_singleton()->get_ticks_usec();
+ }
+#endif
+
+ Callable::CallError err;
+ Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err);
+
+#ifdef DEBUG_ENABLED
+ if (GDScriptLanguage::get_singleton()->profiling) {
+ function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
+ }
+
+ if (err.error != Callable::CallError::CALL_OK) {
+ err_text = _get_call_error(err, "static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs);
+ OPCODE_BREAK;
+ }
+#endif
+
+ ip += 4;
+ }
+ DISPATCH_OPCODE;
+
#ifdef DEBUG_ENABLED
#define OPCODE_CALL_PTR(m_type) \
OPCODE(OPCODE_CALL_PTRCALL_##m_type) { \
@@ -1605,10 +1733,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_CALL_PTR(VECTOR3I);
OPCODE_CALL_PTR(TRANSFORM2D);
OPCODE_CALL_PTR(PLANE);
- OPCODE_CALL_PTR(QUAT);
+ OPCODE_CALL_PTR(QUATERNION);
OPCODE_CALL_PTR(AABB);
OPCODE_CALL_PTR(BASIS);
- OPCODE_CALL_PTR(TRANSFORM);
+ OPCODE_CALL_PTR(TRANSFORM3D);
OPCODE_CALL_PTR(COLOR);
OPCODE_CALL_PTR(STRING_NAME);
OPCODE_CALL_PTR(NODE_PATH);
@@ -1842,7 +1970,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (err.error != Callable::CallError::CALL_OK) {
// TODO: Add this information in debug.
- String methodstr = "<unkown function>";
+ String methodstr = "<unknown function>";
if (dst->get_type() == Variant::STRING) {
// Call provided error string.
err_text = "Error calling GDScript utility function '" + methodstr + "': " + String(*dst);
@@ -1861,7 +1989,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
ip += instr_arg_count;
- int self_fun = _code_ptr[ip + 1];
+ int argc = _code_ptr[ip + 1];
+ GD_ERR_BREAK(argc < 0);
+
+ int self_fun = _code_ptr[ip + 2];
#ifdef DEBUG_ENABLED
if (self_fun < 0 || self_fun >= _global_names_count) {
err_text = "compiler bug, function name not found";
@@ -1870,9 +2001,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
const StringName *methodname = &_global_names_ptr[self_fun];
- int argc = _code_ptr[ip + 2];
- GD_ERR_BREAK(argc < 0);
-
Variant **argptrs = instruction_args;
GET_INSTRUCTION_ARG(dst, argc);
@@ -2023,6 +2151,34 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
DISPATCH_OPCODE;
+ OPCODE(OPCODE_CREATE_LAMBDA) {
+ CHECK_SPACE(2 + instr_arg_count);
+
+ ip += instr_arg_count;
+
+ int captures_count = _code_ptr[ip + 1];
+ GD_ERR_BREAK(captures_count < 0);
+
+ int lambda_index = _code_ptr[ip + 2];
+ GD_ERR_BREAK(lambda_index < 0 || lambda_index >= _lambdas_count);
+ GDScriptFunction *lambda = _lambdas_ptr[lambda_index];
+
+ Vector<Variant> captures;
+ captures.resize(captures_count);
+ for (int i = 0; i < captures_count; i++) {
+ GET_INSTRUCTION_ARG(arg, i);
+ captures.write[i] = *arg;
+ }
+
+ GDScriptLambdaCallable *callable = memnew(GDScriptLambdaCallable(Ref<GDScript>(script), lambda, captures));
+
+ GET_INSTRUCTION_ARG(result, captures_count);
+ *result = Callable(callable);
+
+ ip += 3;
+ }
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_JUMP) {
CHECK_SPACE(2);
int to = _code_ptr[ip + 1];
@@ -2973,6 +3129,50 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
DISPATCH_OPCODE;
+#define OPCODE_TYPE_ADJUST(m_v_type, m_c_type) \
+ OPCODE(OPCODE_TYPE_ADJUST_##m_v_type) { \
+ CHECK_SPACE(2); \
+ GET_INSTRUCTION_ARG(arg, 0); \
+ VariantTypeAdjust<m_c_type>::adjust(arg); \
+ ip += 2; \
+ } \
+ DISPATCH_OPCODE
+
+ OPCODE_TYPE_ADJUST(BOOL, bool);
+ OPCODE_TYPE_ADJUST(INT, int64_t);
+ OPCODE_TYPE_ADJUST(FLOAT, double);
+ OPCODE_TYPE_ADJUST(STRING, String);
+ OPCODE_TYPE_ADJUST(VECTOR2, Vector2);
+ OPCODE_TYPE_ADJUST(VECTOR2I, Vector2i);
+ OPCODE_TYPE_ADJUST(RECT2, Rect2);
+ OPCODE_TYPE_ADJUST(RECT2I, Rect2i);
+ OPCODE_TYPE_ADJUST(VECTOR3, Vector3);
+ OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i);
+ OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D);
+ OPCODE_TYPE_ADJUST(PLANE, Plane);
+ OPCODE_TYPE_ADJUST(QUATERNION, Quaternion);
+ OPCODE_TYPE_ADJUST(AABB, AABB);
+ OPCODE_TYPE_ADJUST(BASIS, Basis);
+ OPCODE_TYPE_ADJUST(TRANSFORM, Transform3D);
+ OPCODE_TYPE_ADJUST(COLOR, Color);
+ OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
+ OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
+ OPCODE_TYPE_ADJUST(RID, RID);
+ OPCODE_TYPE_ADJUST(OBJECT, Object *);
+ OPCODE_TYPE_ADJUST(CALLABLE, Callable);
+ OPCODE_TYPE_ADJUST(SIGNAL, Signal);
+ OPCODE_TYPE_ADJUST(DICTIONARY, Dictionary);
+ OPCODE_TYPE_ADJUST(ARRAY, Array);
+ OPCODE_TYPE_ADJUST(PACKED_BYTE_ARRAY, PackedByteArray);
+ OPCODE_TYPE_ADJUST(PACKED_INT32_ARRAY, PackedInt32Array);
+ OPCODE_TYPE_ADJUST(PACKED_INT64_ARRAY, PackedInt64Array);
+ OPCODE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY, PackedFloat32Array);
+ OPCODE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY, PackedFloat64Array);
+ OPCODE_TYPE_ADJUST(PACKED_STRING_ARRAY, PackedStringArray);
+ OPCODE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY, PackedVector2Array);
+ OPCODE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY, PackedVector3Array);
+ OPCODE_TYPE_ADJUST(PACKED_COLOR_ARRAY, PackedColorArray);
+
OPCODE(OPCODE_ASSERT) {
CHECK_SPACE(3);