as_module.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2016 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::CallExit()
  377. {
  378. if( !isGlobalVarInitialized ) return;
  379. asCSymbolTableIterator<asCGlobalProperty> it = scriptGlobals.List();
  380. while( it )
  381. {
  382. if( (*it)->type.IsObject() )
  383. {
  384. void **obj = (void**)(*it)->GetAddressOfValue();
  385. if( *obj )
  386. {
  387. asCObjectType *ot = CastToObjectType((*it)->type.GetTypeInfo());
  388. if( ot->flags & asOBJ_REF )
  389. {
  390. asASSERT( (ot->flags & asOBJ_NOCOUNT) || ot->beh.release );
  391. if( ot->beh.release )
  392. engine->CallObjectMethod(*obj, ot->beh.release);
  393. }
  394. else
  395. {
  396. if( ot->beh.destruct )
  397. engine->CallObjectMethod(*obj, ot->beh.destruct);
  398. engine->CallFree(*obj);
  399. }
  400. // Set the address to 0 as someone might try to access the variable afterwards
  401. *obj = 0;
  402. }
  403. }
  404. else if ((*it)->type.IsFuncdef())
  405. {
  406. asCScriptFunction **func = (asCScriptFunction**)(*it)->GetAddressOfValue();
  407. if (*func)
  408. {
  409. (*func)->Release();
  410. *func = 0;
  411. }
  412. }
  413. it++;
  414. }
  415. isGlobalVarInitialized = false;
  416. }
  417. // internal
  418. bool asCModule::HasExternalReferences(bool shuttingDown)
  419. {
  420. // Check all entiteis in the module for any external references.
  421. // If there are any external references the module cannot be deleted yet.
  422. asCSymbolTableIterator<asCGlobalProperty> it = scriptGlobals.List();
  423. while (it)
  424. {
  425. asCGlobalProperty *desc = *it;
  426. if (desc->GetInitFunc() && desc->GetInitFunc()->externalRefCount.get())
  427. {
  428. if( !shuttingDown )
  429. return true;
  430. else
  431. {
  432. asCString msg;
  433. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  434. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  435. // TODO: Use a better error message
  436. asCString tmpName = "init " + desc->name;
  437. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, tmpName.AddressOf(), desc->GetInitFunc()->GetFuncType());
  438. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  439. }
  440. }
  441. it++;
  442. }
  443. for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
  444. if( scriptFunctions[n] && scriptFunctions[n]->externalRefCount.get() )
  445. {
  446. if( !shuttingDown )
  447. return true;
  448. else
  449. {
  450. asCString msg;
  451. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  452. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  453. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, scriptFunctions[n]->GetName(), scriptFunctions[n]->GetFuncType());
  454. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  455. }
  456. }
  457. for( asUINT n = 0; n < classTypes.GetLength(); n++ )
  458. if( classTypes[n] && classTypes[n]->externalRefCount.get() )
  459. {
  460. if( !shuttingDown )
  461. return true;
  462. else
  463. {
  464. asCString msg;
  465. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  466. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  467. msg.Format(TXT_PREV_TYPE_IS_NAMED_s, classTypes[n]->GetName());
  468. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  469. }
  470. }
  471. for( asUINT n = 0; n < funcDefs.GetLength(); n++ )
  472. if( funcDefs[n] && funcDefs[n]->externalRefCount.get() )
  473. {
  474. if( !shuttingDown )
  475. return true;
  476. else
  477. {
  478. asCString msg;
  479. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  480. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  481. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, funcDefs[n]->GetName(), funcDefs[n]->funcdef->GetFuncType());
  482. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  483. }
  484. }
  485. for( asUINT n = 0; n < templateInstances.GetLength(); n++ )
  486. if( templateInstances[n] && templateInstances[n]->externalRefCount.get() )
  487. {
  488. if( !shuttingDown )
  489. return true;
  490. else
  491. {
  492. asCString msg;
  493. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf());
  494. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  495. msg.Format(TXT_PREV_TYPE_IS_NAMED_s, templateInstances[n]->GetName());
  496. engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  497. }
  498. }
  499. return false;
  500. }
  501. // internal
  502. void asCModule::InternalReset()
  503. {
  504. CallExit();
  505. asUINT n;
  506. // Remove all global functions
  507. globalFunctions.Clear();
  508. // Destroy the internals of the global properties here, but do not yet remove them from the
  509. // engine, because functions need the engine's varAddressMap to get to the property. If the
  510. // property is removed already, it may leak as the refCount doesn't reach 0.
  511. asCSymbolTableIterator<asCGlobalProperty> globIt = scriptGlobals.List();
  512. while( globIt )
  513. {
  514. (*globIt)->DestroyInternal();
  515. globIt++;
  516. }
  517. UnbindAllImportedFunctions();
  518. // Free bind information
  519. for( n = 0; n < bindInformations.GetLength(); n++ )
  520. {
  521. if( bindInformations[n] )
  522. {
  523. bindInformations[n]->importedFunctionSignature->ReleaseInternal();
  524. asDELETE(bindInformations[n], sBindInfo);
  525. }
  526. }
  527. bindInformations.SetLength(0);
  528. // Free declared types, including classes, typedefs, and enums
  529. for( n = 0; n < templateInstances.GetLength(); n++ )
  530. {
  531. asCObjectType *type = templateInstances[n];
  532. if( engine->FindNewOwnerForSharedType(type, this) != this )
  533. {
  534. // The type is owned by another module, just release our reference
  535. type->ReleaseInternal();
  536. continue;
  537. }
  538. // Orphan the template instance
  539. type->module = 0;
  540. // No other module is holding the template type
  541. engine->RemoveTemplateInstanceType(type);
  542. type->ReleaseInternal();
  543. }
  544. templateInstances.SetLength(0);
  545. for( n = 0; n < classTypes.GetLength(); n++ )
  546. {
  547. asCObjectType *type = classTypes[n];
  548. if( type->IsShared() )
  549. {
  550. // The type is shared, so transfer ownership to another module that also uses it
  551. if( engine->FindNewOwnerForSharedType(type, this) != this )
  552. {
  553. // The type is owned by another module, just release our reference
  554. type->ReleaseInternal();
  555. continue;
  556. }
  557. }
  558. // The type should be destroyed now
  559. type->DestroyInternal();
  560. // Remove the type from the engine
  561. if( type->IsShared() )
  562. {
  563. engine->sharedScriptTypes.RemoveValue(type);
  564. type->ReleaseInternal();
  565. }
  566. // Release it from the module
  567. type->module = 0;
  568. type->ReleaseInternal();
  569. }
  570. classTypes.SetLength(0);
  571. for( n = 0; n < enumTypes.GetLength(); n++ )
  572. {
  573. asCEnumType *type = enumTypes[n];
  574. if( type->IsShared() )
  575. {
  576. // The type is shared, so transfer ownership to another module that also uses it
  577. if( engine->FindNewOwnerForSharedType(type, this) != this )
  578. {
  579. // The type is owned by another module, just release our reference
  580. type->ReleaseInternal();
  581. continue;
  582. }
  583. }
  584. // Remove the type from the engine
  585. if( type->IsShared() )
  586. {
  587. engine->sharedScriptTypes.RemoveValue(type);
  588. type->ReleaseInternal();
  589. }
  590. // Release it from the module
  591. type->module = 0;
  592. type->ReleaseInternal();
  593. }
  594. enumTypes.SetLength(0);
  595. for( n = 0; n < typeDefs.GetLength(); n++ )
  596. {
  597. asCTypedefType *type = typeDefs[n];
  598. // The type should be destroyed now
  599. type->DestroyInternal();
  600. // Release it from the module
  601. type->module = 0;
  602. type->ReleaseInternal();
  603. }
  604. typeDefs.SetLength(0);
  605. // Free funcdefs
  606. for( n = 0; n < funcDefs.GetLength(); n++ )
  607. {
  608. asCFuncdefType *func = funcDefs[n];
  609. asASSERT(func);
  610. if( func->funcdef && func->funcdef->IsShared() )
  611. {
  612. // The funcdef is shared, so transfer ownership to another module that also uses it
  613. if( engine->FindNewOwnerForSharedType(func, this) != this )
  614. {
  615. // The funcdef is owned by another module, just release our reference
  616. func->ReleaseInternal();
  617. continue;
  618. }
  619. }
  620. func->DestroyInternal();
  621. engine->RemoveFuncdef(func);
  622. func->module = 0;
  623. func->ReleaseInternal();
  624. }
  625. funcDefs.SetLength(0);
  626. // Then release the functions
  627. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  628. {
  629. asCScriptFunction *func = scriptFunctions[n];
  630. if( func->IsShared() )
  631. {
  632. // The func is shared, so transfer ownership to another module that also uses it
  633. if( engine->FindNewOwnerForSharedFunc(func, this) != this )
  634. {
  635. // The func is owned by another module, just release our reference
  636. func->ReleaseInternal();
  637. continue;
  638. }
  639. }
  640. func->DestroyInternal();
  641. func->module = 0;
  642. func->ReleaseInternal();
  643. }
  644. scriptFunctions.SetLength(0);
  645. // Now remove and release the global properties as there are no more references to them
  646. globIt = scriptGlobals.List();
  647. while( globIt )
  648. {
  649. engine->RemoveGlobalProperty(*globIt);
  650. asASSERT( (*globIt)->refCount.get() == 1 );
  651. (*globIt)->Release();
  652. globIt++;
  653. }
  654. scriptGlobals.Clear();
  655. asASSERT( IsEmpty() );
  656. }
  657. // interface
  658. asIScriptFunction *asCModule::GetFunctionByName(const char *in_name) const
  659. {
  660. asSNameSpace *ns = defaultNamespace;
  661. while( ns )
  662. {
  663. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, in_name);
  664. if( idxs.GetLength() != 1 )
  665. return 0;
  666. const asIScriptFunction *func = globalFunctions.Get(idxs[0]);
  667. if( func )
  668. return const_cast<asIScriptFunction*>(func);
  669. // Recursively search parent namespaces
  670. ns = engine->GetParentNameSpace(ns);
  671. }
  672. return 0;
  673. }
  674. // interface
  675. asUINT asCModule::GetImportedFunctionCount() const
  676. {
  677. return (asUINT)bindInformations.GetLength();
  678. }
  679. // interface
  680. int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
  681. {
  682. asCBuilder bld(engine, const_cast<asCModule*>(this));
  683. // Don't write parser errors to the message callback
  684. bld.silent = true;
  685. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  686. bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  687. // TODO: optimize: Improve linear search
  688. // Search script functions for matching interface
  689. int id = -1;
  690. for( asUINT n = 0; n < bindInformations.GetLength(); ++n )
  691. {
  692. if( func.name == bindInformations[n]->importedFunctionSignature->name &&
  693. func.returnType == bindInformations[n]->importedFunctionSignature->returnType &&
  694. func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() )
  695. {
  696. bool match = true;
  697. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  698. {
  699. if( func.parameterTypes[p] != bindInformations[n]->importedFunctionSignature->parameterTypes[p] )
  700. {
  701. match = false;
  702. break;
  703. }
  704. }
  705. if( match )
  706. {
  707. if( id == -1 )
  708. id = n;
  709. else
  710. return asMULTIPLE_FUNCTIONS;
  711. }
  712. }
  713. }
  714. if( id == -1 ) return asNO_FUNCTION;
  715. return id;
  716. }
  717. // interface
  718. asUINT asCModule::GetFunctionCount() const
  719. {
  720. return (asUINT)globalFunctions.GetSize();
  721. }
  722. // interface
  723. asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const
  724. {
  725. asCBuilder bld(engine, const_cast<asCModule*>(this));
  726. // Don't write parser errors to the message callback
  727. bld.silent = true;
  728. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  729. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  730. if( r < 0 )
  731. {
  732. // Invalid declaration
  733. // TODO: Write error to message stream
  734. return 0;
  735. }
  736. // Use the defaultNamespace implicitly unless an explicit namespace has been provided
  737. asSNameSpace *ns = func.nameSpace == engine->nameSpaces[0] ? defaultNamespace : func.nameSpace;
  738. // Search script functions for matching interface
  739. while( ns )
  740. {
  741. asIScriptFunction *f = 0;
  742. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, func.name);
  743. for( unsigned int n = 0; n < idxs.GetLength(); n++ )
  744. {
  745. const asCScriptFunction *funcPtr = globalFunctions.Get(idxs[n]);
  746. if( funcPtr->objectType == 0 &&
  747. func.returnType == funcPtr->returnType &&
  748. func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
  749. )
  750. {
  751. bool match = true;
  752. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  753. {
  754. if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
  755. {
  756. match = false;
  757. break;
  758. }
  759. }
  760. if( match )
  761. {
  762. if( f == 0 )
  763. f = const_cast<asCScriptFunction*>(funcPtr);
  764. else
  765. // Multiple functions
  766. return 0;
  767. }
  768. }
  769. }
  770. if( f )
  771. return f;
  772. else
  773. {
  774. // Search for matching functions in the parent namespace
  775. ns = engine->GetParentNameSpace(ns);
  776. }
  777. }
  778. return 0;
  779. }
  780. // interface
  781. asUINT asCModule::GetGlobalVarCount() const
  782. {
  783. return (asUINT)scriptGlobals.GetSize();
  784. }
  785. // interface
  786. int asCModule::GetGlobalVarIndexByName(const char *in_name) const
  787. {
  788. asSNameSpace *ns = defaultNamespace;
  789. // Find the global var id
  790. while( ns )
  791. {
  792. int id = scriptGlobals.GetFirstIndex(ns, in_name);
  793. if( id >= 0 ) return id;
  794. // Recursively search parent namespaces
  795. ns = engine->GetParentNameSpace(ns);
  796. }
  797. return asNO_GLOBAL_VAR;
  798. }
  799. // interface
  800. int asCModule::RemoveGlobalVar(asUINT index)
  801. {
  802. asCGlobalProperty *prop = scriptGlobals.Get(index);
  803. if( !prop )
  804. return asINVALID_ARG;
  805. // Destroy the internal of the global variable (removes the initialization function)
  806. prop->DestroyInternal();
  807. // Check if the module is the only one referring to the module, if so remove it from the engine too
  808. // If the property is not removed now, it will be removed later when the module is discarded
  809. if( prop->refCount.get() == 2 )
  810. engine->RemoveGlobalProperty(prop);
  811. // Remove the global variable from the module
  812. scriptGlobals.Erase(index);
  813. prop->Release();
  814. return 0;
  815. }
  816. // interface
  817. int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
  818. {
  819. asCBuilder bld(engine, const_cast<asCModule*>(this));
  820. // Don't write parser errors to the message callback
  821. bld.silent = true;
  822. asCString declName;
  823. asSNameSpace *nameSpace;
  824. asCDataType dt;
  825. int r = bld.ParseVariableDeclaration(decl, defaultNamespace, declName, nameSpace, dt);
  826. if( r < 0 )
  827. return r;
  828. // Search global variables for a match
  829. while( nameSpace )
  830. {
  831. int id = scriptGlobals.GetFirstIndex(nameSpace, declName, asCCompGlobPropType(dt));
  832. if( id != -1 )
  833. return id;
  834. // Recursively search parent namespace
  835. nameSpace = engine->GetParentNameSpace(nameSpace);
  836. }
  837. return asNO_GLOBAL_VAR;
  838. }
  839. // interface
  840. void *asCModule::GetAddressOfGlobalVar(asUINT index)
  841. {
  842. asCGlobalProperty *prop = scriptGlobals.Get(index);
  843. if( !prop )
  844. return 0;
  845. // For object variables it's necessary to dereference the pointer to get the address of the value
  846. if( prop->type.IsObject() &&
  847. !prop->type.IsObjectHandle() )
  848. return *(void**)(prop->GetAddressOfValue());
  849. return (void*)(prop->GetAddressOfValue());
  850. }
  851. // interface
  852. const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespace) const
  853. {
  854. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  855. if (!prop) return 0;
  856. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  857. *tempString = prop->type.Format(defaultNamespace);
  858. *tempString += " ";
  859. if( includeNamespace && prop->nameSpace->name != "" )
  860. *tempString += prop->nameSpace->name + "::";
  861. *tempString += prop->name;
  862. return tempString->AddressOf();
  863. }
  864. // interface
  865. int asCModule::GetGlobalVar(asUINT index, const char **out_name, const char **out_nameSpace, int *out_typeId, bool *out_isConst) const
  866. {
  867. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  868. if (!prop) return 0;
  869. if( out_name )
  870. *out_name = prop->name.AddressOf();
  871. if( out_nameSpace )
  872. *out_nameSpace = prop->nameSpace->name.AddressOf();
  873. if( out_typeId )
  874. *out_typeId = engine->GetTypeIdFromDataType(prop->type);
  875. if( out_isConst )
  876. *out_isConst = prop->type.IsReadOnly();
  877. return asSUCCESS;
  878. }
  879. // interface
  880. asUINT asCModule::GetObjectTypeCount() const
  881. {
  882. return (asUINT)classTypes.GetLength();
  883. }
  884. // interface
  885. asITypeInfo *asCModule::GetObjectTypeByIndex(asUINT index) const
  886. {
  887. if( index >= classTypes.GetLength() )
  888. return 0;
  889. return classTypes[index];
  890. }
  891. #ifdef AS_DEPRECATED
  892. // Deprecated since 2.31.0, 2015-12-06
  893. // interface
  894. asITypeInfo *asCModule::GetObjectTypeByName(const char *in_name) const
  895. {
  896. asITypeInfo *ti = GetTypeInfoByName(in_name);
  897. return CastToObjectType(reinterpret_cast<asCTypeInfo*>(ti));
  898. }
  899. #endif
  900. // interface
  901. asITypeInfo *asCModule::GetTypeInfoByName(const char *in_name) const
  902. {
  903. asSNameSpace *ns = defaultNamespace;
  904. while (ns)
  905. {
  906. for (asUINT n = 0; n < classTypes.GetLength(); n++)
  907. {
  908. if (classTypes[n] &&
  909. classTypes[n]->name == in_name &&
  910. classTypes[n]->nameSpace == ns)
  911. return classTypes[n];
  912. }
  913. for (asUINT n = 0; n < enumTypes.GetLength(); n++)
  914. {
  915. if (enumTypes[n] &&
  916. enumTypes[n]->name == in_name &&
  917. enumTypes[n]->nameSpace == ns)
  918. return enumTypes[n];
  919. }
  920. for (asUINT n = 0; n < typeDefs.GetLength(); n++)
  921. {
  922. if (typeDefs[n] &&
  923. typeDefs[n]->name == in_name &&
  924. typeDefs[n]->nameSpace == ns)
  925. return typeDefs[n];
  926. }
  927. // Recursively search parent namespace
  928. ns = engine->GetParentNameSpace(ns);
  929. }
  930. return 0;
  931. }
  932. // interface
  933. int asCModule::GetTypeIdByDecl(const char *decl) const
  934. {
  935. asCDataType dt;
  936. // This const cast is safe since we know the engine won't be modified
  937. asCBuilder bld(engine, const_cast<asCModule*>(this));
  938. // Don't write parser errors to the message callback
  939. bld.silent = true;
  940. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  941. if( r < 0 )
  942. return asINVALID_TYPE;
  943. return engine->GetTypeIdFromDataType(dt);
  944. }
  945. #ifdef AS_DEPRECATED
  946. // Deprecated since 2.31.0, 2015-12-06
  947. // interface
  948. asITypeInfo *asCModule::GetObjectTypeByDecl(const char *decl) const
  949. {
  950. asITypeInfo *ti = GetTypeInfoByDecl(decl);
  951. return CastToObjectType(reinterpret_cast<asCTypeInfo*>(ti));
  952. }
  953. #endif
  954. // interface
  955. asITypeInfo *asCModule::GetTypeInfoByDecl(const char *decl) const
  956. {
  957. asCDataType dt;
  958. // This const cast is safe since we know the engine won't be modified
  959. asCBuilder bld(engine, const_cast<asCModule*>(this));
  960. // Don't write parser errors to the message callback
  961. bld.silent = true;
  962. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  963. if (r < 0)
  964. return 0;
  965. return dt.GetTypeInfo();
  966. }
  967. // interface
  968. asUINT asCModule::GetEnumCount() const
  969. {
  970. return enumTypes.GetLength();
  971. }
  972. // interface
  973. asITypeInfo *asCModule::GetEnumByIndex(asUINT index) const
  974. {
  975. if( index >= enumTypes.GetLength() )
  976. return 0;
  977. return enumTypes[index];
  978. }
  979. #ifdef AS_DEPRECATED
  980. // Deprecated since 2.31.0, 2015-12-06
  981. // interface
  982. int asCModule::GetEnumValueCount(int enumTypeId) const
  983. {
  984. asITypeInfo *ti = engine->GetTypeInfoById(enumTypeId);
  985. asCEnumType *e = CastToEnumType(reinterpret_cast<asCTypeInfo*>(ti));
  986. if (e == 0)
  987. return asINVALID_TYPE;
  988. return e->GetEnumValueCount();
  989. }
  990. #endif
  991. #ifdef AS_DEPRECATED
  992. // Deprecated since 2.31.0, 2015-12-06
  993. // interface
  994. const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
  995. {
  996. asITypeInfo *ti = engine->GetTypeInfoById(enumTypeId);
  997. asCEnumType *e = CastToEnumType(reinterpret_cast<asCTypeInfo*>(ti));
  998. if (e == 0)
  999. return 0;
  1000. return e->GetEnumValueByIndex(index, outValue);
  1001. }
  1002. #endif
  1003. // interface
  1004. asUINT asCModule::GetTypedefCount() const
  1005. {
  1006. return (asUINT)typeDefs.GetLength();
  1007. }
  1008. // interface
  1009. asITypeInfo *asCModule::GetTypedefByIndex(asUINT index) const
  1010. {
  1011. if( index >= typeDefs.GetLength() )
  1012. return 0;
  1013. return typeDefs[index];
  1014. }
  1015. // internal
  1016. int asCModule::GetNextImportedFunctionId()
  1017. {
  1018. // TODO: multithread: This will break if one thread if freeing a module, while another is being compiled
  1019. if( engine->freeImportedFunctionIdxs.GetLength() )
  1020. return FUNC_IMPORTED | (asUINT)engine->freeImportedFunctionIdxs[engine->freeImportedFunctionIdxs.GetLength()-1];
  1021. return FUNC_IMPORTED | (asUINT)engine->importedFunctions.GetLength();
  1022. }
  1023. #ifndef AS_NO_COMPILER
  1024. // internal
  1025. 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 isConstMethod, bool isGlobalFunction, bool isPrivate, bool isProtected, bool isFinal, bool isOverride, bool isShared, asSNameSpace *ns)
  1026. {
  1027. asASSERT(id >= 0);
  1028. // Store the function information
  1029. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT);
  1030. if( func == 0 )
  1031. {
  1032. // Free the default args
  1033. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1034. if( defaultArgs[n] )
  1035. asDELETE(defaultArgs[n], asCString);
  1036. return asOUT_OF_MEMORY;
  1037. }
  1038. if( ns == 0 )
  1039. ns = engine->nameSpaces[0];
  1040. // All methods of shared objects are also shared
  1041. if( objType && objType->IsShared() )
  1042. isShared = true;
  1043. func->name = funcName;
  1044. func->nameSpace = ns;
  1045. func->id = id;
  1046. func->returnType = returnType;
  1047. if( func->funcType == asFUNC_SCRIPT )
  1048. {
  1049. func->scriptData->scriptSectionIdx = sectionIdx;
  1050. func->scriptData->declaredAt = declaredAt;
  1051. }
  1052. func->parameterTypes = params;
  1053. func->parameterNames = paramNames;
  1054. func->inOutFlags = inOutFlags;
  1055. func->defaultArgs = defaultArgs;
  1056. func->objectType = objType;
  1057. if( objType )
  1058. objType->AddRefInternal();
  1059. func->isReadOnly = isConstMethod;
  1060. func->isPrivate = isPrivate;
  1061. func->isProtected = isProtected;
  1062. func->isFinal = isFinal;
  1063. func->isOverride = isOverride;
  1064. func->isShared = isShared;
  1065. asASSERT( params.GetLength() == inOutFlags.GetLength() && params.GetLength() == defaultArgs.GetLength() );
  1066. // Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
  1067. asASSERT( !(!objType && isFinal) );
  1068. asASSERT( !(!objType && isOverride) );
  1069. // The internal ref count was already set by the constructor
  1070. scriptFunctions.PushLast(func);
  1071. engine->AddScriptFunction(func);
  1072. // Compute the signature id
  1073. if( objType )
  1074. func->ComputeSignatureId();
  1075. // Add reference
  1076. if( isGlobalFunction )
  1077. globalFunctions.Put(func);
  1078. return 0;
  1079. }
  1080. // internal
  1081. int asCModule::AddScriptFunction(asCScriptFunction *func)
  1082. {
  1083. scriptFunctions.PushLast(func);
  1084. func->AddRefInternal();
  1085. engine->AddScriptFunction(func);
  1086. // If the function that is being added is an already compiled shared function
  1087. // then it is necessary to look for anonymous functions that may be declared
  1088. // within it and add those as well
  1089. if( func->isShared && func->funcType == asFUNC_SCRIPT )
  1090. {
  1091. // Loop through the byte code and check all the
  1092. // asBC_FuncPtr instructions for anonymous functions
  1093. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  1094. asUINT bcLength = (asUINT)func->scriptData->byteCode.GetLength();
  1095. for( asUINT n = 0; n < bcLength; )
  1096. {
  1097. int c = *(asBYTE*)&bc[n];
  1098. if( c == asBC_FuncPtr )
  1099. {
  1100. asCScriptFunction *f = reinterpret_cast<asCScriptFunction*>(asBC_PTRARG(&bc[n]));
  1101. // Anonymous functions start with $
  1102. // There are never two equal anonymous functions so it is not necessary to look for duplicates
  1103. if( f && f->name[0] == '$' )
  1104. {
  1105. AddScriptFunction(f);
  1106. globalFunctions.Put(f);
  1107. }
  1108. }
  1109. n += asBCTypeSize[asBCInfo[c].type];
  1110. }
  1111. }
  1112. return 0;
  1113. }
  1114. // internal
  1115. 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)
  1116. {
  1117. asASSERT(id >= 0);
  1118. // Store the function information
  1119. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED);
  1120. if( func == 0 )
  1121. {
  1122. // Free the default args
  1123. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1124. if( defaultArgs[n] )
  1125. asDELETE(defaultArgs[n], asCString);
  1126. return asOUT_OF_MEMORY;
  1127. }
  1128. func->name = funcName;
  1129. func->id = id;
  1130. func->returnType = returnType;
  1131. func->nameSpace = ns;
  1132. func->parameterTypes = params;
  1133. func->inOutFlags = inOutFlags;
  1134. func->defaultArgs = defaultArgs;
  1135. func->objectType = 0;
  1136. sBindInfo *info = asNEW(sBindInfo);
  1137. if( info == 0 )
  1138. {
  1139. asDELETE(func, asCScriptFunction);
  1140. return asOUT_OF_MEMORY;
  1141. }
  1142. info->importedFunctionSignature = func;
  1143. info->boundFunctionId = -1;
  1144. info->importFromModule = moduleName;
  1145. bindInformations.PushLast(info);
  1146. // Add the info to the array in the engine
  1147. if( engine->freeImportedFunctionIdxs.GetLength() )
  1148. engine->importedFunctions[engine->freeImportedFunctionIdxs.PopLast()] = info;
  1149. else
  1150. engine->importedFunctions.PushLast(info);
  1151. return 0;
  1152. }
  1153. #endif
  1154. // internal
  1155. asCScriptFunction *asCModule::GetImportedFunction(int index) const
  1156. {
  1157. return bindInformations[index]->importedFunctionSignature;
  1158. }
  1159. // interface
  1160. int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
  1161. {
  1162. // First unbind the old function
  1163. int r = UnbindImportedFunction(index);
  1164. if( r < 0 ) return r;
  1165. // Must verify that the interfaces are equal
  1166. asCScriptFunction *dst = GetImportedFunction(index);
  1167. if( dst == 0 ) return asNO_FUNCTION;
  1168. if( func == 0 )
  1169. return asINVALID_ARG;
  1170. asCScriptFunction *src = engine->GetScriptFunction(func->GetId());
  1171. if( src == 0 )
  1172. return asNO_FUNCTION;
  1173. // Verify return type
  1174. if( dst->returnType != src->returnType )
  1175. return asINVALID_INTERFACE;
  1176. if( dst->parameterTypes.GetLength() != src->parameterTypes.GetLength() )
  1177. return asINVALID_INTERFACE;
  1178. for( asUINT n = 0; n < dst->parameterTypes.GetLength(); ++n )
  1179. {
  1180. if( dst->parameterTypes[n] != src->parameterTypes[n] )
  1181. return asINVALID_INTERFACE;
  1182. }
  1183. bindInformations[index]->boundFunctionId = src->GetId();
  1184. src->AddRefInternal();
  1185. return asSUCCESS;
  1186. }
  1187. // interface
  1188. int asCModule::UnbindImportedFunction(asUINT index)
  1189. {
  1190. if( index >= bindInformations.GetLength() )
  1191. return asINVALID_ARG;
  1192. // Remove reference to old module
  1193. if( bindInformations[index] )
  1194. {
  1195. int oldFuncID = bindInformations[index]->boundFunctionId;
  1196. if( oldFuncID != -1 )
  1197. {
  1198. bindInformations[index]->boundFunctionId = -1;
  1199. engine->scriptFunctions[oldFuncID]->ReleaseInternal();
  1200. }
  1201. }
  1202. return asSUCCESS;
  1203. }
  1204. // interface
  1205. const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
  1206. {
  1207. asCScriptFunction *func = GetImportedFunction(index);
  1208. if( func == 0 ) return 0;
  1209. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  1210. *tempString = func->GetDeclarationStr();
  1211. return tempString->AddressOf();
  1212. }
  1213. // interface
  1214. const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const
  1215. {
  1216. if( index >= bindInformations.GetLength() )
  1217. return 0;
  1218. return bindInformations[index]->importFromModule.AddressOf();
  1219. }
  1220. // inteface
  1221. int asCModule::BindAllImportedFunctions()
  1222. {
  1223. bool notAllFunctionsWereBound = false;
  1224. // Bind imported functions
  1225. int c = GetImportedFunctionCount();
  1226. for( int n = 0; n < c; ++n )
  1227. {
  1228. asCScriptFunction *importFunc = GetImportedFunction(n);
  1229. if( importFunc == 0 ) return asERROR;
  1230. asCString str = importFunc->GetDeclarationStr(false, true);
  1231. // Get module name from where the function should be imported
  1232. const char *moduleName = GetImportedFunctionSourceModule(n);
  1233. if( moduleName == 0 ) return asERROR;
  1234. asCModule *srcMod = engine->GetModule(moduleName, false);
  1235. asIScriptFunction *func = 0;
  1236. if( srcMod )
  1237. func = srcMod->GetFunctionByDecl(str.AddressOf());
  1238. if( func == 0 )
  1239. notAllFunctionsWereBound = true;
  1240. else
  1241. {
  1242. if( BindImportedFunction(n, func) < 0 )
  1243. notAllFunctionsWereBound = true;
  1244. }
  1245. }
  1246. if( notAllFunctionsWereBound )
  1247. return asCANT_BIND_ALL_FUNCTIONS;
  1248. return asSUCCESS;
  1249. }
  1250. // interface
  1251. int asCModule::UnbindAllImportedFunctions()
  1252. {
  1253. asUINT c = GetImportedFunctionCount();
  1254. for( asUINT n = 0; n < c; ++n )
  1255. UnbindImportedFunction(n);
  1256. return asSUCCESS;
  1257. }
  1258. // internal
  1259. asCTypeInfo *asCModule::GetType(const char *type, asSNameSpace *ns)
  1260. {
  1261. asUINT n;
  1262. // TODO: optimize: Improve linear search
  1263. for (n = 0; n < classTypes.GetLength(); n++)
  1264. if (classTypes[n]->name == type &&
  1265. classTypes[n]->nameSpace == ns)
  1266. return classTypes[n];
  1267. for (n = 0; n < enumTypes.GetLength(); n++)
  1268. if (enumTypes[n]->name == type &&
  1269. enumTypes[n]->nameSpace == ns)
  1270. return enumTypes[n];
  1271. for (n = 0; n < typeDefs.GetLength(); n++)
  1272. if (typeDefs[n]->name == type &&
  1273. typeDefs[n]->nameSpace == ns)
  1274. return typeDefs[n];
  1275. for (n = 0; n < funcDefs.GetLength(); n++)
  1276. if (funcDefs[n]->name == type &&
  1277. funcDefs[n]->nameSpace == ns)
  1278. return funcDefs[n];
  1279. return 0;
  1280. }
  1281. // internal
  1282. asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns)
  1283. {
  1284. asUINT n;
  1285. // TODO: optimize: Improve linear search
  1286. for( n = 0; n < classTypes.GetLength(); n++ )
  1287. if( classTypes[n]->name == type &&
  1288. classTypes[n]->nameSpace == ns )
  1289. return classTypes[n];
  1290. return 0;
  1291. }
  1292. // internal
  1293. asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *propName, const asCDataType &dt, asSNameSpace *ns)
  1294. {
  1295. asCGlobalProperty *prop = engine->AllocateGlobalProperty();
  1296. prop->name = propName;
  1297. prop->nameSpace = ns;
  1298. // Allocate the memory for this property based on its type
  1299. prop->type = dt;
  1300. prop->AllocateMemory();
  1301. // Make an entry in the address to variable map
  1302. engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  1303. // Store the variable in the module scope
  1304. scriptGlobals.Put(prop);
  1305. prop->AddRef();
  1306. return prop;
  1307. }
  1308. // internal
  1309. bool asCModule::IsEmpty() const
  1310. {
  1311. if( scriptFunctions.GetLength() ) return false;
  1312. if( globalFunctions.GetSize() ) return false;
  1313. if( bindInformations.GetLength() ) return false;
  1314. if( scriptGlobals.GetSize() ) return false;
  1315. if( classTypes.GetLength() ) return false;
  1316. if( enumTypes.GetLength() ) return false;
  1317. if( typeDefs.GetLength() ) return false;
  1318. if( funcDefs.GetLength() ) return false;
  1319. return true;
  1320. }
  1321. // interface
  1322. int asCModule::SaveByteCode(asIBinaryStream *out, bool stripDebugInfo) const
  1323. {
  1324. #ifdef AS_NO_COMPILER
  1325. UNUSED_VAR(out);
  1326. UNUSED_VAR(stripDebugInfo);
  1327. return asNOT_SUPPORTED;
  1328. #else
  1329. if( out == 0 ) return asINVALID_ARG;
  1330. // Make sure there is actually something to save
  1331. if( IsEmpty() )
  1332. return asERROR;
  1333. asCWriter write(const_cast<asCModule*>(this), out, engine, stripDebugInfo);
  1334. return write.Write();
  1335. #endif
  1336. }
  1337. // interface
  1338. int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped)
  1339. {
  1340. if( in == 0 ) return asINVALID_ARG;
  1341. // Don't allow the module to be rebuilt if there are still
  1342. // external references that will need the previous code
  1343. if( HasExternalReferences(false) )
  1344. {
  1345. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
  1346. return asMODULE_IS_IN_USE;
  1347. }
  1348. // Only permit loading bytecode if no other thread is currently compiling
  1349. // TODO: It should be possible to have multiple threads perform compilations
  1350. int r = engine->RequestBuild();
  1351. if( r < 0 )
  1352. return r;
  1353. asCReader read(this, in, engine);
  1354. r = read.Read(wasDebugInfoStripped);
  1355. if (r < 0)
  1356. {
  1357. engine->BuildCompleted();
  1358. return r;
  1359. }
  1360. JITCompile();
  1361. #ifdef AS_DEBUG
  1362. // Verify that there are no unwanted gaps in the scriptFunctions array.
  1363. for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ )
  1364. {
  1365. int id = n;
  1366. if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) )
  1367. asASSERT( false );
  1368. }
  1369. #endif
  1370. engine->BuildCompleted();
  1371. return r;
  1372. }
  1373. // interface
  1374. int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  1375. {
  1376. #ifdef AS_NO_COMPILER
  1377. UNUSED_VAR(sectionName);
  1378. UNUSED_VAR(code);
  1379. UNUSED_VAR(lineOffset);
  1380. return asNOT_SUPPORTED;
  1381. #else
  1382. // Validate arguments
  1383. if( code == 0 )
  1384. return asINVALID_ARG;
  1385. // Only one thread may build at one time
  1386. // TODO: It should be possible to have multiple threads perform compilations
  1387. int r = engine->RequestBuild();
  1388. if( r < 0 )
  1389. return r;
  1390. // Prepare the engine
  1391. engine->PrepareEngine();
  1392. if( engine->configFailed )
  1393. {
  1394. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1395. engine->BuildCompleted();
  1396. return asINVALID_CONFIGURATION;
  1397. }
  1398. // Compile the global variable and add it to the module scope
  1399. asCBuilder varBuilder(engine, this);
  1400. asCString str = code;
  1401. r = varBuilder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset);
  1402. engine->BuildCompleted();
  1403. // Initialize the variable
  1404. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  1405. {
  1406. // Clear the memory
  1407. asCGlobalProperty *prop = scriptGlobals.GetLast();
  1408. if( prop )
  1409. {
  1410. memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords());
  1411. if( prop->GetInitFunc() )
  1412. {
  1413. // Call the init function for the global variable
  1414. asIScriptContext *ctx = 0;
  1415. r = engine->CreateContext(&ctx, true);
  1416. if( r < 0 )
  1417. return r;
  1418. r = ctx->Prepare(prop->GetInitFunc());
  1419. if( r >= 0 )
  1420. r = ctx->Execute();
  1421. ctx->Release();
  1422. }
  1423. }
  1424. }
  1425. return r;
  1426. #endif
  1427. }
  1428. // interface
  1429. int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc)
  1430. {
  1431. // Make sure the outFunc is null if the function fails, so the
  1432. // application doesn't attempt to release a non-existent function
  1433. if( outFunc )
  1434. *outFunc = 0;
  1435. #ifdef AS_NO_COMPILER
  1436. UNUSED_VAR(sectionName);
  1437. UNUSED_VAR(code);
  1438. UNUSED_VAR(lineOffset);
  1439. UNUSED_VAR(compileFlags);
  1440. return asNOT_SUPPORTED;
  1441. #else
  1442. // Validate arguments
  1443. if( code == 0 ||
  1444. (compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) )
  1445. return asINVALID_ARG;
  1446. // Only one thread may build at one time
  1447. // TODO: It should be possible to have multiple threads perform compilations
  1448. int r = engine->RequestBuild();
  1449. if( r < 0 )
  1450. return r;
  1451. // Prepare the engine
  1452. engine->PrepareEngine();
  1453. if( engine->configFailed )
  1454. {
  1455. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1456. engine->BuildCompleted();
  1457. return asINVALID_CONFIGURATION;
  1458. }
  1459. // Compile the single function
  1460. asCBuilder funcBuilder(engine, this);
  1461. asCString str = code;
  1462. asCScriptFunction *func = 0;
  1463. r = funcBuilder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
  1464. engine->BuildCompleted();
  1465. if( r >= 0 && outFunc && func )
  1466. {
  1467. // Return the function to the caller and add an external reference
  1468. *outFunc = func;
  1469. func->AddRef();
  1470. }
  1471. // Release our reference to the function
  1472. if( func )
  1473. func->ReleaseInternal();
  1474. return r;
  1475. #endif
  1476. }
  1477. // interface
  1478. int asCModule::RemoveFunction(asIScriptFunction *func)
  1479. {
  1480. // Find the global function
  1481. asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
  1482. int idx = globalFunctions.GetIndex(f);
  1483. if( idx >= 0 )
  1484. {
  1485. globalFunctions.Erase(idx);
  1486. scriptFunctions.RemoveValue(f);
  1487. f->ReleaseInternal();
  1488. return 0;
  1489. }
  1490. return asNO_FUNCTION;
  1491. }
  1492. #ifndef AS_NO_COMPILER
  1493. // internal
  1494. int asCModule::AddFuncDef(const asCString &funcName, asSNameSpace *ns, asCObjectType *parent)
  1495. {
  1496. // namespace and parent are mutually exclusive
  1497. asASSERT((ns == 0 && parent) || (ns && parent == 0));
  1498. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF);
  1499. if (func == 0)
  1500. return asOUT_OF_MEMORY;
  1501. func->name = funcName;
  1502. func->nameSpace = ns;
  1503. func->module = this;
  1504. asCFuncdefType *fdt = asNEW(asCFuncdefType)(engine, func);
  1505. funcDefs.PushLast(fdt); // The constructor set the refcount to 1
  1506. engine->funcDefs.PushLast(fdt); // doesn't increase refcount
  1507. func->id = engine->GetNextScriptFunctionId();
  1508. engine->AddScriptFunction(func);
  1509. if (parent)
  1510. {
  1511. parent->childFuncDefs.PushLast(fdt);
  1512. fdt->parentClass = parent;
  1513. }
  1514. return (int)funcDefs.GetLength()-1;
  1515. }
  1516. #endif
  1517. // interface
  1518. asDWORD asCModule::SetAccessMask(asDWORD mask)
  1519. {
  1520. asDWORD old = accessMask;
  1521. accessMask = mask;
  1522. return old;
  1523. }
  1524. END_AS_NAMESPACE