1 /*************************************************************************/
2 /*  gd_script.cpp                                                        */
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 #include "gd_script.h"
31 #include "gd_compiler.h"
32 #include "global_constants.h"
33 #include "globals.h"
34 #include "io/file_access_encrypted.h"
35 #include "os/file_access.h"
36 #include "os/os.h"
37 
38 ///////////////////////////
39 
GDNativeClass(const StringName & p_name)40 GDNativeClass::GDNativeClass(const StringName &p_name) {
41 
42 	name = p_name;
43 }
44 
45 /*void GDNativeClass::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount){
46 
47 
48 }*/
49 
_get(const StringName & p_name,Variant & r_ret) const50 bool GDNativeClass::_get(const StringName &p_name, Variant &r_ret) const {
51 
52 	bool ok;
53 	int v = ObjectTypeDB::get_integer_constant(name, p_name, &ok);
54 
55 	if (ok) {
56 		r_ret = v;
57 		return true;
58 	} else {
59 		return false;
60 	}
61 }
62 
_bind_methods()63 void GDNativeClass::_bind_methods() {
64 
65 	ObjectTypeDB::bind_method(_MD("new"), &GDNativeClass::_new);
66 }
67 
_new()68 Variant GDNativeClass::_new() {
69 
70 	Object *o = instance();
71 	if (!o) {
72 		ERR_EXPLAIN("Class type: '" + String(name) + "' is not instantiable.");
73 		ERR_FAIL_COND_V(!o, Variant());
74 	}
75 
76 	Reference *ref = o->cast_to<Reference>();
77 	if (ref) {
78 		return REF(ref);
79 	} else {
80 		return o;
81 	}
82 }
83 
instance()84 Object *GDNativeClass::instance() {
85 
86 	return ObjectTypeDB::instance(name);
87 }
88 
_create_instance(const Variant ** p_args,int p_argcount,Object * p_owner,bool p_isref,Variant::CallError & r_error)89 GDInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
90 
91 	/* STEP 1, CREATE */
92 
93 	GDInstance *instance = memnew(GDInstance);
94 	instance->base_ref = p_isref;
95 	instance->members.resize(member_indices.size());
96 	instance->script = Ref<GDScript>(this);
97 	instance->owner = p_owner;
98 #ifdef DEBUG_ENABLED
99 	//needed for hot reloading
100 	for (Map<StringName, MemberInfo>::Element *E = member_indices.front(); E; E = E->next()) {
101 		instance->member_indices_cache[E->key()] = E->get().index;
102 	}
103 #endif
104 	instance->owner->set_script_instance(instance);
105 
106 	/* STEP 2, INITIALIZE AND CONSRTUCT */
107 
108 	instances.insert(instance->owner);
109 
110 	initializer->call(instance, p_args, p_argcount, r_error);
111 
112 	if (r_error.error != Variant::CallError::CALL_OK) {
113 		instance->script = Ref<GDScript>();
114 		instance->owner->set_script_instance(NULL);
115 		instances.erase(p_owner);
116 		ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing
117 	}
118 
119 	//@TODO make thread safe
120 	return instance;
121 }
122 
_new(const Variant ** p_args,int p_argcount,Variant::CallError & r_error)123 Variant GDScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
124 
125 	/* STEP 1, CREATE */
126 
127 	if (!valid) {
128 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
129 		return Variant();
130 	}
131 
132 	r_error.error = Variant::CallError::CALL_OK;
133 	REF ref;
134 	Object *owner = NULL;
135 
136 	GDScript *_baseptr = this;
137 	while (_baseptr->_base) {
138 		_baseptr = _baseptr->_base;
139 	}
140 
141 	if (_baseptr->native.ptr()) {
142 		owner = _baseptr->native->instance();
143 	} else {
144 		owner = memnew(Reference); //by default, no base means use reference
145 	}
146 
147 	Reference *r = owner->cast_to<Reference>();
148 	if (r) {
149 		ref = REF(r);
150 	}
151 
152 	GDInstance *instance = _create_instance(p_args, p_argcount, owner, r != NULL, r_error);
153 	if (!instance) {
154 		if (ref.is_null()) {
155 			memdelete(owner); //no owner, sorry
156 		}
157 		return Variant();
158 	}
159 
160 	if (ref.is_valid()) {
161 		return ref;
162 	} else {
163 		return owner;
164 	}
165 }
166 
can_instance() const167 bool GDScript::can_instance() const {
168 
169 	//return valid; //any script in GDscript can instance
170 	return valid || (!tool && !ScriptServer::is_scripting_enabled());
171 }
172 
get_instance_base_type() const173 StringName GDScript::get_instance_base_type() const {
174 
175 	if (native.is_valid())
176 		return native->get_name();
177 	if (base.is_valid())
178 		return base->get_instance_base_type();
179 	return StringName();
180 }
181 
182 struct _GDScriptMemberSort {
183 
184 	int index;
185 	StringName name;
operator <_GDScriptMemberSort186 	_FORCE_INLINE_ bool operator<(const _GDScriptMemberSort &p_member) const { return index < p_member.index; }
187 };
188 
189 #ifdef TOOLS_ENABLED
190 
_placeholder_erased(PlaceHolderScriptInstance * p_placeholder)191 void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
192 
193 	placeholders.erase(p_placeholder);
194 }
195 
196 /*
197 void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {
198 
199 
200 	List<PropertyInfo> plist;
201 	GDScript *scr=this;
202 
203 	Map<StringName,Variant> default_values;
204 	while(scr) {
205 
206 		Vector<_GDScriptMemberSort> msort;
207 		for(Map<StringName,PropertyInfo>::Element *E=scr->member_info.front();E;E=E->next()) {
208 
209 			_GDScriptMemberSort ms;
210 			ERR_CONTINUE(!scr->member_indices.has(E->key()));
211 			ms.index=scr->member_indices[E->key()].index;
212 			ms.name=E->key();
213 
214 			msort.push_back(ms);
215 
216 		}
217 
218 		msort.sort();
219 		msort.invert();
220 		for(int i=0;i<msort.size();i++) {
221 
222 			plist.push_front(scr->member_info[msort[i].name]);
223 			if (scr->member_default_values.has(msort[i].name))
224 				default_values[msort[i].name]=scr->member_default_values[msort[i].name];
225 			else {
226 				Variant::CallError err;
227 				default_values[msort[i].name]=Variant::construct(scr->member_info[msort[i].name].type,NULL,0,err);
228 			}
229 		}
230 
231 		scr=scr->_base;
232 	}
233 
234 
235 	p_placeholder->update(plist,default_values);
236 
237 }*/
238 #endif
239 
get_property_default_value(const StringName & p_property,Variant & r_value) const240 bool GDScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
241 
242 #ifdef TOOLS_ENABLED
243 
244 	//for (const Map<StringName,Variant>::Element *I=member_default_values.front();I;I=I->next()) {
245 	//	print_line("\t"+String(String(I->key())+":"+String(I->get())));
246 	//}
247 	const Map<StringName, Variant>::Element *E = member_default_values_cache.find(p_property);
248 	if (E) {
249 		r_value = E->get();
250 		return true;
251 	}
252 
253 	if (base_cache.is_valid()) {
254 		return base_cache->get_property_default_value(p_property, r_value);
255 	}
256 #endif
257 	return false;
258 }
259 
instance_create(Object * p_this)260 ScriptInstance *GDScript::instance_create(Object *p_this) {
261 
262 	if (!tool && !ScriptServer::is_scripting_enabled()) {
263 
264 #ifdef TOOLS_ENABLED
265 
266 		//instance a fake script for editing the values
267 		//plist.invert();
268 
269 		/*print_line("CREATING PLACEHOLDER");
270 		for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
271 			print_line(E->get().name);
272 		}*/
273 		PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(GDScriptLanguage::get_singleton(), Ref<Script>(this), p_this));
274 		placeholders.insert(si);
275 		//_update_placeholder(si);
276 		_update_exports();
277 		return si;
278 #else
279 		return NULL;
280 #endif
281 	}
282 
283 	GDScript *top = this;
284 	while (top->_base)
285 		top = top->_base;
286 
287 	if (top->native.is_valid()) {
288 		if (!ObjectTypeDB::is_type(p_this->get_type_name(), top->native->get_name())) {
289 
290 			if (ScriptDebugger::get_singleton()) {
291 				GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), 0, "Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type: '" + p_this->get_type() + "'");
292 			}
293 			ERR_EXPLAIN("Script inherits from native type '" + String(top->native->get_name()) + "', so it can't be instanced in object of type: '" + p_this->get_type() + "'");
294 			ERR_FAIL_V(NULL);
295 		}
296 	}
297 
298 	Variant::CallError unchecked_error;
299 	return _create_instance(NULL, 0, p_this, p_this->cast_to<Reference>(), unchecked_error);
300 }
instance_has(const Object * p_this) const301 bool GDScript::instance_has(const Object *p_this) const {
302 
303 	return instances.has((Object *)p_this);
304 }
305 
has_source_code() const306 bool GDScript::has_source_code() const {
307 
308 	return source != "";
309 }
get_source_code() const310 String GDScript::get_source_code() const {
311 
312 	return source;
313 }
set_source_code(const String & p_code)314 void GDScript::set_source_code(const String &p_code) {
315 
316 	if (source == p_code)
317 		return;
318 	source = p_code;
319 #ifdef TOOLS_ENABLED
320 	source_changed_cache = true;
321 //print_line("SC CHANGED "+get_path());
322 #endif
323 }
324 
325 #ifdef TOOLS_ENABLED
_update_exports_values(Map<StringName,Variant> & values,List<PropertyInfo> & propnames)326 void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) {
327 
328 	if (base_cache.is_valid()) {
329 		base_cache->_update_exports_values(values, propnames);
330 	}
331 
332 	for (Map<StringName, Variant>::Element *E = member_default_values_cache.front(); E; E = E->next()) {
333 		values[E->key()] = E->get();
334 	}
335 
336 	for (List<PropertyInfo>::Element *E = members_cache.front(); E; E = E->next()) {
337 		propnames.push_back(E->get());
338 	}
339 }
340 #endif
341 
_update_exports()342 bool GDScript::_update_exports() {
343 
344 #ifdef TOOLS_ENABLED
345 
346 	bool changed = false;
347 
348 	if (source_changed_cache) {
349 		//print_line("updating source for "+get_path());
350 		source_changed_cache = false;
351 		changed = true;
352 
353 		String basedir = path;
354 
355 		if (basedir == "")
356 			basedir = get_path();
357 
358 		if (basedir != "")
359 			basedir = basedir.get_base_dir();
360 
361 		GDParser parser;
362 		Error err = parser.parse(source, basedir, true, path);
363 
364 		if (err == OK) {
365 
366 			const GDParser::Node *root = parser.get_parse_tree();
367 			ERR_FAIL_COND_V(root->type != GDParser::Node::TYPE_CLASS, false);
368 
369 			const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode *>(root);
370 
371 			if (base_cache.is_valid()) {
372 				base_cache->inheriters_cache.erase(get_instance_ID());
373 				base_cache = Ref<GDScript>();
374 			}
375 
376 			if (c->extends_used && String(c->extends_file) != "" && String(c->extends_file) != get_path()) {
377 
378 				String path = c->extends_file;
379 				if (path.is_rel_path()) {
380 
381 					String base = get_path();
382 					if (base == "" || base.is_rel_path()) {
383 
384 						ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data());
385 					} else {
386 						path = base.get_base_dir().plus_file(path);
387 					}
388 				}
389 
390 				if (path != get_path()) {
391 
392 					Ref<GDScript> bf = ResourceLoader::load(path);
393 
394 					if (bf.is_valid()) {
395 
396 						//print_line("parent is: "+bf->get_path());
397 						base_cache = bf;
398 						bf->inheriters_cache.insert(get_instance_ID());
399 
400 						//bf->_update_exports(p_instances,true,false);
401 					}
402 				} else {
403 					ERR_PRINT(("Path extending itself in  " + path).utf8().get_data());
404 				}
405 			}
406 
407 			members_cache.clear();
408 			member_default_values_cache.clear();
409 
410 			for (int i = 0; i < c->variables.size(); i++) {
411 				if (c->variables[i]._export.type == Variant::NIL)
412 					continue;
413 
414 				members_cache.push_back(c->variables[i]._export);
415 				//print_line("found "+c->variables[i]._export.name);
416 				member_default_values_cache[c->variables[i].identifier] = c->variables[i].default_value;
417 			}
418 
419 			_signals.clear();
420 
421 			for (int i = 0; i < c->_signals.size(); i++) {
422 				_signals[c->_signals[i].name] = c->_signals[i].arguments;
423 			}
424 		}
425 	} else {
426 		//print_line("unchaged is "+get_path());
427 	}
428 
429 	if (base_cache.is_valid()) {
430 		if (base_cache->_update_exports()) {
431 			changed = true;
432 		}
433 	}
434 
435 	if (/*changed &&*/ placeholders.size()) { //hm :(
436 
437 		//print_line("updating placeholders for "+get_path());
438 
439 		//update placeholders if any
440 		Map<StringName, Variant> values;
441 		List<PropertyInfo> propnames;
442 		_update_exports_values(values, propnames);
443 
444 		for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
445 
446 			E->get()->update(propnames, values);
447 		}
448 	}
449 
450 	return changed;
451 
452 #endif
453 	return false;
454 }
455 
update_exports()456 void GDScript::update_exports() {
457 
458 #ifdef TOOLS_ENABLED
459 
460 	_update_exports();
461 
462 	Set<ObjectID> copy = inheriters_cache; //might get modified
463 
464 	//print_line("update exports for "+get_path()+" ic: "+itos(copy.size()));
465 	for (Set<ObjectID>::Element *E = copy.front(); E; E = E->next()) {
466 		Object *id = ObjectDB::get_instance(E->get());
467 		if (!id)
468 			continue;
469 		GDScript *s = id->cast_to<GDScript>();
470 		if (!s)
471 			continue;
472 		s->update_exports();
473 	}
474 
475 #endif
476 }
477 
_set_subclass_path(Ref<GDScript> & p_sc,const String & p_path)478 void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) {
479 
480 	p_sc->path = p_path;
481 	for (Map<StringName, Ref<GDScript> >::Element *E = p_sc->subclasses.front(); E; E = E->next()) {
482 
483 		_set_subclass_path(E->get(), p_path);
484 	}
485 }
486 
reload(bool p_keep_state)487 Error GDScript::reload(bool p_keep_state) {
488 
489 	ERR_FAIL_COND_V(!p_keep_state && instances.size(), ERR_ALREADY_IN_USE);
490 
491 	String basedir = path;
492 
493 	if (basedir == "")
494 		basedir = get_path();
495 
496 	if (basedir != "")
497 		basedir = basedir.get_base_dir();
498 
499 	valid = false;
500 	GDParser parser;
501 	Error err = parser.parse(source, basedir, false, path);
502 	if (err) {
503 		if (ScriptDebugger::get_singleton()) {
504 			GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), parser.get_error_line(), "Parser Error: " + parser.get_error());
505 		}
506 		_err_print_error("GDScript::reload", path.empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_error_line(), ("Parse Error: " + parser.get_error()).utf8().get_data(), ERR_HANDLER_SCRIPT);
507 		ERR_FAIL_V(ERR_PARSE_ERROR);
508 	}
509 
510 	bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool_script();
511 
512 	GDCompiler compiler;
513 	err = compiler.compile(&parser, this, p_keep_state);
514 
515 	if (err) {
516 
517 		if (can_run) {
518 			if (ScriptDebugger::get_singleton()) {
519 				GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error());
520 			}
521 			_err_print_error("GDScript::reload", path.empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), ERR_HANDLER_SCRIPT);
522 			ERR_FAIL_V(ERR_COMPILATION_FAILED);
523 		} else {
524 			return err;
525 		}
526 	}
527 
528 	valid = true;
529 
530 	for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front(); E; E = E->next()) {
531 
532 		_set_subclass_path(E->get(), path);
533 	}
534 
535 #ifdef TOOLS_ENABLED
536 /*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {
537 
538 		_update_placeholder(E->get());
539 	}*/
540 #endif
541 	return OK;
542 }
543 
get_node_type() const544 String GDScript::get_node_type() const {
545 
546 	return ""; // ?
547 }
548 
get_language() const549 ScriptLanguage *GDScript::get_language() const {
550 
551 	return GDScriptLanguage::get_singleton();
552 }
553 
call(const StringName & p_method,const Variant ** p_args,int p_argcount,Variant::CallError & r_error)554 Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
555 
556 	GDScript *top = this;
557 	while (top) {
558 
559 		Map<StringName, GDFunction *>::Element *E = top->member_functions.find(p_method);
560 		if (E) {
561 
562 			if (!E->get()->is_static()) {
563 				WARN_PRINT(String("Can't call non-static function: '" + String(p_method) + "' in script.").utf8().get_data());
564 			}
565 
566 			return E->get()->call(NULL, p_args, p_argcount, r_error);
567 		}
568 		top = top->_base;
569 	}
570 
571 	//none found, regular
572 
573 	return Script::call(p_method, p_args, p_argcount, r_error);
574 }
575 
_get(const StringName & p_name,Variant & r_ret) const576 bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
577 
578 	{
579 
580 		const GDScript *top = this;
581 		while (top) {
582 
583 			{
584 				const Map<StringName, Variant>::Element *E = top->constants.find(p_name);
585 				if (E) {
586 
587 					r_ret = E->get();
588 					return true;
589 				}
590 			}
591 
592 			{
593 				const Map<StringName, Ref<GDScript> >::Element *E = subclasses.find(p_name);
594 				if (E) {
595 
596 					r_ret = E->get();
597 					return true;
598 				}
599 			}
600 			top = top->_base;
601 		}
602 
603 		if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) {
604 
605 			r_ret = get_source_code();
606 			return true;
607 		}
608 	}
609 
610 	return false;
611 }
_set(const StringName & p_name,const Variant & p_value)612 bool GDScript::_set(const StringName &p_name, const Variant &p_value) {
613 
614 	if (p_name == GDScriptLanguage::get_singleton()->strings._script_source) {
615 
616 		set_source_code(p_value);
617 		reload();
618 	} else
619 		return false;
620 
621 	return true;
622 }
623 
_get_property_list(List<PropertyInfo> * p_properties) const624 void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const {
625 
626 	p_properties->push_back(PropertyInfo(Variant::STRING, "script/source", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
627 }
628 
_bind_methods()629 void GDScript::_bind_methods() {
630 
631 	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT, "new", &GDScript::_new, MethodInfo("new"));
632 
633 	ObjectTypeDB::bind_method(_MD("get_as_byte_code"), &GDScript::get_as_byte_code);
634 }
635 
get_as_byte_code() const636 Vector<uint8_t> GDScript::get_as_byte_code() const {
637 
638 	GDTokenizerBuffer tokenizer;
639 	return tokenizer.parse_code_string(source);
640 };
641 
load_byte_code(const String & p_path)642 Error GDScript::load_byte_code(const String &p_path) {
643 
644 	Vector<uint8_t> bytecode;
645 
646 	if (p_path.ends_with("gde")) {
647 
648 		FileAccess *fa = FileAccess::open(p_path, FileAccess::READ);
649 		ERR_FAIL_COND_V(!fa, ERR_CANT_OPEN);
650 		FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
651 		ERR_FAIL_COND_V(!fae, ERR_CANT_OPEN);
652 		Vector<uint8_t> key;
653 		key.resize(32);
654 		for (int i = 0; i < key.size(); i++) {
655 			key[i] = script_encryption_key[i];
656 		}
657 		Error err = fae->open_and_parse(fa, key, FileAccessEncrypted::MODE_READ);
658 		ERR_FAIL_COND_V(err, err);
659 		bytecode.resize(fae->get_len());
660 		fae->get_buffer(bytecode.ptr(), bytecode.size());
661 		memdelete(fae);
662 	} else {
663 
664 		bytecode = FileAccess::get_file_as_array(p_path);
665 	}
666 	ERR_FAIL_COND_V(bytecode.size() == 0, ERR_PARSE_ERROR);
667 	path = p_path;
668 
669 	String basedir = path;
670 
671 	if (basedir == "")
672 		basedir = get_path();
673 
674 	if (basedir != "")
675 		basedir = basedir.get_base_dir();
676 
677 	valid = false;
678 	GDParser parser;
679 	Error err = parser.parse_bytecode(bytecode, basedir, get_path());
680 	if (err) {
681 		_err_print_error("GDScript::load_byte_code", path.empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_error_line(), ("Parse Error: " + parser.get_error()).utf8().get_data(), ERR_HANDLER_SCRIPT);
682 		ERR_FAIL_V(ERR_PARSE_ERROR);
683 	}
684 
685 	GDCompiler compiler;
686 	err = compiler.compile(&parser, this);
687 
688 	if (err) {
689 		_err_print_error("GDScript::load_byte_code", path.empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), ERR_HANDLER_SCRIPT);
690 		ERR_FAIL_V(ERR_COMPILATION_FAILED);
691 	}
692 
693 	valid = true;
694 
695 	for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front(); E; E = E->next()) {
696 
697 		_set_subclass_path(E->get(), path);
698 	}
699 
700 	return OK;
701 }
702 
load_source_code(const String & p_path)703 Error GDScript::load_source_code(const String &p_path) {
704 
705 	DVector<uint8_t> sourcef;
706 	Error err;
707 	FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
708 	if (err) {
709 
710 		ERR_FAIL_COND_V(err, err);
711 	}
712 
713 	int len = f->get_len();
714 	sourcef.resize(len + 1);
715 	DVector<uint8_t>::Write w = sourcef.write();
716 	int r = f->get_buffer(w.ptr(), len);
717 	f->close();
718 	memdelete(f);
719 	ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
720 	w[len] = 0;
721 
722 	String s;
723 	if (s.parse_utf8((const char *)w.ptr())) {
724 
725 		ERR_EXPLAIN("Script '" + p_path + "' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode.");
726 		ERR_FAIL_V(ERR_INVALID_DATA);
727 	}
728 
729 	source = s;
730 #ifdef TOOLS_ENABLED
731 	source_changed_cache = true;
732 #endif
733 	//print_line("LSC :"+get_path());
734 	path = p_path;
735 	return OK;
736 }
737 
debug_get_member_functions() const738 const Map<StringName, GDFunction *> &GDScript::debug_get_member_functions() const {
739 
740 	return member_functions;
741 }
742 
debug_get_member_by_index(int p_idx) const743 StringName GDScript::debug_get_member_by_index(int p_idx) const {
744 
745 	for (const Map<StringName, MemberInfo>::Element *E = member_indices.front(); E; E = E->next()) {
746 
747 		if (E->get().index == p_idx)
748 			return E->key();
749 	}
750 
751 	return "<error>";
752 }
753 
get_base() const754 Ref<GDScript> GDScript::get_base() const {
755 
756 	return base;
757 }
758 
has_script_signal(const StringName & p_signal) const759 bool GDScript::has_script_signal(const StringName &p_signal) const {
760 	if (_signals.has(p_signal))
761 		return true;
762 	if (base.is_valid()) {
763 		return base->has_script_signal(p_signal);
764 	}
765 #ifdef TOOLS_ENABLED
766 	else if (base_cache.is_valid()) {
767 		return base_cache->has_script_signal(p_signal);
768 	}
769 
770 #endif
771 	return false;
772 }
get_script_signal_list(List<MethodInfo> * r_signals) const773 void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
774 
775 	for (const Map<StringName, Vector<StringName> >::Element *E = _signals.front(); E; E = E->next()) {
776 
777 		MethodInfo mi;
778 		mi.name = E->key();
779 		for (int i = 0; i < E->get().size(); i++) {
780 			PropertyInfo arg;
781 			arg.name = E->get()[i];
782 			mi.arguments.push_back(arg);
783 		}
784 		r_signals->push_back(mi);
785 	}
786 
787 	if (base.is_valid()) {
788 		base->get_script_signal_list(r_signals);
789 	}
790 #ifdef TOOLS_ENABLED
791 	else if (base_cache.is_valid()) {
792 		base_cache->get_script_signal_list(r_signals);
793 	}
794 
795 #endif
796 }
797 
GDScript()798 GDScript::GDScript() :
799 		script_list(this) {
800 
801 	_static_ref = this;
802 	valid = false;
803 	subclass_count = 0;
804 	initializer = NULL;
805 	_base = NULL;
806 	_owner = NULL;
807 	tool = false;
808 #ifdef TOOLS_ENABLED
809 	source_changed_cache = false;
810 #endif
811 
812 #ifdef DEBUG_ENABLED
813 	if (GDScriptLanguage::get_singleton()->lock) {
814 		GDScriptLanguage::get_singleton()->lock->lock();
815 	}
816 	GDScriptLanguage::get_singleton()->script_list.add(&script_list);
817 
818 	if (GDScriptLanguage::get_singleton()->lock) {
819 		GDScriptLanguage::get_singleton()->lock->unlock();
820 	}
821 #endif
822 }
823 
~GDScript()824 GDScript::~GDScript() {
825 	for (Map<StringName, GDFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
826 		memdelete(E->get());
827 	}
828 
829 	for (Map<StringName, Ref<GDScript> >::Element *E = subclasses.front(); E; E = E->next()) {
830 		E->get()->_owner = NULL; //bye, you are no longer owned cause I died
831 	}
832 
833 #ifdef DEBUG_ENABLED
834 	if (GDScriptLanguage::get_singleton()->lock) {
835 		GDScriptLanguage::get_singleton()->lock->lock();
836 	}
837 	GDScriptLanguage::get_singleton()->script_list.remove(&script_list);
838 
839 	if (GDScriptLanguage::get_singleton()->lock) {
840 		GDScriptLanguage::get_singleton()->lock->unlock();
841 	}
842 #endif
843 }
844 
845 //////////////////////////////
846 //         INSTANCE         //
847 //////////////////////////////
848 
set(const StringName & p_name,const Variant & p_value)849 bool GDInstance::set(const StringName &p_name, const Variant &p_value) {
850 
851 	//member
852 	{
853 		const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);
854 		if (E) {
855 			if (E->get().setter) {
856 				const Variant *val = &p_value;
857 				Variant::CallError err;
858 				call(E->get().setter, &val, 1, err);
859 				if (err.error == Variant::CallError::CALL_OK) {
860 					return true; //function exists, call was successful
861 				}
862 			} else
863 				members[E->get().index] = p_value;
864 			return true;
865 		}
866 	}
867 
868 	GDScript *sptr = script.ptr();
869 	while (sptr) {
870 
871 		Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);
872 		if (E) {
873 
874 			Variant name = p_name;
875 			const Variant *args[2] = { &name, &p_value };
876 
877 			Variant::CallError err;
878 			Variant ret = E->get()->call(this, (const Variant **)args, 2, err);
879 			if (err.error == Variant::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool())
880 				return true;
881 		}
882 		sptr = sptr->_base;
883 	}
884 
885 	return false;
886 }
887 
get(const StringName & p_name,Variant & r_ret) const888 bool GDInstance::get(const StringName &p_name, Variant &r_ret) const {
889 
890 	const GDScript *sptr = script.ptr();
891 	while (sptr) {
892 
893 		{
894 			const Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);
895 			if (E) {
896 				if (E->get().getter) {
897 					Variant::CallError err;
898 					r_ret = const_cast<GDInstance *>(this)->call(E->get().getter, NULL, 0, err);
899 					if (err.error == Variant::CallError::CALL_OK) {
900 						return true;
901 					}
902 				}
903 				r_ret = members[E->get().index];
904 				return true; //index found
905 			}
906 		}
907 
908 		{
909 
910 			const GDScript *sl = sptr;
911 			while (sl) {
912 				const Map<StringName, Variant>::Element *E = sl->constants.find(p_name);
913 				if (E) {
914 					r_ret = E->get();
915 					return true; //index found
916 				}
917 				sl = sl->_base;
918 			}
919 		}
920 
921 		{
922 			const Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);
923 			if (E) {
924 
925 				Variant name = p_name;
926 				const Variant *args[1] = { &name };
927 
928 				Variant::CallError err;
929 				Variant ret = const_cast<GDFunction *>(E->get())->call(const_cast<GDInstance *>(this), (const Variant **)args, 1, err);
930 				if (err.error == Variant::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
931 					r_ret = ret;
932 					return true;
933 				}
934 			}
935 		}
936 		sptr = sptr->_base;
937 	}
938 
939 	return false;
940 }
941 
get_property_type(const StringName & p_name,bool * r_is_valid) const942 Variant::Type GDInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
943 
944 	const GDScript *sptr = script.ptr();
945 	while (sptr) {
946 
947 		if (sptr->member_info.has(p_name)) {
948 			if (r_is_valid)
949 				*r_is_valid = true;
950 			return sptr->member_info[p_name].type;
951 		}
952 		sptr = sptr->_base;
953 	}
954 
955 	if (r_is_valid)
956 		*r_is_valid = false;
957 	return Variant::NIL;
958 }
959 
get_property_list(List<PropertyInfo> * p_properties) const960 void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
961 	// exported members, not doen yet!
962 
963 	const GDScript *sptr = script.ptr();
964 	List<PropertyInfo> props;
965 
966 	while (sptr) {
967 
968 		const Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);
969 		if (E) {
970 
971 			Variant::CallError err;
972 			Variant ret = const_cast<GDFunction *>(E->get())->call(const_cast<GDInstance *>(this), NULL, 0, err);
973 			if (err.error == Variant::CallError::CALL_OK) {
974 
975 				if (ret.get_type() != Variant::ARRAY) {
976 
977 					ERR_EXPLAIN("Wrong type for _get_property list, must be an array of dictionaries.");
978 					ERR_FAIL();
979 				}
980 				Array arr = ret;
981 				for (int i = 0; i < arr.size(); i++) {
982 
983 					Dictionary d = arr[i];
984 					ERR_CONTINUE(!d.has("name"));
985 					ERR_CONTINUE(!d.has("type"));
986 					PropertyInfo pinfo;
987 					pinfo.type = Variant::Type(d["type"].operator int());
988 					ERR_CONTINUE(pinfo.type < 0 || pinfo.type >= Variant::VARIANT_MAX);
989 					pinfo.name = d["name"];
990 					ERR_CONTINUE(pinfo.name == "");
991 					if (d.has("hint"))
992 						pinfo.hint = PropertyHint(d["hint"].operator int());
993 					if (d.has("hint_string"))
994 						pinfo.hint_string = d["hint_string"];
995 					if (d.has("usage"))
996 						pinfo.usage = d["usage"];
997 
998 					props.push_back(pinfo);
999 				}
1000 			}
1001 		}
1002 
1003 		//instance a fake script for editing the values
1004 
1005 		Vector<_GDScriptMemberSort> msort;
1006 		for (Map<StringName, PropertyInfo>::Element *E = sptr->member_info.front(); E; E = E->next()) {
1007 
1008 			_GDScriptMemberSort ms;
1009 			ERR_CONTINUE(!sptr->member_indices.has(E->key()));
1010 			ms.index = sptr->member_indices[E->key()].index;
1011 			ms.name = E->key();
1012 			msort.push_back(ms);
1013 		}
1014 
1015 		msort.sort();
1016 		msort.invert();
1017 		for (int i = 0; i < msort.size(); i++) {
1018 
1019 			props.push_front(sptr->member_info[msort[i].name]);
1020 		}
1021 #if 0
1022 		if (sptr->member_functions.has("_get_property_list")) {
1023 
1024 			Variant::CallError err;
1025 			GDFunction *f = const_cast<GDFunction*>(sptr->member_functions["_get_property_list"]);
1026 			Variant plv = f->call(const_cast<GDInstance*>(this),NULL,0,err);
1027 
1028 			if (plv.get_type()!=Variant::ARRAY) {
1029 
1030 				ERR_PRINT("_get_property_list: expected array returned");
1031 			} else {
1032 
1033 				Array pl=plv;
1034 
1035 				for(int i=0;i<pl.size();i++) {
1036 
1037 					Dictionary p = pl[i];
1038 					PropertyInfo pinfo;
1039 					if (!p.has("name")) {
1040 						ERR_PRINT("_get_property_list: expected 'name' key of type string.")
1041 								continue;
1042 					}
1043 					if (!p.has("type")) {
1044 						ERR_PRINT("_get_property_list: expected 'type' key of type integer.")
1045 								continue;
1046 					}
1047 					pinfo.name=p["name"];
1048 					pinfo.type=Variant::Type(int(p["type"]));
1049 					if (p.has("hint"))
1050 						pinfo.hint=PropertyHint(int(p["hint"]));
1051 					if (p.has("hint_string"))
1052 						pinfo.hint_string=p["hint_string"];
1053 					if (p.has("usage"))
1054 						pinfo.usage=p["usage"];
1055 
1056 
1057 					props.push_back(pinfo);
1058 				}
1059 			}
1060 		}
1061 #endif
1062 
1063 		sptr = sptr->_base;
1064 	}
1065 
1066 	//props.invert();
1067 
1068 	for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
1069 
1070 		p_properties->push_back(E->get());
1071 	}
1072 }
1073 
get_method_list(List<MethodInfo> * p_list) const1074 void GDInstance::get_method_list(List<MethodInfo> *p_list) const {
1075 
1076 	const GDScript *sptr = script.ptr();
1077 	while (sptr) {
1078 
1079 		for (Map<StringName, GDFunction *>::Element *E = sptr->member_functions.front(); E; E = E->next()) {
1080 
1081 			MethodInfo mi;
1082 			mi.name = E->key();
1083 			mi.flags |= METHOD_FLAG_FROM_SCRIPT;
1084 			for (int i = 0; i < E->get()->get_argument_count(); i++)
1085 				mi.arguments.push_back(PropertyInfo(Variant::NIL, "arg" + itos(i)));
1086 			p_list->push_back(mi);
1087 		}
1088 		sptr = sptr->_base;
1089 	}
1090 }
1091 
has_method(const StringName & p_method) const1092 bool GDInstance::has_method(const StringName &p_method) const {
1093 
1094 	const GDScript *sptr = script.ptr();
1095 	while (sptr) {
1096 		const Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
1097 		if (E)
1098 			return true;
1099 		sptr = sptr->_base;
1100 	}
1101 
1102 	return false;
1103 }
call(const StringName & p_method,const Variant ** p_args,int p_argcount,Variant::CallError & r_error)1104 Variant GDInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
1105 
1106 	//printf("calling %ls:%i method %ls\n", script->get_path().c_str(), -1, String(p_method).c_str());
1107 
1108 	GDScript *sptr = script.ptr();
1109 	while (sptr) {
1110 		Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
1111 		if (E) {
1112 			return E->get()->call(this, p_args, p_argcount, r_error);
1113 		}
1114 		sptr = sptr->_base;
1115 	}
1116 	r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
1117 	return Variant();
1118 }
1119 
call_multilevel(const StringName & p_method,const Variant ** p_args,int p_argcount)1120 void GDInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
1121 
1122 	GDScript *sptr = script.ptr();
1123 	Variant::CallError ce;
1124 
1125 	while (sptr) {
1126 		Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
1127 		if (E) {
1128 			E->get()->call(this, p_args, p_argcount, ce);
1129 		}
1130 		sptr = sptr->_base;
1131 	}
1132 }
1133 
_ml_call_reversed(GDScript * sptr,const StringName & p_method,const Variant ** p_args,int p_argcount)1134 void GDInstance::_ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount) {
1135 
1136 	if (sptr->_base)
1137 		_ml_call_reversed(sptr->_base, p_method, p_args, p_argcount);
1138 
1139 	Variant::CallError ce;
1140 
1141 	Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(p_method);
1142 	if (E) {
1143 		E->get()->call(this, p_args, p_argcount, ce);
1144 	}
1145 }
1146 
call_multilevel_reversed(const StringName & p_method,const Variant ** p_args,int p_argcount)1147 void GDInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
1148 
1149 	if (script.ptr()) {
1150 		_ml_call_reversed(script.ptr(), p_method, p_args, p_argcount);
1151 	}
1152 }
1153 
notification(int p_notification)1154 void GDInstance::notification(int p_notification) {
1155 
1156 	//notification is not virutal, it gets called at ALL levels just like in C.
1157 	Variant value = p_notification;
1158 	const Variant *args[1] = { &value };
1159 
1160 	GDScript *sptr = script.ptr();
1161 	while (sptr) {
1162 		Map<StringName, GDFunction *>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
1163 		if (E) {
1164 			Variant::CallError err;
1165 			E->get()->call(this, args, 1, err);
1166 			if (err.error != Variant::CallError::CALL_OK) {
1167 				//print error about notification call
1168 			}
1169 		}
1170 		sptr = sptr->_base;
1171 	}
1172 }
1173 
get_script() const1174 Ref<Script> GDInstance::get_script() const {
1175 
1176 	return script;
1177 }
1178 
get_language()1179 ScriptLanguage *GDInstance::get_language() {
1180 
1181 	return GDScriptLanguage::get_singleton();
1182 }
1183 
reload_members()1184 void GDInstance::reload_members() {
1185 
1186 #ifdef DEBUG_ENABLED
1187 
1188 	members.resize(script->member_indices.size()); //resize
1189 
1190 	Vector<Variant> new_members;
1191 	new_members.resize(script->member_indices.size());
1192 
1193 	//pass the values to the new indices
1194 	for (Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.front(); E; E = E->next()) {
1195 
1196 		if (member_indices_cache.has(E->key())) {
1197 			Variant value = members[member_indices_cache[E->key()]];
1198 			new_members[E->get().index] = value;
1199 		}
1200 	}
1201 
1202 	//apply
1203 	members = new_members;
1204 
1205 	//pass the values to the new indices
1206 	member_indices_cache.clear();
1207 	for (Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.front(); E; E = E->next()) {
1208 
1209 		member_indices_cache[E->key()] = E->get().index;
1210 	}
1211 
1212 #endif
1213 }
1214 
GDInstance()1215 GDInstance::GDInstance() {
1216 	owner = NULL;
1217 	base_ref = false;
1218 }
1219 
~GDInstance()1220 GDInstance::~GDInstance() {
1221 	if (script.is_valid() && owner) {
1222 		script->instances.erase(owner);
1223 	}
1224 }
1225 
1226 /************* SCRIPT LANGUAGE **************/
1227 /************* SCRIPT LANGUAGE **************/
1228 /************* SCRIPT LANGUAGE **************/
1229 /************* SCRIPT LANGUAGE **************/
1230 /************* SCRIPT LANGUAGE **************/
1231 
1232 GDScriptLanguage *GDScriptLanguage::singleton = NULL;
1233 
get_name() const1234 String GDScriptLanguage::get_name() const {
1235 
1236 	return "GDScript";
1237 }
1238 
1239 /* LANGUAGE FUNCTIONS */
1240 
_add_global(const StringName & p_name,const Variant & p_value)1241 void GDScriptLanguage::_add_global(const StringName &p_name, const Variant &p_value) {
1242 
1243 	if (globals.has(p_name)) {
1244 		//overwrite existing
1245 		global_array[globals[p_name]] = p_value;
1246 		return;
1247 	}
1248 	globals[p_name] = global_array.size();
1249 	global_array.push_back(p_value);
1250 	_global_array = global_array.ptr();
1251 }
1252 
add_global_constant(const StringName & p_variable,const Variant & p_value)1253 void GDScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) {
1254 
1255 	_add_global(p_variable, p_value);
1256 }
1257 
init()1258 void GDScriptLanguage::init() {
1259 
1260 	//populate global constants
1261 	int gcc = GlobalConstants::get_global_constant_count();
1262 	for (int i = 0; i < gcc; i++) {
1263 
1264 		_add_global(StaticCString::create(GlobalConstants::get_global_constant_name(i)), GlobalConstants::get_global_constant_value(i));
1265 	}
1266 
1267 	_add_global(StaticCString::create("PI"), Math_PI);
1268 
1269 	//populate native classes
1270 
1271 	List<StringName> class_list;
1272 	ObjectTypeDB::get_type_list(&class_list);
1273 	for (List<StringName>::Element *E = class_list.front(); E; E = E->next()) {
1274 
1275 		StringName n = E->get();
1276 		String s = String(n);
1277 		if (s.begins_with("_"))
1278 			n = s.substr(1, s.length());
1279 
1280 		if (globals.has(n))
1281 			continue;
1282 		Ref<GDNativeClass> nc = memnew(GDNativeClass(E->get()));
1283 		_add_global(n, nc);
1284 	}
1285 
1286 	//populate singletons
1287 
1288 	List<Globals::Singleton> singletons;
1289 	Globals::get_singleton()->get_singletons(&singletons);
1290 	for (List<Globals::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
1291 
1292 		_add_global(E->get().name, E->get().ptr);
1293 	}
1294 }
1295 
get_type() const1296 String GDScriptLanguage::get_type() const {
1297 
1298 	return "GDScript";
1299 }
get_extension() const1300 String GDScriptLanguage::get_extension() const {
1301 
1302 	return "gd";
1303 }
execute_file(const String & p_path)1304 Error GDScriptLanguage::execute_file(const String &p_path) {
1305 
1306 	// ??
1307 	return OK;
1308 }
finish()1309 void GDScriptLanguage::finish() {
1310 }
1311 
profiling_start()1312 void GDScriptLanguage::profiling_start() {
1313 
1314 #ifdef DEBUG_ENABLED
1315 	if (lock) {
1316 		lock->lock();
1317 	}
1318 
1319 	SelfList<GDFunction> *elem = function_list.first();
1320 	while (elem) {
1321 		elem->self()->profile.call_count = 0;
1322 		elem->self()->profile.self_time = 0;
1323 		elem->self()->profile.total_time = 0;
1324 		elem->self()->profile.frame_call_count = 0;
1325 		elem->self()->profile.frame_self_time = 0;
1326 		elem->self()->profile.frame_total_time = 0;
1327 		elem->self()->profile.last_frame_call_count = 0;
1328 		elem->self()->profile.last_frame_self_time = 0;
1329 		elem->self()->profile.last_frame_total_time = 0;
1330 		elem = elem->next();
1331 	}
1332 
1333 	profiling = true;
1334 	if (lock) {
1335 		lock->unlock();
1336 	}
1337 
1338 #endif
1339 }
1340 
profiling_stop()1341 void GDScriptLanguage::profiling_stop() {
1342 
1343 #ifdef DEBUG_ENABLED
1344 	if (lock) {
1345 		lock->lock();
1346 	}
1347 
1348 	profiling = false;
1349 	if (lock) {
1350 		lock->unlock();
1351 	}
1352 
1353 #endif
1354 }
1355 
profiling_get_accumulated_data(ProfilingInfo * p_info_arr,int p_info_max)1356 int GDScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) {
1357 
1358 	int current = 0;
1359 #ifdef DEBUG_ENABLED
1360 	if (lock) {
1361 		lock->lock();
1362 	}
1363 
1364 	SelfList<GDFunction> *elem = function_list.first();
1365 	while (elem) {
1366 		if (current >= p_info_max)
1367 			break;
1368 		p_info_arr[current].call_count = elem->self()->profile.call_count;
1369 		p_info_arr[current].self_time = elem->self()->profile.self_time;
1370 		p_info_arr[current].total_time = elem->self()->profile.total_time;
1371 		p_info_arr[current].signature = elem->self()->profile.signature;
1372 		elem = elem->next();
1373 		current++;
1374 	}
1375 
1376 	if (lock) {
1377 		lock->unlock();
1378 	}
1379 
1380 #endif
1381 
1382 	return current;
1383 }
1384 
profiling_get_frame_data(ProfilingInfo * p_info_arr,int p_info_max)1385 int GDScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) {
1386 
1387 	int current = 0;
1388 
1389 #ifdef DEBUG_ENABLED
1390 	if (lock) {
1391 		lock->lock();
1392 	}
1393 
1394 	SelfList<GDFunction> *elem = function_list.first();
1395 	while (elem) {
1396 		if (current >= p_info_max)
1397 			break;
1398 		if (elem->self()->profile.last_frame_call_count > 0) {
1399 			p_info_arr[current].call_count = elem->self()->profile.last_frame_call_count;
1400 			p_info_arr[current].self_time = elem->self()->profile.last_frame_self_time;
1401 			p_info_arr[current].total_time = elem->self()->profile.last_frame_total_time;
1402 			p_info_arr[current].signature = elem->self()->profile.signature;
1403 			//print_line(String(elem->self()->profile.signature)+": "+itos(elem->self()->profile.last_frame_call_count));
1404 			current++;
1405 		}
1406 		elem = elem->next();
1407 	}
1408 
1409 	if (lock) {
1410 		lock->unlock();
1411 	}
1412 
1413 #endif
1414 
1415 	return current;
1416 }
1417 
1418 struct GDScriptDepSort {
1419 
1420 	//must support sorting so inheritance works properly (parent must be reloaded first)
operator ()GDScriptDepSort1421 	bool operator()(const Ref<GDScript> &A, const Ref<GDScript> &B) const {
1422 
1423 		if (A == B)
1424 			return false; //shouldn't happen but..
1425 		const GDScript *I = B->get_base().ptr();
1426 		while (I) {
1427 			if (I == A.ptr()) {
1428 				// A is a base of B
1429 				return true;
1430 			}
1431 
1432 			I = I->get_base().ptr();
1433 		}
1434 
1435 		return false; //not a base
1436 	}
1437 };
1438 
reload_all_scripts()1439 void GDScriptLanguage::reload_all_scripts() {
1440 
1441 #ifdef DEBUG_ENABLED
1442 	print_line("RELOAD ALL SCRIPTS");
1443 	if (lock) {
1444 		lock->lock();
1445 	}
1446 
1447 	List<Ref<GDScript> > scripts;
1448 
1449 	SelfList<GDScript> *elem = script_list.first();
1450 	while (elem) {
1451 		if (elem->self()->get_path().is_resource_file()) {
1452 			print_line("FOUND: " + elem->self()->get_path());
1453 			scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
1454 		}
1455 		elem = elem->next();
1456 	}
1457 
1458 	if (lock) {
1459 		lock->unlock();
1460 	}
1461 
1462 	//as scripts are going to be reloaded, must proceed without locking here
1463 
1464 	scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order
1465 
1466 	for (List<Ref<GDScript> >::Element *E = scripts.front(); E; E = E->next()) {
1467 
1468 		print_line("RELOADING: " + E->get()->get_path());
1469 		E->get()->load_source_code(E->get()->get_path());
1470 		E->get()->reload(true);
1471 	}
1472 #endif
1473 }
1474 
reload_tool_script(const Ref<Script> & p_script,bool p_soft_reload)1475 void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
1476 
1477 #ifdef DEBUG_ENABLED
1478 
1479 	if (lock) {
1480 		lock->lock();
1481 	}
1482 
1483 	List<Ref<GDScript> > scripts;
1484 
1485 	SelfList<GDScript> *elem = script_list.first();
1486 	while (elem) {
1487 		if (elem->self()->get_path().is_resource_file()) {
1488 
1489 			scripts.push_back(Ref<GDScript>(elem->self())); //cast to gdscript to avoid being erased by accident
1490 		}
1491 		elem = elem->next();
1492 	}
1493 
1494 	if (lock) {
1495 		lock->unlock();
1496 	}
1497 
1498 	//when someone asks you why dynamically typed languages are easier to write....
1499 
1500 	Map<Ref<GDScript>, Map<ObjectID, List<Pair<StringName, Variant> > > > to_reload;
1501 
1502 	//as scripts are going to be reloaded, must proceed without locking here
1503 
1504 	scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order
1505 
1506 	for (List<Ref<GDScript> >::Element *E = scripts.front(); E; E = E->next()) {
1507 
1508 		bool reload = E->get() == p_script || to_reload.has(E->get()->get_base());
1509 
1510 		if (!reload)
1511 			continue;
1512 
1513 		to_reload.insert(E->get(), Map<ObjectID, List<Pair<StringName, Variant> > >());
1514 
1515 		if (!p_soft_reload) {
1516 
1517 			//save state and remove script from instances
1518 			Map<ObjectID, List<Pair<StringName, Variant> > > &map = to_reload[E->get()];
1519 
1520 			while (E->get()->instances.front()) {
1521 				Object *obj = E->get()->instances.front()->get();
1522 				//save instance info
1523 				List<Pair<StringName, Variant> > state;
1524 				if (obj->get_script_instance()) {
1525 
1526 					obj->get_script_instance()->get_property_state(state);
1527 					map[obj->get_instance_ID()] = state;
1528 					obj->set_script(RefPtr());
1529 				}
1530 			}
1531 
1532 //same thing for placeholders
1533 #ifdef TOOLS_ENABLED
1534 
1535 			while (E->get()->placeholders.size()) {
1536 				Object *obj = E->get()->placeholders.front()->get()->get_owner();
1537 
1538 				//save instance info
1539 				List<Pair<StringName, Variant> > state;
1540 				if (obj->get_script_instance()) {
1541 
1542 					obj->get_script_instance()->get_property_state(state);
1543 					map[obj->get_instance_ID()] = state;
1544 					obj->set_script(RefPtr());
1545 				} else {
1546 					// no instance found. Let's remove it so we don't loop forever
1547 					E->get()->placeholders.erase(E->get()->placeholders.front()->get());
1548 				}
1549 			}
1550 #endif
1551 
1552 			for (Map<ObjectID, List<Pair<StringName, Variant> > >::Element *F = E->get()->pending_reload_state.front(); F; F = F->next()) {
1553 				map[F->key()] = F->get(); //pending to reload, use this one instead
1554 			}
1555 		}
1556 	}
1557 
1558 	for (Map<Ref<GDScript>, Map<ObjectID, List<Pair<StringName, Variant> > > >::Element *E = to_reload.front(); E; E = E->next()) {
1559 
1560 		Ref<GDScript> scr = E->key();
1561 		scr->reload(p_soft_reload);
1562 
1563 		//restore state if saved
1564 		for (Map<ObjectID, List<Pair<StringName, Variant> > >::Element *F = E->get().front(); F; F = F->next()) {
1565 
1566 			Object *obj = ObjectDB::get_instance(F->key());
1567 			if (!obj)
1568 				continue;
1569 
1570 			if (!p_soft_reload) {
1571 				//clear it just in case (may be a pending reload state)
1572 				obj->set_script(RefPtr());
1573 			}
1574 			obj->set_script(scr.get_ref_ptr());
1575 			if (!obj->get_script_instance()) {
1576 				//failed, save reload state for next time if not saved
1577 				if (!scr->pending_reload_state.has(obj->get_instance_ID())) {
1578 					scr->pending_reload_state[obj->get_instance_ID()] = F->get();
1579 				}
1580 				continue;
1581 			}
1582 
1583 			for (List<Pair<StringName, Variant> >::Element *G = F->get().front(); G; G = G->next()) {
1584 				obj->get_script_instance()->set(G->get().first, G->get().second);
1585 			}
1586 
1587 			scr->pending_reload_state.erase(obj->get_instance_ID()); //as it reloaded, remove pending state
1588 		}
1589 
1590 		//if instance states were saved, set them!
1591 	}
1592 
1593 #endif
1594 }
1595 
frame()1596 void GDScriptLanguage::frame() {
1597 
1598 	//	print_line("calls: "+itos(calls));
1599 	calls = 0;
1600 
1601 #ifdef DEBUG_ENABLED
1602 	if (profiling) {
1603 		if (lock) {
1604 			lock->lock();
1605 		}
1606 
1607 		SelfList<GDFunction> *elem = function_list.first();
1608 		while (elem) {
1609 			elem->self()->profile.last_frame_call_count = elem->self()->profile.frame_call_count;
1610 			elem->self()->profile.last_frame_self_time = elem->self()->profile.frame_self_time;
1611 			elem->self()->profile.last_frame_total_time = elem->self()->profile.frame_total_time;
1612 			elem->self()->profile.frame_call_count = 0;
1613 			elem->self()->profile.frame_self_time = 0;
1614 			elem->self()->profile.frame_total_time = 0;
1615 			elem = elem->next();
1616 		}
1617 
1618 		if (lock) {
1619 			lock->unlock();
1620 		}
1621 	}
1622 
1623 #endif
1624 }
1625 
1626 /* EDITOR FUNCTIONS */
get_reserved_words(List<String> * p_words) const1627 void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
1628 
1629 	static const char *_reserved_words[] = {
1630 		// operators
1631 		"and",
1632 		"in",
1633 		"not",
1634 		"or",
1635 		// types and values
1636 		"false",
1637 		"float",
1638 		"int",
1639 		"bool",
1640 		"null",
1641 		"PI",
1642 		"self",
1643 		"true",
1644 		// functions
1645 		"assert",
1646 		"breakpoint",
1647 		"class",
1648 		"extends",
1649 		"func",
1650 		"preload",
1651 		"setget",
1652 		"signal",
1653 		"tool",
1654 		"yield",
1655 		// var
1656 		"const",
1657 		"enum",
1658 		"export",
1659 		"onready",
1660 		"static",
1661 		"var",
1662 		// control flow
1663 		"break",
1664 		"continue",
1665 		"if",
1666 		"elif",
1667 		"else",
1668 		"for",
1669 		"pass",
1670 		"return",
1671 		"while",
1672 		0
1673 	};
1674 
1675 	const char **w = _reserved_words;
1676 
1677 	while (*w) {
1678 
1679 		p_words->push_back(*w);
1680 		w++;
1681 	}
1682 
1683 	for (int i = 0; i < GDFunctions::FUNC_MAX; i++) {
1684 		p_words->push_back(GDFunctions::get_func_name(GDFunctions::Function(i)));
1685 	}
1686 }
1687 
GDScriptLanguage()1688 GDScriptLanguage::GDScriptLanguage() {
1689 
1690 	calls = 0;
1691 	ERR_FAIL_COND(singleton);
1692 	singleton = this;
1693 	strings._init = StaticCString::create("_init");
1694 	strings._notification = StaticCString::create("_notification");
1695 	strings._set = StaticCString::create("_set");
1696 	strings._get = StaticCString::create("_get");
1697 	strings._get_property_list = StaticCString::create("_get_property_list");
1698 	strings._script_source = StaticCString::create("script/source");
1699 	_debug_parse_err_line = -1;
1700 	_debug_parse_err_file = "";
1701 
1702 #ifdef NO_THREADS
1703 	lock = NULL;
1704 #else
1705 	lock = Mutex::create();
1706 #endif
1707 	profiling = false;
1708 	script_frame_time = 0;
1709 
1710 	_debug_call_stack_pos = 0;
1711 	int dmcs = GLOBAL_DEF("debug/script_max_call_stack", 1024);
1712 	if (ScriptDebugger::get_singleton()) {
1713 		//debugging enabled!
1714 
1715 		_debug_max_call_stack = dmcs;
1716 		if (_debug_max_call_stack < 1024)
1717 			_debug_max_call_stack = 1024;
1718 		_call_stack = memnew_arr(CallLevel, _debug_max_call_stack + 1);
1719 
1720 	} else {
1721 		_debug_max_call_stack = 0;
1722 		_call_stack = NULL;
1723 	}
1724 }
1725 
~GDScriptLanguage()1726 GDScriptLanguage::~GDScriptLanguage() {
1727 
1728 	if (lock) {
1729 		memdelete(lock);
1730 		lock = NULL;
1731 	}
1732 	if (_call_stack) {
1733 		memdelete_arr(_call_stack);
1734 	}
1735 	singleton = NULL;
1736 }
1737 
1738 /*************** RESOURCE ***************/
1739 
load(const String & p_path,const String & p_original_path,Error * r_error)1740 RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error) {
1741 
1742 	if (r_error)
1743 		*r_error = ERR_FILE_CANT_OPEN;
1744 
1745 	GDScript *script = memnew(GDScript);
1746 
1747 	Ref<GDScript> scriptres(script);
1748 
1749 	if (p_path.ends_with(".gde") || p_path.ends_with(".gdc")) {
1750 
1751 		script->set_script_path(p_original_path); // script needs this.
1752 		script->set_path(p_original_path);
1753 		Error err = script->load_byte_code(p_path);
1754 
1755 		if (err != OK) {
1756 
1757 			ERR_FAIL_COND_V(err != OK, RES());
1758 		}
1759 
1760 	} else {
1761 		Error err = script->load_source_code(p_path);
1762 
1763 		if (err != OK) {
1764 
1765 			ERR_FAIL_COND_V(err != OK, RES());
1766 		}
1767 
1768 		script->set_script_path(p_original_path); // script needs this.
1769 		script->set_path(p_original_path);
1770 		//script->set_name(p_path.get_file());
1771 
1772 		script->reload();
1773 	}
1774 	if (r_error)
1775 		*r_error = OK;
1776 
1777 	return scriptres;
1778 }
get_recognized_extensions(List<String> * p_extensions) const1779 void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const {
1780 
1781 	p_extensions->push_back("gd");
1782 	p_extensions->push_back("gdc");
1783 	p_extensions->push_back("gde");
1784 }
1785 
handles_type(const String & p_type) const1786 bool ResourceFormatLoaderGDScript::handles_type(const String &p_type) const {
1787 
1788 	return (p_type == "Script" || p_type == "GDScript");
1789 }
1790 
get_resource_type(const String & p_path) const1791 String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const {
1792 
1793 	String el = p_path.extension().to_lower();
1794 	if (el == "gd" || el == "gdc" || el == "gde")
1795 		return "GDScript";
1796 	return "";
1797 }
1798 
save(const String & p_path,const RES & p_resource,uint32_t p_flags)1799 Error ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
1800 
1801 	Ref<GDScript> sqscr = p_resource;
1802 	ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);
1803 
1804 	String source = sqscr->get_source_code();
1805 
1806 	Error err;
1807 	FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
1808 
1809 	if (err) {
1810 
1811 		ERR_FAIL_COND_V(err, err);
1812 	}
1813 
1814 	file->store_string(source);
1815 	if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
1816 		memdelete(file);
1817 		return ERR_CANT_CREATE;
1818 	}
1819 	file->close();
1820 	memdelete(file);
1821 
1822 	if (ScriptServer::is_reload_scripts_on_save_enabled()) {
1823 		GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, false);
1824 	}
1825 
1826 	return OK;
1827 }
1828 
get_recognized_extensions(const RES & p_resource,List<String> * p_extensions) const1829 void ResourceFormatSaverGDScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
1830 
1831 	if (p_resource->cast_to<GDScript>()) {
1832 		p_extensions->push_back("gd");
1833 	}
1834 }
recognize(const RES & p_resource) const1835 bool ResourceFormatSaverGDScript::recognize(const RES &p_resource) const {
1836 
1837 	return p_resource->cast_to<GDScript>() != NULL;
1838 }
1839