as_module.cpp 34 KB

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