1 #ifndef GD_FUNCTION_H 2 #define GD_FUNCTION_H 3 4 #include "os/thread.h" 5 #include "pair.h" 6 #include "reference.h" 7 #include "self_list.h" 8 #include "string_db.h" 9 #include "variant.h" 10 11 class GDInstance; 12 class GDScript; 13 14 class GDFunction { 15 public: 16 enum Opcode { 17 OPCODE_OPERATOR, 18 OPCODE_EXTENDS_TEST, 19 OPCODE_SET, 20 OPCODE_GET, 21 OPCODE_SET_NAMED, 22 OPCODE_GET_NAMED, 23 OPCODE_ASSIGN, 24 OPCODE_ASSIGN_TRUE, 25 OPCODE_ASSIGN_FALSE, 26 OPCODE_CONSTRUCT, //only for basic types!! 27 OPCODE_CONSTRUCT_ARRAY, 28 OPCODE_CONSTRUCT_DICTIONARY, 29 OPCODE_CALL, 30 OPCODE_CALL_RETURN, 31 OPCODE_CALL_BUILT_IN, 32 OPCODE_CALL_SELF, 33 OPCODE_CALL_SELF_BASE, 34 OPCODE_YIELD, 35 OPCODE_YIELD_SIGNAL, 36 OPCODE_YIELD_RESUME, 37 OPCODE_JUMP, 38 OPCODE_JUMP_IF, 39 OPCODE_JUMP_IF_NOT, 40 OPCODE_JUMP_TO_DEF_ARGUMENT, 41 OPCODE_RETURN, 42 OPCODE_ITERATE_BEGIN, 43 OPCODE_ITERATE, 44 OPCODE_ASSERT, 45 OPCODE_BREAKPOINT, 46 OPCODE_LINE, 47 OPCODE_END 48 }; 49 50 enum Address { 51 ADDR_BITS = 24, 52 ADDR_MASK = ((1 << ADDR_BITS) - 1), 53 ADDR_TYPE_MASK = ~ADDR_MASK, 54 ADDR_TYPE_SELF = 0, 55 ADDR_TYPE_CLASS = 1, 56 ADDR_TYPE_MEMBER = 2, 57 ADDR_TYPE_CLASS_CONSTANT = 3, 58 ADDR_TYPE_LOCAL_CONSTANT = 4, 59 ADDR_TYPE_STACK = 5, 60 ADDR_TYPE_STACK_VARIABLE = 6, 61 ADDR_TYPE_GLOBAL = 7, 62 ADDR_TYPE_NIL = 8 63 }; 64 65 struct StackDebug { 66 67 int line; 68 int pos; 69 bool added; 70 StringName identifier; 71 }; 72 73 private: 74 friend class GDCompiler; 75 76 StringName source; 77 78 mutable Variant nil; 79 mutable Variant *_constants_ptr; 80 int _constant_count; 81 const StringName *_global_names_ptr; 82 int _global_names_count; 83 const int *_default_arg_ptr; 84 int _default_arg_count; 85 const int *_code_ptr; 86 int _code_size; 87 int _argument_count; 88 int _stack_size; 89 int _call_size; 90 int _initial_line; 91 bool _static; 92 GDScript *_script; 93 94 StringName name; 95 Vector<Variant> constants; 96 Vector<StringName> global_names; 97 Vector<int> default_arguments; 98 Vector<int> code; 99 100 #ifdef TOOLS_ENABLED 101 Vector<StringName> arg_names; 102 #endif 103 104 List<StackDebug> stack_debug; 105 106 _FORCE_INLINE_ Variant *_get_variant(int p_address, GDInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const; 107 _FORCE_INLINE_ String _get_call_error(const Variant::CallError &p_err, const String &p_where, const Variant **argptrs) const; 108 109 friend class GDScriptLanguage; 110 111 SelfList<GDFunction> function_list; 112 #ifdef DEBUG_ENABLED 113 CharString func_cname; 114 const char *_func_cname; 115 116 struct Profile { 117 StringName signature; 118 uint64_t call_count; 119 uint64_t self_time; 120 uint64_t total_time; 121 uint64_t frame_call_count; 122 uint64_t frame_self_time; 123 uint64_t frame_total_time; 124 uint64_t last_frame_call_count; 125 uint64_t last_frame_self_time; 126 uint64_t last_frame_total_time; 127 } profile; 128 129 #endif 130 131 public: 132 struct CallState { 133 134 ObjectID instance_id; //by debug only 135 ObjectID script_id; 136 137 GDInstance *instance; 138 Vector<uint8_t> stack; 139 int stack_size; 140 Variant self; 141 uint32_t alloca_size; 142 GDScript *_class; 143 int ip; 144 int line; 145 int defarg; 146 Variant result; 147 }; 148 is_static()149 _FORCE_INLINE_ bool is_static() const { return _static; } 150 151 const int *get_code() const; //used for debug 152 int get_code_size() const; 153 Variant get_constant(int p_idx) const; 154 StringName get_global_name(int p_idx) const; 155 StringName get_name() const; 156 int get_max_stack_size() const; 157 int get_default_argument_count() const; 158 int get_default_argument_addr(int p_idx) const; get_script()159 GDScript *get_script() const { return _script; } get_source()160 StringName get_source() const { return source; } 161 162 void debug_get_stack_member_state(int p_line, List<Pair<StringName, int> > *r_stackvars) const; 163 is_empty()164 _FORCE_INLINE_ bool is_empty() const { return _code_size == 0; } 165 get_argument_count()166 int get_argument_count() const { return _argument_count; } get_argument_name(int p_idx)167 StringName get_argument_name(int p_idx) const { 168 #ifdef TOOLS_ENABLED 169 ERR_FAIL_INDEX_V(p_idx, arg_names.size(), StringName()); 170 return arg_names[p_idx]; 171 #endif 172 return StringName(); 173 } get_default_argument(int p_idx)174 Variant get_default_argument(int p_idx) const { 175 ERR_FAIL_INDEX_V(p_idx, default_arguments.size(), Variant()); 176 return default_arguments[p_idx]; 177 } 178 179 Variant call(GDInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state = NULL); 180 181 GDFunction(); 182 ~GDFunction(); 183 }; 184 185 class GDFunctionState : public Reference { 186 187 OBJ_TYPE(GDFunctionState, Reference); 188 friend class GDFunction; 189 GDFunction *function; 190 GDFunction::CallState state; 191 Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error); 192 193 protected: 194 static void _bind_methods(); 195 196 public: 197 bool is_valid(bool p_extended_check = false) const; 198 Variant resume(const Variant &p_arg = Variant()); 199 GDFunctionState(); 200 ~GDFunctionState(); 201 }; 202 203 #endif // GD_FUNCTION_H 204