1 | /**************************************************************************/ |
2 | /* gdscript_function.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef GDSCRIPT_FUNCTION_H |
32 | #define GDSCRIPT_FUNCTION_H |
33 | |
34 | #include "gdscript_utility_functions.h" |
35 | |
36 | #include "core/object/ref_counted.h" |
37 | #include "core/object/script_language.h" |
38 | #include "core/os/thread.h" |
39 | #include "core/string/string_name.h" |
40 | #include "core/templates/pair.h" |
41 | #include "core/templates/self_list.h" |
42 | #include "core/variant/variant.h" |
43 | |
44 | class GDScriptInstance; |
45 | class GDScript; |
46 | |
47 | class GDScriptDataType { |
48 | private: |
49 | GDScriptDataType *container_element_type = nullptr; |
50 | |
51 | public: |
52 | enum Kind { |
53 | UNINITIALIZED, |
54 | BUILTIN, |
55 | NATIVE, |
56 | SCRIPT, |
57 | GDSCRIPT, |
58 | }; |
59 | |
60 | Kind kind = UNINITIALIZED; |
61 | |
62 | bool has_type = false; |
63 | Variant::Type builtin_type = Variant::NIL; |
64 | StringName native_type; |
65 | Script *script_type = nullptr; |
66 | Ref<Script> script_type_ref; |
67 | |
68 | bool is_type(const Variant &p_variant, bool p_allow_implicit_conversion = false) const { |
69 | if (!has_type) { |
70 | return true; // Can't type check |
71 | } |
72 | |
73 | switch (kind) { |
74 | case UNINITIALIZED: |
75 | break; |
76 | case BUILTIN: { |
77 | Variant::Type var_type = p_variant.get_type(); |
78 | bool valid = builtin_type == var_type; |
79 | if (valid && builtin_type == Variant::ARRAY && has_container_element_type()) { |
80 | Array array = p_variant; |
81 | if (array.is_typed()) { |
82 | Variant::Type array_builtin_type = (Variant::Type)array.get_typed_builtin(); |
83 | StringName array_native_type = array.get_typed_class_name(); |
84 | Ref<Script> array_script_type_ref = array.get_typed_script(); |
85 | |
86 | if (array_script_type_ref.is_valid()) { |
87 | valid = (container_element_type->kind == SCRIPT || container_element_type->kind == GDSCRIPT) && container_element_type->script_type == array_script_type_ref.ptr(); |
88 | } else if (array_native_type != StringName()) { |
89 | valid = container_element_type->kind == NATIVE && container_element_type->native_type == array_native_type; |
90 | } else { |
91 | valid = container_element_type->kind == BUILTIN && container_element_type->builtin_type == array_builtin_type; |
92 | } |
93 | } else { |
94 | valid = false; |
95 | } |
96 | } else if (!valid && p_allow_implicit_conversion) { |
97 | valid = Variant::can_convert_strict(var_type, builtin_type); |
98 | } |
99 | return valid; |
100 | } break; |
101 | case NATIVE: { |
102 | if (p_variant.get_type() == Variant::NIL) { |
103 | return true; |
104 | } |
105 | if (p_variant.get_type() != Variant::OBJECT) { |
106 | return false; |
107 | } |
108 | |
109 | bool was_freed = false; |
110 | Object *obj = p_variant.get_validated_object_with_check(was_freed); |
111 | if (!obj) { |
112 | return !was_freed; |
113 | } |
114 | |
115 | if (!ClassDB::is_parent_class(obj->get_class_name(), native_type)) { |
116 | return false; |
117 | } |
118 | return true; |
119 | } break; |
120 | case SCRIPT: |
121 | case GDSCRIPT: { |
122 | if (p_variant.get_type() == Variant::NIL) { |
123 | return true; |
124 | } |
125 | if (p_variant.get_type() != Variant::OBJECT) { |
126 | return false; |
127 | } |
128 | |
129 | bool was_freed = false; |
130 | Object *obj = p_variant.get_validated_object_with_check(was_freed); |
131 | if (!obj) { |
132 | return !was_freed; |
133 | } |
134 | |
135 | Ref<Script> base = obj && obj->get_script_instance() ? obj->get_script_instance()->get_script() : nullptr; |
136 | bool valid = false; |
137 | while (base.is_valid()) { |
138 | if (base == script_type) { |
139 | valid = true; |
140 | break; |
141 | } |
142 | base = base->get_base_script(); |
143 | } |
144 | return valid; |
145 | } break; |
146 | } |
147 | return false; |
148 | } |
149 | |
150 | void set_container_element_type(const GDScriptDataType &p_element_type) { |
151 | container_element_type = memnew(GDScriptDataType(p_element_type)); |
152 | } |
153 | |
154 | GDScriptDataType get_container_element_type() const { |
155 | ERR_FAIL_COND_V(container_element_type == nullptr, GDScriptDataType()); |
156 | return *container_element_type; |
157 | } |
158 | |
159 | bool has_container_element_type() const { |
160 | return container_element_type != nullptr; |
161 | } |
162 | |
163 | void unset_container_element_type() { |
164 | if (container_element_type) { |
165 | memdelete(container_element_type); |
166 | } |
167 | container_element_type = nullptr; |
168 | } |
169 | |
170 | GDScriptDataType() = default; |
171 | |
172 | void operator=(const GDScriptDataType &p_other) { |
173 | kind = p_other.kind; |
174 | has_type = p_other.has_type; |
175 | builtin_type = p_other.builtin_type; |
176 | native_type = p_other.native_type; |
177 | script_type = p_other.script_type; |
178 | script_type_ref = p_other.script_type_ref; |
179 | unset_container_element_type(); |
180 | if (p_other.has_container_element_type()) { |
181 | set_container_element_type(p_other.get_container_element_type()); |
182 | } |
183 | } |
184 | |
185 | GDScriptDataType(const GDScriptDataType &p_other) { |
186 | *this = p_other; |
187 | } |
188 | |
189 | ~GDScriptDataType() { |
190 | unset_container_element_type(); |
191 | } |
192 | }; |
193 | |
194 | class GDScriptFunction { |
195 | public: |
196 | enum Opcode { |
197 | OPCODE_OPERATOR, |
198 | OPCODE_OPERATOR_VALIDATED, |
199 | OPCODE_TYPE_TEST_BUILTIN, |
200 | OPCODE_TYPE_TEST_ARRAY, |
201 | OPCODE_TYPE_TEST_NATIVE, |
202 | OPCODE_TYPE_TEST_SCRIPT, |
203 | OPCODE_SET_KEYED, |
204 | OPCODE_SET_KEYED_VALIDATED, |
205 | OPCODE_SET_INDEXED_VALIDATED, |
206 | OPCODE_GET_KEYED, |
207 | OPCODE_GET_KEYED_VALIDATED, |
208 | OPCODE_GET_INDEXED_VALIDATED, |
209 | OPCODE_SET_NAMED, |
210 | OPCODE_SET_NAMED_VALIDATED, |
211 | OPCODE_GET_NAMED, |
212 | OPCODE_GET_NAMED_VALIDATED, |
213 | OPCODE_SET_MEMBER, |
214 | OPCODE_GET_MEMBER, |
215 | OPCODE_SET_STATIC_VARIABLE, // Only for GDScript. |
216 | OPCODE_GET_STATIC_VARIABLE, // Only for GDScript. |
217 | OPCODE_ASSIGN, |
218 | OPCODE_ASSIGN_TRUE, |
219 | OPCODE_ASSIGN_FALSE, |
220 | OPCODE_ASSIGN_TYPED_BUILTIN, |
221 | OPCODE_ASSIGN_TYPED_ARRAY, |
222 | OPCODE_ASSIGN_TYPED_NATIVE, |
223 | OPCODE_ASSIGN_TYPED_SCRIPT, |
224 | OPCODE_CAST_TO_BUILTIN, |
225 | OPCODE_CAST_TO_NATIVE, |
226 | OPCODE_CAST_TO_SCRIPT, |
227 | OPCODE_CONSTRUCT, // Only for basic types! |
228 | OPCODE_CONSTRUCT_VALIDATED, // Only for basic types! |
229 | OPCODE_CONSTRUCT_ARRAY, |
230 | OPCODE_CONSTRUCT_TYPED_ARRAY, |
231 | OPCODE_CONSTRUCT_DICTIONARY, |
232 | OPCODE_CALL, |
233 | OPCODE_CALL_RETURN, |
234 | OPCODE_CALL_ASYNC, |
235 | OPCODE_CALL_UTILITY, |
236 | OPCODE_CALL_UTILITY_VALIDATED, |
237 | OPCODE_CALL_GDSCRIPT_UTILITY, |
238 | OPCODE_CALL_BUILTIN_TYPE_VALIDATED, |
239 | OPCODE_CALL_SELF_BASE, |
240 | OPCODE_CALL_METHOD_BIND, |
241 | OPCODE_CALL_METHOD_BIND_RET, |
242 | OPCODE_CALL_BUILTIN_STATIC, |
243 | OPCODE_CALL_NATIVE_STATIC, |
244 | // ptrcall have one instruction per return type. |
245 | OPCODE_CALL_PTRCALL_NO_RETURN, |
246 | OPCODE_CALL_PTRCALL_BOOL, |
247 | OPCODE_CALL_PTRCALL_INT, |
248 | OPCODE_CALL_PTRCALL_FLOAT, |
249 | OPCODE_CALL_PTRCALL_STRING, |
250 | OPCODE_CALL_PTRCALL_VECTOR2, |
251 | OPCODE_CALL_PTRCALL_VECTOR2I, |
252 | OPCODE_CALL_PTRCALL_RECT2, |
253 | OPCODE_CALL_PTRCALL_RECT2I, |
254 | OPCODE_CALL_PTRCALL_VECTOR3, |
255 | OPCODE_CALL_PTRCALL_VECTOR3I, |
256 | OPCODE_CALL_PTRCALL_TRANSFORM2D, |
257 | OPCODE_CALL_PTRCALL_VECTOR4, |
258 | OPCODE_CALL_PTRCALL_VECTOR4I, |
259 | OPCODE_CALL_PTRCALL_PLANE, |
260 | OPCODE_CALL_PTRCALL_QUATERNION, |
261 | OPCODE_CALL_PTRCALL_AABB, |
262 | OPCODE_CALL_PTRCALL_BASIS, |
263 | OPCODE_CALL_PTRCALL_TRANSFORM3D, |
264 | OPCODE_CALL_PTRCALL_PROJECTION, |
265 | OPCODE_CALL_PTRCALL_COLOR, |
266 | OPCODE_CALL_PTRCALL_STRING_NAME, |
267 | OPCODE_CALL_PTRCALL_NODE_PATH, |
268 | OPCODE_CALL_PTRCALL_RID, |
269 | OPCODE_CALL_PTRCALL_OBJECT, |
270 | OPCODE_CALL_PTRCALL_CALLABLE, |
271 | OPCODE_CALL_PTRCALL_SIGNAL, |
272 | OPCODE_CALL_PTRCALL_DICTIONARY, |
273 | OPCODE_CALL_PTRCALL_ARRAY, |
274 | OPCODE_CALL_PTRCALL_PACKED_BYTE_ARRAY, |
275 | OPCODE_CALL_PTRCALL_PACKED_INT32_ARRAY, |
276 | OPCODE_CALL_PTRCALL_PACKED_INT64_ARRAY, |
277 | OPCODE_CALL_PTRCALL_PACKED_FLOAT32_ARRAY, |
278 | OPCODE_CALL_PTRCALL_PACKED_FLOAT64_ARRAY, |
279 | OPCODE_CALL_PTRCALL_PACKED_STRING_ARRAY, |
280 | OPCODE_CALL_PTRCALL_PACKED_VECTOR2_ARRAY, |
281 | OPCODE_CALL_PTRCALL_PACKED_VECTOR3_ARRAY, |
282 | OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY, |
283 | OPCODE_AWAIT, |
284 | OPCODE_AWAIT_RESUME, |
285 | OPCODE_CREATE_LAMBDA, |
286 | OPCODE_CREATE_SELF_LAMBDA, |
287 | OPCODE_JUMP, |
288 | OPCODE_JUMP_IF, |
289 | OPCODE_JUMP_IF_NOT, |
290 | OPCODE_JUMP_TO_DEF_ARGUMENT, |
291 | OPCODE_JUMP_IF_SHARED, |
292 | OPCODE_RETURN, |
293 | OPCODE_RETURN_TYPED_BUILTIN, |
294 | OPCODE_RETURN_TYPED_ARRAY, |
295 | OPCODE_RETURN_TYPED_NATIVE, |
296 | OPCODE_RETURN_TYPED_SCRIPT, |
297 | OPCODE_ITERATE_BEGIN, |
298 | OPCODE_ITERATE_BEGIN_INT, |
299 | OPCODE_ITERATE_BEGIN_FLOAT, |
300 | OPCODE_ITERATE_BEGIN_VECTOR2, |
301 | OPCODE_ITERATE_BEGIN_VECTOR2I, |
302 | OPCODE_ITERATE_BEGIN_VECTOR3, |
303 | OPCODE_ITERATE_BEGIN_VECTOR3I, |
304 | OPCODE_ITERATE_BEGIN_STRING, |
305 | OPCODE_ITERATE_BEGIN_DICTIONARY, |
306 | OPCODE_ITERATE_BEGIN_ARRAY, |
307 | OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY, |
308 | OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY, |
309 | OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY, |
310 | OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY, |
311 | OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY, |
312 | OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY, |
313 | OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, |
314 | OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, |
315 | OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY, |
316 | OPCODE_ITERATE_BEGIN_OBJECT, |
317 | OPCODE_ITERATE, |
318 | OPCODE_ITERATE_INT, |
319 | OPCODE_ITERATE_FLOAT, |
320 | OPCODE_ITERATE_VECTOR2, |
321 | OPCODE_ITERATE_VECTOR2I, |
322 | OPCODE_ITERATE_VECTOR3, |
323 | OPCODE_ITERATE_VECTOR3I, |
324 | OPCODE_ITERATE_STRING, |
325 | OPCODE_ITERATE_DICTIONARY, |
326 | OPCODE_ITERATE_ARRAY, |
327 | OPCODE_ITERATE_PACKED_BYTE_ARRAY, |
328 | OPCODE_ITERATE_PACKED_INT32_ARRAY, |
329 | OPCODE_ITERATE_PACKED_INT64_ARRAY, |
330 | OPCODE_ITERATE_PACKED_FLOAT32_ARRAY, |
331 | OPCODE_ITERATE_PACKED_FLOAT64_ARRAY, |
332 | OPCODE_ITERATE_PACKED_STRING_ARRAY, |
333 | OPCODE_ITERATE_PACKED_VECTOR2_ARRAY, |
334 | OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, |
335 | OPCODE_ITERATE_PACKED_COLOR_ARRAY, |
336 | OPCODE_ITERATE_OBJECT, |
337 | OPCODE_STORE_GLOBAL, |
338 | OPCODE_STORE_NAMED_GLOBAL, |
339 | OPCODE_TYPE_ADJUST_BOOL, |
340 | OPCODE_TYPE_ADJUST_INT, |
341 | OPCODE_TYPE_ADJUST_FLOAT, |
342 | OPCODE_TYPE_ADJUST_STRING, |
343 | OPCODE_TYPE_ADJUST_VECTOR2, |
344 | OPCODE_TYPE_ADJUST_VECTOR2I, |
345 | OPCODE_TYPE_ADJUST_RECT2, |
346 | OPCODE_TYPE_ADJUST_RECT2I, |
347 | OPCODE_TYPE_ADJUST_VECTOR3, |
348 | OPCODE_TYPE_ADJUST_VECTOR3I, |
349 | OPCODE_TYPE_ADJUST_TRANSFORM2D, |
350 | OPCODE_TYPE_ADJUST_VECTOR4, |
351 | OPCODE_TYPE_ADJUST_VECTOR4I, |
352 | OPCODE_TYPE_ADJUST_PLANE, |
353 | OPCODE_TYPE_ADJUST_QUATERNION, |
354 | OPCODE_TYPE_ADJUST_AABB, |
355 | OPCODE_TYPE_ADJUST_BASIS, |
356 | OPCODE_TYPE_ADJUST_TRANSFORM3D, |
357 | OPCODE_TYPE_ADJUST_PROJECTION, |
358 | OPCODE_TYPE_ADJUST_COLOR, |
359 | OPCODE_TYPE_ADJUST_STRING_NAME, |
360 | OPCODE_TYPE_ADJUST_NODE_PATH, |
361 | OPCODE_TYPE_ADJUST_RID, |
362 | OPCODE_TYPE_ADJUST_OBJECT, |
363 | OPCODE_TYPE_ADJUST_CALLABLE, |
364 | OPCODE_TYPE_ADJUST_SIGNAL, |
365 | OPCODE_TYPE_ADJUST_DICTIONARY, |
366 | OPCODE_TYPE_ADJUST_ARRAY, |
367 | OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, |
368 | OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, |
369 | OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, |
370 | OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, |
371 | OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, |
372 | OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, |
373 | OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, |
374 | OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, |
375 | OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, |
376 | OPCODE_ASSERT, |
377 | OPCODE_BREAKPOINT, |
378 | OPCODE_LINE, |
379 | OPCODE_END |
380 | }; |
381 | |
382 | enum Address { |
383 | ADDR_BITS = 24, |
384 | ADDR_MASK = ((1 << ADDR_BITS) - 1), |
385 | ADDR_TYPE_MASK = ~ADDR_MASK, |
386 | ADDR_TYPE_STACK = 0, |
387 | ADDR_TYPE_CONSTANT = 1, |
388 | ADDR_TYPE_MEMBER = 2, |
389 | ADDR_TYPE_MAX = 3, |
390 | }; |
391 | |
392 | enum FixedAddresses { |
393 | ADDR_STACK_SELF = 0, |
394 | ADDR_STACK_CLASS = 1, |
395 | ADDR_STACK_NIL = 2, |
396 | FIXED_ADDRESSES_MAX = 3, |
397 | ADDR_SELF = ADDR_STACK_SELF | (ADDR_TYPE_STACK << ADDR_BITS), |
398 | ADDR_CLASS = ADDR_STACK_CLASS | (ADDR_TYPE_STACK << ADDR_BITS), |
399 | ADDR_NIL = ADDR_STACK_NIL | (ADDR_TYPE_STACK << ADDR_BITS), |
400 | }; |
401 | |
402 | struct StackDebug { |
403 | int line; |
404 | int pos; |
405 | bool added; |
406 | StringName identifier; |
407 | }; |
408 | |
409 | private: |
410 | friend class GDScript; |
411 | friend class GDScriptCompiler; |
412 | friend class GDScriptByteCodeGenerator; |
413 | friend class GDScriptLanguage; |
414 | |
415 | StringName name; |
416 | StringName source; |
417 | bool _static = false; |
418 | Vector<GDScriptDataType> argument_types; |
419 | GDScriptDataType return_type; |
420 | MethodInfo method_info; |
421 | Variant rpc_config; |
422 | |
423 | GDScript *_script = nullptr; |
424 | int _initial_line = 0; |
425 | int _argument_count = 0; |
426 | int _stack_size = 0; |
427 | int _instruction_args_size = 0; |
428 | int _ptrcall_args_size = 0; |
429 | |
430 | SelfList<GDScriptFunction> function_list{ this }; |
431 | mutable Variant nil; |
432 | HashMap<int, Variant::Type> temporary_slots; |
433 | List<StackDebug> stack_debug; |
434 | |
435 | Vector<int> code; |
436 | Vector<int> default_arguments; |
437 | Vector<Variant> constants; |
438 | Vector<StringName> global_names; |
439 | Vector<Variant::ValidatedOperatorEvaluator> operator_funcs; |
440 | Vector<Variant::ValidatedSetter> setters; |
441 | Vector<Variant::ValidatedGetter> getters; |
442 | Vector<Variant::ValidatedKeyedSetter> keyed_setters; |
443 | Vector<Variant::ValidatedKeyedGetter> keyed_getters; |
444 | Vector<Variant::ValidatedIndexedSetter> indexed_setters; |
445 | Vector<Variant::ValidatedIndexedGetter> indexed_getters; |
446 | Vector<Variant::ValidatedBuiltInMethod> builtin_methods; |
447 | Vector<Variant::ValidatedConstructor> constructors; |
448 | Vector<Variant::ValidatedUtilityFunction> utilities; |
449 | Vector<GDScriptUtilityFunctions::FunctionPtr> gds_utilities; |
450 | Vector<MethodBind *> methods; |
451 | Vector<GDScriptFunction *> lambdas; |
452 | |
453 | int _code_size = 0; |
454 | int _default_arg_count = 0; |
455 | int _constant_count = 0; |
456 | int _global_names_count = 0; |
457 | int _operator_funcs_count = 0; |
458 | int _setters_count = 0; |
459 | int _getters_count = 0; |
460 | int _keyed_setters_count = 0; |
461 | int _keyed_getters_count = 0; |
462 | int _indexed_setters_count = 0; |
463 | int _indexed_getters_count = 0; |
464 | int _builtin_methods_count = 0; |
465 | int _constructors_count = 0; |
466 | int _utilities_count = 0; |
467 | int _gds_utilities_count = 0; |
468 | int _methods_count = 0; |
469 | int _lambdas_count = 0; |
470 | |
471 | int *_code_ptr = nullptr; |
472 | const int *_default_arg_ptr = nullptr; |
473 | mutable Variant *_constants_ptr = nullptr; |
474 | const StringName *_global_names_ptr = nullptr; |
475 | const Variant::ValidatedOperatorEvaluator *_operator_funcs_ptr = nullptr; |
476 | const Variant::ValidatedSetter *_setters_ptr = nullptr; |
477 | const Variant::ValidatedGetter *_getters_ptr = nullptr; |
478 | const Variant::ValidatedKeyedSetter *_keyed_setters_ptr = nullptr; |
479 | const Variant::ValidatedKeyedGetter *_keyed_getters_ptr = nullptr; |
480 | const Variant::ValidatedIndexedSetter *_indexed_setters_ptr = nullptr; |
481 | const Variant::ValidatedIndexedGetter *_indexed_getters_ptr = nullptr; |
482 | const Variant::ValidatedBuiltInMethod *_builtin_methods_ptr = nullptr; |
483 | const Variant::ValidatedConstructor *_constructors_ptr = nullptr; |
484 | const Variant::ValidatedUtilityFunction *_utilities_ptr = nullptr; |
485 | const GDScriptUtilityFunctions::FunctionPtr *_gds_utilities_ptr = nullptr; |
486 | MethodBind **_methods_ptr = nullptr; |
487 | GDScriptFunction **_lambdas_ptr = nullptr; |
488 | |
489 | #ifdef DEBUG_ENABLED |
490 | CharString func_cname; |
491 | const char *_func_cname = nullptr; |
492 | |
493 | Vector<String> operator_names; |
494 | Vector<String> setter_names; |
495 | Vector<String> getter_names; |
496 | Vector<String> builtin_methods_names; |
497 | Vector<String> constructors_names; |
498 | Vector<String> utilities_names; |
499 | Vector<String> gds_utilities_names; |
500 | |
501 | struct Profile { |
502 | StringName signature; |
503 | SafeNumeric<uint64_t> call_count; |
504 | SafeNumeric<uint64_t> self_time; |
505 | SafeNumeric<uint64_t> total_time; |
506 | SafeNumeric<uint64_t> frame_call_count; |
507 | SafeNumeric<uint64_t> frame_self_time; |
508 | SafeNumeric<uint64_t> frame_total_time; |
509 | uint64_t last_frame_call_count = 0; |
510 | uint64_t last_frame_self_time = 0; |
511 | uint64_t last_frame_total_time = 0; |
512 | } profile; |
513 | #endif |
514 | |
515 | _FORCE_INLINE_ String _get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const; |
516 | Variant _get_default_variant_for_data_type(const GDScriptDataType &p_data_type); |
517 | |
518 | public: |
519 | static constexpr int MAX_CALL_DEPTH = 2048; // Limit to try to avoid crash because of a stack overflow. |
520 | |
521 | struct CallState { |
522 | GDScript *script = nullptr; |
523 | GDScriptInstance *instance = nullptr; |
524 | #ifdef DEBUG_ENABLED |
525 | StringName function_name; |
526 | String script_path; |
527 | #endif |
528 | Vector<uint8_t> stack; |
529 | int stack_size = 0; |
530 | uint32_t alloca_size = 0; |
531 | int ip = 0; |
532 | int line = 0; |
533 | int defarg = 0; |
534 | Variant result; |
535 | }; |
536 | |
537 | _FORCE_INLINE_ StringName get_name() const { return name; } |
538 | _FORCE_INLINE_ StringName get_source() const { return source; } |
539 | _FORCE_INLINE_ GDScript *get_script() const { return _script; } |
540 | _FORCE_INLINE_ bool is_static() const { return _static; } |
541 | _FORCE_INLINE_ MethodInfo get_method_info() const { return method_info; } |
542 | _FORCE_INLINE_ Variant get_rpc_config() const { return rpc_config; } |
543 | _FORCE_INLINE_ int get_max_stack_size() const { return _stack_size; } |
544 | |
545 | Variant get_constant(int p_idx) const; |
546 | StringName get_global_name(int p_idx) const; |
547 | |
548 | Variant call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state = nullptr); |
549 | void debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const; |
550 | |
551 | #ifdef DEBUG_ENABLED |
552 | void disassemble(const Vector<String> &p_code_lines) const; |
553 | #endif |
554 | |
555 | GDScriptFunction(); |
556 | ~GDScriptFunction(); |
557 | }; |
558 | |
559 | class GDScriptFunctionState : public RefCounted { |
560 | GDCLASS(GDScriptFunctionState, RefCounted); |
561 | friend class GDScriptFunction; |
562 | GDScriptFunction *function = nullptr; |
563 | GDScriptFunction::CallState state; |
564 | Variant _signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error); |
565 | Ref<GDScriptFunctionState> first_state; |
566 | |
567 | SelfList<GDScriptFunctionState> scripts_list; |
568 | SelfList<GDScriptFunctionState> instances_list; |
569 | |
570 | protected: |
571 | static void _bind_methods(); |
572 | |
573 | public: |
574 | bool is_valid(bool p_extended_check = false) const; |
575 | Variant resume(const Variant &p_arg = Variant()); |
576 | |
577 | void _clear_stack(); |
578 | void _clear_connections(); |
579 | |
580 | GDScriptFunctionState(); |
581 | ~GDScriptFunctionState(); |
582 | }; |
583 | |
584 | #endif // GDSCRIPT_FUNCTION_H |
585 | |