as_module.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2012 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. BEGIN_AS_NAMESPACE
  34. // internal
  35. asCModule::asCModule(const char *name, asCScriptEngine *engine)
  36. {
  37. this->name = name;
  38. this->engine = engine;
  39. userData = 0;
  40. builder = 0;
  41. isGlobalVarInitialized = false;
  42. accessMask = 1;
  43. }
  44. // internal
  45. asCModule::~asCModule()
  46. {
  47. InternalReset();
  48. if( builder )
  49. {
  50. asDELETE(builder,asCBuilder);
  51. builder = 0;
  52. }
  53. // Clean the user data
  54. if( userData && engine->cleanModuleFunc )
  55. engine->cleanModuleFunc(this);
  56. // Remove the module from the engine
  57. if( engine )
  58. {
  59. if( engine->lastModule == this )
  60. engine->lastModule = 0;
  61. engine->scriptModules.RemoveValue(this);
  62. }
  63. }
  64. // interface
  65. void *asCModule::SetUserData(void *data)
  66. {
  67. void *oldData = userData;
  68. userData = data;
  69. return oldData;
  70. }
  71. // interface
  72. void *asCModule::GetUserData() const
  73. {
  74. return userData;
  75. }
  76. // interface
  77. asIScriptEngine *asCModule::GetEngine() const
  78. {
  79. return engine;
  80. }
  81. // interface
  82. void asCModule::SetName(const char *name)
  83. {
  84. this->name = name;
  85. }
  86. // interface
  87. const char *asCModule::GetName() const
  88. {
  89. return name.AddressOf();
  90. }
  91. // interface
  92. int asCModule::SetDefaultNamespace(const char *nameSpace)
  93. {
  94. // TODO: cleanup: This function is similar to asCScriptEngine::SetDefaultNamespace. Can we reuse the code?
  95. if( nameSpace == 0 )
  96. return asINVALID_ARG;
  97. defaultNamespace = nameSpace;
  98. if( defaultNamespace != "" )
  99. {
  100. // Make sure the namespace is composed of alternating identifier and ::
  101. size_t pos = 0;
  102. bool expectIdentifier = true;
  103. size_t len;
  104. eTokenType t = ttIdentifier;
  105. for( ; pos < defaultNamespace.GetLength(); pos += len )
  106. {
  107. t = engine->tok.GetToken(defaultNamespace.AddressOf() + pos, defaultNamespace.GetLength() - pos, &len);
  108. if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) )
  109. return asINVALID_DECLARATION;
  110. expectIdentifier = !expectIdentifier;
  111. }
  112. // If the namespace ends with :: then strip it off
  113. if( t == ttScope )
  114. defaultNamespace.SetLength(defaultNamespace.GetLength()-2);
  115. }
  116. return 0;
  117. }
  118. // interface
  119. int asCModule::AddScriptSection(const char *name, const char *code, size_t codeLength, int lineOffset)
  120. {
  121. #ifdef AS_NO_COMPILER
  122. UNUSED_VAR(name);
  123. UNUSED_VAR(code);
  124. UNUSED_VAR(codeLength);
  125. UNUSED_VAR(lineOffset);
  126. return asNOT_SUPPORTED;
  127. #else
  128. if( !builder )
  129. {
  130. builder = asNEW(asCBuilder)(engine, this);
  131. if( builder == 0 )
  132. return asOUT_OF_MEMORY;
  133. }
  134. return builder->AddCode(name, code, (int)codeLength, lineOffset, (int)engine->GetScriptSectionNameIndex(name ? name : ""), engine->ep.copyScriptSections);
  135. #endif
  136. }
  137. // internal
  138. void asCModule::JITCompile()
  139. {
  140. for (unsigned int i = 0; i < scriptFunctions.GetLength(); i++)
  141. {
  142. scriptFunctions[i]->JITCompile();
  143. }
  144. }
  145. // interface
  146. int asCModule::Build()
  147. {
  148. #ifdef AS_NO_COMPILER
  149. return asNOT_SUPPORTED;
  150. #else
  151. // Only one thread may build at one time
  152. // TODO: It should be possible to have multiple threads perform compilations
  153. int r = engine->RequestBuild();
  154. if( r < 0 )
  155. return r;
  156. engine->PrepareEngine();
  157. if( engine->configFailed )
  158. {
  159. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  160. engine->BuildCompleted();
  161. return asINVALID_CONFIGURATION;
  162. }
  163. InternalReset();
  164. if( !builder )
  165. {
  166. engine->BuildCompleted();
  167. return asSUCCESS;
  168. }
  169. // Compile the script
  170. r = builder->Build();
  171. asDELETE(builder,asCBuilder);
  172. builder = 0;
  173. if( r < 0 )
  174. {
  175. // Reset module again
  176. InternalReset();
  177. engine->BuildCompleted();
  178. return r;
  179. }
  180. JITCompile();
  181. engine->PrepareEngine();
  182. engine->BuildCompleted();
  183. // Initialize global variables
  184. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  185. r = ResetGlobalVars(0);
  186. return r;
  187. #endif
  188. }
  189. // interface
  190. int asCModule::ResetGlobalVars(asIScriptContext *ctx)
  191. {
  192. if( isGlobalVarInitialized )
  193. CallExit();
  194. return CallInit(ctx);
  195. }
  196. #ifdef AS_DEPRECATED
  197. // Deprecated since 2.24.0 - 2012-05-20
  198. // interface
  199. int asCModule::GetFunctionIdByIndex(asUINT index) const
  200. {
  201. if( index >= globalFunctions.GetLength() )
  202. return asNO_FUNCTION;
  203. return globalFunctions[index]->id;
  204. }
  205. #endif
  206. // interface
  207. asIScriptFunction *asCModule::GetFunctionByIndex(asUINT index) const
  208. {
  209. if( index >= globalFunctions.GetLength() )
  210. return 0;
  211. return globalFunctions[index];
  212. }
  213. // internal
  214. int asCModule::CallInit(asIScriptContext *myCtx)
  215. {
  216. if( isGlobalVarInitialized )
  217. return asERROR;
  218. // Each global variable needs to be cleared individually
  219. asUINT n;
  220. for( n = 0; n < scriptGlobals.GetLength(); n++ )
  221. {
  222. if( scriptGlobals[n] )
  223. {
  224. memset(scriptGlobals[n]->GetAddressOfValue(), 0, sizeof(asDWORD)*scriptGlobals[n]->type.GetSizeOnStackDWords());
  225. }
  226. }
  227. // Call the init function for each of the global variables
  228. asIScriptContext *ctx = myCtx;
  229. int r = asEXECUTION_FINISHED;
  230. for( n = 0; n < scriptGlobals.GetLength() && r == asEXECUTION_FINISHED; n++ )
  231. {
  232. if( scriptGlobals[n]->GetInitFunc() )
  233. {
  234. if( ctx == 0 )
  235. {
  236. r = engine->CreateContext(&ctx, true);
  237. if( r < 0 )
  238. break;
  239. }
  240. r = ctx->Prepare(scriptGlobals[n]->GetInitFunc());
  241. if( r >= 0 )
  242. {
  243. r = ctx->Execute();
  244. if( r != asEXECUTION_FINISHED )
  245. {
  246. asCString msg;
  247. msg.Format(TXT_FAILED_TO_INITIALIZE_s, scriptGlobals[n]->name.AddressOf());
  248. asCScriptFunction *func = scriptGlobals[n]->GetInitFunc();
  249. engine->WriteMessage(func->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptSectionIdx]->AddressOf() : "",
  250. func->GetLineNumber(0) & 0xFFFFF,
  251. func->GetLineNumber(0) >> 20,
  252. asMSGTYPE_ERROR,
  253. msg.AddressOf());
  254. if( r == asEXECUTION_EXCEPTION )
  255. {
  256. const asIScriptFunction *function = ctx->GetExceptionFunction();
  257. msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration());
  258. engine->WriteMessage(function->GetScriptSectionName(),
  259. ctx->GetExceptionLineNumber(),
  260. 0,
  261. asMSGTYPE_INFORMATION,
  262. msg.AddressOf());
  263. }
  264. }
  265. }
  266. }
  267. }
  268. if( ctx && !myCtx )
  269. {
  270. ctx->Release();
  271. ctx = 0;
  272. }
  273. // Even if the initialization failed we need to set the
  274. // flag that the variables have been initialized, otherwise
  275. // the module won't free those variables that really were
  276. // initialized.
  277. isGlobalVarInitialized = true;
  278. if( r != asEXECUTION_FINISHED )
  279. return asINIT_GLOBAL_VARS_FAILED;
  280. return asSUCCESS;
  281. }
  282. // internal
  283. void asCModule::CallExit()
  284. {
  285. if( !isGlobalVarInitialized ) return;
  286. for( size_t n = 0; n < scriptGlobals.GetLength(); n++ )
  287. {
  288. if( scriptGlobals[n]->type.IsObject() )
  289. {
  290. void **obj = (void**)scriptGlobals[n]->GetAddressOfValue();
  291. if( *obj )
  292. {
  293. asCObjectType *ot = scriptGlobals[n]->type.GetObjectType();
  294. if( ot->flags & asOBJ_REF )
  295. {
  296. asASSERT( (ot->flags & asOBJ_NOCOUNT) || ot->beh.release );
  297. if( ot->beh.release )
  298. engine->CallObjectMethod(*obj, ot->beh.release);
  299. }
  300. else
  301. {
  302. if( ot->beh.destruct )
  303. engine->CallObjectMethod(*obj, ot->beh.destruct);
  304. engine->CallFree(*obj);
  305. }
  306. // Set the address to 0 as someone might try to access the variable afterwards
  307. *obj = 0;
  308. }
  309. }
  310. }
  311. isGlobalVarInitialized = false;
  312. }
  313. // internal
  314. void asCModule::InternalReset()
  315. {
  316. CallExit();
  317. size_t n;
  318. // Release all global functions
  319. for( n = 0; n < globalFunctions.GetLength(); n++ )
  320. {
  321. if( globalFunctions[n] )
  322. globalFunctions[n]->Release();
  323. }
  324. globalFunctions.SetLength(0);
  325. // First release all compiled functions
  326. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  327. {
  328. if( scriptFunctions[n] )
  329. {
  330. // Remove the module reference in the functions
  331. scriptFunctions[n]->module = 0;
  332. scriptFunctions[n]->Release();
  333. }
  334. }
  335. scriptFunctions.SetLength(0);
  336. // Release the global properties declared in the module
  337. for( n = 0; n < scriptGlobals.GetLength(); n++ )
  338. scriptGlobals[n]->Release();
  339. scriptGlobals.SetLength(0);
  340. UnbindAllImportedFunctions();
  341. // Free bind information
  342. for( n = 0; n < bindInformations.GetLength(); n++ )
  343. {
  344. if( bindInformations[n] )
  345. {
  346. asUINT id = bindInformations[n]->importedFunctionSignature->id & 0xFFFF;
  347. engine->importedFunctions[id] = 0;
  348. engine->freeImportedFunctionIdxs.PushLast(id);
  349. asDELETE(bindInformations[n]->importedFunctionSignature, asCScriptFunction);
  350. asDELETE(bindInformations[n], sBindInfo);
  351. }
  352. }
  353. bindInformations.SetLength(0);
  354. // Free declared types, including classes, typedefs, and enums
  355. for( n = 0; n < classTypes.GetLength(); n++ )
  356. classTypes[n]->Release();
  357. classTypes.SetLength(0);
  358. for( n = 0; n < enumTypes.GetLength(); n++ )
  359. enumTypes[n]->Release();
  360. enumTypes.SetLength(0);
  361. for( n = 0; n < typeDefs.GetLength(); n++ )
  362. typeDefs[n]->Release();
  363. typeDefs.SetLength(0);
  364. // Free funcdefs
  365. for( n = 0; n < funcDefs.GetLength(); n++ )
  366. {
  367. // TODO: funcdefs: These may be shared between modules, so we can't just remove them
  368. engine->funcDefs.RemoveValue(funcDefs[n]);
  369. funcDefs[n]->Release();
  370. }
  371. funcDefs.SetLength(0);
  372. }
  373. #ifdef AS_DEPRECATED
  374. // Deprecated since 2.24.0 - 2012-05-20
  375. // interface
  376. int asCModule::GetFunctionIdByName(const char *name) const
  377. {
  378. // TODO: optimize: Improve linear search
  379. // Find the function id
  380. int id = -1;
  381. for( size_t n = 0; n < globalFunctions.GetLength(); n++ )
  382. {
  383. if( globalFunctions[n]->name == name &&
  384. globalFunctions[n]->nameSpace == defaultNamespace )
  385. {
  386. if( id == -1 )
  387. id = globalFunctions[n]->id;
  388. else
  389. return asMULTIPLE_FUNCTIONS;
  390. }
  391. }
  392. if( id == -1 ) return asNO_FUNCTION;
  393. return id;
  394. }
  395. #endif
  396. // interface
  397. asIScriptFunction *asCModule::GetFunctionByName(const char *name) const
  398. {
  399. asIScriptFunction *func = 0;
  400. for( size_t n = 0; n < globalFunctions.GetLength(); n++ )
  401. {
  402. if( globalFunctions[n]->name == name &&
  403. globalFunctions[n]->nameSpace == defaultNamespace )
  404. {
  405. if( func == 0 )
  406. func = globalFunctions[n];
  407. else
  408. {
  409. // Multiple functions with the same name
  410. return 0;
  411. }
  412. }
  413. }
  414. return func;
  415. }
  416. // interface
  417. asUINT asCModule::GetImportedFunctionCount() const
  418. {
  419. return (asUINT)bindInformations.GetLength();
  420. }
  421. // interface
  422. int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
  423. {
  424. asCBuilder bld(engine, const_cast<asCModule*>(this));
  425. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  426. bld.ParseFunctionDeclaration(0, decl, &func, false);
  427. // TODO: optimize: Improve linear search
  428. // Search script functions for matching interface
  429. int id = -1;
  430. for( asUINT n = 0; n < bindInformations.GetLength(); ++n )
  431. {
  432. if( func.name == bindInformations[n]->importedFunctionSignature->name &&
  433. func.returnType == bindInformations[n]->importedFunctionSignature->returnType &&
  434. func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() )
  435. {
  436. bool match = true;
  437. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  438. {
  439. if( func.parameterTypes[p] != bindInformations[n]->importedFunctionSignature->parameterTypes[p] )
  440. {
  441. match = false;
  442. break;
  443. }
  444. }
  445. if( match )
  446. {
  447. if( id == -1 )
  448. id = n;
  449. else
  450. return asMULTIPLE_FUNCTIONS;
  451. }
  452. }
  453. }
  454. if( id == -1 ) return asNO_FUNCTION;
  455. return id;
  456. }
  457. // interface
  458. asUINT asCModule::GetFunctionCount() const
  459. {
  460. return (asUINT)globalFunctions.GetLength();
  461. }
  462. #ifdef AS_DEPRECATED
  463. // Deprecated since 2.24.0 - 2012-05-20
  464. // interface
  465. int asCModule::GetFunctionIdByDecl(const char *decl) const
  466. {
  467. asCBuilder bld(engine, const_cast<asCModule*>(this));
  468. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  469. int r = bld.ParseFunctionDeclaration(0, decl, &func, false);
  470. if( r < 0 )
  471. return asINVALID_DECLARATION;
  472. // Use the defaultNamespace implicitly unless an explicit namespace has been provided
  473. asCString ns = func.nameSpace == "" ? defaultNamespace : func.nameSpace;
  474. // TODO: optimize: Improve linear search
  475. // Search script functions for matching interface
  476. int id = -1;
  477. for( size_t n = 0; n < globalFunctions.GetLength(); ++n )
  478. {
  479. if( globalFunctions[n]->objectType == 0 &&
  480. func.name == globalFunctions[n]->name &&
  481. func.returnType == globalFunctions[n]->returnType &&
  482. func.parameterTypes.GetLength() == globalFunctions[n]->parameterTypes.GetLength() &&
  483. ns == globalFunctions[n]->nameSpace )
  484. {
  485. bool match = true;
  486. for( size_t p = 0; p < func.parameterTypes.GetLength(); ++p )
  487. {
  488. if( func.parameterTypes[p] != globalFunctions[n]->parameterTypes[p] )
  489. {
  490. match = false;
  491. break;
  492. }
  493. }
  494. if( match )
  495. {
  496. if( id == -1 )
  497. id = globalFunctions[n]->id;
  498. else
  499. return asMULTIPLE_FUNCTIONS;
  500. }
  501. }
  502. }
  503. if( id == -1 ) return asNO_FUNCTION;
  504. return id;
  505. }
  506. #endif
  507. // interface
  508. asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const
  509. {
  510. asCBuilder bld(engine, const_cast<asCModule*>(this));
  511. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  512. int r = bld.ParseFunctionDeclaration(0, decl, &func, false);
  513. if( r < 0 )
  514. {
  515. // Invalid declaration
  516. // TODO: Write error to message stream
  517. return 0;
  518. }
  519. // Use the defaultNamespace implicitly unless an explicit namespace has been provided
  520. asCString ns = func.nameSpace == "" ? defaultNamespace : func.nameSpace;
  521. // TODO: optimize: Improve linear search
  522. // Search script functions for matching interface
  523. asIScriptFunction *f = 0;
  524. for( size_t n = 0; n < globalFunctions.GetLength(); ++n )
  525. {
  526. if( globalFunctions[n]->objectType == 0 &&
  527. func.name == globalFunctions[n]->name &&
  528. func.returnType == globalFunctions[n]->returnType &&
  529. func.parameterTypes.GetLength() == globalFunctions[n]->parameterTypes.GetLength() &&
  530. ns == globalFunctions[n]->nameSpace )
  531. {
  532. bool match = true;
  533. for( size_t p = 0; p < func.parameterTypes.GetLength(); ++p )
  534. {
  535. if( func.parameterTypes[p] != globalFunctions[n]->parameterTypes[p] )
  536. {
  537. match = false;
  538. break;
  539. }
  540. }
  541. if( match )
  542. {
  543. if( f == 0 )
  544. f = globalFunctions[n];
  545. else
  546. // Multiple functions
  547. return 0;
  548. }
  549. }
  550. }
  551. return f;
  552. }
  553. // interface
  554. asUINT asCModule::GetGlobalVarCount() const
  555. {
  556. return (asUINT)scriptGlobals.GetLength();
  557. }
  558. // interface
  559. int asCModule::GetGlobalVarIndexByName(const char *name) const
  560. {
  561. // Find the global var id
  562. int id = -1;
  563. for( size_t n = 0; n < scriptGlobals.GetLength(); n++ )
  564. {
  565. if( scriptGlobals[n]->name == name &&
  566. scriptGlobals[n]->nameSpace == defaultNamespace )
  567. {
  568. id = (int)n;
  569. break;
  570. }
  571. }
  572. if( id == -1 ) return asNO_GLOBAL_VAR;
  573. return id;
  574. }
  575. // interface
  576. int asCModule::RemoveGlobalVar(asUINT index)
  577. {
  578. if( index >= scriptGlobals.GetLength() )
  579. return asINVALID_ARG;
  580. scriptGlobals[index]->Release();
  581. scriptGlobals.RemoveIndex(index);
  582. return 0;
  583. }
  584. // interface
  585. int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
  586. {
  587. asCBuilder bld(engine, const_cast<asCModule*>(this));
  588. asCString name, nameSpace;
  589. asCDataType dt;
  590. bld.ParseVariableDeclaration(decl, defaultNamespace, name, nameSpace, dt);
  591. // TODO: optimize: Improve linear search
  592. // Search global variables for a match
  593. int id = -1;
  594. for( size_t n = 0; n < scriptGlobals.GetLength(); ++n )
  595. {
  596. if( name == scriptGlobals[n]->name &&
  597. nameSpace == scriptGlobals[n]->nameSpace &&
  598. dt == scriptGlobals[n]->type )
  599. {
  600. id = (int)n;
  601. break;
  602. }
  603. }
  604. if( id == -1 ) return asNO_GLOBAL_VAR;
  605. return id;
  606. }
  607. // interface
  608. void *asCModule::GetAddressOfGlobalVar(asUINT index)
  609. {
  610. if( index >= scriptGlobals.GetLength() )
  611. return 0;
  612. // For object variables it's necessary to dereference the pointer to get the address of the value
  613. if( scriptGlobals[index]->type.IsObject() &&
  614. !scriptGlobals[index]->type.IsObjectHandle() )
  615. return *(void**)(scriptGlobals[index]->GetAddressOfValue());
  616. return (void*)(scriptGlobals[index]->GetAddressOfValue());
  617. }
  618. // interface
  619. const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespace) const
  620. {
  621. if( index >= scriptGlobals.GetLength() )
  622. return 0;
  623. asCGlobalProperty *prop = scriptGlobals[index];
  624. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  625. *tempString = prop->type.Format();
  626. *tempString += " ";
  627. if( includeNamespace )
  628. *tempString += prop->nameSpace + "::";
  629. *tempString += prop->name;
  630. return tempString->AddressOf();
  631. }
  632. // interface
  633. int asCModule::GetGlobalVar(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst) const
  634. {
  635. if( index >= scriptGlobals.GetLength() )
  636. return asINVALID_ARG;
  637. asCGlobalProperty *prop = scriptGlobals[index];
  638. if( name )
  639. *name = prop->name.AddressOf();
  640. if( nameSpace )
  641. *nameSpace = prop->nameSpace.AddressOf();
  642. if( typeId )
  643. *typeId = engine->GetTypeIdFromDataType(prop->type);
  644. if( isConst )
  645. *isConst = prop->type.IsReadOnly();
  646. return asSUCCESS;
  647. }
  648. // interface
  649. asUINT asCModule::GetObjectTypeCount() const
  650. {
  651. return (asUINT)classTypes.GetLength();
  652. }
  653. // interface
  654. asIObjectType *asCModule::GetObjectTypeByIndex(asUINT index) const
  655. {
  656. if( index >= classTypes.GetLength() )
  657. return 0;
  658. return classTypes[index];
  659. }
  660. // interface
  661. asIObjectType *asCModule::GetObjectTypeByName(const char *name) const
  662. {
  663. for( asUINT n = 0; n < classTypes.GetLength(); n++ )
  664. {
  665. if( classTypes[n] &&
  666. classTypes[n]->name == name &&
  667. classTypes[n]->nameSpace == defaultNamespace )
  668. return classTypes[n];
  669. }
  670. return 0;
  671. }
  672. // interface
  673. int asCModule::GetTypeIdByDecl(const char *decl) const
  674. {
  675. asCDataType dt;
  676. asCBuilder bld(engine, const_cast<asCModule*>(this));
  677. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  678. if( r < 0 )
  679. return asINVALID_TYPE;
  680. return engine->GetTypeIdFromDataType(dt);
  681. }
  682. // interface
  683. asUINT asCModule::GetEnumCount() const
  684. {
  685. return (asUINT)enumTypes.GetLength();
  686. }
  687. // interface
  688. const char *asCModule::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace) const
  689. {
  690. if( index >= enumTypes.GetLength() )
  691. return 0;
  692. if( enumTypeId )
  693. *enumTypeId = GetTypeIdByDecl(enumTypes[index]->name.AddressOf());
  694. if( nameSpace )
  695. *nameSpace = enumTypes[index]->name.AddressOf();
  696. return enumTypes[index]->name.AddressOf();
  697. }
  698. // interface
  699. int asCModule::GetEnumValueCount(int enumTypeId) const
  700. {
  701. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  702. asCObjectType *t = dt.GetObjectType();
  703. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  704. return asINVALID_TYPE;
  705. return (int)t->enumValues.GetLength();
  706. }
  707. // interface
  708. const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
  709. {
  710. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  711. asCObjectType *t = dt.GetObjectType();
  712. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  713. return 0;
  714. if( index >= t->enumValues.GetLength() )
  715. return 0;
  716. if( outValue )
  717. *outValue = t->enumValues[index]->value;
  718. return t->enumValues[index]->name.AddressOf();
  719. }
  720. // interface
  721. asUINT asCModule::GetTypedefCount() const
  722. {
  723. return (asUINT)typeDefs.GetLength();
  724. }
  725. // interface
  726. const char *asCModule::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace) const
  727. {
  728. if( index >= typeDefs.GetLength() )
  729. return 0;
  730. if( typeId )
  731. *typeId = GetTypeIdByDecl(typeDefs[index]->name.AddressOf());
  732. if( nameSpace )
  733. *nameSpace = typeDefs[index]->nameSpace.AddressOf();
  734. return typeDefs[index]->name.AddressOf();
  735. }
  736. // internal
  737. int asCModule::GetNextImportedFunctionId()
  738. {
  739. // TODO: multithread: This will break if one thread if freeing a module, while another is being compiled
  740. if( engine->freeImportedFunctionIdxs.GetLength() )
  741. return FUNC_IMPORTED | (asUINT)engine->freeImportedFunctionIdxs[engine->freeImportedFunctionIdxs.GetLength()-1];
  742. return FUNC_IMPORTED | (asUINT)engine->importedFunctions.GetLength();
  743. }
  744. // internal
  745. int asCModule::AddScriptFunction(int sectionIdx, int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, asCString **defaultArgs, int paramCount, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isFinal, bool isOverride, bool isShared, const asCString &ns)
  746. {
  747. asASSERT(id >= 0);
  748. // Store the function information
  749. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT);
  750. if( func == 0 )
  751. return asOUT_OF_MEMORY;
  752. func->name = name;
  753. func->nameSpace = ns;
  754. func->id = id;
  755. func->returnType = returnType;
  756. func->scriptSectionIdx = sectionIdx;
  757. for( int n = 0; n < paramCount; n++ )
  758. {
  759. func->parameterTypes.PushLast(params[n]);
  760. func->inOutFlags.PushLast(inOutFlags[n]);
  761. func->defaultArgs.PushLast(defaultArgs[n]);
  762. }
  763. func->objectType = objType;
  764. func->isReadOnly = isConstMethod;
  765. func->isPrivate = isPrivate;
  766. func->isFinal = isFinal;
  767. func->isOverride = isOverride;
  768. // All methods of shared objects are also shared
  769. if( objType && objType->IsShared() )
  770. isShared = true;
  771. func->isShared = isShared;
  772. // Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
  773. asASSERT( !(!objType && isFinal) );
  774. asASSERT( !(!objType && isOverride) );
  775. // The script function's refCount was initialized to 1
  776. scriptFunctions.PushLast(func);
  777. engine->SetScriptFunction(func);
  778. // Compute the signature id
  779. if( objType )
  780. func->ComputeSignatureId();
  781. // Add reference
  782. if( isGlobalFunction )
  783. {
  784. globalFunctions.PushLast(func);
  785. func->AddRef();
  786. }
  787. return 0;
  788. }
  789. // internal
  790. int asCModule::AddScriptFunction(asCScriptFunction *func)
  791. {
  792. scriptFunctions.PushLast(func);
  793. func->AddRef();
  794. engine->SetScriptFunction(func);
  795. return 0;
  796. }
  797. // internal
  798. int asCModule::AddImportedFunction(int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, int paramCount, const asCString &moduleName)
  799. {
  800. asASSERT(id >= 0);
  801. // Store the function information
  802. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED);
  803. if( func == 0 )
  804. return asOUT_OF_MEMORY;
  805. func->name = name;
  806. func->id = id;
  807. func->returnType = returnType;
  808. for( int n = 0; n < paramCount; n++ )
  809. {
  810. func->parameterTypes.PushLast(params[n]);
  811. func->inOutFlags.PushLast(inOutFlags[n]);
  812. }
  813. func->objectType = 0;
  814. sBindInfo *info = asNEW(sBindInfo);
  815. if( info == 0 )
  816. return asOUT_OF_MEMORY;
  817. info->importedFunctionSignature = func;
  818. info->boundFunctionId = -1;
  819. info->importFromModule = moduleName;
  820. bindInformations.PushLast(info);
  821. // Add the info to the array in the engine
  822. if( engine->freeImportedFunctionIdxs.GetLength() )
  823. engine->importedFunctions[engine->freeImportedFunctionIdxs.PopLast()] = info;
  824. else
  825. engine->importedFunctions.PushLast(info);
  826. return 0;
  827. }
  828. // internal
  829. asCScriptFunction *asCModule::GetImportedFunction(int index) const
  830. {
  831. return bindInformations[index]->importedFunctionSignature;
  832. }
  833. // interface
  834. int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
  835. {
  836. // First unbind the old function
  837. int r = UnbindImportedFunction(index);
  838. if( r < 0 ) return r;
  839. // Must verify that the interfaces are equal
  840. asCScriptFunction *dst = GetImportedFunction(index);
  841. if( dst == 0 ) return asNO_FUNCTION;
  842. if( func == 0 )
  843. return asINVALID_ARG;
  844. asCScriptFunction *src = engine->GetScriptFunction(func->GetId());
  845. if( src == 0 )
  846. return asNO_FUNCTION;
  847. // Verify return type
  848. if( dst->returnType != src->returnType )
  849. return asINVALID_INTERFACE;
  850. if( dst->parameterTypes.GetLength() != src->parameterTypes.GetLength() )
  851. return asINVALID_INTERFACE;
  852. for( size_t n = 0; n < dst->parameterTypes.GetLength(); ++n )
  853. {
  854. if( dst->parameterTypes[n] != src->parameterTypes[n] )
  855. return asINVALID_INTERFACE;
  856. }
  857. bindInformations[index]->boundFunctionId = src->GetId();
  858. src->AddRef();
  859. return asSUCCESS;
  860. }
  861. // interface
  862. int asCModule::UnbindImportedFunction(asUINT index)
  863. {
  864. if( index >= bindInformations.GetLength() )
  865. return asINVALID_ARG;
  866. // Remove reference to old module
  867. if( bindInformations[index] )
  868. {
  869. int oldFuncID = bindInformations[index]->boundFunctionId;
  870. if( oldFuncID != -1 )
  871. {
  872. bindInformations[index]->boundFunctionId = -1;
  873. engine->scriptFunctions[oldFuncID]->Release();
  874. }
  875. }
  876. return asSUCCESS;
  877. }
  878. // interface
  879. const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
  880. {
  881. asCScriptFunction *func = GetImportedFunction(index);
  882. if( func == 0 ) return 0;
  883. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  884. *tempString = func->GetDeclarationStr();
  885. return tempString->AddressOf();
  886. }
  887. // interface
  888. const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const
  889. {
  890. if( index >= bindInformations.GetLength() )
  891. return 0;
  892. return bindInformations[index]->importFromModule.AddressOf();
  893. }
  894. // inteface
  895. int asCModule::BindAllImportedFunctions()
  896. {
  897. bool notAllFunctionsWereBound = false;
  898. // Bind imported functions
  899. int c = GetImportedFunctionCount();
  900. for( int n = 0; n < c; ++n )
  901. {
  902. asCScriptFunction *importFunc = GetImportedFunction(n);
  903. if( importFunc == 0 ) return asERROR;
  904. asCString str = importFunc->GetDeclarationStr();
  905. // Get module name from where the function should be imported
  906. const char *moduleName = GetImportedFunctionSourceModule(n);
  907. if( moduleName == 0 ) return asERROR;
  908. asCModule *srcMod = engine->GetModule(moduleName, false);
  909. asIScriptFunction *func = 0;
  910. if( srcMod )
  911. func = srcMod->GetFunctionByDecl(str.AddressOf());
  912. if( func == 0 )
  913. notAllFunctionsWereBound = true;
  914. else
  915. {
  916. if( BindImportedFunction(n, func) < 0 )
  917. notAllFunctionsWereBound = true;
  918. }
  919. }
  920. if( notAllFunctionsWereBound )
  921. return asCANT_BIND_ALL_FUNCTIONS;
  922. return asSUCCESS;
  923. }
  924. // interface
  925. int asCModule::UnbindAllImportedFunctions()
  926. {
  927. asUINT c = GetImportedFunctionCount();
  928. for( asUINT n = 0; n < c; ++n )
  929. UnbindImportedFunction(n);
  930. return asSUCCESS;
  931. }
  932. // internal
  933. asCObjectType *asCModule::GetObjectType(const char *type, const asCString &ns)
  934. {
  935. size_t n;
  936. // TODO: optimize: Improve linear search
  937. for( n = 0; n < classTypes.GetLength(); n++ )
  938. if( classTypes[n]->name == type &&
  939. classTypes[n]->nameSpace == ns )
  940. return classTypes[n];
  941. for( n = 0; n < enumTypes.GetLength(); n++ )
  942. if( enumTypes[n]->name == type &&
  943. enumTypes[n]->nameSpace == ns )
  944. return enumTypes[n];
  945. for( n = 0; n < typeDefs.GetLength(); n++ )
  946. if( typeDefs[n]->name == type &&
  947. typeDefs[n]->nameSpace == ns )
  948. return typeDefs[n];
  949. return 0;
  950. }
  951. // internal
  952. asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *name, const asCDataType &dt, const asCString &ns)
  953. {
  954. asCGlobalProperty *prop = engine->AllocateGlobalProperty();
  955. prop->name = name;
  956. prop->nameSpace = ns;
  957. // Allocate the memory for this property based on its type
  958. prop->type = dt;
  959. prop->AllocateMemory();
  960. // Store the variable in the module scope (the reference count is already set to 1)
  961. scriptGlobals.PushLast(prop);
  962. return prop;
  963. }
  964. #ifdef AS_DEPRECATED
  965. // Deprecated since 2.23.0 - 2012-01-30
  966. // internal
  967. void asCModule::ResolveInterfaceIds(asCArray<void*> *substitutions)
  968. {
  969. // For each of the interfaces declared in the script find identical interface in the engine.
  970. // If an identical interface was found then substitute the current id for the identical interface's id,
  971. // then remove this interface declaration. If an interface was modified by the declaration, then
  972. // retry the detection of identical interface for it since it may now match another.
  973. // For an interface to be equal to another the name and methods must match. If the interface
  974. // references another interface, then that must be checked as well, which can lead to circular references.
  975. // Example:
  976. //
  977. // interface A { void f(B@); }
  978. // interface B { void f(A@); void f(C@); }
  979. // interface C { void f(A@); }
  980. //
  981. // A1 equals A2 if and only if B1 equals B2
  982. // B1 equals B2 if and only if A1 equals A2 and C1 equals C2
  983. // C1 equals C2 if and only if A1 equals A2
  984. unsigned int i;
  985. // The interface can only be equal to interfaces declared in other modules.
  986. // Interfaces registered by the application will conflict with this one if it has the same name.
  987. // This means that we only need to look for the interfaces in the engine->classTypes, but not in engine->objectTypes.
  988. asCArray<sObjectTypePair> equals;
  989. for( i = 0; i < classTypes.GetLength(); i++ )
  990. {
  991. asCObjectType *intf1 = classTypes[i];
  992. if( !intf1->IsInterface() )
  993. continue;
  994. // The interface may have been determined to be equal to another already
  995. bool found = false;
  996. for( unsigned int e = 0; e < equals.GetLength(); e++ )
  997. {
  998. if( equals[e].a == intf1 )
  999. {
  1000. found = true;
  1001. break;
  1002. }
  1003. }
  1004. if( found )
  1005. continue;
  1006. for( unsigned int n = 0; n < engine->classTypes.GetLength(); n++ )
  1007. {
  1008. // Don't compare against self
  1009. if( engine->classTypes[n] == intf1 )
  1010. continue;
  1011. asCObjectType *intf2 = engine->classTypes[n];
  1012. // Assume the interface are equal, then validate this
  1013. sObjectTypePair pair = {intf1,intf2};
  1014. equals.PushLast(pair);
  1015. if( AreInterfacesEqual(intf1, intf2, equals) )
  1016. break;
  1017. // Since they are not equal, remove them from the list again
  1018. equals.PopLast();
  1019. }
  1020. }
  1021. // For each of the interfaces that have been found to be equal we need to
  1022. // remove the new declaration and instead have the module use the existing one.
  1023. for( i = 0; i < equals.GetLength(); i++ )
  1024. {
  1025. // Substitute the old object type from the module's class types
  1026. unsigned int c;
  1027. for( c = 0; c < classTypes.GetLength(); c++ )
  1028. {
  1029. if( classTypes[c] == equals[i].a )
  1030. {
  1031. if( substitutions )
  1032. {
  1033. substitutions->PushLast(equals[i].a);
  1034. substitutions->PushLast(equals[i].b);
  1035. }
  1036. classTypes[c] = equals[i].b;
  1037. equals[i].b->AddRef();
  1038. break;
  1039. }
  1040. }
  1041. // Remove the old object type from the engine's class types
  1042. engine->classTypes.RemoveValue(equals[i].a);
  1043. // Only interfaces in the module are using the type so far
  1044. for( c = 0; c < classTypes.GetLength(); c++ )
  1045. {
  1046. if( classTypes[c]->IsInterface() )
  1047. {
  1048. asCObjectType *intf = classTypes[c];
  1049. for( asUINT m = 0; m < intf->GetMethodCount(); m++ )
  1050. {
  1051. asCScriptFunction *func = engine->GetScriptFunction(intf->methods[m]);
  1052. if( func )
  1053. {
  1054. // Check if it is the same type
  1055. if( func->returnType.GetObjectType() == equals[i].a )
  1056. func->returnType.SetObjectType(equals[i].b);
  1057. // Look for template instances that uses the interface as subtype
  1058. else if( func->returnType.IsTemplate() &&
  1059. func->returnType.GetSubType().GetObjectType() == equals[i].a )
  1060. {
  1061. // Find the originating template type
  1062. asCObjectType *templ = 0;
  1063. for( asUINT t = 0; t < engine->registeredObjTypes.GetLength(); t++ )
  1064. if( (engine->registeredObjTypes[t]->flags & asOBJ_TEMPLATE) &&
  1065. engine->registeredObjTypes[t]->name == func->returnType.GetObjectType()->name &&
  1066. !engine->templateInstanceTypes.Exists(engine->registeredObjTypes[t]) )
  1067. {
  1068. templ = engine->registeredObjTypes[t];
  1069. break;
  1070. }
  1071. asASSERT( templ );
  1072. asCDataType subType = func->returnType.GetSubType();
  1073. subType.SetObjectType(equals[i].b);
  1074. func->returnType.SetObjectType(engine->GetTemplateInstanceType(templ, subType));
  1075. }
  1076. for( asUINT p = 0; p < func->GetParamCount(); p++ )
  1077. {
  1078. // Check if it is the same type
  1079. if( func->parameterTypes[p].GetObjectType() == equals[i].a )
  1080. func->parameterTypes[p].SetObjectType(equals[i].b);
  1081. // Look for template instances that uses the interface as subtype
  1082. else if( func->parameterTypes[p].IsTemplate() &&
  1083. func->parameterTypes[p].GetSubType().GetObjectType() == equals[i].a )
  1084. {
  1085. // Find the originating template type
  1086. asCObjectType *templ = 0;
  1087. for( asUINT t = 0; t < engine->registeredObjTypes.GetLength(); t++ )
  1088. if( (engine->registeredObjTypes[t]->flags & asOBJ_TEMPLATE) &&
  1089. engine->registeredObjTypes[t]->name == func->parameterTypes[p].GetObjectType()->name &&
  1090. !engine->templateInstanceTypes.Exists(engine->registeredObjTypes[t]) )
  1091. {
  1092. templ = engine->registeredObjTypes[t];
  1093. break;
  1094. }
  1095. asASSERT( templ );
  1096. asCDataType subType = func->parameterTypes[p].GetSubType();
  1097. subType.SetObjectType(equals[i].b);
  1098. func->parameterTypes[p].SetObjectType(engine->GetTemplateInstanceType(templ, subType));
  1099. }
  1100. }
  1101. }
  1102. }
  1103. }
  1104. }
  1105. // Substitute all interface methods in the module. Delete all methods for the old interface
  1106. for( unsigned int m = 0; m < equals[i].a->methods.GetLength(); m++ )
  1107. {
  1108. for( c = 0; c < scriptFunctions.GetLength(); c++ )
  1109. {
  1110. if( scriptFunctions[c]->id == equals[i].a->methods[m] )
  1111. {
  1112. if( substitutions )
  1113. substitutions->PushLast(scriptFunctions[c]);
  1114. scriptFunctions[c]->Release();
  1115. scriptFunctions[c] = engine->GetScriptFunction(equals[i].b->methods[m]);
  1116. scriptFunctions[c]->AddRef();
  1117. if( substitutions )
  1118. substitutions->PushLast(scriptFunctions[c]);
  1119. }
  1120. }
  1121. }
  1122. // If there was a template instance, it needs to be removed first
  1123. for( asUINT n = 0; n < engine->templateTypes.GetLength(); n++ )
  1124. {
  1125. if( engine->templateTypes[n]->templateSubType.GetObjectType() == equals[i].a )
  1126. {
  1127. // The use of the template has already been exchanged above
  1128. engine->RemoveTemplateInstanceType(engine->templateTypes[n]);
  1129. n--;
  1130. }
  1131. }
  1132. // Deallocate the object type
  1133. asDELETE(equals[i].a, asCObjectType);
  1134. }
  1135. }
  1136. // internal
  1137. bool asCModule::AreInterfacesEqual(asCObjectType *a, asCObjectType *b, asCArray<sObjectTypePair> &equals)
  1138. {
  1139. // An interface is considered equal to another if the following criterias apply:
  1140. //
  1141. // - The interface names are equal
  1142. // - The number of methods is equal
  1143. // - All the methods are equal
  1144. // - The order of the methods is equal
  1145. // - If a method returns or takes an interface by handle or reference, both interfaces must be equal
  1146. // ------------
  1147. // TODO: Study the possiblity of allowing interfaces where methods are declared in different orders to
  1148. // be considered equal. The compiler and VM can handle this, but it complicates the comparison of interfaces
  1149. // where multiple methods take different interfaces as parameters (or return values). Example:
  1150. //
  1151. // interface A
  1152. // {
  1153. // void f(B, C);
  1154. // void f(B);
  1155. // void f(C);
  1156. // }
  1157. //
  1158. // If 'void f(B)' in module A is compared against 'void f(C)' in module B, then the code will assume
  1159. // interface B in module A equals interface C in module B. Thus 'void f(B, C)' in module A won't match
  1160. // 'void f(C, B)' in module B.
  1161. // ------------
  1162. // Are both interfaces?
  1163. if( !a->IsInterface() || !b->IsInterface() )
  1164. return false;
  1165. // Are the names equal?
  1166. if( a->name != b->name )
  1167. return false;
  1168. // Are the namespaces equal?
  1169. if( a->nameSpace != b->nameSpace )
  1170. return false;
  1171. // Are the number of methods equal?
  1172. if( a->methods.GetLength() != b->methods.GetLength() )
  1173. return false;
  1174. // Keep the number of equals in the list so we can restore it later if necessary
  1175. int prevEquals = (int)equals.GetLength();
  1176. // Are the methods equal to each other?
  1177. bool match = true;
  1178. for( unsigned int n = 0; n < a->methods.GetLength(); n++ )
  1179. {
  1180. match = false;
  1181. asCScriptFunction *funcA = (asCScriptFunction*)engine->GetFunctionById(a->methods[n]);
  1182. asCScriptFunction *funcB = (asCScriptFunction*)engine->GetFunctionById(b->methods[n]);
  1183. // funcB can be null if the module that created the interface has been
  1184. // discarded but the type has not yet been released by the engine.
  1185. if( funcB == 0 )
  1186. break;
  1187. // The methods must have the same name and the same number of parameters
  1188. if( funcA->name != funcB->name ||
  1189. funcA->parameterTypes.GetLength() != funcB->parameterTypes.GetLength() )
  1190. break;
  1191. // The return types must be equal. If the return type is an interface the interfaces must match.
  1192. if( !AreTypesEqual(funcA->returnType, funcB->returnType, equals) )
  1193. break;
  1194. match = true;
  1195. for( unsigned int p = 0; p < funcA->parameterTypes.GetLength(); p++ )
  1196. {
  1197. if( !AreTypesEqual(funcA->parameterTypes[p], funcB->parameterTypes[p], equals) ||
  1198. funcA->inOutFlags[p] != funcB->inOutFlags[p] )
  1199. {
  1200. match = false;
  1201. break;
  1202. }
  1203. }
  1204. if( !match )
  1205. break;
  1206. }
  1207. // For each of the new interfaces that we're assuming to be equal, we need to validate this
  1208. if( match )
  1209. {
  1210. for( unsigned int n = prevEquals; n < equals.GetLength(); n++ )
  1211. {
  1212. if( !AreInterfacesEqual(equals[n].a, equals[n].b, equals) )
  1213. {
  1214. match = false;
  1215. break;
  1216. }
  1217. }
  1218. }
  1219. if( !match )
  1220. {
  1221. // The interfaces doesn't match.
  1222. // Restore the list of previous equals before we go on, so
  1223. // the caller can continue comparing with another interface
  1224. equals.SetLength(prevEquals);
  1225. }
  1226. return match;
  1227. }
  1228. // internal
  1229. bool asCModule::AreTypesEqual(const asCDataType &a, const asCDataType &b, asCArray<sObjectTypePair> &equals)
  1230. {
  1231. if( !a.IsEqualExceptInterfaceType(b) )
  1232. return false;
  1233. asCObjectType *ai = a.GetObjectType();
  1234. asCObjectType *bi = b.GetObjectType();
  1235. if( ai && (ai->flags & asOBJ_TEMPLATE) )
  1236. {
  1237. ai = ai->templateSubType.GetObjectType();
  1238. bi = bi->templateSubType.GetObjectType();
  1239. }
  1240. if( ai && ai->IsInterface() )
  1241. {
  1242. // If the interface is in the equals list, then the pair must match the pair in the list
  1243. bool found = false;
  1244. unsigned int e;
  1245. for( e = 0; e < equals.GetLength(); e++ )
  1246. {
  1247. if( equals[e].a == ai )
  1248. {
  1249. found = true;
  1250. break;
  1251. }
  1252. }
  1253. if( found )
  1254. {
  1255. // Do the pairs match?
  1256. if( equals[e].b != bi )
  1257. return false;
  1258. }
  1259. else
  1260. {
  1261. // Assume they are equal from now on
  1262. sObjectTypePair pair = {ai, bi};
  1263. equals.PushLast(pair);
  1264. }
  1265. }
  1266. return true;
  1267. }
  1268. #endif // AS_DEPRECATED
  1269. // interface
  1270. int asCModule::SaveByteCode(asIBinaryStream *out) const
  1271. {
  1272. #ifdef AS_NO_COMPILER
  1273. UNUSED_VAR(out);
  1274. return asNOT_SUPPORTED;
  1275. #else
  1276. if( out == 0 ) return asINVALID_ARG;
  1277. asCWriter write(const_cast<asCModule*>(this), out, engine);
  1278. return write.Write();
  1279. #endif
  1280. }
  1281. // interface
  1282. int asCModule::LoadByteCode(asIBinaryStream *in)
  1283. {
  1284. if( in == 0 ) return asINVALID_ARG;
  1285. // Only permit loading bytecode if no other thread is currently compiling
  1286. // TODO: It should be possible to have multiple threads perform compilations
  1287. int r = engine->RequestBuild();
  1288. if( r < 0 )
  1289. return r;
  1290. asCReader read(this, in, engine);
  1291. r = read.Read();
  1292. JITCompile();
  1293. engine->BuildCompleted();
  1294. return r;
  1295. }
  1296. // interface
  1297. int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  1298. {
  1299. #ifdef AS_NO_COMPILER
  1300. UNUSED_VAR(sectionName);
  1301. UNUSED_VAR(code);
  1302. UNUSED_VAR(lineOffset);
  1303. return asNOT_SUPPORTED;
  1304. #else
  1305. // Validate arguments
  1306. if( code == 0 )
  1307. return asINVALID_ARG;
  1308. // Only one thread may build at one time
  1309. // TODO: It should be possible to have multiple threads perform compilations
  1310. int r = engine->RequestBuild();
  1311. if( r < 0 )
  1312. return r;
  1313. // Prepare the engine
  1314. engine->PrepareEngine();
  1315. if( engine->configFailed )
  1316. {
  1317. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1318. engine->BuildCompleted();
  1319. return asINVALID_CONFIGURATION;
  1320. }
  1321. // Compile the global variable and add it to the module scope
  1322. asCBuilder builder(engine, this);
  1323. asCString str = code;
  1324. // TODO: namespace: Add the global var to the default namespace
  1325. r = builder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset);
  1326. engine->BuildCompleted();
  1327. // Initialize the variable
  1328. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  1329. {
  1330. // Clear the memory
  1331. asCGlobalProperty *prop = scriptGlobals[scriptGlobals.GetLength()-1];
  1332. memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords());
  1333. if( prop->GetInitFunc() )
  1334. {
  1335. // Call the init function for the global variable
  1336. asIScriptContext *ctx = 0;
  1337. int r = engine->CreateContext(&ctx, true);
  1338. if( r < 0 )
  1339. return r;
  1340. r = ctx->Prepare(prop->GetInitFunc());
  1341. if( r >= 0 )
  1342. r = ctx->Execute();
  1343. ctx->Release();
  1344. }
  1345. }
  1346. return r;
  1347. #endif
  1348. }
  1349. // interface
  1350. int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc)
  1351. {
  1352. #ifdef AS_NO_COMPILER
  1353. UNUSED_VAR(sectionName);
  1354. UNUSED_VAR(code);
  1355. UNUSED_VAR(lineOffset);
  1356. UNUSED_VAR(compileFlags);
  1357. UNUSED_VAR(outFunc);
  1358. return asNOT_SUPPORTED;
  1359. #else
  1360. asASSERT(outFunc == 0 || *outFunc == 0);
  1361. // Validate arguments
  1362. if( code == 0 ||
  1363. (compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) )
  1364. return asINVALID_ARG;
  1365. // Only one thread may build at one time
  1366. // TODO: It should be possible to have multiple threads perform compilations
  1367. int r = engine->RequestBuild();
  1368. if( r < 0 )
  1369. return r;
  1370. // Prepare the engine
  1371. engine->PrepareEngine();
  1372. if( engine->configFailed )
  1373. {
  1374. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1375. engine->BuildCompleted();
  1376. return asINVALID_CONFIGURATION;
  1377. }
  1378. // Compile the single function
  1379. asCBuilder builder(engine, this);
  1380. asCString str = code;
  1381. asCScriptFunction *func = 0;
  1382. // TODO: namespace: Add the function to the default namespace
  1383. r = builder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
  1384. engine->BuildCompleted();
  1385. if( r >= 0 && outFunc )
  1386. {
  1387. // Return the function to the caller
  1388. *outFunc = func;
  1389. func->AddRef();
  1390. }
  1391. // Release our reference to the function
  1392. if( func )
  1393. func->Release();
  1394. return r;
  1395. #endif
  1396. }
  1397. #ifdef AS_DEPRECATED
  1398. // Deprecated since 2.24.0 - 2012-05-20
  1399. // interface
  1400. int asCModule::RemoveFunction(int funcId)
  1401. {
  1402. if( funcId >= 0 && funcId < (int)engine->scriptFunctions.GetLength() )
  1403. return RemoveFunction(engine->scriptFunctions[funcId]);
  1404. return asNO_FUNCTION;
  1405. }
  1406. #endif
  1407. // interface
  1408. int asCModule::RemoveFunction(asIScriptFunction *func)
  1409. {
  1410. // Find the global function
  1411. asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
  1412. int idx = globalFunctions.IndexOf(f);
  1413. if( idx >= 0 )
  1414. {
  1415. globalFunctions.RemoveIndex(idx);
  1416. f->Release();
  1417. scriptFunctions.RemoveValue(f);
  1418. f->Release();
  1419. return 0;
  1420. }
  1421. return asNO_FUNCTION;
  1422. }
  1423. // internal
  1424. int asCModule::AddFuncDef(const char *name, const asCString &ns)
  1425. {
  1426. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF);
  1427. if( func == 0 )
  1428. return asOUT_OF_MEMORY;
  1429. func->name = name;
  1430. func->nameSpace = ns;
  1431. funcDefs.PushLast(func);
  1432. engine->funcDefs.PushLast(func);
  1433. func->id = engine->GetNextScriptFunctionId();
  1434. engine->SetScriptFunction(func);
  1435. return (int)funcDefs.GetLength()-1;
  1436. }
  1437. // interface
  1438. asDWORD asCModule::SetAccessMask(asDWORD mask)
  1439. {
  1440. asDWORD old = accessMask;
  1441. accessMask = mask;
  1442. return old;
  1443. }
  1444. END_AS_NAMESPACE