as_module.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  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. #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. }
  389. // interface
  390. asIScriptFunction *asCModule::GetFunctionByName(const char *name) const
  391. {
  392. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(defaultNamespace, name);
  393. if( idxs.GetLength() != 1 )
  394. return 0;
  395. const asIScriptFunction *func = globalFunctions.Get(idxs[0]);
  396. return const_cast<asIScriptFunction*>(func);
  397. }
  398. // interface
  399. asUINT asCModule::GetImportedFunctionCount() const
  400. {
  401. return (asUINT)bindInformations.GetLength();
  402. }
  403. // interface
  404. int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
  405. {
  406. asCBuilder bld(engine, const_cast<asCModule*>(this));
  407. // Don't write parser errors to the message callback
  408. bld.silent = true;
  409. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  410. bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  411. // TODO: optimize: Improve linear search
  412. // Search script functions for matching interface
  413. int id = -1;
  414. for( asUINT n = 0; n < bindInformations.GetLength(); ++n )
  415. {
  416. if( func.name == bindInformations[n]->importedFunctionSignature->name &&
  417. func.returnType == bindInformations[n]->importedFunctionSignature->returnType &&
  418. func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() )
  419. {
  420. bool match = true;
  421. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  422. {
  423. if( func.parameterTypes[p] != bindInformations[n]->importedFunctionSignature->parameterTypes[p] )
  424. {
  425. match = false;
  426. break;
  427. }
  428. }
  429. if( match )
  430. {
  431. if( id == -1 )
  432. id = n;
  433. else
  434. return asMULTIPLE_FUNCTIONS;
  435. }
  436. }
  437. }
  438. if( id == -1 ) return asNO_FUNCTION;
  439. return id;
  440. }
  441. // interface
  442. asUINT asCModule::GetFunctionCount() const
  443. {
  444. return (asUINT)globalFunctions.GetSize();
  445. }
  446. // interface
  447. asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const
  448. {
  449. asCBuilder bld(engine, const_cast<asCModule*>(this));
  450. // Don't write parser errors to the message callback
  451. bld.silent = true;
  452. asCScriptFunction func(engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  453. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  454. if( r < 0 )
  455. {
  456. // Invalid declaration
  457. // TODO: Write error to message stream
  458. return 0;
  459. }
  460. // Use the defaultNamespace implicitly unless an explicit namespace has been provided
  461. asSNameSpace *ns = func.nameSpace == engine->nameSpaces[0] ? defaultNamespace : func.nameSpace;
  462. // Search script functions for matching interface
  463. asIScriptFunction *f = 0;
  464. const asCArray<unsigned int> &idxs = globalFunctions.GetIndexes(ns, func.name);
  465. for( unsigned int n = 0; n < idxs.GetLength(); n++ )
  466. {
  467. const asCScriptFunction *funcPtr = globalFunctions.Get(idxs[n]);
  468. if( funcPtr->objectType == 0 &&
  469. func.returnType == funcPtr->returnType &&
  470. func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
  471. )
  472. {
  473. bool match = true;
  474. for( size_t p = 0; p < func.parameterTypes.GetLength(); ++p )
  475. {
  476. if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
  477. {
  478. match = false;
  479. break;
  480. }
  481. }
  482. if( match )
  483. {
  484. if( f == 0 )
  485. f = const_cast<asCScriptFunction*>(funcPtr);
  486. else
  487. // Multiple functions
  488. return 0;
  489. }
  490. }
  491. }
  492. return f;
  493. }
  494. // interface
  495. asUINT asCModule::GetGlobalVarCount() const
  496. {
  497. return (asUINT)scriptGlobals.GetSize();
  498. }
  499. // interface
  500. int asCModule::GetGlobalVarIndexByName(const char *name) const
  501. {
  502. // Find the global var id
  503. int id = scriptGlobals.GetFirstIndex(defaultNamespace, name);
  504. if( id == -1 ) return asNO_GLOBAL_VAR;
  505. return id;
  506. }
  507. // interface
  508. int asCModule::RemoveGlobalVar(asUINT index)
  509. {
  510. asCGlobalProperty *prop = scriptGlobals.Get(index);
  511. if( !prop )
  512. return asINVALID_ARG;
  513. prop->Orphan(this);
  514. scriptGlobals.Erase(index);
  515. return 0;
  516. }
  517. // interface
  518. int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
  519. {
  520. asCBuilder bld(engine, const_cast<asCModule*>(this));
  521. // Don't write parser errors to the message callback
  522. bld.silent = true;
  523. asCString name;
  524. asSNameSpace *nameSpace;
  525. asCDataType dt;
  526. int r = bld.ParseVariableDeclaration(decl, defaultNamespace, name, nameSpace, dt);
  527. if( r < 0 )
  528. return r;
  529. // Search global variables for a match
  530. int id = scriptGlobals.GetFirstIndex(nameSpace, name, asCCompGlobPropType(dt));
  531. if( id != -1 )
  532. return id;
  533. return asNO_GLOBAL_VAR;
  534. }
  535. // interface
  536. void *asCModule::GetAddressOfGlobalVar(asUINT index)
  537. {
  538. asCGlobalProperty *prop = scriptGlobals.Get(index);
  539. if( !prop )
  540. return 0;
  541. // For object variables it's necessary to dereference the pointer to get the address of the value
  542. if( prop->type.IsObject() &&
  543. !prop->type.IsObjectHandle() )
  544. return *(void**)(prop->GetAddressOfValue());
  545. return (void*)(prop->GetAddressOfValue());
  546. }
  547. // interface
  548. const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespace) const
  549. {
  550. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  551. if (!prop) return 0;
  552. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  553. *tempString = prop->type.Format();
  554. *tempString += " ";
  555. if( includeNamespace )
  556. *tempString += prop->nameSpace->name + "::";
  557. *tempString += prop->name;
  558. return tempString->AddressOf();
  559. }
  560. // interface
  561. int asCModule::GetGlobalVar(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst) const
  562. {
  563. const asCGlobalProperty *prop = scriptGlobals.Get(index);
  564. if (!prop) return 0;
  565. if( name )
  566. *name = prop->name.AddressOf();
  567. if( nameSpace )
  568. *nameSpace = prop->nameSpace->name.AddressOf();
  569. if( typeId )
  570. *typeId = engine->GetTypeIdFromDataType(prop->type);
  571. if( isConst )
  572. *isConst = prop->type.IsReadOnly();
  573. return asSUCCESS;
  574. }
  575. // interface
  576. asUINT asCModule::GetObjectTypeCount() const
  577. {
  578. return (asUINT)classTypes.GetLength();
  579. }
  580. // interface
  581. asIObjectType *asCModule::GetObjectTypeByIndex(asUINT index) const
  582. {
  583. if( index >= classTypes.GetLength() )
  584. return 0;
  585. return classTypes[index];
  586. }
  587. // interface
  588. asIObjectType *asCModule::GetObjectTypeByName(const char *name) const
  589. {
  590. for( asUINT n = 0; n < classTypes.GetLength(); n++ )
  591. {
  592. if( classTypes[n] &&
  593. classTypes[n]->name == name &&
  594. classTypes[n]->nameSpace == defaultNamespace )
  595. return classTypes[n];
  596. }
  597. return 0;
  598. }
  599. // interface
  600. int asCModule::GetTypeIdByDecl(const char *decl) const
  601. {
  602. asCDataType dt;
  603. // This const cast is safe since we know the engine won't be modified
  604. asCBuilder bld(engine, const_cast<asCModule*>(this));
  605. // Don't write parser errors to the message callback
  606. bld.silent = true;
  607. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  608. if( r < 0 )
  609. return asINVALID_TYPE;
  610. return engine->GetTypeIdFromDataType(dt);
  611. }
  612. // interface
  613. asUINT asCModule::GetEnumCount() const
  614. {
  615. return (asUINT)enumTypes.GetLength();
  616. }
  617. // interface
  618. const char *asCModule::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace) const
  619. {
  620. if( index >= enumTypes.GetLength() )
  621. return 0;
  622. if( enumTypeId )
  623. *enumTypeId = engine->GetTypeIdFromDataType(asCDataType::CreateObject(enumTypes[index], false));
  624. if( nameSpace )
  625. *nameSpace = enumTypes[index]->nameSpace->name.AddressOf();
  626. return enumTypes[index]->name.AddressOf();
  627. }
  628. // interface
  629. int asCModule::GetEnumValueCount(int enumTypeId) const
  630. {
  631. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  632. asCObjectType *t = dt.GetObjectType();
  633. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  634. return asINVALID_TYPE;
  635. return (int)t->enumValues.GetLength();
  636. }
  637. // interface
  638. const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
  639. {
  640. asCDataType dt = engine->GetDataTypeFromTypeId(enumTypeId);
  641. asCObjectType *t = dt.GetObjectType();
  642. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  643. return 0;
  644. if( index >= t->enumValues.GetLength() )
  645. return 0;
  646. if( outValue )
  647. *outValue = t->enumValues[index]->value;
  648. return t->enumValues[index]->name.AddressOf();
  649. }
  650. // interface
  651. asUINT asCModule::GetTypedefCount() const
  652. {
  653. return (asUINT)typeDefs.GetLength();
  654. }
  655. // interface
  656. const char *asCModule::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace) const
  657. {
  658. if( index >= typeDefs.GetLength() )
  659. return 0;
  660. if( typeId )
  661. *typeId = engine->GetTypeIdFromDataType(typeDefs[index]->templateSubTypes[0]);
  662. if( nameSpace )
  663. *nameSpace = typeDefs[index]->nameSpace->name.AddressOf();
  664. return typeDefs[index]->name.AddressOf();
  665. }
  666. // internal
  667. int asCModule::GetNextImportedFunctionId()
  668. {
  669. // TODO: multithread: This will break if one thread if freeing a module, while another is being compiled
  670. if( engine->freeImportedFunctionIdxs.GetLength() )
  671. return FUNC_IMPORTED | (asUINT)engine->freeImportedFunctionIdxs[engine->freeImportedFunctionIdxs.GetLength()-1];
  672. return FUNC_IMPORTED | (asUINT)engine->importedFunctions.GetLength();
  673. }
  674. #ifndef AS_NO_COMPILER
  675. // internal
  676. 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)
  677. {
  678. asASSERT(id >= 0);
  679. // Store the function information
  680. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT);
  681. if( func == 0 )
  682. {
  683. // Free the default args
  684. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  685. if( defaultArgs[n] )
  686. asDELETE(defaultArgs[n], asCString);
  687. return asOUT_OF_MEMORY;
  688. }
  689. if( ns == 0 )
  690. ns = engine->nameSpaces[0];
  691. // All methods of shared objects are also shared
  692. if( objType && objType->IsShared() )
  693. isShared = true;
  694. func->name = name;
  695. func->nameSpace = ns;
  696. func->id = id;
  697. func->returnType = returnType;
  698. if( func->funcType == asFUNC_SCRIPT )
  699. {
  700. func->scriptData->scriptSectionIdx = sectionIdx;
  701. func->scriptData->declaredAt = declaredAt;
  702. }
  703. func->parameterTypes = params;
  704. func->inOutFlags = inOutFlags;
  705. func->defaultArgs = defaultArgs;
  706. func->objectType = objType;
  707. func->isReadOnly = isConstMethod;
  708. func->isPrivate = isPrivate;
  709. func->isFinal = isFinal;
  710. func->isOverride = isOverride;
  711. func->isShared = isShared;
  712. asASSERT( params.GetLength() == inOutFlags.GetLength() && params.GetLength() == defaultArgs.GetLength() );
  713. // Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
  714. asASSERT( !(!objType && isFinal) );
  715. asASSERT( !(!objType && isOverride) );
  716. // The script function's refCount was initialized to 1
  717. scriptFunctions.PushLast(func);
  718. engine->SetScriptFunction(func);
  719. // Compute the signature id
  720. if( objType )
  721. func->ComputeSignatureId();
  722. // Add reference
  723. if( isGlobalFunction )
  724. {
  725. globalFunctions.Put(func);
  726. func->AddRef();
  727. }
  728. return 0;
  729. }
  730. // internal
  731. int asCModule::AddScriptFunction(asCScriptFunction *func)
  732. {
  733. scriptFunctions.PushLast(func);
  734. func->AddRef();
  735. engine->SetScriptFunction(func);
  736. return 0;
  737. }
  738. // internal
  739. 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)
  740. {
  741. asASSERT(id >= 0);
  742. // Store the function information
  743. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED);
  744. if( func == 0 )
  745. {
  746. // Free the default args
  747. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  748. if( defaultArgs[n] )
  749. asDELETE(defaultArgs[n], asCString);
  750. return asOUT_OF_MEMORY;
  751. }
  752. func->name = name;
  753. func->id = id;
  754. func->returnType = returnType;
  755. func->nameSpace = ns;
  756. func->parameterTypes = params;
  757. func->inOutFlags = inOutFlags;
  758. func->defaultArgs = defaultArgs;
  759. func->objectType = 0;
  760. sBindInfo *info = asNEW(sBindInfo);
  761. if( info == 0 )
  762. {
  763. asDELETE(func, asCScriptFunction);
  764. return asOUT_OF_MEMORY;
  765. }
  766. info->importedFunctionSignature = func;
  767. info->boundFunctionId = -1;
  768. info->importFromModule = moduleName;
  769. bindInformations.PushLast(info);
  770. // Add the info to the array in the engine
  771. if( engine->freeImportedFunctionIdxs.GetLength() )
  772. engine->importedFunctions[engine->freeImportedFunctionIdxs.PopLast()] = info;
  773. else
  774. engine->importedFunctions.PushLast(info);
  775. return 0;
  776. }
  777. #endif
  778. // internal
  779. asCScriptFunction *asCModule::GetImportedFunction(int index) const
  780. {
  781. return bindInformations[index]->importedFunctionSignature;
  782. }
  783. // interface
  784. int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
  785. {
  786. // First unbind the old function
  787. int r = UnbindImportedFunction(index);
  788. if( r < 0 ) return r;
  789. // Must verify that the interfaces are equal
  790. asCScriptFunction *dst = GetImportedFunction(index);
  791. if( dst == 0 ) return asNO_FUNCTION;
  792. if( func == 0 )
  793. return asINVALID_ARG;
  794. asCScriptFunction *src = engine->GetScriptFunction(func->GetId());
  795. if( src == 0 )
  796. return asNO_FUNCTION;
  797. // Verify return type
  798. if( dst->returnType != src->returnType )
  799. return asINVALID_INTERFACE;
  800. if( dst->parameterTypes.GetLength() != src->parameterTypes.GetLength() )
  801. return asINVALID_INTERFACE;
  802. for( size_t n = 0; n < dst->parameterTypes.GetLength(); ++n )
  803. {
  804. if( dst->parameterTypes[n] != src->parameterTypes[n] )
  805. return asINVALID_INTERFACE;
  806. }
  807. bindInformations[index]->boundFunctionId = src->GetId();
  808. src->AddRef();
  809. return asSUCCESS;
  810. }
  811. // interface
  812. int asCModule::UnbindImportedFunction(asUINT index)
  813. {
  814. if( index >= bindInformations.GetLength() )
  815. return asINVALID_ARG;
  816. // Remove reference to old module
  817. if( bindInformations[index] )
  818. {
  819. int oldFuncID = bindInformations[index]->boundFunctionId;
  820. if( oldFuncID != -1 )
  821. {
  822. bindInformations[index]->boundFunctionId = -1;
  823. engine->scriptFunctions[oldFuncID]->Release();
  824. }
  825. }
  826. return asSUCCESS;
  827. }
  828. // interface
  829. const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
  830. {
  831. asCScriptFunction *func = GetImportedFunction(index);
  832. if( func == 0 ) return 0;
  833. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  834. *tempString = func->GetDeclarationStr();
  835. return tempString->AddressOf();
  836. }
  837. // interface
  838. const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const
  839. {
  840. if( index >= bindInformations.GetLength() )
  841. return 0;
  842. return bindInformations[index]->importFromModule.AddressOf();
  843. }
  844. // inteface
  845. int asCModule::BindAllImportedFunctions()
  846. {
  847. bool notAllFunctionsWereBound = false;
  848. // Bind imported functions
  849. int c = GetImportedFunctionCount();
  850. for( int n = 0; n < c; ++n )
  851. {
  852. asCScriptFunction *importFunc = GetImportedFunction(n);
  853. if( importFunc == 0 ) return asERROR;
  854. asCString str = importFunc->GetDeclarationStr();
  855. // Get module name from where the function should be imported
  856. const char *moduleName = GetImportedFunctionSourceModule(n);
  857. if( moduleName == 0 ) return asERROR;
  858. asCModule *srcMod = engine->GetModule(moduleName, false);
  859. asIScriptFunction *func = 0;
  860. if( srcMod )
  861. func = srcMod->GetFunctionByDecl(str.AddressOf());
  862. if( func == 0 )
  863. notAllFunctionsWereBound = true;
  864. else
  865. {
  866. if( BindImportedFunction(n, func) < 0 )
  867. notAllFunctionsWereBound = true;
  868. }
  869. }
  870. if( notAllFunctionsWereBound )
  871. return asCANT_BIND_ALL_FUNCTIONS;
  872. return asSUCCESS;
  873. }
  874. // interface
  875. int asCModule::UnbindAllImportedFunctions()
  876. {
  877. asUINT c = GetImportedFunctionCount();
  878. for( asUINT n = 0; n < c; ++n )
  879. UnbindImportedFunction(n);
  880. return asSUCCESS;
  881. }
  882. // internal
  883. asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns)
  884. {
  885. size_t n;
  886. // TODO: optimize: Improve linear search
  887. for( n = 0; n < classTypes.GetLength(); n++ )
  888. if( classTypes[n]->name == type &&
  889. classTypes[n]->nameSpace == ns )
  890. return classTypes[n];
  891. for( n = 0; n < enumTypes.GetLength(); n++ )
  892. if( enumTypes[n]->name == type &&
  893. enumTypes[n]->nameSpace == ns )
  894. return enumTypes[n];
  895. for( n = 0; n < typeDefs.GetLength(); n++ )
  896. if( typeDefs[n]->name == type &&
  897. typeDefs[n]->nameSpace == ns )
  898. return typeDefs[n];
  899. return 0;
  900. }
  901. // internal
  902. asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns)
  903. {
  904. asCGlobalProperty *prop = engine->AllocateGlobalProperty();
  905. prop->name = name;
  906. prop->nameSpace = ns;
  907. // Allocate the memory for this property based on its type
  908. prop->type = dt;
  909. prop->AllocateMemory();
  910. // Make an entry in the address to variable map
  911. engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  912. // Store the variable in the module scope (the reference count is already set to 1)
  913. scriptGlobals.Put(prop);
  914. return prop;
  915. }
  916. // interface
  917. int asCModule::SaveByteCode(asIBinaryStream *out, bool stripDebugInfo) const
  918. {
  919. #ifdef AS_NO_COMPILER
  920. UNUSED_VAR(out);
  921. UNUSED_VAR(stripDebugInfo);
  922. return asNOT_SUPPORTED;
  923. #else
  924. if( out == 0 ) return asINVALID_ARG;
  925. asCWriter write(const_cast<asCModule*>(this), out, engine, stripDebugInfo);
  926. return write.Write();
  927. #endif
  928. }
  929. // interface
  930. int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped)
  931. {
  932. if( in == 0 ) return asINVALID_ARG;
  933. // Only permit loading bytecode if no other thread is currently compiling
  934. // TODO: It should be possible to have multiple threads perform compilations
  935. int r = engine->RequestBuild();
  936. if( r < 0 )
  937. return r;
  938. asCReader read(this, in, engine);
  939. r = read.Read(wasDebugInfoStripped);
  940. JITCompile();
  941. #ifdef AS_DEBUG
  942. // Verify that there are no unwanted gaps in the scriptFunctions array.
  943. for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ )
  944. {
  945. int id = n;
  946. if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) )
  947. asASSERT( false );
  948. }
  949. #endif
  950. engine->BuildCompleted();
  951. return r;
  952. }
  953. // interface
  954. int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  955. {
  956. #ifdef AS_NO_COMPILER
  957. UNUSED_VAR(sectionName);
  958. UNUSED_VAR(code);
  959. UNUSED_VAR(lineOffset);
  960. return asNOT_SUPPORTED;
  961. #else
  962. // Validate arguments
  963. if( code == 0 )
  964. return asINVALID_ARG;
  965. // Only one thread may build at one time
  966. // TODO: It should be possible to have multiple threads perform compilations
  967. int r = engine->RequestBuild();
  968. if( r < 0 )
  969. return r;
  970. // Prepare the engine
  971. engine->PrepareEngine();
  972. if( engine->configFailed )
  973. {
  974. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  975. engine->BuildCompleted();
  976. return asINVALID_CONFIGURATION;
  977. }
  978. // Compile the global variable and add it to the module scope
  979. asCBuilder builder(engine, this);
  980. asCString str = code;
  981. r = builder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset);
  982. engine->BuildCompleted();
  983. // Initialize the variable
  984. if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
  985. {
  986. // Clear the memory
  987. asCGlobalProperty *prop = scriptGlobals.GetLast();
  988. if( prop )
  989. {
  990. memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords());
  991. if( prop->GetInitFunc() )
  992. {
  993. // Call the init function for the global variable
  994. asIScriptContext *ctx = 0;
  995. int r = engine->CreateContext(&ctx, true);
  996. if( r < 0 )
  997. return r;
  998. r = ctx->Prepare(prop->GetInitFunc());
  999. if( r >= 0 )
  1000. r = ctx->Execute();
  1001. ctx->Release();
  1002. }
  1003. }
  1004. }
  1005. return r;
  1006. #endif
  1007. }
  1008. // interface
  1009. int asCModule::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc)
  1010. {
  1011. // Make sure the outFunc is null if the function fails, so the
  1012. // application doesn't attempt to release a non-existent function
  1013. if( outFunc )
  1014. *outFunc = 0;
  1015. #ifdef AS_NO_COMPILER
  1016. UNUSED_VAR(sectionName);
  1017. UNUSED_VAR(code);
  1018. UNUSED_VAR(lineOffset);
  1019. UNUSED_VAR(compileFlags);
  1020. return asNOT_SUPPORTED;
  1021. #else
  1022. // Validate arguments
  1023. if( code == 0 ||
  1024. (compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE) )
  1025. return asINVALID_ARG;
  1026. // Only one thread may build at one time
  1027. // TODO: It should be possible to have multiple threads perform compilations
  1028. int r = engine->RequestBuild();
  1029. if( r < 0 )
  1030. return r;
  1031. // Prepare the engine
  1032. engine->PrepareEngine();
  1033. if( engine->configFailed )
  1034. {
  1035. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1036. engine->BuildCompleted();
  1037. return asINVALID_CONFIGURATION;
  1038. }
  1039. // Compile the single function
  1040. asCBuilder builder(engine, this);
  1041. asCString str = code;
  1042. asCScriptFunction *func = 0;
  1043. r = builder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
  1044. engine->BuildCompleted();
  1045. if( r >= 0 && outFunc && func )
  1046. {
  1047. // Return the function to the caller
  1048. *outFunc = func;
  1049. func->AddRef();
  1050. }
  1051. // Release our reference to the function
  1052. if( func )
  1053. func->Release();
  1054. return r;
  1055. #endif
  1056. }
  1057. // interface
  1058. int asCModule::RemoveFunction(asIScriptFunction *func)
  1059. {
  1060. // Find the global function
  1061. asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
  1062. int idx = globalFunctions.GetIndex(f);
  1063. if( idx >= 0 )
  1064. {
  1065. globalFunctions.Erase(idx);
  1066. f->Release();
  1067. scriptFunctions.RemoveValue(f);
  1068. f->Orphan(this);
  1069. return 0;
  1070. }
  1071. return asNO_FUNCTION;
  1072. }
  1073. #ifndef AS_NO_COMPILER
  1074. // internal
  1075. int asCModule::AddFuncDef(const asCString &name, asSNameSpace *ns)
  1076. {
  1077. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF);
  1078. if( func == 0 )
  1079. return asOUT_OF_MEMORY;
  1080. func->name = name;
  1081. func->nameSpace = ns;
  1082. funcDefs.PushLast(func);
  1083. engine->funcDefs.PushLast(func);
  1084. func->id = engine->GetNextScriptFunctionId();
  1085. engine->SetScriptFunction(func);
  1086. return (int)funcDefs.GetLength()-1;
  1087. }
  1088. #endif
  1089. // interface
  1090. asDWORD asCModule::SetAccessMask(asDWORD mask)
  1091. {
  1092. asDWORD old = accessMask;
  1093. accessMask = mask;
  1094. return old;
  1095. }
  1096. END_AS_NAMESPACE