as_module.cpp 35 KB

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