as_module.cpp 37 KB

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