as_module.cpp 45 KB

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