1 /*************************************************************************/
2 /*  gd_script.h                                                          */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
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 #ifndef GD_SCRIPT_H
31 #define GD_SCRIPT_H
32 
33 #include "gd_function.h"
34 #include "io/resource_loader.h"
35 #include "io/resource_saver.h"
36 #include "script_language.h"
37 class GDNativeClass : public Reference {
38 
39 	OBJ_TYPE(GDNativeClass, Reference);
40 
41 	StringName name;
42 
43 protected:
44 	bool _get(const StringName &p_name, Variant &r_ret) const;
45 	static void _bind_methods();
46 
47 public:
get_name()48 	_FORCE_INLINE_ const StringName &get_name() const { return name; }
49 	Variant _new();
50 	Object *instance();
51 	GDNativeClass(const StringName &p_name);
52 };
53 
54 class GDScript : public Script {
55 
56 	OBJ_TYPE(GDScript, Script);
57 	bool tool;
58 	bool valid;
59 
60 	struct MemberInfo {
61 		int index;
62 		StringName setter;
63 		StringName getter;
64 	};
65 
66 	friend class GDInstance;
67 	friend class GDFunction;
68 	friend class GDCompiler;
69 	friend class GDFunctions;
70 	friend class GDScriptLanguage;
71 
72 	Variant _static_ref; //used for static call
73 	Ref<GDNativeClass> native;
74 	Ref<GDScript> base;
75 	GDScript *_base; //fast pointer access
76 	GDScript *_owner; //for subclasses
77 
78 	Set<StringName> members; //members are just indices to the instanced script.
79 	Map<StringName, Variant> constants;
80 	Map<StringName, GDFunction *> member_functions;
81 	Map<StringName, MemberInfo> member_indices; //members are just indices to the instanced script.
82 	Map<StringName, Ref<GDScript> > subclasses;
83 	Map<StringName, Vector<StringName> > _signals;
84 
85 #ifdef TOOLS_ENABLED
86 
87 	Map<StringName, Variant> member_default_values;
88 
89 	List<PropertyInfo> members_cache;
90 	Map<StringName, Variant> member_default_values_cache;
91 	Ref<GDScript> base_cache;
92 	Set<ObjectID> inheriters_cache;
93 	bool source_changed_cache;
94 	void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames);
95 
96 #endif
97 	Map<StringName, PropertyInfo> member_info;
98 
99 	GDFunction *initializer; //direct pointer to _init , faster to locate
100 
101 	int subclass_count;
102 	Set<Object *> instances;
103 	//exported members
104 	String source;
105 	String path;
106 	String name;
107 	SelfList<GDScript> script_list;
108 
109 	GDInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
110 
111 	void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path);
112 
113 #ifdef TOOLS_ENABLED
114 	Set<PlaceHolderScriptInstance *> placeholders;
115 	//void _update_placeholder(PlaceHolderScriptInstance *p_placeholder);
116 	virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder);
117 #endif
118 
119 #ifdef DEBUG_ENABLED
120 
121 	Map<ObjectID, List<Pair<StringName, Variant> > > pending_reload_state;
122 
123 #endif
124 
125 	bool _update_exports();
126 
127 protected:
128 	bool _get(const StringName &p_name, Variant &r_ret) const;
129 	bool _set(const StringName &p_name, const Variant &p_value);
130 	void _get_property_list(List<PropertyInfo> *p_properties) const;
131 
132 	Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
133 	//	void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount);
134 
135 	static void _bind_methods();
136 
137 public:
is_valid()138 	bool is_valid() const { return valid; }
139 
get_subclasses()140 	const Map<StringName, Ref<GDScript> > &get_subclasses() const { return subclasses; }
get_constants()141 	virtual const Map<StringName, Variant> &get_constants() const { return constants; }
get_members()142 	virtual const Set<StringName> &get_members() const { return members; }
get_member_functions()143 	const Map<StringName, GDFunction *> &get_member_functions() const { return member_functions; }
get_native()144 	const Ref<GDNativeClass> &get_native() const { return native; }
145 
146 	virtual bool has_script_signal(const StringName &p_signal) const;
147 	virtual void get_script_signal_list(List<MethodInfo> *r_signals) const;
148 
is_tool()149 	bool is_tool() const { return tool; }
150 	Ref<GDScript> get_base() const;
151 
debug_get_member_indices()152 	const Map<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; }
153 	const Map<StringName, GDFunction *> &debug_get_member_functions() const; //this is debug only
154 	StringName debug_get_member_by_index(int p_idx) const;
155 
156 	Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
157 	virtual bool can_instance() const;
158 
159 	virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so
160 	virtual ScriptInstance *instance_create(Object *p_this);
161 	virtual bool instance_has(const Object *p_this) const;
162 
163 	virtual bool has_source_code() const;
164 	virtual String get_source_code() const;
165 	virtual void set_source_code(const String &p_code);
166 	virtual void update_exports();
167 
168 	virtual Error reload(bool p_keep_state = false);
169 
170 	virtual String get_node_type() const;
set_script_path(const String & p_path)171 	void set_script_path(const String &p_path) { path = p_path; } //because subclasses need a path too...
172 	Error load_source_code(const String &p_path);
173 	Error load_byte_code(const String &p_path);
174 
175 	Vector<uint8_t> get_as_byte_code() const;
176 
177 	bool get_property_default_value(const StringName &p_property, Variant &r_value) const;
178 
179 	virtual ScriptLanguage *get_language() const;
180 
181 	GDScript();
182 	~GDScript();
183 };
184 
185 class GDInstance : public ScriptInstance {
186 	friend class GDScript;
187 	friend class GDFunction;
188 	friend class GDFunctions;
189 	friend class GDCompiler;
190 
191 	Object *owner;
192 	Ref<GDScript> script;
193 #ifdef DEBUG_ENABLED
194 	Map<StringName, int> member_indices_cache; //used only for hot script reloading
195 #endif
196 	Vector<Variant> members;
197 	bool base_ref;
198 
199 	void _ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount);
200 
201 public:
get_owner()202 	virtual Object *get_owner() { return owner; }
203 
204 	virtual bool set(const StringName &p_name, const Variant &p_value);
205 	virtual bool get(const StringName &p_name, Variant &r_ret) const;
206 	virtual void get_property_list(List<PropertyInfo> *p_properties) const;
207 	virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const;
208 
209 	virtual void get_method_list(List<MethodInfo> *p_list) const;
210 	virtual bool has_method(const StringName &p_method) const;
211 	virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
212 	virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
213 	virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
214 
debug_get_member_by_index(int p_idx)215 	Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
216 
217 	virtual void notification(int p_notification);
218 
219 	virtual Ref<Script> get_script() const;
220 
221 	virtual ScriptLanguage *get_language();
222 
223 	void set_path(const String &p_path);
224 
225 	void reload_members();
226 
227 	GDInstance();
228 	~GDInstance();
229 };
230 
231 class GDScriptLanguage : public ScriptLanguage {
232 
233 	static GDScriptLanguage *singleton;
234 
235 	Variant *_global_array;
236 	Vector<Variant> global_array;
237 	Map<StringName, int> globals;
238 
239 	struct CallLevel {
240 
241 		Variant *stack;
242 		GDFunction *function;
243 		GDInstance *instance;
244 		int *ip;
245 		int *line;
246 	};
247 
248 	int _debug_parse_err_line;
249 	String _debug_parse_err_file;
250 	String _debug_error;
251 	int _debug_call_stack_pos;
252 	int _debug_max_call_stack;
253 	CallLevel *_call_stack;
254 
255 	void _add_global(const StringName &p_name, const Variant &p_value);
256 
257 	Mutex *lock;
258 
259 	friend class GDScript;
260 
261 	SelfList<GDScript>::List script_list;
262 	friend class GDFunction;
263 
264 	SelfList<GDFunction>::List function_list;
265 	bool profiling;
266 	uint64_t script_frame_time;
267 
268 public:
269 	int calls;
270 
271 	bool debug_break(const String &p_error, bool p_allow_continue = true);
272 	bool debug_break_parse(const String &p_file, int p_line, const String &p_error);
273 
enter_function(GDInstance * p_instance,GDFunction * p_function,Variant * p_stack,int * p_ip,int * p_line)274 	_FORCE_INLINE_ void enter_function(GDInstance *p_instance, GDFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) {
275 
276 		if (Thread::get_main_ID() != Thread::get_caller_ID())
277 			return; //no support for other threads than main for now
278 
279 		if (ScriptDebugger::get_singleton()->get_lines_left() > 0 && ScriptDebugger::get_singleton()->get_depth() >= 0)
280 			ScriptDebugger::get_singleton()->set_depth(ScriptDebugger::get_singleton()->get_depth() + 1);
281 
282 		if (_debug_call_stack_pos >= _debug_max_call_stack) {
283 			//stack overflow
284 			_debug_error = "Stack Overflow (Stack Size: " + itos(_debug_max_call_stack) + ")";
285 			ScriptDebugger::get_singleton()->debug(this);
286 			return;
287 		}
288 
289 		_call_stack[_debug_call_stack_pos].stack = p_stack;
290 		_call_stack[_debug_call_stack_pos].instance = p_instance;
291 		_call_stack[_debug_call_stack_pos].function = p_function;
292 		_call_stack[_debug_call_stack_pos].ip = p_ip;
293 		_call_stack[_debug_call_stack_pos].line = p_line;
294 		_debug_call_stack_pos++;
295 	}
296 
exit_function()297 	_FORCE_INLINE_ void exit_function() {
298 
299 		if (Thread::get_main_ID() != Thread::get_caller_ID())
300 			return; //no support for other threads than main for now
301 
302 		if (ScriptDebugger::get_singleton()->get_lines_left() > 0 && ScriptDebugger::get_singleton()->get_depth() >= 0)
303 			ScriptDebugger::get_singleton()->set_depth(ScriptDebugger::get_singleton()->get_depth() - 1);
304 
305 		if (_debug_call_stack_pos == 0) {
306 
307 			_debug_error = "Stack Underflow (Engine Bug)";
308 			ScriptDebugger::get_singleton()->debug(this);
309 			return;
310 		}
311 
312 		_debug_call_stack_pos--;
313 	}
314 
debug_get_current_stack_info()315 	virtual Vector<StackInfo> debug_get_current_stack_info() {
316 		if (Thread::get_main_ID() != Thread::get_caller_ID())
317 			return Vector<StackInfo>();
318 
319 		Vector<StackInfo> csi;
320 		csi.resize(_debug_call_stack_pos);
321 		for (int i = 0; i < _debug_call_stack_pos; i++) {
322 			csi[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0;
323 			csi[_debug_call_stack_pos - i - 1].script = Ref<GDScript>(_call_stack[i].function->get_script());
324 		}
325 		return csi;
326 	}
327 
328 	struct {
329 
330 		StringName _init;
331 		StringName _notification;
332 		StringName _set;
333 		StringName _get;
334 		StringName _get_property_list;
335 		StringName _script_source;
336 
337 	} strings;
338 
get_global_array_size()339 	_FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); }
get_global_array()340 	_FORCE_INLINE_ Variant *get_global_array() { return _global_array; }
get_global_map()341 	_FORCE_INLINE_ const Map<StringName, int> &get_global_map() { return globals; }
342 
get_singleton()343 	_FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; }
344 
345 	virtual String get_name() const;
346 
347 	/* LANGUAGE FUNCTIONS */
348 	virtual void init();
349 	virtual String get_type() const;
350 	virtual String get_extension() const;
351 	virtual Error execute_file(const String &p_path);
352 	virtual void finish();
353 
354 	/* EDITOR FUNCTIONS */
355 	virtual void get_reserved_words(List<String> *p_words) const;
356 	virtual void get_comment_delimiters(List<String> *p_delimiters) const;
357 	virtual void get_string_delimiters(List<String> *p_delimiters) const;
358 	virtual String get_template(const String &p_class_name, const String &p_base_class_name) const;
359 	virtual String get_empty_template(const String &p_class_name, const String &p_base_class_name) const;
360 	virtual String get_nocomment_template(const String &p_class_name, const String &p_base_class_name) const;
361 	virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const;
362 	virtual Script *create_script() const;
363 	virtual bool has_named_classes() const;
364 	virtual int find_function(const String &p_function, const String &p_code) const;
365 	virtual String make_function(const String &p_class, const String &p_name, const StringArray &p_args) const;
366 	virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint);
367 	virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
368 	virtual void add_global_constant(const StringName &p_variable, const Variant &p_value);
369 
370 	/* DEBUGGER FUNCTIONS */
371 
372 	virtual String debug_get_error() const;
373 	virtual int debug_get_stack_level_count() const;
374 	virtual int debug_get_stack_level_line(int p_level) const;
375 	virtual String debug_get_stack_level_function(int p_level) const;
376 	virtual String debug_get_stack_level_source(int p_level) const;
377 	virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
378 	virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
379 	virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1);
380 	virtual ScriptInstance *debug_get_stack_level_instance(int p_level);
381 	virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1);
382 
383 	virtual void reload_all_scripts();
384 	virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload);
385 
386 	virtual void frame();
387 
388 	virtual void get_public_functions(List<MethodInfo> *p_functions) const;
389 	virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const;
390 
391 	virtual void profiling_start();
392 	virtual void profiling_stop();
393 
394 	virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max);
395 	virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max);
396 
397 	/* LOADER FUNCTIONS */
398 
399 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
400 
401 	GDScriptLanguage();
402 	~GDScriptLanguage();
403 };
404 
405 class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
406 public:
407 	virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
408 	virtual void get_recognized_extensions(List<String> *p_extensions) const;
409 	virtual bool handles_type(const String &p_type) const;
410 	virtual String get_resource_type(const String &p_path) const;
411 };
412 
413 class ResourceFormatSaverGDScript : public ResourceFormatSaver {
414 public:
415 	virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
416 	virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
417 	virtual bool recognize(const RES &p_resource) const;
418 };
419 
420 #endif // GD_SCRIPT_H
421