as_module.cpp 33 KB

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