as_module.cpp 46 KB

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