| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797 | /*************************************************************************//*  gd_script.cpp                                                        *//*************************************************************************//*                       This file is part of:                           *//*                           GODOT ENGINE                                *//*                    http://www.godotengine.org                         *//*************************************************************************//* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur.                 *//*                                                                       *//* Permission is hereby granted, free of charge, to any person obtaining *//* a copy of this software and associated documentation files (the       *//* "Software"), to deal in the Software without restriction, including   *//* without limitation the rights to use, copy, modify, merge, publish,   *//* distribute, sublicense, and/or sell copies of the Software, and to    *//* permit persons to whom the Software is furnished to do so, subject to *//* the following conditions:                                             *//*                                                                       *//* The above copyright notice and this permission notice shall be        *//* included in all copies or substantial portions of the Software.       *//*                                                                       *//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *//* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*//* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  *//* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  *//* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     *//* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                *//*************************************************************************/#include "gd_script.h"#include "globals.h"#include "global_constants.h"#include "gd_compiler.h"#include "os/file_access.h"#include "io/file_access_encrypted.h"/* TODO:   *populate globals   *do checks as close to debugger as possible (but don't do debugger)   *const check plz   *check arguments and default arguments in GDFunction   -get property list in instance?   *missing opcodes   -const checks   -make thread safe */Variant *GDFunction::_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self, Variant *p_stack,String& r_error) const{	int address = p_address&ADDR_MASK;	//sequential table (jump table generated by compiler)	switch((p_address&ADDR_TYPE_MASK)>>ADDR_BITS) {		case ADDR_TYPE_SELF: {			if (!p_instance) {				r_error="Cannot access self without instance.";				return NULL;			}			return &self;		} break;		case ADDR_TYPE_CLASS: {			return &p_script->_static_ref;		} break;		case ADDR_TYPE_MEMBER: {			//member indexing is O(1)			if (!p_instance) {				r_error="Cannot access member without instance.";				return NULL;			}			return &p_instance->members[address];		} break;		case ADDR_TYPE_CLASS_CONSTANT: {			//todo change to index!			GDScript *o=p_script;			ERR_FAIL_INDEX_V(address,_global_names_count,NULL);			const StringName *sn = &_global_names_ptr[address];			while(o) {				GDScript *s=o;				while(s) {					Map<StringName,Variant>::Element *E=s->constants.find(*sn);					if (E) {						return &E->get();					}					s=s->_base;				}				o=o->_owner;			}			ERR_EXPLAIN("GDCompiler bug..");			ERR_FAIL_V(NULL);		} break;		case ADDR_TYPE_LOCAL_CONSTANT: {			ERR_FAIL_INDEX_V(address,_constant_count,NULL);			return &_constants_ptr[address];		} break;		case ADDR_TYPE_STACK:		case ADDR_TYPE_STACK_VARIABLE: {			ERR_FAIL_INDEX_V(address,_stack_size,NULL);			return &p_stack[address];		} break;		case ADDR_TYPE_GLOBAL: {			ERR_FAIL_INDEX_V(address,GDScriptLanguage::get_singleton()->get_global_array_size(),NULL);			return &GDScriptLanguage::get_singleton()->get_global_array()[address];		} break;		case ADDR_TYPE_NIL: {			return &nil;		} break;	}	ERR_EXPLAIN("Bad Code! (Addressing Mode)");	ERR_FAIL_V(NULL);	return NULL;}String GDFunction::_get_call_error(const Variant::CallError& p_err, const String& p_where,const Variant**argptrs) const {	String err_text;	if (p_err.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {		int errorarg=p_err.argument;		err_text="Invalid type in "+p_where+". Cannot convert argument "+itos(errorarg+1)+" from "+Variant::get_type_name(argptrs[errorarg]->get_type())+" to "+Variant::get_type_name(p_err.expected)+".";	} else if (p_err.error==Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {		err_text="Invalid call to "+p_where+". Expected "+itos(p_err.argument)+" arguments.";	} else if (p_err.error==Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {		err_text="Invalid call to "+p_where+". Expected "+itos(p_err.argument)+" arguments.";	} else if (p_err.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) {		err_text="Invalid call. Nonexistent "+p_where+".";	} else if (p_err.error==Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL) {		err_text="Attempt to call "+p_where+" on a null instance.";	} else {		err_text="Bug, call error: #"+itos(p_err.error);	}	return err_text;}static String _get_var_type(const Variant* p_type) {	String basestr;	if (p_type->get_type()==Variant::OBJECT) {		Object *bobj = *p_type;		if (!bobj) {			basestr = "null instance";		} else {#ifdef DEBUG_ENABLED			if (ObjectDB::instance_validate(bobj)) {				if (bobj->get_script_instance())					basestr= bobj->get_type()+" ("+bobj->get_script_instance()->get_script()->get_path().get_file()+")";				else					basestr = bobj->get_type();			} else {				basestr="previously freed instance";			}#else			basestr="Object";#endif		}	} else {		basestr = Variant::get_type_name(p_type->get_type());	}	return basestr;}Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError& r_err, CallState *p_state) {	if (!_code_ptr) {		return Variant();	}	r_err.error=Variant::CallError::CALL_OK;	Variant self;	Variant retvalue;	Variant *stack = NULL;	Variant **call_args;	int defarg=0;#ifdef DEBUG_ENABLED	//GDScriptLanguage::get_singleton()->calls++;#endif	uint32_t alloca_size=0;	GDScript *_class;	int ip=0;	int line=_initial_line;	if (p_state) {		//use existing (supplied) state (yielded)		stack=(Variant*)p_state->stack.ptr();		call_args=(Variant**)&p_state->stack[sizeof(Variant)*p_state->stack_size];		line=p_state->line;		ip=p_state->ip;		alloca_size=p_state->stack.size();		_class=p_state->_class;		p_instance=p_state->instance;		defarg=p_state->defarg;		self=p_state->self;		//stack[p_state->result_pos]=p_state->result; //assign stack with result	} else {		if (p_argcount!=_argument_count) {			if (p_argcount>_argument_count) {				r_err.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;				r_err.argument=_argument_count;				return Variant();			} else if (p_argcount < _argument_count - _default_arg_count) {				r_err.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;				r_err.argument=_argument_count - _default_arg_count;				return Variant();			} else {				defarg=_argument_count-p_argcount;			}		}		alloca_size = sizeof(Variant*)*_call_size + sizeof(Variant)*_stack_size;		if (alloca_size) {			uint8_t *aptr = (uint8_t*)alloca(alloca_size);			if (_stack_size) {				stack=(Variant*)aptr;				for(int i=0;i<p_argcount;i++)					memnew_placement(&stack[i],Variant(*p_args[i]));				for(int i=p_argcount;i<_stack_size;i++)					memnew_placement(&stack[i],Variant);			} else {				stack=NULL;			}			if (_call_size) {				call_args = (Variant**)&aptr[sizeof(Variant)*_stack_size];			} else {				call_args=NULL;			}		} else {			stack=NULL;			call_args=NULL;		}		if (p_instance) {			if (p_instance->base_ref && static_cast<Reference*>(p_instance->owner)->is_referenced()) {				self=REF(static_cast<Reference*>(p_instance->owner));			} else {				self=p_instance->owner;			}			_class=p_instance->script.ptr();		} else {			_class=_script;		}	}	String err_text;#ifdef DEBUG_ENABLED    if (ScriptDebugger::get_singleton())        GDScriptLanguage::get_singleton()->enter_function(p_instance,this,stack,&ip,&line);#define CHECK_SPACE(m_space)\	ERR_BREAK((ip+m_space)>_code_size)#define GET_VARIANT_PTR(m_v,m_code_ofs) \	Variant *m_v; \	m_v = _get_variant(_code_ptr[ip+m_code_ofs],p_instance,_class,self,stack,err_text);\	if (!m_v)\		break;#else#define CHECK_SPACE(m_space)#define GET_VARIANT_PTR(m_v,m_code_ofs) \	Variant *m_v; \	m_v = _get_variant(_code_ptr[ip+m_code_ofs],p_instance,_class,self,stack,err_text);#endif	bool exit_ok=false;	while(ip<_code_size) {		int last_opcode=_code_ptr[ip];		switch(_code_ptr[ip]) {			case OPCODE_OPERATOR: {				CHECK_SPACE(5);				bool valid;				Variant::Operator op = (Variant::Operator)_code_ptr[ip+1];				ERR_BREAK(op>=Variant::OP_MAX);				GET_VARIANT_PTR(a,2);				GET_VARIANT_PTR(b,3);				GET_VARIANT_PTR(dst,4);#ifdef DEBUG_ENABLED				Variant ret;				Variant::evaluate(op,*a,*b,ret,valid);#else				Variant::evaluate(op,*a,*b,*dst,valid);#endif				if (!valid) {#ifdef DEBUG_ENABLED					if (ret.get_type()==Variant::STRING) {						//return a string when invalid with the error						err_text=ret;						err_text += " in operator '"+Variant::get_operator_name(op)+"'.";					} else {						err_text="Invalid operands '"+Variant::get_type_name(a->get_type())+"' and '"+Variant::get_type_name(b->get_type())+"' in operator '"+Variant::get_operator_name(op)+"'.";					}#endif					break;				}#ifdef DEBUG_ENABLED				*dst=ret;#endif				ip+=5;			} continue;			case OPCODE_EXTENDS_TEST: {				CHECK_SPACE(4);				GET_VARIANT_PTR(a,1);				GET_VARIANT_PTR(b,2);				GET_VARIANT_PTR(dst,3);#ifdef DEBUG_ENABLED				if (a->get_type()!=Variant::OBJECT || a->operator Object*()==NULL) {					err_text="Left operand of 'extends' is not an instance of anything.";					break;				}				if (b->get_type()!=Variant::OBJECT || b->operator Object*()==NULL) {					err_text="Right operand of 'extends' is not a class.";					break;				}#endif				Object *obj_A = *a;				Object *obj_B = *b;				GDScript *scr_B = obj_B->cast_to<GDScript>();				bool extends_ok=false;				if (scr_B) {					//if B is a script, the only valid condition is that A has an instance which inherits from the script					//in other situation, this shoul return false.					if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language()==GDScriptLanguage::get_singleton()) {						GDInstance *ins = static_cast<GDInstance*>(obj_A->get_script_instance());						GDScript *cmp = ins->script.ptr();						//bool found=false;						while(cmp) {							if (cmp==scr_B) {								//inherits from script, all ok								extends_ok=true;								break;							}							cmp=cmp->_base;						}					}				} else {					GDNativeClass *nc= obj_B->cast_to<GDNativeClass>();					if (!nc) {						err_text="Right operand of 'extends' is not a class (type: '"+obj_B->get_type()+"').";						break;					}					extends_ok=ObjectTypeDB::is_type(obj_A->get_type_name(),nc->get_name());				}				*dst=extends_ok;				ip+=4;			} continue;			case OPCODE_SET: {				CHECK_SPACE(3);				GET_VARIANT_PTR(dst,1);				GET_VARIANT_PTR(index,2);				GET_VARIANT_PTR(value,3);				bool valid;				dst->set(*index,*value,&valid);				if (!valid) {					String v = index->operator String();					if (v!="") {						v="'"+v+"'";					} else {						v="of type '"+_get_var_type(index)+"'";					}					err_text="Invalid set index "+v+" (on base: '"+_get_var_type(dst)+"').";					break;				}				ip+=4;			} continue;			case OPCODE_GET: {				CHECK_SPACE(3);				GET_VARIANT_PTR(src,1);				GET_VARIANT_PTR(index,2);				GET_VARIANT_PTR(dst,3);				bool valid;#ifdef DEBUG_ENABLED//allow better error message in cases where src and dst are the same stack position				Variant ret = src->get(*index,&valid);#else				*dst = src->get(*index,&valid);#endif				if (!valid) {					String v = index->operator String();					if (v!="") {						v="'"+v+"'";					} else {						v="of type '"+_get_var_type(index)+"'";					}					err_text="Invalid get index "+v+" (on base: '"+_get_var_type(src)+"').";					break;				}#ifdef DEBUG_ENABLED				*dst=ret;#endif				ip+=4;			} continue;			case OPCODE_SET_NAMED: {				CHECK_SPACE(3);				GET_VARIANT_PTR(dst,1);				GET_VARIANT_PTR(value,3);				int indexname = _code_ptr[ip+2];				ERR_BREAK(indexname<0 || indexname>=_global_names_count);				const StringName *index = &_global_names_ptr[indexname];				bool valid;				dst->set_named(*index,*value,&valid);				if (!valid) {					String err_type;					err_text="Invalid set index '"+String(*index)+"' (on base: '"+_get_var_type(dst)+"').";					break;				}				ip+=4;			} continue;			case OPCODE_GET_NAMED: {				CHECK_SPACE(3);				GET_VARIANT_PTR(src,1);				GET_VARIANT_PTR(dst,3);				int indexname = _code_ptr[ip+2];				ERR_BREAK(indexname<0 || indexname>=_global_names_count);				const StringName *index = &_global_names_ptr[indexname];				bool valid;#ifdef DEBUG_ENABLED//allow better error message in cases where src and dst are the same stack position				Variant ret = src->get_named(*index,&valid);#else				*dst = src->get_named(*index,&valid);#endif				if (!valid) {					if (src->has_method(*index)) {						err_text="Invalid get index '"+index->operator String()+"' (on base: '"+_get_var_type(src)+"'). Did you mean '."+index->operator String()+"()' ?";					} else {						err_text="Invalid get index '"+index->operator String()+"' (on base: '"+_get_var_type(src)+"').";					}					break;				}#ifdef DEBUG_ENABLED				*dst=ret;#endif				ip+=4;			} continue;			case OPCODE_ASSIGN: {				CHECK_SPACE(3);				GET_VARIANT_PTR(dst,1);				GET_VARIANT_PTR(src,2);				*dst = *src;				ip+=3;			} continue;			case OPCODE_ASSIGN_TRUE: {				CHECK_SPACE(2);				GET_VARIANT_PTR(dst,1);				*dst = true;				ip+=2;			} continue;			case OPCODE_ASSIGN_FALSE: {				CHECK_SPACE(2);				GET_VARIANT_PTR(dst,1);				*dst = false;				ip+=2;			} continue;			case OPCODE_CONSTRUCT: {				CHECK_SPACE(2);				Variant::Type t=Variant::Type(_code_ptr[ip+1]);				int argc=_code_ptr[ip+2];				CHECK_SPACE(argc+2);				Variant **argptrs = call_args;				for(int i=0;i<argc;i++) {					GET_VARIANT_PTR(v,3+i);					argptrs[i]=v;				}				GET_VARIANT_PTR(dst,3+argc);				Variant::CallError err;				*dst = Variant::construct(t,(const Variant**)argptrs,argc,err);				if (err.error!=Variant::CallError::CALL_OK) {					err_text=_get_call_error(err,"'"+Variant::get_type_name(t)+"' constructor",(const Variant**)argptrs);					break;				}				ip+=4+argc;				//construct a basic type			} continue;			case OPCODE_CONSTRUCT_ARRAY: {				CHECK_SPACE(1);				int argc=_code_ptr[ip+1];				Array array(true); //arrays are always shared				array.resize(argc);				CHECK_SPACE(argc+2);				for(int i=0;i<argc;i++) {					GET_VARIANT_PTR(v,2+i);					array[i]=*v;				}				GET_VARIANT_PTR(dst,2+argc);				*dst=array;				ip+=3+argc;			} continue;			case OPCODE_CONSTRUCT_DICTIONARY: {				CHECK_SPACE(1);				int argc=_code_ptr[ip+1];				Dictionary dict(true); //arrays are always shared				CHECK_SPACE(argc*2+2);				for(int i=0;i<argc;i++) {					GET_VARIANT_PTR(k,2+i*2+0);					GET_VARIANT_PTR(v,2+i*2+1);					dict[*k]=*v;				}				GET_VARIANT_PTR(dst,2+argc*2);				*dst=dict;				ip+=3+argc*2;			} continue;			case OPCODE_CALL_RETURN:			case OPCODE_CALL: {				CHECK_SPACE(4);				bool call_ret = _code_ptr[ip]==OPCODE_CALL_RETURN;				int argc=_code_ptr[ip+1];				GET_VARIANT_PTR(base,2);				int nameg=_code_ptr[ip+3];				ERR_BREAK(nameg<0 || nameg>=_global_names_count);				const StringName *methodname = &_global_names_ptr[nameg];				ERR_BREAK(argc<0);				ip+=4;				CHECK_SPACE(argc+1);				Variant **argptrs = call_args;				for(int i=0;i<argc;i++) {					GET_VARIANT_PTR(v,i);					argptrs[i]=v;				}				Variant::CallError err;				if (call_ret) {					GET_VARIANT_PTR(ret,argc);					*ret = base->call(*methodname,(const Variant**)argptrs,argc,err);				} else {					base->call(*methodname,(const Variant**)argptrs,argc,err);				}				if (err.error!=Variant::CallError::CALL_OK) {					String methodstr = *methodname;					String basestr = _get_var_type(base);					if (methodstr=="call") {						if (argc>=1) {							methodstr=String(*argptrs[0])+" (via call)";							if (err.error==Variant::CallError::CALL_ERROR_INVALID_ARGUMENT) {								err.argument-=1;							}						}					} if (methodstr=="free") {						if (err.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) {							if (base->is_ref()) {								err_text="Attempted to free a reference.";								break;							} else if (base->get_type()==Variant::OBJECT) {								err_text="Attempted to free a locked object (calling or emitting).";								break;							}						}					}					err_text=_get_call_error(err,"function '"+methodstr+"' in base '"+basestr+"'",(const Variant**)argptrs);					break;				}				//_call_func(NULL,base,*methodname,ip,argc,p_instance,stack);				ip+=argc+1;			} continue;			case OPCODE_CALL_BUILT_IN: {				CHECK_SPACE(4);				GDFunctions::Function func = GDFunctions::Function(_code_ptr[ip+1]);				int argc=_code_ptr[ip+2];				ERR_BREAK(argc<0);				ip+=3;				CHECK_SPACE(argc+1);				Variant **argptrs = call_args;				for(int i=0;i<argc;i++) {					GET_VARIANT_PTR(v,i);					argptrs[i]=v;				}				GET_VARIANT_PTR(dst,argc);				Variant::CallError err;				GDFunctions::call(func,(const Variant**)argptrs,argc,*dst,err);				if (err.error!=Variant::CallError::CALL_OK) {					String methodstr = GDFunctions::get_func_name(func);					err_text=_get_call_error(err,"built-in function '"+methodstr+"'",(const Variant**)argptrs);					break;				}				ip+=argc+1;			} continue;			case OPCODE_CALL_SELF: {			} break;			case OPCODE_CALL_SELF_BASE: {				CHECK_SPACE(2);				int self_fun = _code_ptr[ip+1];#ifdef DEBUG_ENABLED				if (self_fun<0 || self_fun>=_global_names_count) {					err_text="compiler bug, function name not found";					break;				}#endif				const StringName *methodname = &_global_names_ptr[self_fun];				int argc=_code_ptr[ip+2];				CHECK_SPACE(2+argc+1);				Variant **argptrs = call_args;				for(int i=0;i<argc;i++) {					GET_VARIANT_PTR(v,i+3);					argptrs[i]=v;				}				GET_VARIANT_PTR(dst,argc+3);				const GDScript *gds = _script;				const Map<StringName,GDFunction>::Element *E=NULL;				while (gds->base.ptr()) {					gds=gds->base.ptr();					E=gds->member_functions.find(*methodname);					if (E)						break;				}				Variant::CallError err;				if (E) {					*dst=((GDFunction*)&E->get())->call(p_instance,(const Variant**)argptrs,argc,err);				} else if (gds->native.ptr()) {					if (*methodname!=GDScriptLanguage::get_singleton()->strings._init) {						MethodBind *mb = ObjectTypeDB::get_method(gds->native->get_name(),*methodname);						if (!mb) {							err.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;						} else {							*dst=mb->call(p_instance->owner,(const Variant**)argptrs,argc,err);						}					} else {						err.error=Variant::CallError::CALL_OK;					}				} else {					if (*methodname!=GDScriptLanguage::get_singleton()->strings._init) {						err.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;					} else {						err.error=Variant::CallError::CALL_OK;					}				}				if (err.error!=Variant::CallError::CALL_OK) {					String methodstr = *methodname;					err_text=_get_call_error(err,"function '"+methodstr+"'",(const Variant**)argptrs);					break;				}				ip+=4+argc;			} continue;			case OPCODE_YIELD:			case OPCODE_YIELD_SIGNAL: {				int ipofs=1;				if (_code_ptr[ip]==OPCODE_YIELD_SIGNAL) {					CHECK_SPACE(4);					ipofs+=2;				} else {					CHECK_SPACE(2);				}				Ref<GDFunctionState> gdfs = memnew( GDFunctionState );				gdfs->function=this;				gdfs->state.stack.resize(alloca_size);				//copy variant stack				for(int i=0;i<_stack_size;i++) {					memnew_placement(&gdfs->state.stack[sizeof(Variant)*i],Variant(stack[i]));				}				gdfs->state.stack_size=_stack_size;				gdfs->state.self=self;				gdfs->state.alloca_size=alloca_size;				gdfs->state._class=_class;				gdfs->state.ip=ip+ipofs;				gdfs->state.line=line;				//gdfs->state.result_pos=ip+ipofs-1;				gdfs->state.defarg=defarg;				gdfs->state.instance=p_instance;				gdfs->function=this;				retvalue=gdfs;				if (_code_ptr[ip]==OPCODE_YIELD_SIGNAL) {					GET_VARIANT_PTR(argobj,1);					GET_VARIANT_PTR(argname,2);					//do the oneshot connect					if (argobj->get_type()!=Variant::OBJECT) {						err_text="First argument of yield() not of type object.";						break;					}					if (argname->get_type()!=Variant::STRING) {						err_text="Second argument of yield() not a string (for signal name).";						break;					}					Object *obj=argobj->operator Object *();					String signal = argname->operator String();#ifdef DEBUG_ENABLED					if (!obj) {						err_text="First argument of yield() is null.";						break;					}					if (ScriptDebugger::get_singleton()) {						if (!ObjectDB::instance_validate(obj)) {							err_text="First argument of yield() is a previously freed instance.";							break;						}					}					if (signal.length()==0) {						err_text="Second argument of yield() is an empty string (for signal name).";						break;					}#endif					Error err = obj->connect(signal,gdfs.ptr(),"_signal_callback",varray(gdfs),Object::CONNECT_ONESHOT);					if (err!=OK) {						err_text="Error connecting to signal: "+signal+" during yield().";						break;					}				}				exit_ok=true;			} break;			case OPCODE_YIELD_RESUME: {				CHECK_SPACE(2);				if (!p_state) {					err_text=("Invalid Resume (bug?)");					break;				}				GET_VARIANT_PTR(result,1);				*result=p_state->result;				ip+=2;			} continue;			case OPCODE_JUMP: {				CHECK_SPACE(2);				int to = _code_ptr[ip+1];				ERR_BREAK(to<0 || to>_code_size);				ip=to;			} continue;			case OPCODE_JUMP_IF: {				CHECK_SPACE(3);				GET_VARIANT_PTR(test,1);				bool valid;				bool result = test->booleanize(valid);#ifdef DEBUG_ENABLED				if (!valid) {					err_text="cannot evaluate conditional expression of type: "+Variant::get_type_name(test->get_type());					break;				}#endif				if (result) {					int to = _code_ptr[ip+2];					ERR_BREAK(to<0 || to>_code_size);					ip=to;					continue;				}				ip+=3;			} continue;			case OPCODE_JUMP_IF_NOT: {				CHECK_SPACE(3);				GET_VARIANT_PTR(test,1);				bool valid;				bool result = test->booleanize(valid);#ifdef DEBUG_ENABLED				if (!valid) {					err_text="cannot evaluate conditional expression of type: "+Variant::get_type_name(test->get_type());					break;				}#endif				if (!result) {					int to = _code_ptr[ip+2];					ERR_BREAK(to<0 || to>_code_size);					ip=to;					continue;				}				ip+=3;			} continue;			case OPCODE_JUMP_TO_DEF_ARGUMENT: {				CHECK_SPACE(2);				ip=_default_arg_ptr[defarg];			} continue;			case OPCODE_RETURN: {				CHECK_SPACE(2);				GET_VARIANT_PTR(r,1);				retvalue=*r;				exit_ok=true;			} break;			case OPCODE_ITERATE_BEGIN: {				CHECK_SPACE(8); //space for this an regular iterate				GET_VARIANT_PTR(counter,1);				GET_VARIANT_PTR(container,2);				bool valid;				if (!container->iter_init(*counter,valid)) {					if (!valid) {						err_text="Unable to iterate on object of type  "+Variant::get_type_name(container->get_type())+"'.";						break;					}					int jumpto=_code_ptr[ip+3];					ERR_BREAK(jumpto<0 || jumpto>_code_size);					ip=jumpto;					continue;				}				GET_VARIANT_PTR(iterator,4);				*iterator=container->iter_get(*counter,valid);				if (!valid) {					err_text="Unable to obtain iterator object of type  "+Variant::get_type_name(container->get_type())+"'.";					break;				}				ip+=5; //skip regular iterate which is always next			} continue;			case OPCODE_ITERATE: {				CHECK_SPACE(4);				GET_VARIANT_PTR(counter,1);				GET_VARIANT_PTR(container,2);				bool valid;				if (!container->iter_next(*counter,valid)) {					if (!valid) {						err_text="Unable to iterate on object of type  "+Variant::get_type_name(container->get_type())+"' (type changed since first iteration?).";						break;					}					int jumpto=_code_ptr[ip+3];					ERR_BREAK(jumpto<0 || jumpto>_code_size);					ip=jumpto;					continue;				}				GET_VARIANT_PTR(iterator,4);				*iterator=container->iter_get(*counter,valid);				if (!valid) {					err_text="Unable to obtain iterator object of type  "+Variant::get_type_name(container->get_type())+"' (but was obtained on first iteration?).";					break;				}				ip+=5; //loop again			} continue;			case OPCODE_ASSERT: {				CHECK_SPACE(2);				GET_VARIANT_PTR(test,1);#ifdef DEBUG_ENABLED				bool valid;				bool result = test->booleanize(valid);				if (!valid) {					err_text="cannot evaluate conditional expression of type: "+Variant::get_type_name(test->get_type());					break;				}				if (!result) {					err_text="Assertion failed.";					break;				}#endif				ip+=2;			} continue;			case OPCODE_LINE: {				CHECK_SPACE(2);				line=_code_ptr[ip+1];				ip+=2;				if (ScriptDebugger::get_singleton()) {			    // line					bool do_break=false;					if (ScriptDebugger::get_singleton()->get_lines_left()>0) {						if (ScriptDebugger::get_singleton()->get_depth()<=0)							ScriptDebugger::get_singleton()->set_lines_left( ScriptDebugger::get_singleton()->get_lines_left() -1 );						if (ScriptDebugger::get_singleton()->get_lines_left()<=0)							do_break=true;					}					if (ScriptDebugger::get_singleton()->is_breakpoint(line,source))						do_break=true;					if (do_break) {						GDScriptLanguage::get_singleton()->debug_break("Breakpoint",true);					}					ScriptDebugger::get_singleton()->line_poll();				}			} continue;			case OPCODE_END: {				exit_ok=true;				break;			} break;			default: {				err_text="Illegal opcode "+itos(_code_ptr[ip])+" at address "+itos(ip);			} break;		}		if (exit_ok)			break;		//error		// function, file, line, error, explanation		String err_file;		if (p_instance)			err_file=p_instance->script->path;		else if (_class)			err_file=_class->path;		if (err_file=="")			err_file="<built-in>";		String err_func = name;		if (p_instance && p_instance->script->name!="")			err_func=p_instance->script->name+"."+err_func;		int err_line=line;		if (err_text=="") {			err_text="Internal Script Error! - opcode #"+itos(last_opcode)+" (report please).";		}	if (!GDScriptLanguage::get_singleton()->debug_break(err_text,false)) {            // debugger break did not happen            _err_print_error(err_func.utf8().get_data(),err_file.utf8().get_data(),err_line,err_text.utf8().get_data());        }		break;	}    if (ScriptDebugger::get_singleton())        GDScriptLanguage::get_singleton()->exit_function();	if (_stack_size) {		//free stack		for(int i=0;i<_stack_size;i++)			stack[i].~Variant();	}	return retvalue;}const int* GDFunction::get_code() const {	return _code_ptr;}int GDFunction::get_code_size() const{	return _code_size;}Variant GDFunction::get_constant(int p_idx) const {	ERR_FAIL_INDEX_V(p_idx,constants.size(),"<errconst>");	return constants[p_idx];}StringName GDFunction::get_global_name(int p_idx) const {	ERR_FAIL_INDEX_V(p_idx,global_names.size(),"<errgname>");	return global_names[p_idx];}int GDFunction::get_default_argument_count() const {	return default_arguments.size();}int GDFunction::get_default_argument_addr(int p_arg) const{	ERR_FAIL_INDEX_V(p_arg,default_arguments.size(),-1);	return default_arguments[p_arg];}StringName GDFunction::get_name() const {	return name;}int GDFunction::get_max_stack_size() const {	return _stack_size;}struct _GDFKC {    int order;    List<int> pos;};struct _GDFKCS {    int order;    StringName id;    int pos;    bool operator<(const _GDFKCS &p_r) const {        return order<p_r.order;    }};void GDFunction::debug_get_stack_member_state(int p_line,List<Pair<StringName,int> > *r_stackvars) const {    int oc=0;    Map<StringName,_GDFKC> sdmap;    for( const List<StackDebug>::Element *E=stack_debug.front();E;E=E->next()) {        const StackDebug &sd=E->get();        if (sd.line>p_line)            break;        if (sd.added) {            if (!sdmap.has(sd.identifier)) {                _GDFKC d;                d.order=oc++;                d.pos.push_back(sd.pos);                sdmap[sd.identifier]=d;            } else {                sdmap[sd.identifier].pos.push_back(sd.pos);            }        } else {            ERR_CONTINUE(!sdmap.has(sd.identifier));            sdmap[sd.identifier].pos.pop_back();            if (sdmap[sd.identifier].pos.empty())                sdmap.erase(sd.identifier);        }    }    List<_GDFKCS> stackpositions;    for(Map<StringName,_GDFKC>::Element *E=sdmap.front();E;E=E->next() ) {        _GDFKCS spp;        spp.id=E->key();        spp.order=E->get().order;        spp.pos=E->get().pos.back()->get();        stackpositions.push_back(spp);    }    stackpositions.sort();    for(List<_GDFKCS>::Element *E=stackpositions.front();E;E=E->next()) {        Pair<StringName,int> p;        p.first=E->get().id;        p.second=E->get().pos;        r_stackvars->push_back(p);    }}#if 0void GDFunction::clear() {	name=StringName();	constants.clear();	_stack_size=0;	code.clear();	_constants_ptr=NULL;	_constant_count=0;	_global_names_ptr=NULL;	_global_names_count=0;	_code_ptr=NULL;	_code_size=0;}#endifGDFunction::GDFunction() {	_stack_size=0;	_call_size=0;	name="<anonymous>";#ifdef DEBUG_ENABLED	_func_cname=NULL;#endif}/////////////////////Variant GDFunctionState::_signal_callback(const Variant** p_args, int p_argcount, Variant::CallError& r_error) {	Variant arg;	r_error.error=Variant::CallError::CALL_OK;	ERR_FAIL_COND_V(!function,Variant());	if (p_argcount==0) {		r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;		r_error.argument=1;		return Variant();	} else if (p_argcount==1) {		//noooneee	} else if (p_argcount==2) {		arg=*p_args[0];	} else {		Array extra_args;		for(int i=0;i<p_argcount-1;i++) {			extra_args.push_back(*p_args[i]);		}		arg=extra_args;	}	Ref<GDFunctionState> self = *p_args[p_argcount-1];	if (self.is_null()) {		r_error.error=Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;		r_error.argument=p_argcount-1;		r_error.expected=Variant::OBJECT;		return Variant();	}	state.result=arg;	Variant ret = function->call(NULL,NULL,0,r_error,&state);	function=NULL; //cleaned up;	state.result=Variant();	return ret;}bool GDFunctionState::is_valid() const {	return function!=NULL;}Variant GDFunctionState::resume(const Variant& p_arg) {	ERR_FAIL_COND_V(!function,Variant());	state.result=p_arg;	Variant::CallError err;	Variant ret = function->call(NULL,NULL,0,err,&state);	function=NULL; //cleaned up;	state.result=Variant();	return ret;}void GDFunctionState::_bind_methods() {	ObjectTypeDB::bind_method(_MD("resume:var","arg"),&GDFunctionState::resume,DEFVAL(Variant()));	ObjectTypeDB::bind_method(_MD("is_valid"),&GDFunctionState::is_valid);	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&GDFunctionState::_signal_callback,MethodInfo("_signal_callback"));}GDFunctionState::GDFunctionState() {	function=NULL;}GDFunctionState::~GDFunctionState() {	if (function!=NULL) {		//never called, deinitialize stack		for(int i=0;i<state.stack_size;i++) {			Variant *v=(Variant*)&state.stack[sizeof(Variant)*i];			v->~Variant();		}	}}///////////////////////////GDNativeClass::GDNativeClass(const StringName& p_name) {	name=p_name;}/*void GDNativeClass::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount){}*/bool GDNativeClass::_get(const StringName& p_name,Variant &r_ret) const {	bool ok;	int v = ObjectTypeDB::get_integer_constant(name, p_name, &ok);	if (ok) {		r_ret=v;		return true;	} else {		return false;	}}void GDNativeClass::_bind_methods() {	ObjectTypeDB::bind_method(_MD("new"),&GDNativeClass::_new);}Variant GDNativeClass::_new() {	Object *o = instance();	if (!o) {		ERR_EXPLAIN("Class type: '"+String(name)+"' is not instantiable.");		ERR_FAIL_COND_V(!o,Variant());	}	Reference *ref = o->cast_to<Reference>();	if (ref) {		return REF(ref);	} else {		return o;	}}Object *GDNativeClass::instance() {	return ObjectTypeDB::instance(name);}GDInstance* GDScript::_create_instance(const Variant** p_args,int p_argcount,Object *p_owner,bool p_isref) {	/* STEP 1, CREATE */	GDInstance* instance = memnew( GDInstance );	instance->base_ref=p_isref;	instance->members.resize(member_indices.size());	instance->script=Ref<GDScript>(this);	instance->owner=p_owner;	instance->owner->set_script_instance(instance);	/* STEP 2, INITIALIZE AND CONSRTUCT */	instances.insert(instance->owner);	Variant::CallError err;	initializer->call(instance,p_args,p_argcount,err);	if (err.error!=Variant::CallError::CALL_OK) {		instance->script=Ref<GDScript>();		instance->owner->set_script_instance(NULL);		instances.erase(p_owner);		ERR_FAIL_COND_V(err.error!=Variant::CallError::CALL_OK, NULL); //error consrtucting	}	//@TODO make thread safe	return instance;}Variant GDScript::_new(const Variant** p_args,int p_argcount,Variant::CallError& r_error) {	/* STEP 1, CREATE */	r_error.error=Variant::CallError::CALL_OK;	REF ref;	Object *owner=NULL;	GDScript *_baseptr=this;	while (_baseptr->_base) {		_baseptr=_baseptr->_base;	}	if (_baseptr->native.ptr()) {		owner=_baseptr->native->instance();	} else {		owner=memnew( Reference ); //by default, no base means use reference	}	Reference *r=owner->cast_to<Reference>();	if (r) {		ref=REF(r);	}	GDInstance* instance = _create_instance(p_args,p_argcount,owner,r!=NULL);	if (!instance) {		if (ref.is_null()) {			memdelete(owner); //no owner, sorry		}		return Variant();	}	if (ref.is_valid()) {				return ref;	} else {		return owner;	}}bool GDScript::can_instance() const {	//return valid; //any script in GDscript can instance	return valid || (!tool && !ScriptServer::is_scripting_enabled());}StringName GDScript::get_instance_base_type() const {	if (native.is_valid())		return native->get_name();	if (base.is_valid())		return base->get_instance_base_type();	return StringName();}struct _GDScriptMemberSort {	int index;	StringName name;	_FORCE_INLINE_ bool operator<(const _GDScriptMemberSort& p_member) const { return index < p_member.index; }};#ifdef TOOLS_ENABLEDvoid GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {	placeholders.erase(p_placeholder);}/*void GDScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {	List<PropertyInfo> plist;	GDScript *scr=this;	Map<StringName,Variant> default_values;	while(scr) {		Vector<_GDScriptMemberSort> msort;		for(Map<StringName,PropertyInfo>::Element *E=scr->member_info.front();E;E=E->next()) {			_GDScriptMemberSort ms;			ERR_CONTINUE(!scr->member_indices.has(E->key()));			ms.index=scr->member_indices[E->key()].index;			ms.name=E->key();			msort.push_back(ms);		}		msort.sort();		msort.invert();		for(int i=0;i<msort.size();i++) {			plist.push_front(scr->member_info[msort[i].name]);			if (scr->member_default_values.has(msort[i].name))				default_values[msort[i].name]=scr->member_default_values[msort[i].name];			else {				Variant::CallError err;				default_values[msort[i].name]=Variant::construct(scr->member_info[msort[i].name].type,NULL,0,err);			}		}		scr=scr->_base;	}	p_placeholder->update(plist,default_values);}*/#endifScriptInstance* GDScript::instance_create(Object *p_this) {	if (!tool && !ScriptServer::is_scripting_enabled()) {#ifdef TOOLS_ENABLED		//instance a fake script for editing the values		//plist.invert();		/*print_line("CREATING PLACEHOLDER");		for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {			print_line(E->get().name);		}*/		PlaceHolderScriptInstance *si = memnew( PlaceHolderScriptInstance(GDScriptLanguage::get_singleton(),Ref<Script>(this),p_this) );		placeholders.insert(si);		//_update_placeholder(si);		_update_exports();		return si;#else		return NULL;#endif	}	GDScript *top=this;	while(top->_base)		top=top->_base;	if (top->native.is_valid()) {		if (!ObjectTypeDB::is_type(p_this->get_type_name(),top->native->get_name())) {			if (ScriptDebugger::get_singleton()) {				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()+"'");			}			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()+"'");			ERR_FAIL_V(NULL);		}	}	return _create_instance(NULL,0,p_this,p_this->cast_to<Reference>());}bool GDScript::instance_has(const Object *p_this) const {	return instances.has((Object*)p_this);}bool GDScript::has_source_code() const {	return source!="";}String GDScript::get_source_code() const {	return source;}void GDScript::set_source_code(const String& p_code) {	if (source==p_code)		return;	source=p_code;#ifdef TOOLS_ENABLED	source_changed_cache=true;	//print_line("SC CHANGED "+get_path());#endif}#ifdef TOOLS_ENABLEDvoid GDScript::_update_exports_values(Map<StringName,Variant>& values, List<PropertyInfo> &propnames) {	if (base_cache.is_valid()) {		base_cache->_update_exports_values(values,propnames);	}	for(Map<StringName,Variant>::Element *E=member_default_values_cache.front();E;E=E->next()) {		values[E->key()]=E->get();	}	for (List<PropertyInfo>::Element *E=members_cache.front();E;E=E->next()) {		propnames.push_back(E->get());	}}#endifbool GDScript::_update_exports() {#ifdef TOOLS_ENABLED	bool changed=false;	if (source_changed_cache) {		//print_line("updating source for "+get_path());		source_changed_cache=false;		changed=true;		String basedir=path;		if (basedir=="")			basedir=get_path();		if (basedir!="")			basedir=basedir.get_base_dir();		GDParser parser;		Error err = parser.parse(source,basedir,true,path);		if (err==OK) {			const GDParser::Node* root = parser.get_parse_tree();			ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,false);			const GDParser::ClassNode *c = static_cast<const GDParser::ClassNode*>(root);			if (base_cache.is_valid()) {				base_cache->inheriters_cache.erase(get_instance_ID());				base_cache=Ref<GDScript>();			}			if (c->extends_used && String(c->extends_file)!="" && String(c->extends_file) != get_path()) {				String path = c->extends_file;				if (path.is_rel_path()) {					String base = get_path();					if (base=="" || base.is_rel_path()) {						ERR_PRINT(("Could not resolve relative path for parent class: "+path).utf8().get_data());					} else {						path=base.get_base_dir().plus_file(path);					}				}				Ref<GDScript> bf = ResourceLoader::load(path);				if (bf.is_valid()) {					//print_line("parent is: "+bf->get_path());					base_cache=bf;					bf->inheriters_cache.insert(get_instance_ID());					//bf->_update_exports(p_instances,true,false);				}			}			members_cache.clear();;			member_default_values_cache.clear();			for(int i=0;i<c->variables.size();i++) {				if (c->variables[i]._export.type==Variant::NIL)					continue;				members_cache.push_back(c->variables[i]._export);				//print_line("found "+c->variables[i]._export.name);				member_default_values_cache[c->variables[i].identifier]=c->variables[i].default_value;			}			_signals.clear();			for(int i=0;i<c->_signals.size();i++) {				_signals[c->_signals[i].name]=c->_signals[i].arguments;			}		}	} else {		//print_line("unchaged is "+get_path());	}	if (base_cache.is_valid()) {		if (base_cache->_update_exports()) {			changed = true;		}	}	if (/*changed &&*/ placeholders.size()) { //hm :(		//print_line("updating placeholders for "+get_path());		//update placeholders if any		Map<StringName,Variant> values;		List<PropertyInfo> propnames;		_update_exports_values(values,propnames);		for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {			E->get()->update(propnames,values);		}	}	return changed;#endif	return false;}void GDScript::update_exports() {#ifdef TOOLS_ENABLED	_update_exports();	Set<ObjectID> copy=inheriters_cache; //might get modified	//print_line("update exports for "+get_path()+" ic: "+itos(copy.size()));	for(Set<ObjectID>::Element *E=copy.front();E;E=E->next()) {		Object *id=ObjectDB::get_instance(E->get());		if (!id)			continue;		GDScript *s=id->cast_to<GDScript>();		if (!s)			continue;		s->update_exports();	}#endif}void GDScript::_set_subclass_path(Ref<GDScript>& p_sc,const String& p_path) {	p_sc->path=p_path;	for(Map<StringName,Ref<GDScript> >::Element *E=p_sc->subclasses.front();E;E=E->next()) {		_set_subclass_path(E->get(),p_path);	}}Error GDScript::reload() {	ERR_FAIL_COND_V(instances.size(),ERR_ALREADY_IN_USE);	String basedir=path;	if (basedir=="")		basedir=get_path();	if (basedir!="")		basedir=basedir.get_base_dir();	valid=false;	GDParser parser;	Error err = parser.parse(source,basedir,false,path);	if (err) {		if (ScriptDebugger::get_singleton()) {			GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),parser.get_error_line(),"Parser Error: "+parser.get_error());		}		_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_FAIL_V(ERR_PARSE_ERROR);	}	GDCompiler compiler;	err = compiler.compile(&parser,this);	if (err) {		if (ScriptDebugger::get_singleton()) {			GDScriptLanguage::get_singleton()->debug_break_parse(get_path(),compiler.get_error_line(),"Parser Error: "+compiler.get_error());		}		_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_FAIL_V(ERR_COMPILATION_FAILED);	}	valid=true;	for(Map<StringName,Ref<GDScript> >::Element *E=subclasses.front();E;E=E->next()) {		_set_subclass_path(E->get(),path);	}#ifdef TOOLS_ENABLED	/*for (Set<PlaceHolderScriptInstance*>::Element *E=placeholders.front();E;E=E->next()) {		_update_placeholder(E->get());	}*/#endif	return OK;}String GDScript::get_node_type() const {	return ""; // ?}ScriptLanguage *GDScript::get_language() const {	return GDScriptLanguage::get_singleton();}Variant GDScript::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {	GDScript *top=this;	while(top) {		Map<StringName,GDFunction>::Element *E=top->member_functions.find(p_method);		if (E) {			if (!E->get().is_static()) {				WARN_PRINT(String("Can't call non-static function: '"+String(p_method)+"' in script.").utf8().get_data());			}			return E->get().call(NULL,p_args,p_argcount,r_error);		}		top=top->_base;	}	//none found, regular	return Script::call(p_method,p_args,p_argcount,r_error);}bool GDScript::_get(const StringName& p_name,Variant &r_ret) const {	{		const GDScript *top=this;		while(top) {			{				const Map<StringName,Variant>::Element *E=top->constants.find(p_name);				if (E) {					r_ret= E->get();					return true;				}			}			{				const Map<StringName,Ref<GDScript> >::Element *E=subclasses.find(p_name);				if (E) {					r_ret=E->get();					return true;				}			}			top=top->_base;		}		if (p_name==GDScriptLanguage::get_singleton()->strings._script_source) {			r_ret=get_source_code();			return true;		}	}	return false;}bool GDScript::_set(const StringName& p_name, const Variant& p_value) {	if (p_name==GDScriptLanguage::get_singleton()->strings._script_source) {		set_source_code(p_value);		reload();	} else		return false;	return true;}void GDScript::_get_property_list(List<PropertyInfo> *p_properties) const {	p_properties->push_back( PropertyInfo(Variant::STRING,"script/source",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );}void GDScript::_bind_methods() {	ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo("new"));	}Error GDScript::load_byte_code(const String& p_path) {	Vector<uint8_t> bytecode;	if (p_path.ends_with("gde")) {		FileAccess *fa = FileAccess::open(p_path,FileAccess::READ);		ERR_FAIL_COND_V(!fa,ERR_CANT_OPEN);		FileAccessEncrypted *fae = memnew( FileAccessEncrypted );		ERR_FAIL_COND_V(!fae,ERR_CANT_OPEN);		Vector<uint8_t> key;		key.resize(32);		for(int i=0;i<key.size();i++) {			key[i]=script_encryption_key[i];		}		Error err = fae->open_and_parse(fa,key,FileAccessEncrypted::MODE_READ);		ERR_FAIL_COND_V(err,err);		bytecode.resize(fae->get_len());		fae->get_buffer(bytecode.ptr(),bytecode.size());		memdelete(fae);	} else {		bytecode = FileAccess::get_file_as_array(p_path);	}	ERR_FAIL_COND_V(bytecode.size()==0,ERR_PARSE_ERROR);	path=p_path;	String basedir=path;	if (basedir=="")		basedir=get_path();	if (basedir!="")		basedir=basedir.get_base_dir();	valid=false;	GDParser parser;	Error err = parser.parse_bytecode(bytecode,basedir,get_path());	if (err) {		_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_FAIL_V(ERR_PARSE_ERROR);	}	GDCompiler compiler;	err = compiler.compile(&parser,this);	if (err) {		_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_FAIL_V(ERR_COMPILATION_FAILED);	}	valid=true;	for(Map<StringName,Ref<GDScript> >::Element *E=subclasses.front();E;E=E->next()) {		_set_subclass_path(E->get(),path);	}	return OK;}Error GDScript::load_source_code(const String& p_path) {	DVector<uint8_t> sourcef;	Error err;	FileAccess *f=FileAccess::open(p_path,FileAccess::READ,&err);	if (err) {		ERR_FAIL_COND_V(err,err);	}	int len = f->get_len();	sourcef.resize(len+1);	DVector<uint8_t>::Write w = sourcef.write();	int r = f->get_buffer(w.ptr(),len);	f->close();	memdelete(f);	ERR_FAIL_COND_V(r!=len,ERR_CANT_OPEN);	w[len]=0;	String s;	if (s.parse_utf8((const char*)w.ptr())) {		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.");		ERR_FAIL_V(ERR_INVALID_DATA);	}	source=s;#ifdef TOOLS_ENABLED	source_changed_cache=true;#endif	//print_line("LSC :"+get_path());	path=p_path;	return OK;}const Map<StringName,GDFunction>& GDScript::debug_get_member_functions() const {	return member_functions;}StringName GDScript::debug_get_member_by_index(int p_idx) const {	for(const Map<StringName,MemberInfo>::Element *E=member_indices.front();E;E=E->next()) {		if (E->get().index==p_idx)			return E->key();	}	return "<error>";}Ref<GDScript> GDScript::get_base() const {	return base;}bool GDScript::has_script_signal(const StringName& p_signal) const {	if (_signals.has(p_signal))		return true;	if (base.is_valid()) {		return base->has_script_signal(p_signal);	}#ifdef TOOLS_ENABLED	else if (base_cache.is_valid()){		return base_cache->has_script_signal(p_signal);	}#endif	return false;}void GDScript::get_script_signal_list(List<MethodInfo> *r_signals) const {	for(const Map<StringName,Vector<StringName> >::Element *E=_signals.front();E;E=E->next()) {		MethodInfo mi;		mi.name=E->key();		for(int i=0;i<E->get().size();i++) {			PropertyInfo arg;			arg.name=E->get()[i];			mi.arguments.push_back(arg);		}		r_signals->push_back(mi);	}	if (base.is_valid()) {		base->get_script_signal_list(r_signals);	}#ifdef TOOLS_ENABLED	else if (base_cache.is_valid()){		base_cache->get_script_signal_list(r_signals);	}#endif}GDScript::GDScript() {	_static_ref=this;	valid=false;	subclass_count=0;	initializer=NULL;	_base=NULL;	_owner=NULL;	tool=false;#ifdef TOOLS_ENABLED	source_changed_cache=false;#endif}////////////////////////////////         INSTANCE         ////////////////////////////////bool GDInstance::set(const StringName& p_name, const Variant& p_value) {	//member	{		const Map<StringName,GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);		if (E) {			if (E->get().setter) {				const Variant *val=&p_value;				Variant::CallError err;				call(E->get().setter,&val,1,err);				if (err.error==Variant::CallError::CALL_OK) {					return true; //function exists, call was successful				}			}			else				members[E->get().index] = p_value;			return true;		}	}	GDScript *sptr=script.ptr();	while(sptr) {		 Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._set);		if (E) {			Variant name=p_name;			const Variant *args[2]={&name,&p_value};			Variant::CallError err;			Variant ret = E->get().call(this,(const Variant**)args,2,err);			if (err.error==Variant::CallError::CALL_OK && ret.get_type()==Variant::BOOL && ret.operator bool())				return true;		}		sptr = sptr->_base;	}	return false;}bool GDInstance::get(const StringName& p_name, Variant &r_ret) const {	const GDScript *sptr=script.ptr();	while(sptr) {		{			const Map<StringName,GDScript::MemberInfo>::Element *E = script->member_indices.find(p_name);			if (E) {				if (E->get().getter) {					Variant::CallError err;					r_ret=const_cast<GDInstance*>(this)->call(E->get().getter,NULL,0,err);					if (err.error==Variant::CallError::CALL_OK) {						return true;					}				}				r_ret=members[E->get().index];				return true; //index found			}		}		{			const Map<StringName,Variant>::Element *E = script->constants.find(p_name);			if (E) {				r_ret=E->get();				return true; //index found			}		}		{			const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get);			if (E) {				Variant name=p_name;				const Variant *args[1]={&name};				Variant::CallError err;				Variant ret = const_cast<GDFunction*>(&E->get())->call(const_cast<GDInstance*>(this),(const Variant**)args,1,err);				if (err.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) {					r_ret=ret;					return true;				}			}		}		sptr = sptr->_base;	}	return false;}void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {	// exported members, not doen yet!	const GDScript *sptr=script.ptr();	List<PropertyInfo> props;	while(sptr) {		const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._get_property_list);		if (E) {			Variant::CallError err;			Variant ret = const_cast<GDFunction*>(&E->get())->call(const_cast<GDInstance*>(this),NULL,0,err);			if (err.error==Variant::CallError::CALL_OK) {				if (ret.get_type()!=Variant::ARRAY) {					ERR_EXPLAIN("Wrong type for _get_property list, must be an array of dictionaries.");					ERR_FAIL();				}				Array arr = ret;				for(int i=0;i<arr.size();i++) {					Dictionary d = arr[i];					ERR_CONTINUE(!d.has("name"));					ERR_CONTINUE(!d.has("type"));					PropertyInfo pinfo;					pinfo.type = Variant::Type( d["type"].operator int());					ERR_CONTINUE(pinfo.type<0 || pinfo.type>=Variant::VARIANT_MAX );					pinfo.name = d["name"];					ERR_CONTINUE(pinfo.name=="");					if (d.has("hint"))						pinfo.hint=PropertyHint(d["hint"].operator int());					if (d.has("hint_string"))						pinfo.hint_string=d["hint_string"];					if (d.has("usage"))						pinfo.usage=d["usage"];					props.push_back(pinfo);				}			}		}		//instance a fake script for editing the values		Vector<_GDScriptMemberSort> msort;		for(Map<StringName,PropertyInfo>::Element *E=sptr->member_info.front();E;E=E->next()) {			_GDScriptMemberSort ms;			ERR_CONTINUE(!sptr->member_indices.has(E->key()));			ms.index=sptr->member_indices[E->key()].index;			ms.name=E->key();			msort.push_back(ms);		}		msort.sort();		msort.invert();		for(int i=0;i<msort.size();i++) {			props.push_front(sptr->member_info[msort[i].name]);		}#if 0		if (sptr->member_functions.has("_get_property_list")) {			Variant::CallError err;			GDFunction *f = const_cast<GDFunction*>(&sptr->member_functions["_get_property_list"]);			Variant plv = f->call(const_cast<GDInstance*>(this),NULL,0,err);			if (plv.get_type()!=Variant::ARRAY) {				ERR_PRINT("_get_property_list: expected array returned");			} else {				Array pl=plv;				for(int i=0;i<pl.size();i++) {					Dictionary p = pl[i];					PropertyInfo pinfo;					if (!p.has("name")) {						ERR_PRINT("_get_property_list: expected 'name' key of type string.")						continue;					}					if (!p.has("type")) {						ERR_PRINT("_get_property_list: expected 'type' key of type integer.")						continue;					}					pinfo.name=p["name"];					pinfo.type=Variant::Type(int(p["type"]));					if (p.has("hint"))						pinfo.hint=PropertyHint(int(p["hint"]));					if (p.has("hint_string"))						pinfo.hint_string=p["hint_string"];					if (p.has("usage"))						pinfo.usage=p["usage"];					props.push_back(pinfo);				}			}		}#endif		sptr = sptr->_base;	}	//props.invert();	for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {		p_properties->push_back(E->get());	}}void GDInstance::get_method_list(List<MethodInfo> *p_list) const {	const GDScript *sptr=script.ptr();	while(sptr) {		for (Map<StringName,GDFunction>::Element *E = sptr->member_functions.front();E;E=E->next()) {			MethodInfo mi;			mi.name=E->key();			for(int i=0;i<E->get().get_argument_count();i++)				mi.arguments.push_back(PropertyInfo(Variant::NIL,"arg"+itos(i)));			p_list->push_back(mi);		}		sptr = sptr->_base;	}}bool GDInstance::has_method(const StringName& p_method) const {	const GDScript *sptr=script.ptr();	while(sptr) {		const Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);		if (E)			return true;		sptr = sptr->_base;	}	return false;}Variant GDInstance::call(const StringName& p_method,const Variant** p_args,int p_argcount,Variant::CallError &r_error) {	//printf("calling %ls:%i method %ls\n", script->get_path().c_str(), -1, String(p_method).c_str());	GDScript *sptr=script.ptr();	while(sptr) {		Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);		if (E) {			return E->get().call(this,p_args,p_argcount,r_error);		}		sptr = sptr->_base;	}	r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;	return Variant();}void GDInstance::call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount) {	GDScript *sptr=script.ptr();	Variant::CallError ce;	while(sptr) {		Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);		if (E) {			E->get().call(this,p_args,p_argcount,ce);		}		sptr = sptr->_base;	}}void GDInstance::_ml_call_reversed(GDScript *sptr,const StringName& p_method,const Variant** p_args,int p_argcount) {	if (sptr->_base)		_ml_call_reversed(sptr->_base,p_method,p_args,p_argcount);	Variant::CallError ce;	Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(p_method);	if (E) {		E->get().call(this,p_args,p_argcount,ce);	}}void GDInstance::call_multilevel_reversed(const StringName& p_method,const Variant** p_args,int p_argcount) {	if (script.ptr()) {		_ml_call_reversed(script.ptr(),p_method,p_args,p_argcount);	}}void GDInstance::notification(int p_notification) {	//notification is not virutal, it gets called at ALL levels just like in C.	Variant value=p_notification;	const Variant *args[1]={&value };	GDScript *sptr=script.ptr();	while(sptr) {		Map<StringName,GDFunction>::Element *E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);		if (E) {			Variant::CallError err;			E->get().call(this,args,1,err);			if (err.error!=Variant::CallError::CALL_OK) {				//print error about notification call			}		}		sptr = sptr->_base;	}}Ref<Script> GDInstance::get_script() const {	return script;}ScriptLanguage *GDInstance::get_language() {	return GDScriptLanguage::get_singleton();}GDInstance::GDInstance() {	owner=NULL;	base_ref=false;}GDInstance::~GDInstance() {	if (script.is_valid() && owner) {		script->instances.erase(owner);	}}/************* SCRIPT LANGUAGE **************//************* SCRIPT LANGUAGE **************//************* SCRIPT LANGUAGE **************//************* SCRIPT LANGUAGE **************//************* SCRIPT LANGUAGE **************/GDScriptLanguage *GDScriptLanguage::singleton=NULL;String GDScriptLanguage::get_name() const {	return "GDScript";}/* LANGUAGE FUNCTIONS */void GDScriptLanguage::_add_global(const StringName& p_name,const Variant& p_value) {	if (globals.has(p_name)) {		//overwrite existing		global_array[globals[p_name]]=p_value;		return;	}	globals[p_name]=global_array.size();	global_array.push_back(p_value);	_global_array=global_array.ptr();}void GDScriptLanguage::init() {	//populate global constants	int gcc=GlobalConstants::get_global_constant_count();	for(int i=0;i<gcc;i++) {		_add_global(StaticCString::create(GlobalConstants::get_global_constant_name(i)),GlobalConstants::get_global_constant_value(i));	}	_add_global(StaticCString::create("PI"),Math_PI);	//populate native classes	List<String> class_list;	ObjectTypeDB::get_type_list(&class_list);	for(List<String>::Element *E=class_list.front();E;E=E->next()) {		StringName n = E->get();		String s = String(n);		if (s.begins_with("_"))			n=s.substr(1,s.length());		if (globals.has(n))			continue;		Ref<GDNativeClass> nc = memnew( GDNativeClass(E->get()) );		_add_global(n,nc);	}	//populate singletons	List<Globals::Singleton> singletons;	Globals::get_singleton()->get_singletons(&singletons);	for(List<Globals::Singleton>::Element *E=singletons.front();E;E=E->next()) {		_add_global(E->get().name,E->get().ptr);	}}String GDScriptLanguage::get_type() const {	return "GDScript";}String GDScriptLanguage::get_extension() const {	return "gd";}Error GDScriptLanguage::execute_file(const String& p_path)  {	// ??	return OK;}void GDScriptLanguage::finish()  {}void GDScriptLanguage::frame() {//	print_line("calls: "+itos(calls));	calls=0;}/* EDITOR FUNCTIONS */void GDScriptLanguage::get_reserved_words(List<String> *p_words) const  {	static const char *_reserved_words[]={		"break",		"class",		"continue",		"const",		"else",		"elif",		"enum",		"extends"	,		"for"	,		"func"	,		"if"	,		"in"	,		"null"	,		"not"	,		"return"	,		"self"	,		"while"	,		"true"	,		"false"	,		"tool",		"var",		"setget",		"pass",		"and",		"or",		"export",		"assert",		"yield",		"static",		"float",		"int",		"signal",	0};	const char **w=_reserved_words;	while (*w) {		p_words->push_back(*w);		w++;	}	for(int i=0;i<GDFunctions::FUNC_MAX;i++) {		p_words->push_back(GDFunctions::get_func_name(GDFunctions::Function(i)));	}}GDScriptLanguage::GDScriptLanguage() {	calls=0;	ERR_FAIL_COND(singleton);	singleton=this;	strings._init = StaticCString::create("_init");	strings._notification = StaticCString::create("_notification");	strings._set= StaticCString::create("_set");	strings._get= StaticCString::create("_get");	strings._get_property_list= StaticCString::create("_get_property_list");	strings._script_source=StaticCString::create("script/source");	_debug_parse_err_line=-1;	_debug_parse_err_file="";    _debug_call_stack_pos=0;    int dmcs=GLOBAL_DEF("debug/script_max_call_stack",1024);    if (ScriptDebugger::get_singleton()) {        //debugging enabled!	_debug_max_call_stack = dmcs;        if (_debug_max_call_stack<1024)            _debug_max_call_stack=1024;	_call_stack = memnew_arr( CallLevel, _debug_max_call_stack+1 );    } else {        _debug_max_call_stack=0;        _call_stack=NULL;    }}GDScriptLanguage::~GDScriptLanguage() {    if (_call_stack)  {        memdelete_arr(_call_stack);    }    singleton=NULL;}/*************** RESOURCE ***************/RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_original_path) {	GDScript *script = memnew( GDScript );	Ref<GDScript> scriptres(script);	if (p_path.ends_with(".gde") || p_path.ends_with(".gdc")) {		script->set_script_path(p_original_path); // script needs this.		script->set_path(p_original_path);		Error err = script->load_byte_code(p_path);		if (err!=OK) {			ERR_FAIL_COND_V(err!=OK, RES());		}	} else {		Error err = script->load_source_code(p_path);		if (err!=OK) {			ERR_FAIL_COND_V(err!=OK, RES());		}		script->set_script_path(p_original_path); // script needs this.		script->set_path(p_original_path);		//script->set_name(p_path.get_file());		script->reload();	}	return scriptres;}void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const {	p_extensions->push_back("gd");	p_extensions->push_back("gdc");	p_extensions->push_back("gde");}bool ResourceFormatLoaderGDScript::handles_type(const String& p_type) const {	return (p_type=="Script" || p_type=="GDScript");}String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const {	String el = p_path.extension().to_lower();	if (el=="gd" || el=="gdc" || el=="gde")		return "GDScript";	return "";}Error ResourceFormatSaverGDScript::save(const String &p_path,const RES& p_resource,uint32_t p_flags) {	Ref<GDScript> sqscr = p_resource;	ERR_FAIL_COND_V(sqscr.is_null(),ERR_INVALID_PARAMETER);	String source = sqscr->get_source_code();	Error err;	FileAccess *file = FileAccess::open(p_path,FileAccess::WRITE,&err);	if (err) {		ERR_FAIL_COND_V(err,err);	}	file->store_string(source);	if (file->get_error()!=OK && file->get_error()!=ERR_FILE_EOF) {		memdelete(file);		return ERR_CANT_CREATE;	}	file->close();	memdelete(file);	return OK;}void ResourceFormatSaverGDScript::get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const {	if (p_resource->cast_to<GDScript>()) {		p_extensions->push_back("gd");	}}bool ResourceFormatSaverGDScript::recognize(const RES& p_resource) const {	return p_resource->cast_to<GDScript>()!=NULL;}
 |