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