as_module.cpp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2013 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. BEGIN_AS_NAMESPACE
  35. // internal
  36. asCModule::asCModule(const char *name, asCScriptEngine *engine)
  37. {
  38. this->name = name;
  39. this->engine = engine;
  40. userData = 0;
  41. builder = 0;
  42. isGlobalVarInitialized = false;
  43. accessMask = 1;
  44. defaultNamespace = engine->nameSpaces[0];
  45. }
  46. // internal
  47. asCModule::~asCModule()
  48. {
  49. InternalReset();
  50. if( builder )
  51. {
  52. asDELETE(builder,asCBuilder);
  53. builder = 0;
  54. }
  55. if( engine )
  56. {
  57. // Clean the user data
  58. if( userData && engine->cleanModuleFunc )
  59. engine->cleanModuleFunc(this);
  60. // Remove the module from the engine
  61. if( engine->lastModule == this )
  62. engine->lastModule = 0;
  63. engine->scriptModules.RemoveValue(this);
  64. // Allow the engine to clean up what is not used
  65. engine->CleanupAfterDiscardModule();
  66. }
  67. }
  68. // interface
  69. void asCModule::Discard()
  70. {
  71. asDELETE(this,asCModule);
  72. }
  73. // interface
  74. void *asCModule::SetUserData(void *data)
  75. {
  76. void *oldData = userData;
  77. userData = data;
  78. return oldData;
  79. }
  80. // interface
  81. void *asCModule::GetUserData() const
  82. {
  83. return userData;
  84. }
  85. // interface
  86. asIScriptEngine *asCModule::GetEngine() const
  87. {
  88. return engine;
  89. }
  90. // interface
  91. void asCModule::SetName(const char *name)
  92. {
  93. this->name = name;
  94. }
  95. // interface
  96. const char *asCModule::GetName() const
  97. {
  98. return name.AddressOf();
  99. }
  100. // interface
  101. const char *asCModule::GetDefaultNamespace() const
  102. {
  103. return defaultNamespace->name.AddressOf();
  104. }
  105. // interface
  106. int asCModule::SetDefaultNamespace(const char *nameSpace)
  107. {
  108. // TODO: cleanup: This function is similar to asCScriptEngine::SetDefaultNamespace. Can we reuse the code?
  109. if( nameSpace == 0 )
  110. return asINVALID_ARG;
  111. asCString ns = nameSpace;
  112. if( ns != "" )
  113. {
  114. // Make sure the namespace is composed of alternating identifier and ::
  115. size_t pos = 0;
  116. bool expectIdentifier = true;
  117. size_t len;
  118. eTokenType t = ttIdentifier;
  119. for( ; pos < ns.GetLength(); pos += len )
  120. {
  121. t = engine->tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len);
  122. if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) )
  123. return asINVALID_DECLARATION;
  124. expectIdentifier = !expectIdentifier;
  125. }
  126. // If the namespace ends with :: then strip it off
  127. if( t == ttScope )
  128. ns.SetLength(ns.GetLength()-2);
  129. }
  130. defaultNamespace = engine->AddNameSpace(ns.AddressOf());
  131. return 0;
  132. }
  133. // interface
  134. int asCModule::AddScriptSection(const char *name, const char *code, size_t codeLength, int lineOffset)
  135. {
  136. #ifdef AS_NO_COMPILER
  137. UNUSED_VAR(name);
  138. UNUSED_VAR(code);
  139. UNUSED_VAR(codeLength);
  140. UNUSED_VAR(lineOffset);
  141. return asNOT_SUPPORTED;
  142. #else
  143. if( !builder )
  144. {
  145. builder = asNEW(asCBuilder)(engine, this);
  146. if( builder == 0 )
  147. return asOUT_OF_MEMORY;
  148. }
  149. return builder->AddCode(name, code, (int)codeLength, lineOffset, (int)engine->GetScriptSectionNameIndex(name ? name : ""), engine->ep.copyScriptSections);
  150. #endif
  151. }
  152. // internal
  153. void asCModule::JITCompile()
  154. {
  155. for (unsigned int i = 0; i < scriptFunctions.GetLength(); i++)
  156. {
  157. scriptFunctions[i]->JITCompile();
  158. }
  159. }
  160. // interface
  161. int asCModule::Build()
  162. {
  163. #ifdef AS_NO_COMPILER
  164. return asNOT_SUPPORTED;
  165. #else
  166. TimeIt("asCModule::Build");
  167. // Only one thread may build at one time
  168. // TODO: It should be possible to have multiple threads perform compilations
  169. int r = engine->RequestBuild();
  170. if( r < 0 )
  171. return r;
  172. engine->PrepareEngine();
  173. if( engine->configFailed )
  174. {
  175. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  176. engine->BuildCompleted();
  177. return asINVALID_CONFIGURATION;
  178. }
  179. InternalReset();
  180. if( !builder )
  181. {
  182. engine->BuildCompleted();
  183. return asSUCCESS;
  184. }
  185. // Compile the script
  186. r = builder->Build();
  187. asDELETE(builder,asCBuilder);
  188. builder = 0;
  189. if( r < 0 )
  190. {
  191. // Reset module again
  192. InternalReset();
  193. engine->BuildCompleted();
  194. return r;
  195. }
  196. JITCompile();
  197. engine->PrepareEngine();
  198. #ifdef AS_DEBUG
  199. // Verify that there are no unwanted gaps in the scriptFunctions array.
  200. for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ )
  201. {
  202. int id = n;
  203. if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) )
  204. asASSERT( false );
  205. }
  206. #endif
  207. engine->BuildCompleted();
  208. // Initialize global variables
  209. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  210. r = ResetGlobalVars(0);
  211. return r;
  212. #endif
  213. }
  214. // interface
  215. int asCModule::ResetGlobalVars(asIScriptContext *ctx)
  216. {
  217. if( isGlobalVarInitialized )
  218. CallExit();
  219. return CallInit(ctx);
  220. }
  221. // interface
  222. asIScriptFunction *asCModule::GetFunctionByIndex(asUINT index) const
  223. {
  224. return const_cast<asCScriptFunction*>(globalFunctions.Get(index));
  225. }
  226. // internal
  227. int asCModule::CallInit(asIScriptContext *myCtx)
  228. {
  229. if( isGlobalVarInitialized )
  230. return asERROR;
  231. // Each global variable needs to be cleared individually
  232. asCSymbolTableIterator<asCGlobalProperty> it = scriptGlobals.List();
  233. while( it )
  234. {
  235. asCGlobalProperty *desc = *it;
  236. memset(desc->GetAddressOfValue(), 0, sizeof(asDWORD)*desc->type.GetSizeOnStackDWords());
  237. it++;
  238. }
  239. // Call the init function for each of the global variables
  240. asIScriptContext *ctx = myCtx;
  241. int r = asEXECUTION_FINISHED;
  242. it = scriptGlobals.List();
  243. while( it && r == asEXECUTION_FINISHED )
  244. {
  245. asCGlobalProperty *desc = *it;
  246. it++;
  247. if( desc->GetInitFunc() )
  248. {
  249. if( ctx == 0 )
  250. {
  251. r = engine->CreateContext(&ctx, true);
  252. if( r < 0 )
  253. break;
  254. }
  255. r = ctx->Prepare(desc->GetInitFunc());
  256. if( r >= 0 )
  257. {
  258. r = ctx->Execute();
  259. if( r != asEXECUTION_FINISHED )
  260. {
  261. asCString msg;
  262. msg.Format(TXT_FAILED_TO_INITIALIZE_s, desc->name.AddressOf());
  263. asCScriptFunction *func = desc->GetInitFunc();
  264. engine->WriteMessage(func->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptSectionIdx]->AddressOf() : "",
  265. func->GetLineNumber(0, 0) & 0xFFFFF,
  266. func->GetLineNumber(0, 0) >> 20,
  267. asMSGTYPE_ERROR,
  268. msg.AddressOf());
  269. if( r == asEXECUTION_EXCEPTION )
  270. {
  271. const asIScriptFunction *function = ctx->GetExceptionFunction();
  272. msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration());
  273. engine->WriteMessage(function->GetScriptSectionName(),
  274. ctx->GetExceptionLineNumber(),
  275. 0,
  276. asMSGTYPE_INFORMATION,
  277. msg.AddressOf());
  278. }
  279. }
  280. }
  281. }
  282. }
  283. if( ctx && !myCtx )
  284. {
  285. ctx->Release();
  286. ctx = 0;
  287. }
  288. // Even if the initialization failed we need to set the
  289. // flag that the variables have been initialized, otherwise
  290. // the module won't free those variables that really were
  291. // initialized.
  292. isGlobalVarInitialized = true;
  293. if( r != asEXECUTION_FINISHED )
  294. return asINIT_GLOBAL_VARS_FAILED;
  295. return asSUCCESS;
  296. }
  297. // internal
  298. void asCModule::CallExit()
  299. {
  300. if( !isGlobalVarInitialized ) return;
  301. asCSymbolTableIterator<asCGlobalProperty> it = scriptGlobals.List();
  302. while( it )
  303. {
  304. if( (*it)->type.IsObject() )
  305. {
  306. void **obj = (void**)(*it)->GetAddressOfValue();
  307. if( *obj )
  308. {
  309. asCObjectType *ot = (*it)->type.GetObjectType();
  310. if( ot->flags & asOBJ_REF )
  311. {
  312. asASSERT( (ot->flags & asOBJ_NOCOUNT) || ot->beh.release );
  313. if( ot->beh.release )
  314. engine->CallObjectMethod(*obj, ot->beh.release);
  315. }
  316. else
  317. {
  318. if( ot->beh.destruct )
  319. engine->CallObjectMethod(*obj, ot->beh.destruct);
  320. engine->CallFree(*obj);
  321. }
  322. // Set the address to 0 as someone might try to access the variable afterwards
  323. *obj = 0;
  324. }
  325. }
  326. it++;
  327. }
  328. isGlobalVarInitialized = false;
  329. }
  330. // internal
  331. void asCModule::InternalReset()
  332. {
  333. CallExit();
  334. size_t n;
  335. // Release all global functions
  336. asCSymbolTable<asCScriptFunction>::iterator funcIt = globalFunctions.List();
  337. for( ; funcIt; funcIt++ )
  338. (*funcIt)->Release();
  339. globalFunctions.Clear();
  340. // First release all compiled functions
  341. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  342. if( scriptFunctions[n] )
  343. scriptFunctions[n]->Orphan(this);
  344. scriptFunctions.SetLength(0);
  345. // Release the global properties declared in the module
  346. asCSymbolTableIterator<asCGlobalProperty> globIt = scriptGlobals.List();
  347. while( globIt )
  348. {
  349. (*globIt)->Orphan(this);
  350. globIt++;
  351. }
  352. scriptGlobals.Clear();
  353. UnbindAllImportedFunctions();
  354. // Free bind information
  355. for( n = 0; n < bindInformations.GetLength(); n++ )
  356. {
  357. if( bindInformations[n] )
  358. {
  359. asUINT id = bindInformations[n]->importedFunctionSignature->id & ~FUNC_IMPORTED;
  360. engine->importedFunctions[id] = 0;
  361. engine->freeImportedFunctionIdxs.PushLast(id);
  362. asDELETE(bindInformations[n]->importedFunctionSignature, asCScriptFunction);
  363. asDELETE(bindInformations[n], sBindInfo);
  364. }
  365. }
  366. bindInformations.SetLength(0);
  367. // Free declared types, including classes, typedefs, and enums
  368. // TODO: optimize: Check if it is possible to destroy the object directly without notifying the GC
  369. for( n = 0; n < classTypes.GetLength(); n++ )
  370. classTypes[n]->Orphan(this);
  371. classTypes.SetLength(0);
  372. for( n = 0; n < enumTypes.GetLength(); n++ )
  373. enumTypes[n]->Release();
  374. enumTypes.SetLength(0);
  375. for( n = 0; n < typeDefs.GetLength(); n++ )
  376. typeDefs[n]->Release();
  377. typeDefs.SetLength(0);
  378. // Free funcdefs
  379. for( n = 0; n < funcDefs.GetLength(); n++ )
  380. {
  381. // The funcdefs are not removed from the engine at this moment as they may still be referred
  382. // to by other types. The engine's ClearUnusedTypes will take care of the clean up.
  383. funcDefs[n]->Release();
  384. }
  385. funcDefs.SetLength(0);
  386. }
  387. // interface
  388. asIScriptFunction *asCModule::GetFunctionByName(const char *name) const
  389. {
  390. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(defaultNamespace, name);
  391. if( idxs.GetLength() != 1 )
  392. return 0;
  393. const asIScriptFunction *func = globalFunctions.Get(idxs[0]);
  394. return const_cast<asIScriptFunction*>(func);
  395. }
  396. // interface
  397. asUINT asCModule::GetImportedFunctionCount() const
  398. {
  399. return (asUINT)bindInformations.GetLength();
  400. }
  401. // interface
  402. int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
  403. {
  404. asCBuilder bld(engine, const_cast<asCModule*>(this));
  405. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  406. bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  407. // TODO: optimize: Improve linear search
  408. // Search script functions for matching interface
  409. int id = -1;
  410. for( asUINT n = 0; n < bindInformations.GetLength(); ++n )
  411. {
  412. if( func.name == bindInformations[n]->importedFunctionSignature->name &&
  413. func.returnType == bindInformations[n]->importedFunctionSignature->returnType &&
  414. func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() )
  415. {
  416. bool match = true;
  417. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  418. {
  419. if( func.parameterTypes[p] != bindInformations[n]->importedFunctionSignature->parameterTypes[p] )
  420. {
  421. match = false;
  422. break;
  423. }
  424. }
  425. if( match )
  426. {
  427. if( id == -1 )
  428. id = n;
  429. else
  430. return asMULTIPLE_FUNCTIONS;
  431. }
  432. }
  433. }
  434. if( id == -1 ) return asNO_FUNCTION;
  435. return id;
  436. }
  437. // interface
  438. asUINT asCModule::GetFunctionCount() const
  439. {
  440. return (asUINT)globalFunctions.GetSize();
  441. }
  442. // interface
  443. asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const
  444. {
  445. asCBuilder bld(engine, const_cast<asCModule*>(this));
  446. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  447. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  448. if( r < 0 )
  449. {
  450. // Invalid declaration
  451. // TODO: Write error to message stream
  452. return 0;
  453. }
  454. // Use the defaultNamespace implicitly unless an explicit namespace has been provided
  455. asSNameSpace *ns = func.nameSpace == engine->nameSpaces[0] ? defaultNamespace : func.nameSpace;
  456. // Search script functions for matching interface
  457. asIScriptFunction *f = 0;
  458. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, func.name);
  459. for( unsigned int n = 0; n < idxs.GetLength(); n++ )
  460. {
  461. const asCScriptFunction *funcPtr = globalFunctions.Get(idxs[n]);
  462. if( funcPtr->objectType == 0 &&
  463. func.returnType == funcPtr->returnType &&
  464. func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
  465. )
  466. {
  467. bool match = true;
  468. for( size_t p = 0; p < func.parameterTypes.GetLength(); ++p )
  469. {
  470. if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
  471. {
  472. match = false;
  473. break;
  474. }
  475. }
  476. if( match )
  477. {
  478. if( f == 0 )
  479. f = const_cast<asCScriptFunction*>(funcPtr);
  480. else
  481. // Multiple functions
  482. return 0;
  483. }
  484. }
  485. }
  486. return f;
  487. }
  488. // interface
  489. asUINT asCModule::GetGlobalVarCount() const
  490. {
  491. return (asUINT)scriptGlobals.GetSize();
  492. }
  493. // interface
  494. int asCModule::GetGlobalVarIndexByName(const char *name) const
  495. {
  496. // Find the global var id
  497. int id = scriptGlobals.GetFirstIndex(defaultNamespace, name);
  498. if( id == -1 ) return asNO_GLOBAL_VAR;
  499. return id;
  500. }
  501. // interface
  502. int asCModule::RemoveGlobalVar(asUINT index)
  503. {
  504. asCGlobalProperty *prop = scriptGlobals.Get(index);
  505. if( !prop )
  506. return asINVALID_ARG;
  507. prop->Orphan(this);
  508. scriptGlobals.Erase(index);
  509. return 0;
  510. }
  511. // interface
  512. int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
  513. {
  514. asCBuilder bld(engine, const_cast<asCModule*>(this));
  515. asCString name;
  516. asSNameSpace *nameSpace;
  517. asCDataType dt;
  518. int r = bld.ParseVariableDeclaration(decl, defaultNamespace, name, nameSpace, dt);
  519. if( r < 0 )
  520. return r;
  521. // Search global variables for a match
  522. int id = scriptGlobals.GetFirstIndex(nameSpace, name, asCCompGlobPropType(dt));
  523. if( id != -1 )
  524. return id;
  525. return asNO_GLOBAL_VAR;
  526. }
  527. // interface
  528. void *asCModule::GetAddressOfGlobalVar(asUINT index)
  529. {
  530. asCGlobalProperty *prop = scriptGlobals.Get(index);
  531. if( !prop )
  532. return 0;
  533. // For object variables it's necessary to dereference the pointer to get the address of the value
  534. if( prop->type.IsObject() &&
  535. !prop->type.IsObjectHandle() )
  536. return *(void**)(prop->GetAddressOfValue());
  537. return (void*)(prop->GetAddressOfValue());
  538. }
  539. // interface
  540. const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespace) const
  541. {
  542. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  543. if (!prop) return 0;
  544. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  545. *tempString = prop->type.Format();
  546. *tempString += " ";
  547. if( includeNamespace )
  548. *tempString += prop->nameSpace->name + "::";
  549. *tempString += prop->name;
  550. return tempString->AddressOf();
  551. }
  552. // interface
  553. int asCModule::GetGlobalVar(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst) const
  554. {
  555. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  556. if (!prop) return 0;
  557. if( name )
  558. *name = prop->name.AddressOf();
  559. if( nameSpace )
  560. *nameSpace = prop->nameSpace->name.AddressOf();
  561. if( typeId )
  562. *typeId = engine->GetTypeIdFromDataType(prop->type);
  563. if( isConst )
  564. *isConst = prop->type.IsReadOnly();
  565. return asSUCCESS;
  566. }
  567. // interface
  568. asUINT asCModule::GetObjectTypeCount() const
  569. {
  570. return (asUINT)classTypes.GetLength();
  571. }
  572. // interface
  573. asIObjectType *asCModule::GetObjectTypeByIndex(asUINT index) const
  574. {
  575. if( index >= classTypes.GetLength() )
  576. return 0;
  577. return classTypes[index];
  578. }
  579. // interface
  580. asIObjectType *asCModule::GetObjectTypeByName(const char *name) const
  581. {
  582. for( asUINT n = 0; n < classTypes.GetLength(); n++ )
  583. {
  584. if( classTypes[n] &&
  585. classTypes[n]->name == name &&
  586. classTypes[n]->nameSpace == defaultNamespace )
  587. return classTypes[n];
  588. }
  589. return 0;
  590. }
  591. // interface
  592. int asCModule::GetTypeIdByDecl(const char *decl) const
  593. {
  594. asCDataType dt;
  595. asCBuilder bld(engine, const_cast<asCModule*>(this));
  596. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  597. if( r < 0 )
  598. return asINVALID_TYPE;
  599. return engine->GetTypeIdFromDataType(dt);
  600. }
  601. // interface
  602. asUINT asCModule::GetEnumCount() const
  603. {
  604. return (asUINT)enumTypes.GetLength();
  605. }
  606. // interface
  607. const char *asCModule::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace) const
  608. {
  609. if( index >= enumTypes.GetLength() )
  610. return 0;
  611. if( enumTypeId )
  612. *enumTypeId = engine->GetTypeIdFromDataType(asCDataType::CreateObject(enumTypes[index], false));
  613. if( nameSpace )
  614. *nameSpace = enumTypes[index]->nameSpace->name.AddressOf();
  615. return enumTypes[index]->name.AddressOf();
  616. }
  617. // interface
  618. int asCModule::GetEnumValueCount(int enumTypeId) const
  619. {
  620. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  621. asCObjectType *t = dt.GetObjectType();
  622. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  623. return asINVALID_TYPE;
  624. return (int)t->enumValues.GetLength();
  625. }
  626. // interface
  627. const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
  628. {
  629. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  630. asCObjectType *t = dt.GetObjectType();
  631. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  632. return 0;
  633. if( index >= t->enumValues.GetLength() )
  634. return 0;
  635. if( outValue )
  636. *outValue = t->enumValues[index]->value;
  637. return t->enumValues[index]->name.AddressOf();
  638. }
  639. // interface
  640. asUINT asCModule::GetTypedefCount() const
  641. {
  642. return (asUINT)typeDefs.GetLength();
  643. }
  644. // interface
  645. const char *asCModule::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace) const
  646. {
  647. if( index >= typeDefs.GetLength() )
  648. return 0;
  649. if( typeId )
  650. *typeId = engine->GetTypeIdFromDataType(typeDefs[index]->templateSubTypes[0]);
  651. if( nameSpace )
  652. *nameSpace = typeDefs[index]->nameSpace->name.AddressOf();
  653. return typeDefs[index]->name.AddressOf();
  654. }
  655. // internal
  656. int asCModule::GetNextImportedFunctionId()
  657. {
  658. // TODO: multithread: This will break if one thread if freeing a module, while another is being compiled
  659. if( engine->freeImportedFunctionIdxs.GetLength() )
  660. return FUNC_IMPORTED | (asUINT)engine->freeImportedFunctionIdxs[engine->freeImportedFunctionIdxs.GetLength()-1];
  661. return FUNC_IMPORTED | (asUINT)engine->importedFunctions.GetLength();
  662. }
  663. #ifndef AS_NO_COMPILER
  664. // internal
  665. int asCModule::AddScriptFunction(int sectionIdx, int id, const asCString &name, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isFinal, bool isOverride, bool isShared, asSNameSpace *ns)
  666. {
  667. asASSERT(id >= 0);
  668. // Store the function information
  669. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT);
  670. if( func == 0 )
  671. return asOUT_OF_MEMORY;
  672. if( ns == 0 )
  673. ns = engine->nameSpaces[0];
  674. // All methods of shared objects are also shared
  675. if( objType && objType->IsShared() )
  676. isShared = true;
  677. func->name = name;
  678. func->nameSpace = ns;
  679. func->id = id;
  680. func->returnType = returnType;
  681. func->scriptSectionIdx = sectionIdx;
  682. func->parameterTypes = params;
  683. func->inOutFlags = inOutFlags;
  684. func->defaultArgs = defaultArgs;
  685. func->objectType = objType;
  686. func->isReadOnly = isConstMethod;
  687. func->isPrivate = isPrivate;
  688. func->isFinal = isFinal;
  689. func->isOverride = isOverride;
  690. func->isShared = isShared;
  691. asASSERT( params.GetLength() == inOutFlags.GetLength() && params.GetLength() == defaultArgs.GetLength() );
  692. // Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
  693. asASSERT( !(!objType && isFinal) );
  694. asASSERT( !(!objType && isOverride) );
  695. // The script function's refCount was initialized to 1
  696. scriptFunctions.PushLast(func);
  697. engine->SetScriptFunction(func);
  698. // Compute the signature id
  699. if( objType )
  700. func->ComputeSignatureId();
  701. // Add reference
  702. if( isGlobalFunction )
  703. {
  704. globalFunctions.Put(func);
  705. func->AddRef();
  706. }
  707. return 0;
  708. }
  709. // internal
  710. int asCModule::AddScriptFunction(asCScriptFunction *func)
  711. {
  712. scriptFunctions.PushLast(func);
  713. func->AddRef();
  714. engine->SetScriptFunction(func);
  715. return 0;
  716. }
  717. // internal
  718. 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)
  719. {
  720. asASSERT(id >= 0);
  721. // Store the function information
  722. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED);
  723. if( func == 0 )
  724. return asOUT_OF_MEMORY;
  725. func->name = name;
  726. func->id = id;
  727. func->returnType = returnType;
  728. func->nameSpace = ns;
  729. func->parameterTypes = params;
  730. func->inOutFlags = inOutFlags;
  731. func->defaultArgs = defaultArgs;
  732. func->objectType = 0;
  733. sBindInfo *info = asNEW(sBindInfo);
  734. if( info == 0 )
  735. return asOUT_OF_MEMORY;
  736. info->importedFunctionSignature = func;
  737. info->boundFunctionId = -1;
  738. info->importFromModule = moduleName;
  739. bindInformations.PushLast(info);
  740. // Add the info to the array in the engine
  741. if( engine->freeImportedFunctionIdxs.GetLength() )
  742. engine->importedFunctions[engine->freeImportedFunctionIdxs.PopLast()] = info;
  743. else
  744. engine->importedFunctions.PushLast(info);
  745. return 0;
  746. }
  747. #endif
  748. // internal
  749. asCScriptFunction *asCModule::GetImportedFunction(int index) const
  750. {
  751. return bindInformations[index]->importedFunctionSignature;
  752. }
  753. // interface
  754. int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
  755. {
  756. // First unbind the old function
  757. int r = UnbindImportedFunction(index);
  758. if( r < 0 ) return r;
  759. // Must verify that the interfaces are equal
  760. asCScriptFunction *dst = GetImportedFunction(index);
  761. if( dst == 0 ) return asNO_FUNCTION;
  762. if( func == 0 )
  763. return asINVALID_ARG;
  764. asCScriptFunction *src = engine->GetScriptFunction(func->GetId());
  765. if( src == 0 )
  766. return asNO_FUNCTION;
  767. // Verify return type
  768. if( dst->returnType != src->returnType )
  769. return asINVALID_INTERFACE;
  770. if( dst->parameterTypes.GetLength() != src->parameterTypes.GetLength() )
  771. return asINVALID_INTERFACE;
  772. for( size_t n = 0; n < dst->parameterTypes.GetLength(); ++n )
  773. {
  774. if( dst->parameterTypes[n] != src->parameterTypes[n] )
  775. return asINVALID_INTERFACE;
  776. }
  777. bindInformations[index]->boundFunctionId = src->GetId();
  778. src->AddRef();
  779. return asSUCCESS;
  780. }
  781. // interface
  782. int asCModule::UnbindImportedFunction(asUINT index)
  783. {
  784. if( index >= bindInformations.GetLength() )
  785. return asINVALID_ARG;
  786. // Remove reference to old module
  787. if( bindInformations[index] )
  788. {
  789. int oldFuncID = bindInformations[index]->boundFunctionId;
  790. if( oldFuncID != -1 )
  791. {
  792. bindInformations[index]->boundFunctionId = -1;
  793. engine->scriptFunctions[oldFuncID]->Release();
  794. }
  795. }
  796. return asSUCCESS;
  797. }
  798. // interface
  799. const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
  800. {
  801. asCScriptFunction *func = GetImportedFunction(index);
  802. if( func == 0 ) return 0;
  803. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  804. *tempString = func->GetDeclarationStr();
  805. return tempString->AddressOf();
  806. }
  807. // interface
  808. const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const
  809. {
  810. if( index >= bindInformations.GetLength() )
  811. return 0;
  812. return bindInformations[index]->importFromModule.AddressOf();
  813. }
  814. // inteface
  815. int asCModule::BindAllImportedFunctions()
  816. {
  817. bool notAllFunctionsWereBound = false;
  818. // Bind imported functions
  819. int c = GetImportedFunctionCount();
  820. for( int n = 0; n < c; ++n )
  821. {
  822. asCScriptFunction *importFunc = GetImportedFunction(n);
  823. if( importFunc == 0 ) return asERROR;
  824. asCString str = importFunc->GetDeclarationStr();
  825. // Get module name from where the function should be imported
  826. const char *moduleName = GetImportedFunctionSourceModule(n);
  827. if( moduleName == 0 ) return asERROR;
  828. asCModule *srcMod = engine->GetModule(moduleName, false);
  829. asIScriptFunction *func = 0;
  830. if( srcMod )
  831. func = srcMod->GetFunctionByDecl(str.AddressOf());
  832. if( func == 0 )
  833. notAllFunctionsWereBound = true;
  834. else
  835. {
  836. if( BindImportedFunction(n, func) < 0 )
  837. notAllFunctionsWereBound = true;
  838. }
  839. }
  840. if( notAllFunctionsWereBound )
  841. return asCANT_BIND_ALL_FUNCTIONS;
  842. return asSUCCESS;
  843. }
  844. // interface
  845. int asCModule::UnbindAllImportedFunctions()
  846. {
  847. asUINT c = GetImportedFunctionCount();
  848. for( asUINT n = 0; n < c; ++n )
  849. UnbindImportedFunction(n);
  850. return asSUCCESS;
  851. }
  852. // internal
  853. asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns)
  854. {
  855. size_t n;
  856. // TODO: optimize: Improve linear search
  857. for( n = 0; n < classTypes.GetLength(); n++ )
  858. if( classTypes[n]->name == type &&
  859. classTypes[n]->nameSpace == ns )
  860. return classTypes[n];
  861. for( n = 0; n < enumTypes.GetLength(); n++ )
  862. if( enumTypes[n]->name == type &&
  863. enumTypes[n]->nameSpace == ns )
  864. return enumTypes[n];
  865. for( n = 0; n < typeDefs.GetLength(); n++ )
  866. if( typeDefs[n]->name == type &&
  867. typeDefs[n]->nameSpace == ns )
  868. return typeDefs[n];
  869. return 0;
  870. }
  871. // internal
  872. asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns)
  873. {
  874. asCGlobalProperty *prop = engine->AllocateGlobalProperty();
  875. prop->name = name;
  876. prop->nameSpace = ns;
  877. // Allocate the memory for this property based on its type
  878. prop->type = dt;
  879. prop->AllocateMemory();
  880. // Make an entry in the address to variable map
  881. engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  882. // Store the variable in the module scope (the reference count is already set to 1)
  883. scriptGlobals.Put(prop);
  884. return prop;
  885. }
  886. // interface
  887. int asCModule::SaveByteCode(asIBinaryStream *out, bool stripDebugInfo) const
  888. {
  889. #ifdef AS_NO_COMPILER
  890. UNUSED_VAR(out);
  891. UNUSED_VAR(stripDebugInfo);
  892. return asNOT_SUPPORTED;
  893. #else
  894. if( out == 0 ) return asINVALID_ARG;
  895. asCWriter write(const_cast<asCModule*>(this), out, engine, stripDebugInfo);
  896. return write.Write();
  897. #endif
  898. }
  899. // interface
  900. int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped)
  901. {
  902. if( in == 0 ) return asINVALID_ARG;
  903. // Only permit loading bytecode if no other thread is currently compiling
  904. // TODO: It should be possible to have multiple threads perform compilations
  905. int r = engine->RequestBuild();
  906. if( r < 0 )
  907. return r;
  908. asCReader read(this, in, engine);
  909. r = read.Read(wasDebugInfoStripped);
  910. JITCompile();
  911. #ifdef AS_DEBUG
  912. // Verify that there are no unwanted gaps in the scriptFunctions array.
  913. for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ )
  914. {
  915. int id = n;
  916. if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) )
  917. asASSERT( false );
  918. }
  919. #endif
  920. engine->BuildCompleted();
  921. return r;
  922. }
  923. // interface
  924. int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  925. {
  926. #ifdef AS_NO_COMPILER
  927. UNUSED_VAR(sectionName);
  928. UNUSED_VAR(code);
  929. UNUSED_VAR(lineOffset);
  930. return asNOT_SUPPORTED;
  931. #else
  932. // Validate arguments
  933. if( code == 0 )
  934. return asINVALID_ARG;
  935. // Only one thread may build at one time
  936. // TODO: It should be possible to have multiple threads perform compilations
  937. int r = engine->RequestBuild();
  938. if( r < 0 )
  939. return r;
  940. // Prepare the engine
  941. engine->PrepareEngine();
  942. if( engine->configFailed )
  943. {
  944. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  945. engine->BuildCompleted();
  946. return asINVALID_CONFIGURATION;
  947. }
  948. // Compile the global variable and add it to the module scope
  949. asCBuilder builder(engine, this);
  950. asCString str = code;
  951. r = builder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset);
  952. engine->BuildCompleted();
  953. // Initialize the variable
  954. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  955. {
  956. // Clear the memory
  957. asCGlobalProperty *prop = scriptGlobals.GetLast();
  958. if( prop )
  959. {
  960. memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords());
  961. if( prop->GetInitFunc() )
  962. {
  963. // Call the init function for the global variable
  964. asIScriptContext *ctx = 0;
  965. int r = engine->CreateContext(&ctx, true);
  966. if( r < 0 )
  967. return r;
  968. r = ctx->Prepare(prop->GetInitFunc());
  969. if( r >= 0 )
  970. r = ctx->Execute();
  971. ctx->Release();
  972. }
  973. }
  974. }
  975. return r;
  976. #endif
  977. }
  978. // interface
  979. int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc)
  980. {
  981. // Make sure the outFunc is null if the function fails, so the
  982. // application doesn't attempt to release a non-existent function
  983. if( outFunc )
  984. *outFunc = 0;
  985. #ifdef AS_NO_COMPILER
  986. UNUSED_VAR(sectionName);
  987. UNUSED_VAR(code);
  988. UNUSED_VAR(lineOffset);
  989. UNUSED_VAR(compileFlags);
  990. return asNOT_SUPPORTED;
  991. #else
  992. // Validate arguments
  993. if( code == 0 ||
  994. (compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) )
  995. return asINVALID_ARG;
  996. // Only one thread may build at one time
  997. // TODO: It should be possible to have multiple threads perform compilations
  998. int r = engine->RequestBuild();
  999. if( r < 0 )
  1000. return r;
  1001. // Prepare the engine
  1002. engine->PrepareEngine();
  1003. if( engine->configFailed )
  1004. {
  1005. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1006. engine->BuildCompleted();
  1007. return asINVALID_CONFIGURATION;
  1008. }
  1009. // Compile the single function
  1010. asCBuilder builder(engine, this);
  1011. asCString str = code;
  1012. asCScriptFunction *func = 0;
  1013. r = builder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
  1014. engine->BuildCompleted();
  1015. if( r >= 0 && outFunc && func )
  1016. {
  1017. // Return the function to the caller
  1018. *outFunc = func;
  1019. func->AddRef();
  1020. }
  1021. // Release our reference to the function
  1022. if( func )
  1023. func->Release();
  1024. return r;
  1025. #endif
  1026. }
  1027. // interface
  1028. int asCModule::RemoveFunction(asIScriptFunction *func)
  1029. {
  1030. // Find the global function
  1031. asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
  1032. int idx = globalFunctions.GetIndex(f);
  1033. if( idx >= 0 )
  1034. {
  1035. globalFunctions.Erase(idx);
  1036. f->Release();
  1037. scriptFunctions.RemoveValue(f);
  1038. f->Orphan(this);
  1039. return 0;
  1040. }
  1041. return asNO_FUNCTION;
  1042. }
  1043. #ifndef AS_NO_COMPILER
  1044. // internal
  1045. int asCModule::AddFuncDef(const asCString &name, asSNameSpace *ns)
  1046. {
  1047. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF);
  1048. if( func == 0 )
  1049. return asOUT_OF_MEMORY;
  1050. func->name = name;
  1051. func->nameSpace = ns;
  1052. funcDefs.PushLast(func);
  1053. engine->funcDefs.PushLast(func);
  1054. func->id = engine->GetNextScriptFunctionId();
  1055. engine->SetScriptFunction(func);
  1056. return (int)funcDefs.GetLength()-1;
  1057. }
  1058. #endif
  1059. // interface
  1060. asDWORD asCModule::SetAccessMask(asDWORD mask)
  1061. {
  1062. asDWORD old = accessMask;
  1063. accessMask = mask;
  1064. return old;
  1065. }
  1066. END_AS_NAMESPACE