as_module.cpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2015 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_module.cpp
  25. //
  26. // A class that holds a script module
  27. //
  28. #include "as_config.h"
  29. #include "as_module.h"
  30. #include "as_builder.h"
  31. #include "as_context.h"
  32. #include "as_texts.h"
  33. #include "as_debug.h"
  34. #include "as_restore.h"
  35. BEGIN_AS_NAMESPACE
  36. // TODO: 2.30.0: redesign: Improved method for discarding modules (faster clean-up, less abuse of garbage collector)
  37. //
  38. // I need to separate the reference counter for internal references and outside references:
  39. //
  40. // - Internal references are for example, when the module refers to a function or object since it is declared in the module, or when
  41. // a function refers to another function since it is being called in the code.
  42. // - Outside references are for example object instances holding a reference to the object type, or a context currently
  43. // executing a function.
  44. //
  45. // If no object instances are alive or no contexts are alive it is known that functions from a discarded module
  46. // can be called, so they can be destroyed without any need to execute the complex garbage collection routines.
  47. //
  48. // If there are live objects, the entire module should be kept for safe keeping, though no longer visible.
  49. //
  50. // TODO: It may not be necessary to keep track of internal references. Without keeping track of internal references, can I still
  51. // handle RemoveFunction and RemoveGlobalVariable correctly?
  52. //
  53. // TODO: How to avoid global variables keeping code alive? For example a script object, or a funcdef?
  54. // Can I do a quick check of the object types and functions to count number of outside references, and then do another
  55. // check over the global variables to subtract the outside references coming from these? What if the outside reference
  56. // is added by an application type in a global variable that the engine doesn't know about? Example, a global dictionary
  57. // holding object instances. Should discarding a module immediately destroy the content of the global variables? What if
  58. // a live object tries to access the global variable after it has been discarded? Throwing a script exception is acceptable?
  59. // Perhaps I need to allow the user to provide a clean-up routine that will be executed before destroying the objects.
  60. // Or I might just put that responsibility on the application.
  61. // internal
  62. asCModule::asCModule(const char *name, asCScriptEngine *engine)
  63. {
  64. this->name = name;
  65. this->engine = engine;
  66. userData = 0;
  67. builder = 0;
  68. isGlobalVarInitialized = false;
  69. accessMask = 1;
  70. defaultNamespace = engine->nameSpaces[0];
  71. }
  72. // internal
  73. asCModule::~asCModule()
  74. {
  75. InternalReset();
  76. // The builder is not removed by InternalReset because it holds the script
  77. // sections that will be built, so we need to explictly remove it now if it exists
  78. if( builder )
  79. {
  80. asDELETE(builder,asCBuilder);
  81. builder = 0;
  82. }
  83. if( engine )
  84. {
  85. // Clean the user data
  86. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  87. {
  88. if( userData[n+1] )
  89. {
  90. for( asUINT c = 0; c < engine->cleanModuleFuncs.GetLength(); c++ )
  91. if( engine->cleanModuleFuncs[c].type == userData[n] )
  92. engine->cleanModuleFuncs[c].cleanFunc(this);
  93. }
  94. }
  95. // Remove the module from the engine
  96. ACQUIREEXCLUSIVE(engine->engineRWLock);
  97. // The module must have been discarded before it is deleted
  98. asASSERT( !engine->scriptModules.Exists(this) );
  99. engine->discardedModules.RemoveValue(this);
  100. RELEASEEXCLUSIVE(engine->engineRWLock);
  101. }
  102. }
  103. // interface
  104. void asCModule::Discard()
  105. {
  106. // Reset the global variables already so that no object in the global variables keep the module alive forever.
  107. // If any live object tries to access the global variables during clean up they will fail with a script exception,
  108. // so the application must keep that in mind before discarding a module.
  109. CallExit();
  110. // Keep a local copy of the engine pointer, because once the module is moved do the discarded
  111. // pile, it is possible that another thread might discard it while we are still in here. So no
  112. // further access to members may be done after that
  113. asCScriptEngine *lEngine = engine;
  114. // Instead of deleting the module immediately, move it to the discarded pile
  115. // This will turn it invisible to the application, yet keep it alive until all
  116. // external references to its entities have been released.
  117. ACQUIREEXCLUSIVE(engine->engineRWLock);
  118. if( lEngine->lastModule == this )
  119. lEngine->lastModule = 0;
  120. lEngine->scriptModules.RemoveValue(this);
  121. lEngine->discardedModules.PushLast(this);
  122. RELEASEEXCLUSIVE(lEngine->engineRWLock);
  123. // Allow the engine to go over the list of discarded modules to see what can be cleaned up at this moment.
  124. // Don't do this if the engine is already shutting down, as it will be done explicitly by the engine itself with error reporting
  125. if( !lEngine->shuttingDown )
  126. {
  127. if( lEngine->ep.autoGarbageCollect )
  128. lEngine->GarbageCollect();
  129. else
  130. {
  131. // GarbageCollect calls DeleteDiscardedModules, so no need
  132. // to call it again if we already called GarbageCollect
  133. lEngine->DeleteDiscardedModules();
  134. }
  135. }
  136. }
  137. // interface
  138. void *asCModule::SetUserData(void *data, asPWORD type)
  139. {
  140. // As a thread might add a new new user data at the same time as another
  141. // it is necessary to protect both read and write access to the userData member
  142. ACQUIREEXCLUSIVE(engine->engineRWLock);
  143. // It is not intended to store a lot of different types of userdata,
  144. // so a more complex structure like a associative map would just have
  145. // more overhead than a simple array.
  146. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  147. {
  148. if( userData[n] == type )
  149. {
  150. void *oldData = reinterpret_cast<void*>(userData[n+1]);
  151. userData[n+1] = reinterpret_cast<asPWORD>(data);
  152. RELEASEEXCLUSIVE(engine->engineRWLock);
  153. return oldData;
  154. }
  155. }
  156. userData.PushLast(type);
  157. userData.PushLast(reinterpret_cast<asPWORD>(data));
  158. RELEASEEXCLUSIVE(engine->engineRWLock);
  159. return 0;
  160. }
  161. // interface
  162. void *asCModule::GetUserData(asPWORD type) const
  163. {
  164. // There may be multiple threads reading, but when
  165. // setting the user data nobody must be reading.
  166. ACQUIRESHARED(engine->engineRWLock);
  167. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  168. {
  169. if( userData[n] == type )
  170. {
  171. void *ud = reinterpret_cast<void*>(userData[n+1]);
  172. RELEASESHARED(engine->engineRWLock);
  173. return ud;
  174. }
  175. }
  176. RELEASESHARED(engine->engineRWLock);
  177. return 0;
  178. }
  179. // interface
  180. asIScriptEngine *asCModule::GetEngine() const
  181. {
  182. return engine;
  183. }
  184. // interface
  185. void asCModule::SetName(const char *name)
  186. {
  187. this->name = name;
  188. }
  189. // interface
  190. const char *asCModule::GetName() const
  191. {
  192. return name.AddressOf();
  193. }
  194. // interface
  195. const char *asCModule::GetDefaultNamespace() const
  196. {
  197. return defaultNamespace->name.AddressOf();
  198. }
  199. // interface
  200. int asCModule::SetDefaultNamespace(const char *nameSpace)
  201. {
  202. // TODO: cleanup: This function is similar to asCScriptEngine::SetDefaultNamespace. Can we reuse the code?
  203. if( nameSpace == 0 )
  204. return asINVALID_ARG;
  205. asCString ns = nameSpace;
  206. if( ns != "" )
  207. {
  208. // Make sure the namespace is composed of alternating identifier and ::
  209. size_t pos = 0;
  210. bool expectIdentifier = true;
  211. size_t len;
  212. eTokenType t = ttIdentifier;
  213. for( ; pos < ns.GetLength(); pos += len )
  214. {
  215. t = engine->tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len);
  216. if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) )
  217. return asINVALID_DECLARATION;
  218. expectIdentifier = !expectIdentifier;
  219. }
  220. // If the namespace ends with :: then strip it off
  221. if( t == ttScope )
  222. ns.SetLength(ns.GetLength()-2);
  223. }
  224. defaultNamespace = engine->AddNameSpace(ns.AddressOf());
  225. return 0;
  226. }
  227. // interface
  228. int asCModule::AddScriptSection(const char *name, const char *code, size_t codeLength, int lineOffset)
  229. {
  230. #ifdef AS_NO_COMPILER
  231. UNUSED_VAR(name);
  232. UNUSED_VAR(code);
  233. UNUSED_VAR(codeLength);
  234. UNUSED_VAR(lineOffset);
  235. return asNOT_SUPPORTED;
  236. #else
  237. if( !builder )
  238. {
  239. builder = asNEW(asCBuilder)(engine, this);
  240. if( builder == 0 )
  241. return asOUT_OF_MEMORY;
  242. }
  243. return builder->AddCode(name, code, (int)codeLength, lineOffset, (int)engine->GetScriptSectionNameIndex(name ? name : ""), engine->ep.copyScriptSections);
  244. #endif
  245. }
  246. // internal
  247. void asCModule::JITCompile()
  248. {
  249. asIJITCompiler *jit = engine->GetJITCompiler();
  250. if( !jit )
  251. return;
  252. for (unsigned int i = 0; i < scriptFunctions.GetLength(); i++)
  253. scriptFunctions[i]->JITCompile();
  254. }
  255. // interface
  256. int asCModule::Build()
  257. {
  258. #ifdef AS_NO_COMPILER
  259. return asNOT_SUPPORTED;
  260. #else
  261. TimeIt("asCModule::Build");
  262. // Don't allow the module to be rebuilt if there are still
  263. // external references that will need the previous code
  264. // TODO: 2.30.0: interface: The asIScriptModule must have a method for querying if the module is used
  265. if( HasExternalReferences(false) )
  266. {
  267. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
  268. return asMODULE_IS_IN_USE;
  269. }
  270. // Only one thread may build at one time
  271. // TODO: It should be possible to have multiple threads perform compilations
  272. int r = engine->RequestBuild();
  273. if( r < 0 )
  274. return r;
  275. engine->PrepareEngine();
  276. if( engine->configFailed )
  277. {
  278. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  279. engine->BuildCompleted();
  280. return asINVALID_CONFIGURATION;
  281. }
  282. InternalReset();
  283. if( !builder )
  284. {
  285. engine->BuildCompleted();
  286. return asSUCCESS;
  287. }
  288. // Compile the script
  289. r = builder->Build();
  290. asDELETE(builder,asCBuilder);
  291. builder = 0;
  292. if( r < 0 )
  293. {
  294. // Reset module again
  295. InternalReset();
  296. engine->BuildCompleted();
  297. return r;
  298. }
  299. JITCompile();
  300. engine->PrepareEngine();
  301. #ifdef AS_DEBUG
  302. // Verify that there are no unwanted gaps in the scriptFunctions array.
  303. for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ )
  304. {
  305. int id = n;
  306. if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) )
  307. asASSERT( false );
  308. }
  309. #endif
  310. engine->BuildCompleted();
  311. // Initialize global variables
  312. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  313. r = ResetGlobalVars(0);
  314. return r;
  315. #endif
  316. }
  317. // interface
  318. int asCModule::ResetGlobalVars(asIScriptContext *ctx)
  319. {
  320. if( isGlobalVarInitialized )
  321. CallExit();
  322. return CallInit(ctx);
  323. }
  324. // interface
  325. asIScriptFunction *asCModule::GetFunctionByIndex(asUINT index) const
  326. {
  327. return const_cast<asCScriptFunction*>(globalFunctions.Get(index));
  328. }
  329. // internal
  330. int asCModule::CallInit(asIScriptContext *myCtx)
  331. {
  332. if( isGlobalVarInitialized )
  333. return asERROR;
  334. // Each global variable needs to be cleared individually
  335. asCSymbolTableIterator<asCGlobalProperty> it = scriptGlobals.List();
  336. while( it )
  337. {
  338. asCGlobalProperty *desc = *it;
  339. memset(desc->GetAddressOfValue(), 0, sizeof(asDWORD)*desc->type.GetSizeOnStackDWords());
  340. it++;
  341. }
  342. // Call the init function for each of the global variables
  343. asIScriptContext *ctx = myCtx;
  344. int r = asEXECUTION_FINISHED;
  345. it = scriptGlobals.List();
  346. while( it && r == asEXECUTION_FINISHED )
  347. {
  348. asCGlobalProperty *desc = *it;
  349. it++;
  350. if( desc->GetInitFunc() )
  351. {
  352. if( ctx == 0 )
  353. {
  354. ctx = engine->RequestContext();
  355. if( ctx == 0 )
  356. break;
  357. }
  358. r = ctx->Prepare(desc->GetInitFunc());
  359. if( r >= 0 )
  360. {
  361. r = ctx->Execute();
  362. if( r != asEXECUTION_FINISHED )
  363. {
  364. asCString msg;
  365. msg.Format(TXT_FAILED_TO_INITIALIZE_s, desc->name.AddressOf());
  366. asCScriptFunction *func = desc->GetInitFunc();
  367. engine->WriteMessage(func->scriptData->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptData->scriptSectionIdx]->AddressOf() : "",
  368. func->GetLineNumber(0, 0) & 0xFFFFF,
  369. func->GetLineNumber(0, 0) >> 20,
  370. asMSGTYPE_ERROR,
  371. msg.AddressOf());
  372. if( r == asEXECUTION_EXCEPTION )
  373. {
  374. const asIScriptFunction *function = ctx->GetExceptionFunction();
  375. msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration());
  376. engine->WriteMessage(function->GetScriptSectionName(),
  377. ctx->GetExceptionLineNumber(),
  378. 0,
  379. asMSGTYPE_INFORMATION,
  380. msg.AddressOf());
  381. }
  382. }
  383. }
  384. }
  385. }
  386. if( ctx && !myCtx )
  387. {
  388. engine->ReturnContext(ctx);
  389. ctx = 0;
  390. }
  391. // Even if the initialization failed we need to set the
  392. // flag that the variables have been initialized, otherwise
  393. // the module won't free those variables that really were
  394. // initialized.
  395. isGlobalVarInitialized = true;
  396. if( r != asEXECUTION_FINISHED )
  397. return asINIT_GLOBAL_VARS_FAILED;
  398. return asSUCCESS;
  399. }
  400. // internal
  401. void asCModule::CallExit()
  402. {
  403. if( !isGlobalVarInitialized ) return;
  404. asCSymbolTableIterator<asCGlobalProperty> it = scriptGlobals.List();
  405. while( it )
  406. {
  407. if( (*it)->type.IsObject() )
  408. {
  409. void **obj = (void**)(*it)->GetAddressOfValue();
  410. if( *obj )
  411. {
  412. asCObjectType *ot = (*it)->type.GetObjectType();
  413. if( ot->flags & asOBJ_REF )
  414. {
  415. asASSERT( (ot->flags & asOBJ_NOCOUNT) || ot->beh.release );
  416. if( ot->beh.release )
  417. engine->CallObjectMethod(*obj, ot->beh.release);
  418. }
  419. else
  420. {
  421. if( ot->beh.destruct )
  422. engine->CallObjectMethod(*obj, ot->beh.destruct);
  423. engine->CallFree(*obj);
  424. }
  425. // Set the address to 0 as someone might try to access the variable afterwards
  426. *obj = 0;
  427. }
  428. }
  429. it++;
  430. }
  431. isGlobalVarInitialized = false;
  432. }
  433. // internal
  434. bool asCModule::HasExternalReferences(bool shuttingDown)
  435. {
  436. // Check all entiteis in the module for any external references.
  437. // If there are any external references the module cannot be deleted yet.
  438. for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
  439. if( scriptFunctions[n] && scriptFunctions[n]->externalRefCount.get() )
  440. {
  441. if( !shuttingDown )
  442. return true;
  443. else
  444. {
  445. asCString msg;
  446. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  447. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  448. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, scriptFunctions[n]->GetName(), scriptFunctions[n]->GetFuncType());
  449. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  450. }
  451. }
  452. for( asUINT n = 0; n < classTypes.GetLength(); n++ )
  453. if( classTypes[n] && classTypes[n]->externalRefCount.get() )
  454. {
  455. if( !shuttingDown )
  456. return true;
  457. else
  458. {
  459. asCString msg;
  460. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  461. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  462. msg.Format(TXT_PREV_TYPE_IS_NAMED_s, classTypes[n]->GetName());
  463. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  464. }
  465. }
  466. for( asUINT n = 0; n < funcDefs.GetLength(); n++ )
  467. if( funcDefs[n] && funcDefs[n]->externalRefCount.get() )
  468. {
  469. if( !shuttingDown )
  470. return true;
  471. else
  472. {
  473. asCString msg;
  474. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  475. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  476. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, funcDefs[n]->GetName(), funcDefs[n]->GetFuncType());
  477. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  478. }
  479. }
  480. for( asUINT n = 0; n < templateInstances.GetLength(); n++ )
  481. if( templateInstances[n] && templateInstances[n]->externalRefCount.get() )
  482. {
  483. if( !shuttingDown )
  484. return true;
  485. else
  486. {
  487. asCString msg;
  488. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  489. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  490. msg.Format(TXT_PREV_TYPE_IS_NAMED_s, templateInstances[n]->GetName());
  491. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  492. }
  493. }
  494. return false;
  495. }
  496. // internal
  497. void asCModule::InternalReset()
  498. {
  499. CallExit();
  500. asUINT n;
  501. // Remove all global functions
  502. globalFunctions.Clear();
  503. // Destroy the internals of the global properties here, but do not yet remove them from the
  504. // engine, because functions need the engine's varAddressMap to get to the property. If the
  505. // property is removed already, it may leak as the refCount doesn't reach 0.
  506. asCSymbolTableIterator<asCGlobalProperty> globIt = scriptGlobals.List();
  507. while( globIt )
  508. {
  509. (*globIt)->DestroyInternal();
  510. globIt++;
  511. }
  512. UnbindAllImportedFunctions();
  513. // Free bind information
  514. for( n = 0; n < bindInformations.GetLength(); n++ )
  515. {
  516. if( bindInformations[n] )
  517. {
  518. bindInformations[n]->importedFunctionSignature->ReleaseInternal();
  519. asDELETE(bindInformations[n], sBindInfo);
  520. }
  521. }
  522. bindInformations.SetLength(0);
  523. // Free declared types, including classes, typedefs, and enums
  524. for( n = 0; n < templateInstances.GetLength(); n++ )
  525. {
  526. asCObjectType *type = templateInstances[n];
  527. if( engine->FindNewOwnerForSharedType(type, this) != this )
  528. {
  529. // The type is owned by another module, just release our reference
  530. type->ReleaseInternal();
  531. continue;
  532. }
  533. // Orphan the template instance
  534. type->module = 0;
  535. // No other module is holding the template type
  536. engine->RemoveTemplateInstanceType(type);
  537. type->ReleaseInternal();
  538. }
  539. templateInstances.SetLength(0);
  540. for( n = 0; n < classTypes.GetLength(); n++ )
  541. {
  542. asCObjectType *type = classTypes[n];
  543. if( type->IsShared() )
  544. {
  545. // The type is shared, so transfer ownership to another module that also uses it
  546. if( engine->FindNewOwnerForSharedType(type, this) != this )
  547. {
  548. // The type is owned by another module, just release our reference
  549. type->ReleaseInternal();
  550. continue;
  551. }
  552. }
  553. // The type should be destroyed now
  554. type->DestroyInternal();
  555. // Remove the type from the engine
  556. if( type->IsShared() )
  557. {
  558. engine->sharedScriptTypes.RemoveValue(type);
  559. type->ReleaseInternal();
  560. }
  561. // Release it from the module
  562. type->module = 0;
  563. type->ReleaseInternal();
  564. }
  565. classTypes.SetLength(0);
  566. for( n = 0; n < enumTypes.GetLength(); n++ )
  567. {
  568. asCObjectType *type = enumTypes[n];
  569. if( type->IsShared() )
  570. {
  571. // The type is shared, so transfer ownership to another module that also uses it
  572. if( engine->FindNewOwnerForSharedType(type, this) != this )
  573. {
  574. // The type is owned by another module, just release our reference
  575. type->ReleaseInternal();
  576. continue;
  577. }
  578. }
  579. // The type should be destroyed now
  580. type->DestroyInternal();
  581. // Remove the type from the engine
  582. if( type->IsShared() )
  583. {
  584. engine->sharedScriptTypes.RemoveValue(type);
  585. type->ReleaseInternal();
  586. }
  587. // Release it from the module
  588. type->module = 0;
  589. type->ReleaseInternal();
  590. }
  591. enumTypes.SetLength(0);
  592. for( n = 0; n < typeDefs.GetLength(); n++ )
  593. {
  594. asCObjectType *type = typeDefs[n];
  595. // The type should be destroyed now
  596. type->DestroyInternal();
  597. // Release it from the module
  598. type->module = 0;
  599. type->ReleaseInternal();
  600. }
  601. typeDefs.SetLength(0);
  602. // Free funcdefs
  603. for( n = 0; n < funcDefs.GetLength(); n++ )
  604. {
  605. asCScriptFunction *func = funcDefs[n];
  606. if( func->IsShared() )
  607. {
  608. // The func is shared, so transfer ownership to another module that also uses it
  609. if( engine->FindNewOwnerForSharedFunc(func, this) != this )
  610. {
  611. // The func is owned by another module, just release our reference
  612. func->ReleaseInternal();
  613. continue;
  614. }
  615. }
  616. func->DestroyInternal();
  617. engine->RemoveFuncdef(func);
  618. func->module = 0;
  619. func->ReleaseInternal();
  620. }
  621. funcDefs.SetLength(0);
  622. // Then release the functions
  623. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  624. {
  625. asCScriptFunction *func = scriptFunctions[n];
  626. if( func->IsShared() )
  627. {
  628. // The func is shared, so transfer ownership to another module that also uses it
  629. if( engine->FindNewOwnerForSharedFunc(func, this) != this )
  630. {
  631. // The func is owned by another module, just release our reference
  632. func->ReleaseInternal();
  633. continue;
  634. }
  635. }
  636. func->DestroyInternal();
  637. func->module = 0;
  638. func->ReleaseInternal();
  639. }
  640. scriptFunctions.SetLength(0);
  641. // Now remove and release the global properties as there are no more references to them
  642. globIt = scriptGlobals.List();
  643. while( globIt )
  644. {
  645. engine->RemoveGlobalProperty(*globIt);
  646. asASSERT( (*globIt)->refCount.get() == 1 );
  647. (*globIt)->Release();
  648. globIt++;
  649. }
  650. scriptGlobals.Clear();
  651. asASSERT( IsEmpty() );
  652. }
  653. // interface
  654. asIScriptFunction *asCModule::GetFunctionByName(const char *name) const
  655. {
  656. asSNameSpace *ns = defaultNamespace;
  657. while( ns )
  658. {
  659. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, name);
  660. if( idxs.GetLength() != 1 )
  661. return 0;
  662. const asIScriptFunction *func = globalFunctions.Get(idxs[0]);
  663. if( func )
  664. return const_cast<asIScriptFunction*>(func);
  665. // Recursively search parent namespaces
  666. ns = engine->GetParentNameSpace(ns);
  667. }
  668. return 0;
  669. }
  670. // interface
  671. asUINT asCModule::GetImportedFunctionCount() const
  672. {
  673. return (asUINT)bindInformations.GetLength();
  674. }
  675. // interface
  676. int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
  677. {
  678. asCBuilder bld(engine, const_cast<asCModule*>(this));
  679. // Don't write parser errors to the message callback
  680. bld.silent = true;
  681. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  682. bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  683. // TODO: optimize: Improve linear search
  684. // Search script functions for matching interface
  685. int id = -1;
  686. for( asUINT n = 0; n < bindInformations.GetLength(); ++n )
  687. {
  688. if( func.name == bindInformations[n]->importedFunctionSignature->name &&
  689. func.returnType == bindInformations[n]->importedFunctionSignature->returnType &&
  690. func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() )
  691. {
  692. bool match = true;
  693. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  694. {
  695. if( func.parameterTypes[p] != bindInformations[n]->importedFunctionSignature->parameterTypes[p] )
  696. {
  697. match = false;
  698. break;
  699. }
  700. }
  701. if( match )
  702. {
  703. if( id == -1 )
  704. id = n;
  705. else
  706. return asMULTIPLE_FUNCTIONS;
  707. }
  708. }
  709. }
  710. if( id == -1 ) return asNO_FUNCTION;
  711. return id;
  712. }
  713. // interface
  714. asUINT asCModule::GetFunctionCount() const
  715. {
  716. return (asUINT)globalFunctions.GetSize();
  717. }
  718. // interface
  719. asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const
  720. {
  721. asCBuilder bld(engine, const_cast<asCModule*>(this));
  722. // Don't write parser errors to the message callback
  723. bld.silent = true;
  724. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  725. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  726. if( r < 0 )
  727. {
  728. // Invalid declaration
  729. // TODO: Write error to message stream
  730. return 0;
  731. }
  732. // Use the defaultNamespace implicitly unless an explicit namespace has been provided
  733. asSNameSpace *ns = func.nameSpace == engine->nameSpaces[0] ? defaultNamespace : func.nameSpace;
  734. // Search script functions for matching interface
  735. while( ns )
  736. {
  737. asIScriptFunction *f = 0;
  738. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, func.name);
  739. for( unsigned int n = 0; n < idxs.GetLength(); n++ )
  740. {
  741. const asCScriptFunction *funcPtr = globalFunctions.Get(idxs[n]);
  742. if( funcPtr->objectType == 0 &&
  743. func.returnType == funcPtr->returnType &&
  744. func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
  745. )
  746. {
  747. bool match = true;
  748. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  749. {
  750. if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
  751. {
  752. match = false;
  753. break;
  754. }
  755. }
  756. if( match )
  757. {
  758. if( f == 0 )
  759. f = const_cast<asCScriptFunction*>(funcPtr);
  760. else
  761. // Multiple functions
  762. return 0;
  763. }
  764. }
  765. }
  766. if( f )
  767. return f;
  768. else
  769. {
  770. // Search for matching functions in the parent namespace
  771. ns = engine->GetParentNameSpace(ns);
  772. }
  773. }
  774. return 0;
  775. }
  776. // interface
  777. asUINT asCModule::GetGlobalVarCount() const
  778. {
  779. return (asUINT)scriptGlobals.GetSize();
  780. }
  781. // interface
  782. int asCModule::GetGlobalVarIndexByName(const char *name) const
  783. {
  784. asSNameSpace *ns = defaultNamespace;
  785. // Find the global var id
  786. while( ns )
  787. {
  788. int id = scriptGlobals.GetFirstIndex(ns, name);
  789. if( id >= 0 ) return id;
  790. // Recursively search parent namespaces
  791. ns = engine->GetParentNameSpace(ns);
  792. }
  793. return asNO_GLOBAL_VAR;
  794. }
  795. // interface
  796. int asCModule::RemoveGlobalVar(asUINT index)
  797. {
  798. // TODO: 2.30.0: redesign: Before removing the variable, clear it to free the object
  799. // The property shouldn't be orphaned.
  800. asCGlobalProperty *prop = scriptGlobals.Get(index);
  801. if( !prop )
  802. return asINVALID_ARG;
  803. // Destroy the internal of the global variable (removes the initialization function)
  804. prop->DestroyInternal();
  805. // Check if the module is the only one referring to the module, if so remove it from the engine too
  806. // If the property is not removed now, it will be removed later when the module is discarded
  807. if( prop->refCount.get() == 2 )
  808. engine->RemoveGlobalProperty(prop);
  809. // Remove the global variable from the module
  810. prop->Release();
  811. scriptGlobals.Erase(index);
  812. return 0;
  813. }
  814. // interface
  815. int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
  816. {
  817. asCBuilder bld(engine, const_cast<asCModule*>(this));
  818. // Don't write parser errors to the message callback
  819. bld.silent = true;
  820. asCString name;
  821. asSNameSpace *nameSpace;
  822. asCDataType dt;
  823. int r = bld.ParseVariableDeclaration(decl, defaultNamespace, name, nameSpace, dt);
  824. if( r < 0 )
  825. return r;
  826. // Search global variables for a match
  827. while( nameSpace )
  828. {
  829. int id = scriptGlobals.GetFirstIndex(nameSpace, name, asCCompGlobPropType(dt));
  830. if( id != -1 )
  831. return id;
  832. // Recursively search parent namespace
  833. nameSpace = engine->GetParentNameSpace(nameSpace);
  834. }
  835. return asNO_GLOBAL_VAR;
  836. }
  837. // interface
  838. void *asCModule::GetAddressOfGlobalVar(asUINT index)
  839. {
  840. asCGlobalProperty *prop = scriptGlobals.Get(index);
  841. if( !prop )
  842. return 0;
  843. // For object variables it's necessary to dereference the pointer to get the address of the value
  844. if( prop->type.IsObject() &&
  845. !prop->type.IsObjectHandle() )
  846. return *(void**)(prop->GetAddressOfValue());
  847. return (void*)(prop->GetAddressOfValue());
  848. }
  849. // interface
  850. const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespace) const
  851. {
  852. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  853. if (!prop) return 0;
  854. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  855. *tempString = prop->type.Format(defaultNamespace);
  856. *tempString += " ";
  857. if( includeNamespace && prop->nameSpace->name != "" )
  858. *tempString += prop->nameSpace->name + "::";
  859. *tempString += prop->name;
  860. return tempString->AddressOf();
  861. }
  862. // interface
  863. int asCModule::GetGlobalVar(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst) const
  864. {
  865. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  866. if (!prop) return 0;
  867. if( name )
  868. *name = prop->name.AddressOf();
  869. if( nameSpace )
  870. *nameSpace = prop->nameSpace->name.AddressOf();
  871. if( typeId )
  872. *typeId = engine->GetTypeIdFromDataType(prop->type);
  873. if( isConst )
  874. *isConst = prop->type.IsReadOnly();
  875. return asSUCCESS;
  876. }
  877. // interface
  878. asUINT asCModule::GetObjectTypeCount() const
  879. {
  880. return (asUINT)classTypes.GetLength();
  881. }
  882. // interface
  883. asIObjectType *asCModule::GetObjectTypeByIndex(asUINT index) const
  884. {
  885. if( index >= classTypes.GetLength() )
  886. return 0;
  887. return classTypes[index];
  888. }
  889. // interface
  890. asIObjectType *asCModule::GetObjectTypeByName(const char *name) const
  891. {
  892. asSNameSpace *ns = defaultNamespace;
  893. while( ns )
  894. {
  895. for( asUINT n = 0; n < classTypes.GetLength(); n++ )
  896. {
  897. if( classTypes[n] &&
  898. classTypes[n]->name == name &&
  899. classTypes[n]->nameSpace == ns )
  900. return classTypes[n];
  901. }
  902. // Recursively search parent namespace
  903. ns = engine->GetParentNameSpace(ns);
  904. }
  905. return 0;
  906. }
  907. // interface
  908. int asCModule::GetTypeIdByDecl(const char *decl) const
  909. {
  910. asCDataType dt;
  911. // This const cast is safe since we know the engine won't be modified
  912. asCBuilder bld(engine, const_cast<asCModule*>(this));
  913. // Don't write parser errors to the message callback
  914. bld.silent = true;
  915. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  916. if( r < 0 )
  917. return asINVALID_TYPE;
  918. return engine->GetTypeIdFromDataType(dt);
  919. }
  920. // interface
  921. asIObjectType *asCModule::GetObjectTypeByDecl(const char *decl) const
  922. {
  923. asCDataType dt;
  924. // This const cast is safe since we know the engine won't be modified
  925. asCBuilder bld(engine, const_cast<asCModule*>(this));
  926. // Don't write parser errors to the message callback
  927. bld.silent = true;
  928. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  929. if( r < 0 )
  930. return 0;
  931. return dt.GetObjectType();
  932. }
  933. // interface
  934. asUINT asCModule::GetEnumCount() const
  935. {
  936. return (asUINT)enumTypes.GetLength();
  937. }
  938. // interface
  939. const char *asCModule::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace) const
  940. {
  941. if( index >= enumTypes.GetLength() )
  942. return 0;
  943. if( enumTypeId )
  944. *enumTypeId = engine->GetTypeIdFromDataType(asCDataType::CreateObject(enumTypes[index], false));
  945. if( nameSpace )
  946. *nameSpace = enumTypes[index]->nameSpace->name.AddressOf();
  947. return enumTypes[index]->name.AddressOf();
  948. }
  949. // interface
  950. int asCModule::GetEnumValueCount(int enumTypeId) const
  951. {
  952. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  953. asCObjectType *t = dt.GetObjectType();
  954. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  955. return asINVALID_TYPE;
  956. return (int)t->enumValues.GetLength();
  957. }
  958. // interface
  959. const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
  960. {
  961. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  962. asCObjectType *t = dt.GetObjectType();
  963. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  964. return 0;
  965. if( index >= t->enumValues.GetLength() )
  966. return 0;
  967. if( outValue )
  968. *outValue = t->enumValues[index]->value;
  969. return t->enumValues[index]->name.AddressOf();
  970. }
  971. // interface
  972. asUINT asCModule::GetTypedefCount() const
  973. {
  974. return (asUINT)typeDefs.GetLength();
  975. }
  976. // interface
  977. const char *asCModule::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace) const
  978. {
  979. if( index >= typeDefs.GetLength() )
  980. return 0;
  981. if( typeId )
  982. *typeId = engine->GetTypeIdFromDataType(typeDefs[index]->templateSubTypes[0]);
  983. if( nameSpace )
  984. *nameSpace = typeDefs[index]->nameSpace->name.AddressOf();
  985. return typeDefs[index]->name.AddressOf();
  986. }
  987. // internal
  988. int asCModule::GetNextImportedFunctionId()
  989. {
  990. // TODO: multithread: This will break if one thread if freeing a module, while another is being compiled
  991. if( engine->freeImportedFunctionIdxs.GetLength() )
  992. return FUNC_IMPORTED | (asUINT)engine->freeImportedFunctionIdxs[engine->freeImportedFunctionIdxs.GetLength()-1];
  993. return FUNC_IMPORTED | (asUINT)engine->importedFunctions.GetLength();
  994. }
  995. #ifndef AS_NO_COMPILER
  996. // internal
  997. int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isProtected, bool isFinal, bool isOverride, bool isShared, asSNameSpace *ns)
  998. {
  999. asASSERT(id >= 0);
  1000. // Store the function information
  1001. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT);
  1002. if( func == 0 )
  1003. {
  1004. // Free the default args
  1005. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1006. if( defaultArgs[n] )
  1007. asDELETE(defaultArgs[n], asCString);
  1008. return asOUT_OF_MEMORY;
  1009. }
  1010. if( ns == 0 )
  1011. ns = engine->nameSpaces[0];
  1012. // All methods of shared objects are also shared
  1013. if( objType && objType->IsShared() )
  1014. isShared = true;
  1015. func->name = name;
  1016. func->nameSpace = ns;
  1017. func->id = id;
  1018. func->returnType = returnType;
  1019. if( func->funcType == asFUNC_SCRIPT )
  1020. {
  1021. func->scriptData->scriptSectionIdx = sectionIdx;
  1022. func->scriptData->declaredAt = declaredAt;
  1023. }
  1024. func->parameterTypes = params;
  1025. func->parameterNames = paramNames;
  1026. func->inOutFlags = inOutFlags;
  1027. func->defaultArgs = defaultArgs;
  1028. func->objectType = objType;
  1029. if( objType )
  1030. objType->AddRefInternal();
  1031. func->isReadOnly = isConstMethod;
  1032. func->isPrivate = isPrivate;
  1033. func->isProtected = isProtected;
  1034. func->isFinal = isFinal;
  1035. func->isOverride = isOverride;
  1036. func->isShared = isShared;
  1037. asASSERT( params.GetLength() == inOutFlags.GetLength() && params.GetLength() == defaultArgs.GetLength() );
  1038. // Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
  1039. asASSERT( !(!objType && isFinal) );
  1040. asASSERT( !(!objType && isOverride) );
  1041. // The internal ref count was already set by the constructor
  1042. scriptFunctions.PushLast(func);
  1043. engine->AddScriptFunction(func);
  1044. // Compute the signature id
  1045. if( objType )
  1046. func->ComputeSignatureId();
  1047. // Add reference
  1048. if( isGlobalFunction )
  1049. globalFunctions.Put(func);
  1050. return 0;
  1051. }
  1052. // internal
  1053. int asCModule::AddScriptFunction(asCScriptFunction *func)
  1054. {
  1055. scriptFunctions.PushLast(func);
  1056. func->AddRefInternal();
  1057. engine->AddScriptFunction(func);
  1058. return 0;
  1059. }
  1060. // internal
  1061. int asCModule::AddImportedFunction(int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, asSNameSpace *ns, const asCString &moduleName)
  1062. {
  1063. asASSERT(id >= 0);
  1064. // Store the function information
  1065. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED);
  1066. if( func == 0 )
  1067. {
  1068. // Free the default args
  1069. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1070. if( defaultArgs[n] )
  1071. asDELETE(defaultArgs[n], asCString);
  1072. return asOUT_OF_MEMORY;
  1073. }
  1074. func->name = name;
  1075. func->id = id;
  1076. func->returnType = returnType;
  1077. func->nameSpace = ns;
  1078. func->parameterTypes = params;
  1079. func->inOutFlags = inOutFlags;
  1080. func->defaultArgs = defaultArgs;
  1081. func->objectType = 0;
  1082. sBindInfo *info = asNEW(sBindInfo);
  1083. if( info == 0 )
  1084. {
  1085. asDELETE(func, asCScriptFunction);
  1086. return asOUT_OF_MEMORY;
  1087. }
  1088. info->importedFunctionSignature = func;
  1089. info->boundFunctionId = -1;
  1090. info->importFromModule = moduleName;
  1091. bindInformations.PushLast(info);
  1092. // Add the info to the array in the engine
  1093. if( engine->freeImportedFunctionIdxs.GetLength() )
  1094. engine->importedFunctions[engine->freeImportedFunctionIdxs.PopLast()] = info;
  1095. else
  1096. engine->importedFunctions.PushLast(info);
  1097. return 0;
  1098. }
  1099. #endif
  1100. // internal
  1101. asCScriptFunction *asCModule::GetImportedFunction(int index) const
  1102. {
  1103. return bindInformations[index]->importedFunctionSignature;
  1104. }
  1105. // interface
  1106. int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
  1107. {
  1108. // First unbind the old function
  1109. int r = UnbindImportedFunction(index);
  1110. if( r < 0 ) return r;
  1111. // Must verify that the interfaces are equal
  1112. asCScriptFunction *dst = GetImportedFunction(index);
  1113. if( dst == 0 ) return asNO_FUNCTION;
  1114. if( func == 0 )
  1115. return asINVALID_ARG;
  1116. asCScriptFunction *src = engine->GetScriptFunction(func->GetId());
  1117. if( src == 0 )
  1118. return asNO_FUNCTION;
  1119. // Verify return type
  1120. if( dst->returnType != src->returnType )
  1121. return asINVALID_INTERFACE;
  1122. if( dst->parameterTypes.GetLength() != src->parameterTypes.GetLength() )
  1123. return asINVALID_INTERFACE;
  1124. for( asUINT n = 0; n < dst->parameterTypes.GetLength(); ++n )
  1125. {
  1126. if( dst->parameterTypes[n] != src->parameterTypes[n] )
  1127. return asINVALID_INTERFACE;
  1128. }
  1129. bindInformations[index]->boundFunctionId = src->GetId();
  1130. src->AddRefInternal();
  1131. return asSUCCESS;
  1132. }
  1133. // interface
  1134. int asCModule::UnbindImportedFunction(asUINT index)
  1135. {
  1136. if( index >= bindInformations.GetLength() )
  1137. return asINVALID_ARG;
  1138. // Remove reference to old module
  1139. if( bindInformations[index] )
  1140. {
  1141. int oldFuncID = bindInformations[index]->boundFunctionId;
  1142. if( oldFuncID != -1 )
  1143. {
  1144. bindInformations[index]->boundFunctionId = -1;
  1145. engine->scriptFunctions[oldFuncID]->ReleaseInternal();
  1146. }
  1147. }
  1148. return asSUCCESS;
  1149. }
  1150. // interface
  1151. const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
  1152. {
  1153. asCScriptFunction *func = GetImportedFunction(index);
  1154. if( func == 0 ) return 0;
  1155. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  1156. *tempString = func->GetDeclarationStr();
  1157. return tempString->AddressOf();
  1158. }
  1159. // interface
  1160. const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const
  1161. {
  1162. if( index >= bindInformations.GetLength() )
  1163. return 0;
  1164. return bindInformations[index]->importFromModule.AddressOf();
  1165. }
  1166. // inteface
  1167. int asCModule::BindAllImportedFunctions()
  1168. {
  1169. bool notAllFunctionsWereBound = false;
  1170. // Bind imported functions
  1171. int c = GetImportedFunctionCount();
  1172. for( int n = 0; n < c; ++n )
  1173. {
  1174. asCScriptFunction *importFunc = GetImportedFunction(n);
  1175. if( importFunc == 0 ) return asERROR;
  1176. asCString str = importFunc->GetDeclarationStr(false, true);
  1177. // Get module name from where the function should be imported
  1178. const char *moduleName = GetImportedFunctionSourceModule(n);
  1179. if( moduleName == 0 ) return asERROR;
  1180. asCModule *srcMod = engine->GetModule(moduleName, false);
  1181. asIScriptFunction *func = 0;
  1182. if( srcMod )
  1183. func = srcMod->GetFunctionByDecl(str.AddressOf());
  1184. if( func == 0 )
  1185. notAllFunctionsWereBound = true;
  1186. else
  1187. {
  1188. if( BindImportedFunction(n, func) < 0 )
  1189. notAllFunctionsWereBound = true;
  1190. }
  1191. }
  1192. if( notAllFunctionsWereBound )
  1193. return asCANT_BIND_ALL_FUNCTIONS;
  1194. return asSUCCESS;
  1195. }
  1196. // interface
  1197. int asCModule::UnbindAllImportedFunctions()
  1198. {
  1199. asUINT c = GetImportedFunctionCount();
  1200. for( asUINT n = 0; n < c; ++n )
  1201. UnbindImportedFunction(n);
  1202. return asSUCCESS;
  1203. }
  1204. // internal
  1205. asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns)
  1206. {
  1207. asUINT n;
  1208. // TODO: optimize: Improve linear search
  1209. for( n = 0; n < classTypes.GetLength(); n++ )
  1210. if( classTypes[n]->name == type &&
  1211. classTypes[n]->nameSpace == ns )
  1212. return classTypes[n];
  1213. for( n = 0; n < enumTypes.GetLength(); n++ )
  1214. if( enumTypes[n]->name == type &&
  1215. enumTypes[n]->nameSpace == ns )
  1216. return enumTypes[n];
  1217. for( n = 0; n < typeDefs.GetLength(); n++ )
  1218. if( typeDefs[n]->name == type &&
  1219. typeDefs[n]->nameSpace == ns )
  1220. return typeDefs[n];
  1221. return 0;
  1222. }
  1223. // internal
  1224. asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns)
  1225. {
  1226. asCGlobalProperty *prop = engine->AllocateGlobalProperty();
  1227. prop->name = name;
  1228. prop->nameSpace = ns;
  1229. // Allocate the memory for this property based on its type
  1230. prop->type = dt;
  1231. prop->AllocateMemory();
  1232. // Make an entry in the address to variable map
  1233. engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  1234. // Store the variable in the module scope
  1235. scriptGlobals.Put(prop);
  1236. prop->AddRef();
  1237. return prop;
  1238. }
  1239. // internal
  1240. bool asCModule::IsEmpty() const
  1241. {
  1242. if( scriptFunctions.GetLength() ) return false;
  1243. if( globalFunctions.GetSize() ) return false;
  1244. if( bindInformations.GetLength() ) return false;
  1245. if( scriptGlobals.GetSize() ) return false;
  1246. if( classTypes.GetLength() ) return false;
  1247. if( enumTypes.GetLength() ) return false;
  1248. if( typeDefs.GetLength() ) return false;
  1249. if( funcDefs.GetLength() ) return false;
  1250. return true;
  1251. }
  1252. // interface
  1253. int asCModule::SaveByteCode(asIBinaryStream *out, bool stripDebugInfo) const
  1254. {
  1255. #ifdef AS_NO_COMPILER
  1256. UNUSED_VAR(out);
  1257. UNUSED_VAR(stripDebugInfo);
  1258. return asNOT_SUPPORTED;
  1259. #else
  1260. if( out == 0 ) return asINVALID_ARG;
  1261. // Make sure there is actually something to save
  1262. if( IsEmpty() )
  1263. return asERROR;
  1264. asCWriter write(const_cast<asCModule*>(this), out, engine, stripDebugInfo);
  1265. return write.Write();
  1266. #endif
  1267. }
  1268. // interface
  1269. int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped)
  1270. {
  1271. if( in == 0 ) return asINVALID_ARG;
  1272. // Don't allow the module to be rebuilt if there are still
  1273. // external references that will need the previous code
  1274. if( HasExternalReferences(false) )
  1275. {
  1276. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
  1277. return asMODULE_IS_IN_USE;
  1278. }
  1279. // Only permit loading bytecode if no other thread is currently compiling
  1280. // TODO: It should be possible to have multiple threads perform compilations
  1281. int r = engine->RequestBuild();
  1282. if( r < 0 )
  1283. return r;
  1284. asCReader read(this, in, engine);
  1285. r = read.Read(wasDebugInfoStripped);
  1286. JITCompile();
  1287. #ifdef AS_DEBUG
  1288. // Verify that there are no unwanted gaps in the scriptFunctions array.
  1289. for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ )
  1290. {
  1291. int id = n;
  1292. if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) )
  1293. asASSERT( false );
  1294. }
  1295. #endif
  1296. engine->BuildCompleted();
  1297. return r;
  1298. }
  1299. // interface
  1300. int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  1301. {
  1302. #ifdef AS_NO_COMPILER
  1303. UNUSED_VAR(sectionName);
  1304. UNUSED_VAR(code);
  1305. UNUSED_VAR(lineOffset);
  1306. return asNOT_SUPPORTED;
  1307. #else
  1308. // Validate arguments
  1309. if( code == 0 )
  1310. return asINVALID_ARG;
  1311. // Only one thread may build at one time
  1312. // TODO: It should be possible to have multiple threads perform compilations
  1313. int r = engine->RequestBuild();
  1314. if( r < 0 )
  1315. return r;
  1316. // Prepare the engine
  1317. engine->PrepareEngine();
  1318. if( engine->configFailed )
  1319. {
  1320. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1321. engine->BuildCompleted();
  1322. return asINVALID_CONFIGURATION;
  1323. }
  1324. // Compile the global variable and add it to the module scope
  1325. asCBuilder builder(engine, this);
  1326. asCString str = code;
  1327. r = builder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset);
  1328. engine->BuildCompleted();
  1329. // Initialize the variable
  1330. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  1331. {
  1332. // Clear the memory
  1333. asCGlobalProperty *prop = scriptGlobals.GetLast();
  1334. if( prop )
  1335. {
  1336. memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords());
  1337. if( prop->GetInitFunc() )
  1338. {
  1339. // Call the init function for the global variable
  1340. asIScriptContext *ctx = 0;
  1341. int r = engine->CreateContext(&ctx, true);
  1342. if( r < 0 )
  1343. return r;
  1344. r = ctx->Prepare(prop->GetInitFunc());
  1345. if( r >= 0 )
  1346. r = ctx->Execute();
  1347. ctx->Release();
  1348. }
  1349. }
  1350. }
  1351. return r;
  1352. #endif
  1353. }
  1354. // interface
  1355. int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc)
  1356. {
  1357. // Make sure the outFunc is null if the function fails, so the
  1358. // application doesn't attempt to release a non-existent function
  1359. if( outFunc )
  1360. *outFunc = 0;
  1361. #ifdef AS_NO_COMPILER
  1362. UNUSED_VAR(sectionName);
  1363. UNUSED_VAR(code);
  1364. UNUSED_VAR(lineOffset);
  1365. UNUSED_VAR(compileFlags);
  1366. return asNOT_SUPPORTED;
  1367. #else
  1368. // Validate arguments
  1369. if( code == 0 ||
  1370. (compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) )
  1371. return asINVALID_ARG;
  1372. // Only one thread may build at one time
  1373. // TODO: It should be possible to have multiple threads perform compilations
  1374. int r = engine->RequestBuild();
  1375. if( r < 0 )
  1376. return r;
  1377. // Prepare the engine
  1378. engine->PrepareEngine();
  1379. if( engine->configFailed )
  1380. {
  1381. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1382. engine->BuildCompleted();
  1383. return asINVALID_CONFIGURATION;
  1384. }
  1385. // Compile the single function
  1386. asCBuilder builder(engine, this);
  1387. asCString str = code;
  1388. asCScriptFunction *func = 0;
  1389. r = builder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
  1390. engine->BuildCompleted();
  1391. if( r >= 0 && outFunc && func )
  1392. {
  1393. // Return the function to the caller and add an external reference
  1394. *outFunc = func;
  1395. func->AddRef();
  1396. }
  1397. // Release our reference to the function
  1398. if( func )
  1399. func->ReleaseInternal();
  1400. return r;
  1401. #endif
  1402. }
  1403. // interface
  1404. int asCModule::RemoveFunction(asIScriptFunction *func)
  1405. {
  1406. // TODO: 2.30.0: redesign: Check if there are any references before removing the function
  1407. // if there are, just hide it from the visible but do not destroy or
  1408. // remove it from the module.
  1409. //
  1410. // Only if the function has no live references, nor internal references
  1411. // can it be immediately removed, and its internal references released.
  1412. //
  1413. // Check if any previously hidden functions are without references,
  1414. // if so they should removed too.
  1415. // Find the global function
  1416. asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
  1417. int idx = globalFunctions.GetIndex(f);
  1418. if( idx >= 0 )
  1419. {
  1420. globalFunctions.Erase(idx);
  1421. scriptFunctions.RemoveValue(f);
  1422. f->ReleaseInternal();
  1423. return 0;
  1424. }
  1425. return asNO_FUNCTION;
  1426. }
  1427. #ifndef AS_NO_COMPILER
  1428. // internal
  1429. int asCModule::AddFuncDef(const asCString &name, asSNameSpace *ns)
  1430. {
  1431. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF);
  1432. if( func == 0 )
  1433. return asOUT_OF_MEMORY;
  1434. func->name = name;
  1435. func->nameSpace = ns;
  1436. funcDefs.PushLast(func);
  1437. engine->funcDefs.PushLast(func);
  1438. func->id = engine->GetNextScriptFunctionId();
  1439. engine->AddScriptFunction(func);
  1440. return (int)funcDefs.GetLength()-1;
  1441. }
  1442. #endif
  1443. // interface
  1444. asDWORD asCModule::SetAccessMask(asDWORD mask)
  1445. {
  1446. asDWORD old = accessMask;
  1447. accessMask = mask;
  1448. return old;
  1449. }
  1450. END_AS_NAMESPACE