as_builder.cpp 109 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2011 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. // Modified by Lasse Öörni for Urho3D
  24. //
  25. // as_builder.cpp
  26. //
  27. // This is the class that manages the compilation of the scripts
  28. //
  29. #include "as_config.h"
  30. #include "as_builder.h"
  31. #include "as_parser.h"
  32. #include "as_compiler.h"
  33. #include "as_tokendef.h"
  34. #include "as_string_util.h"
  35. #include "as_outputbuffer.h"
  36. #include "as_texts.h"
  37. #include "as_scriptobject.h"
  38. BEGIN_AS_NAMESPACE
  39. asCBuilder::asCBuilder(asCScriptEngine *engine, asCModule *module)
  40. {
  41. this->engine = engine;
  42. this->module = module;
  43. }
  44. asCBuilder::~asCBuilder()
  45. {
  46. asUINT n;
  47. // Free all functions
  48. for( n = 0; n < functions.GetLength(); n++ )
  49. {
  50. if( functions[n] )
  51. {
  52. if( functions[n]->node )
  53. {
  54. functions[n]->node->Destroy(engine);
  55. }
  56. if( functions[n]->explicitSignature )
  57. {
  58. asDELETE(functions[n]->explicitSignature,sExplicitSignature);
  59. }
  60. asDELETE(functions[n],sFunctionDescription);
  61. }
  62. functions[n] = 0;
  63. }
  64. // Free all global variables
  65. for( n = 0; n < globVariables.GetLength(); n++ )
  66. {
  67. if( globVariables[n] )
  68. {
  69. if( globVariables[n]->nextNode )
  70. {
  71. globVariables[n]->nextNode->Destroy(engine);
  72. }
  73. asDELETE(globVariables[n],sGlobalVariableDescription);
  74. globVariables[n] = 0;
  75. }
  76. }
  77. // Free all the loaded files
  78. for( n = 0; n < scripts.GetLength(); n++ )
  79. {
  80. if( scripts[n] )
  81. {
  82. asDELETE(scripts[n],asCScriptCode);
  83. }
  84. scripts[n] = 0;
  85. }
  86. // Free all class declarations
  87. for( n = 0; n < classDeclarations.GetLength(); n++ )
  88. {
  89. if( classDeclarations[n] )
  90. {
  91. if( classDeclarations[n]->node )
  92. {
  93. classDeclarations[n]->node->Destroy(engine);
  94. }
  95. asDELETE(classDeclarations[n],sClassDeclaration);
  96. classDeclarations[n] = 0;
  97. }
  98. }
  99. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  100. {
  101. if( interfaceDeclarations[n] )
  102. {
  103. if( interfaceDeclarations[n]->node )
  104. {
  105. interfaceDeclarations[n]->node->Destroy(engine);
  106. }
  107. asDELETE(interfaceDeclarations[n],sClassDeclaration);
  108. interfaceDeclarations[n] = 0;
  109. }
  110. }
  111. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  112. {
  113. if( namedTypeDeclarations[n] )
  114. {
  115. if( namedTypeDeclarations[n]->node )
  116. {
  117. namedTypeDeclarations[n]->node->Destroy(engine);
  118. }
  119. asDELETE(namedTypeDeclarations[n],sClassDeclaration);
  120. namedTypeDeclarations[n] = 0;
  121. }
  122. }
  123. for( n = 0; n < funcDefs.GetLength(); n++ )
  124. {
  125. if( funcDefs[n] )
  126. {
  127. if( funcDefs[n]->node )
  128. funcDefs[n]->node->Destroy(engine);
  129. asDELETE(funcDefs[n],sFuncDef);
  130. funcDefs[n] = 0;
  131. }
  132. }
  133. }
  134. int asCBuilder::AddCode(const char *name, const char *code, int codeLength, int lineOffset, int sectionIdx, bool makeCopy)
  135. {
  136. asCScriptCode *script = asNEW(asCScriptCode);
  137. int r = script->SetCode(name, code, codeLength, makeCopy);
  138. script->lineOffset = lineOffset;
  139. script->idx = sectionIdx;
  140. scripts.PushLast(script);
  141. return r;
  142. }
  143. int asCBuilder::Build()
  144. {
  145. numErrors = 0;
  146. numWarnings = 0;
  147. preMessage.isSet = false;
  148. ParseScripts();
  149. CompileClasses();
  150. CompileGlobalVariables();
  151. CompileFunctions();
  152. if( numErrors > 0 )
  153. return asERROR;
  154. return asSUCCESS;
  155. }
  156. int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  157. {
  158. numErrors = 0;
  159. numWarnings = 0;
  160. preMessage.isSet = false;
  161. // Add the string to the script code
  162. asCScriptCode *script = asNEW(asCScriptCode);
  163. script->SetCode(sectionName, code, true);
  164. script->lineOffset = lineOffset;
  165. scripts.PushLast(script);
  166. // Parse the string
  167. asCParser parser(this);
  168. if( parser.ParseScript(scripts[0]) < 0 )
  169. return asERROR;
  170. asCScriptNode *node = parser.GetScriptNode();
  171. // Make sure there is nothing else than the global variable in the script code
  172. if( node == 0 ||
  173. node->firstChild == 0 ||
  174. node->firstChild != node->lastChild ||
  175. node->firstChild->nodeType != snGlobalVar )
  176. {
  177. WriteError(script->name.AddressOf(), TXT_ONLY_ONE_VARIABLE_ALLOWED, 0, 0);
  178. return asERROR;
  179. }
  180. node = node->firstChild;
  181. node->DisconnectParent();
  182. RegisterGlobalVar(node, script);
  183. CompileGlobalVariables();
  184. if( numErrors > 0 )
  185. {
  186. // Remove the variable from the module, if it was registered
  187. if( globVariables.GetLength() > 0 )
  188. {
  189. module->RemoveGlobalVar(module->GetGlobalVarCount()-1);
  190. }
  191. return asERROR;
  192. }
  193. return 0;
  194. }
  195. int asCBuilder::ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func)
  196. {
  197. int firstArgWithDefaultValue = -1;
  198. for( asUINT n = 0; n < func->defaultArgs.GetLength(); n++ )
  199. {
  200. if( func->defaultArgs[n] )
  201. firstArgWithDefaultValue = n;
  202. else if( firstArgWithDefaultValue >= 0 )
  203. {
  204. int r, c;
  205. script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  206. asCString str;
  207. str.Format(TXT_DEF_ARG_MISSING_IN_FUNC_s, func->GetDeclaration());
  208. WriteError(script->name.AddressOf(), str.AddressOf(), r, c);
  209. return asINVALID_DECLARATION;
  210. }
  211. }
  212. return 0;
  213. }
  214. int asCBuilder::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asCScriptFunction **outFunc)
  215. {
  216. asASSERT(outFunc != 0);
  217. numErrors = 0;
  218. numWarnings = 0;
  219. preMessage.isSet = false;
  220. // Add the string to the script code
  221. asCScriptCode *script = asNEW(asCScriptCode);
  222. script->SetCode(sectionName, code, true);
  223. script->lineOffset = lineOffset;
  224. scripts.PushLast(script);
  225. // Parse the string
  226. asCParser parser(this);
  227. if( parser.ParseScript(scripts[0]) < 0 )
  228. return asERROR;
  229. asCScriptNode *node = parser.GetScriptNode();
  230. // Make sure there is nothing else than the function in the script code
  231. if( node == 0 ||
  232. node->firstChild == 0 ||
  233. node->firstChild != node->lastChild ||
  234. node->firstChild->nodeType != snFunction )
  235. {
  236. WriteError(script->name.AddressOf(), TXT_ONLY_ONE_FUNCTION_ALLOWED, 0, 0);
  237. return asERROR;
  238. }
  239. // Find the function node
  240. node = node->firstChild;
  241. // Create the function
  242. bool isConstructor, isDestructor, isPrivate, isFinal, isOverride;
  243. asCScriptFunction *func = asNEW(asCScriptFunction)(engine,module,asFUNC_SCRIPT);
  244. GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate, isFinal, isOverride);
  245. func->id = engine->GetNextScriptFunctionId();
  246. func->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  247. // Make sure the default args are declared correctly
  248. int r = ValidateDefaultArgs(script, node, func);
  249. if( r < 0 )
  250. {
  251. func->Release();
  252. return asERROR;
  253. }
  254. // Tell the engine that the function exists already so the compiler can access it
  255. if( compileFlags & asCOMP_ADD_TO_MODULE )
  256. {
  257. int r = CheckNameConflict(func->name.AddressOf(), node, scripts[0]);
  258. if( r < 0 )
  259. {
  260. func->Release();
  261. return asERROR;
  262. }
  263. module->globalFunctions.PushLast(func);
  264. func->AddRef();
  265. module->AddScriptFunction(func);
  266. }
  267. else
  268. engine->SetScriptFunction(func);
  269. // Fill in the function info for the builder too
  270. node->DisconnectParent();
  271. sFunctionDescription *funcDesc = asNEW(sFunctionDescription);
  272. functions.PushLast(funcDesc);
  273. funcDesc->script = scripts[0];
  274. funcDesc->node = node;
  275. funcDesc->name = func->name;
  276. funcDesc->funcId = func->id;
  277. funcDesc->explicitSignature = 0;
  278. asCCompiler compiler(engine);
  279. if( compiler.CompileFunction(this, functions[0]->script, 0, functions[0]->node, func) >= 0 )
  280. {
  281. // Return the function
  282. *outFunc = func;
  283. }
  284. else
  285. {
  286. // If the function was added to the module then remove it again
  287. if( compileFlags & asCOMP_ADD_TO_MODULE )
  288. {
  289. module->globalFunctions.RemoveValue(func);
  290. module->scriptFunctions.RemoveValue(func);
  291. func->Release();
  292. func->Release();
  293. }
  294. func->Release();
  295. return asERROR;
  296. }
  297. return asSUCCESS;
  298. }
  299. void asCBuilder::ParseScripts()
  300. {
  301. asCArray<asCParser*> parsers((int)scripts.GetLength());
  302. // Parse all the files as if they were one
  303. asUINT n = 0;
  304. for( n = 0; n < scripts.GetLength(); n++ )
  305. {
  306. asCParser *parser = asNEW(asCParser)(this);
  307. parsers.PushLast(parser);
  308. // Parse the script file
  309. parser->ParseScript(scripts[n]);
  310. }
  311. if( numErrors == 0 )
  312. {
  313. // Find all type declarations
  314. for( n = 0; n < scripts.GetLength(); n++ )
  315. {
  316. asCScriptNode *node = parsers[n]->GetScriptNode();
  317. // Find structure definitions first
  318. node = node->firstChild;
  319. while( node )
  320. {
  321. asCScriptNode *next = node->next;
  322. if( node->nodeType == snClass )
  323. {
  324. node->DisconnectParent();
  325. RegisterClass(node, scripts[n]);
  326. }
  327. else if( node->nodeType == snInterface )
  328. {
  329. node->DisconnectParent();
  330. RegisterInterface(node, scripts[n]);
  331. }
  332. // Handle enumeration
  333. else if( node->nodeType == snEnum )
  334. {
  335. node->DisconnectParent();
  336. RegisterEnum(node, scripts[n]);
  337. }
  338. // Handle typedef
  339. else if( node->nodeType == snTypedef )
  340. {
  341. node->DisconnectParent();
  342. RegisterTypedef(node, scripts[n]);
  343. }
  344. else if( node->nodeType == snFuncDef )
  345. {
  346. node->DisconnectParent();
  347. RegisterFuncDef(node, scripts[n]);
  348. }
  349. node = next;
  350. }
  351. }
  352. // Register the complete function definitions
  353. for( n = 0; n < funcDefs.GetLength(); n++ )
  354. {
  355. CompleteFuncDef(funcDefs[n]);
  356. }
  357. // Register script methods found in the interfaces
  358. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  359. {
  360. sClassDeclaration *decl = interfaceDeclarations[n];
  361. if( decl->isExistingShared ) continue; // TODO: shared: Should really verify that the methods match the original
  362. asCScriptNode *node = decl->node->firstChild->next;
  363. while( node )
  364. {
  365. asCScriptNode *next = node->next;
  366. if( node->nodeType == snFunction )
  367. {
  368. node->DisconnectParent();
  369. RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, decl->script, decl->objType, true);
  370. }
  371. else if( node->nodeType == snVirtualProperty )
  372. {
  373. node->DisconnectParent();
  374. RegisterVirtualProperty(node, decl->script, decl->objType, true, false);
  375. }
  376. node = next;
  377. }
  378. }
  379. // Now the interfaces have been completely established, now we need to determine if
  380. // the same interface has already been registered before, and if so reuse the interface id.
  381. module->ResolveInterfaceIds();
  382. // Register script methods found in the structures
  383. for( n = 0; n < classDeclarations.GetLength(); n++ )
  384. {
  385. sClassDeclaration *decl = classDeclarations[n];
  386. if( decl->isExistingShared ) continue; // TODO: shared: Should really verify that the methods match the original
  387. asCScriptNode *node = decl->node->firstChild->next;
  388. // Skip list of classes and interfaces
  389. while( node && node->nodeType == snIdentifier )
  390. node = node->next;
  391. while( node )
  392. {
  393. asCScriptNode *next = node->next;
  394. if( node->nodeType == snFunction )
  395. {
  396. node->DisconnectParent();
  397. RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, decl->script, decl->objType);
  398. }
  399. else if( node->nodeType == snVirtualProperty )
  400. {
  401. node->DisconnectParent();
  402. RegisterVirtualProperty(node, decl->script, decl->objType, false, false);
  403. }
  404. node = next;
  405. }
  406. // Make sure the default factory & constructor exists for classes
  407. if( decl->objType->beh.construct == engine->scriptTypeBehaviours.beh.construct )
  408. {
  409. if( decl->objType->beh.constructors.GetLength() == 1 || engine->ep.alwaysImplDefaultConstruct )
  410. {
  411. AddDefaultConstructor(decl->objType, decl->script);
  412. }
  413. else
  414. {
  415. // As the class has another constructor we shouldn't provide the default constructor
  416. if( decl->objType->beh.construct )
  417. {
  418. engine->scriptFunctions[decl->objType->beh.construct]->Release();
  419. decl->objType->beh.construct = 0;
  420. decl->objType->beh.constructors.RemoveIndex(0);
  421. }
  422. if( decl->objType->beh.factory )
  423. {
  424. engine->scriptFunctions[decl->objType->beh.factory]->Release();
  425. decl->objType->beh.factory = 0;
  426. decl->objType->beh.factories.RemoveIndex(0);
  427. }
  428. if( decl->objType->beh.copy )
  429. {
  430. engine->scriptFunctions[decl->objType->beh.copy]->Release();
  431. decl->objType->beh.copy = 0;
  432. }
  433. }
  434. }
  435. }
  436. // Find other global nodes
  437. for( n = 0; n < scripts.GetLength(); n++ )
  438. {
  439. // Find other global nodes
  440. asCScriptNode *node = parsers[n]->GetScriptNode();
  441. node = node->firstChild;
  442. while( node )
  443. {
  444. asCScriptNode *next = node->next;
  445. node->DisconnectParent();
  446. if( node->nodeType == snFunction )
  447. {
  448. RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, scripts[n], 0, false, true);
  449. }
  450. else if( node->nodeType == snGlobalVar )
  451. {
  452. RegisterGlobalVar(node, scripts[n]);
  453. }
  454. else if( node->nodeType == snVirtualProperty )
  455. {
  456. RegisterVirtualProperty(node, scripts[n], 0, false, true);
  457. }
  458. else if( node->nodeType == snImport )
  459. {
  460. RegisterImportedFunction(module->GetNextImportedFunctionId(), node, scripts[n]);
  461. }
  462. else
  463. {
  464. // Unused script node
  465. int r, c;
  466. scripts[n]->ConvertPosToRowCol(node->tokenPos, &r, &c);
  467. WriteWarning(scripts[n]->name.AddressOf(), TXT_UNUSED_SCRIPT_NODE, r, c);
  468. node->Destroy(engine);
  469. }
  470. node = next;
  471. }
  472. }
  473. }
  474. for( n = 0; n < parsers.GetLength(); n++ )
  475. {
  476. asDELETE(parsers[n],asCParser);
  477. }
  478. }
  479. void asCBuilder::CompileFunctions()
  480. {
  481. // Compile each function
  482. for( asUINT n = 0; n < functions.GetLength(); n++ )
  483. {
  484. sFunctionDescription *current = functions[n];
  485. if( current == 0 ) continue;
  486. asCCompiler compiler(engine);
  487. asCScriptFunction *func = engine->scriptFunctions[current->funcId];
  488. if( current->node )
  489. {
  490. int r, c;
  491. current->script->ConvertPosToRowCol(current->node->tokenPos, &r, &c);
  492. asCString str = func->GetDeclarationStr();
  493. str.Format(TXT_COMPILING_s, str.AddressOf());
  494. WriteInfo(current->script->name.AddressOf(), str.AddressOf(), r, c, true);
  495. compiler.CompileFunction(this, current->script, current->explicitSignature, current->node, func);
  496. preMessage.isSet = false;
  497. }
  498. else if( current->name == current->objType->name )
  499. {
  500. asCScriptNode *node = 0;
  501. for( asUINT n = 0; n < classDeclarations.GetLength(); n++ )
  502. {
  503. if( classDeclarations[n]->name == current->name )
  504. {
  505. node = classDeclarations[n]->node;
  506. break;
  507. }
  508. }
  509. int r = 0, c = 0;
  510. if( node )
  511. current->script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  512. asCString str = func->GetDeclarationStr();
  513. str.Format(TXT_COMPILING_s, str.AddressOf());
  514. WriteInfo(current->script->name.AddressOf(), str.AddressOf(), r, c, true);
  515. // This is the default constructor, that is generated
  516. // automatically if not implemented by the user.
  517. compiler.CompileDefaultConstructor(this, current->script, node, func);
  518. preMessage.isSet = false;
  519. }
  520. else
  521. {
  522. // This is a property accessor, but no implementation was provided for it
  523. asASSERT( current->explicitSignature );
  524. }
  525. }
  526. }
  527. int asCBuilder::ParseDataType(const char *datatype, asCDataType *result)
  528. {
  529. numErrors = 0;
  530. numWarnings = 0;
  531. preMessage.isSet = false;
  532. asCScriptCode source;
  533. source.SetCode("", datatype, true);
  534. asCParser parser(this);
  535. int r = parser.ParseDataType(&source);
  536. if( r < 0 )
  537. return asINVALID_TYPE;
  538. // Get data type and property name
  539. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  540. *result = CreateDataTypeFromNode(dataType, &source, true);
  541. if( numErrors > 0 )
  542. return asINVALID_TYPE;
  543. return asSUCCESS;
  544. }
  545. int asCBuilder::ParseTemplateDecl(const char *decl, asCString *name, asCString *subtypeName)
  546. {
  547. numErrors = 0;
  548. numWarnings = 0;
  549. preMessage.isSet = false;
  550. asCScriptCode source;
  551. source.SetCode("", decl, true);
  552. asCParser parser(this);
  553. int r = parser.ParseTemplateDecl(&source);
  554. if( r < 0 )
  555. return asINVALID_TYPE;
  556. // Get the template name and subtype name
  557. asCScriptNode *node = parser.GetScriptNode()->firstChild;
  558. name->Assign(&decl[node->tokenPos], node->tokenLength);
  559. node = node->next;
  560. subtypeName->Assign(&decl[node->tokenPos], node->tokenLength);
  561. // TODO: template: check for name conflicts
  562. if( numErrors > 0 )
  563. return asINVALID_DECLARATION;
  564. return asSUCCESS;
  565. }
  566. int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &name, asCDataType &type)
  567. {
  568. numErrors = 0;
  569. numWarnings = 0;
  570. preMessage.isSet = false;
  571. if( dt )
  572. {
  573. // Verify that the object type exist
  574. if( dt->GetObjectType() == 0 )
  575. return asINVALID_OBJECT;
  576. }
  577. // Check property declaration and type
  578. asCScriptCode source;
  579. source.SetCode(TXT_PROPERTY, decl, true);
  580. asCParser parser(this);
  581. int r = parser.ParsePropertyDeclaration(&source);
  582. if( r < 0 )
  583. return asINVALID_DECLARATION;
  584. // Get data type and property name
  585. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  586. asCScriptNode *nameNode = dataType->next;
  587. type = CreateDataTypeFromNode(dataType, &source);
  588. name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength);
  589. // Validate that the type really can be a registered property
  590. // We cannot use CanBeInstanciated, as it is allowed to register
  591. // properties of type that cannot otherwise be instanciated
  592. if( type.GetFuncDef() && !type.IsObjectHandle() )
  593. {
  594. // Function definitions must always be handles
  595. return asINVALID_DECLARATION;
  596. }
  597. // Verify property name
  598. if( dt )
  599. {
  600. if( CheckNameConflictMember(dt->GetObjectType(), name.AddressOf(), nameNode, &source, true) < 0 )
  601. return asNAME_TAKEN;
  602. }
  603. else
  604. {
  605. if( CheckNameConflict(name.AddressOf(), nameNode, &source) < 0 )
  606. return asNAME_TAKEN;
  607. }
  608. if( numErrors > 0 )
  609. return asINVALID_DECLARATION;
  610. return asSUCCESS;
  611. }
  612. asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *prop)
  613. {
  614. asASSERT(obj.GetObjectType() != 0);
  615. // TODO: optimize: Improve linear search
  616. asCArray<asCObjectProperty *> &props = obj.GetObjectType()->properties;
  617. for( asUINT n = 0; n < props.GetLength(); n++ )
  618. {
  619. if( props[n]->name == prop )
  620. {
  621. if( module->accessMask & props[n]->accessMask )
  622. return props[n];
  623. else
  624. return 0;
  625. }
  626. }
  627. return 0;
  628. }
  629. asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, bool *isCompiled, bool *isPureConstant, asQWORD *constantValue, bool *isAppProp)
  630. {
  631. asUINT n;
  632. if( isCompiled ) *isCompiled = true;
  633. if( isPureConstant ) *isPureConstant = false;
  634. if( isAppProp ) *isAppProp = false;
  635. // TODO: optimize: Improve linear search
  636. // Check application registered properties
  637. asCArray<asCGlobalProperty *> *props = &(engine->registeredGlobalProps);
  638. for( n = 0; n < props->GetLength(); ++n )
  639. if( (*props)[n] && (*props)[n]->name == prop )
  640. {
  641. if( module )
  642. {
  643. // Determine if the module has access to the property
  644. if( module->accessMask & (*props)[n]->accessMask )
  645. {
  646. #ifdef AS_DEPRECATED
  647. // deprecated since 2011-10-04
  648. // Find the config group for the global property
  649. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar((*props)[n]->id);
  650. if( !group || group->HasModuleAccess(module->name.AddressOf()) )
  651. continue;
  652. #endif
  653. if( isAppProp ) *isAppProp = true;
  654. return (*props)[n];
  655. }
  656. }
  657. else
  658. {
  659. // We're not compiling a module right now, so it must be a registered global property
  660. if( isAppProp ) *isAppProp = true;
  661. return (*props)[n];
  662. }
  663. }
  664. // TODO: optimize: Improve linear search
  665. // Check properties being compiled now
  666. asCArray<sGlobalVariableDescription *> *gvars = &globVariables;
  667. for( n = 0; n < gvars->GetLength(); ++n )
  668. {
  669. if( (*gvars)[n] && (*gvars)[n]->name == prop )
  670. {
  671. if( isCompiled ) *isCompiled = (*gvars)[n]->isCompiled;
  672. if( isPureConstant ) *isPureConstant = (*gvars)[n]->isPureConstant;
  673. if( constantValue ) *constantValue = (*gvars)[n]->constantValue;
  674. return (*gvars)[n]->property;
  675. }
  676. }
  677. // TODO: optimize: Improve linear search
  678. // Check previously compiled global variables
  679. if( module )
  680. {
  681. props = &module->scriptGlobals;
  682. for( n = 0; n < props->GetLength(); ++n )
  683. if( (*props)[n]->name == prop )
  684. return (*props)[n];
  685. }
  686. return 0;
  687. }
  688. int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle)
  689. {
  690. // TODO: Can't we use GetParsedFunctionDetails to do most of what is done in this function?
  691. numErrors = 0;
  692. numWarnings = 0;
  693. preMessage.isSet = false;
  694. asCScriptCode source;
  695. source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);
  696. asCParser parser(this);
  697. int r = parser.ParseFunctionDefinition(&source);
  698. if( r < 0 )
  699. return asINVALID_DECLARATION;
  700. asCScriptNode *node = parser.GetScriptNode();
  701. // Find name
  702. asCScriptNode *n = node->firstChild->next->next;
  703. func->name.Assign(&source.code[n->tokenPos], n->tokenLength);
  704. // Initialize a script function object for registration
  705. bool autoHandle;
  706. // Scoped reference types are allowed to use handle when returned from application functions
  707. func->returnType = CreateDataTypeFromNode(node->firstChild, &source, true, objType);
  708. func->returnType = ModifyDataTypeFromNode(func->returnType, node->firstChild->next, &source, 0, &autoHandle);
  709. if( autoHandle && (!func->returnType.IsObjectHandle() || func->returnType.IsReference()) )
  710. return asINVALID_DECLARATION;
  711. if( returnAutoHandle ) *returnAutoHandle = autoHandle;
  712. // Reference types cannot be returned by value from system functions
  713. if( isSystemFunction &&
  714. (func->returnType.GetObjectType() &&
  715. (func->returnType.GetObjectType()->flags & asOBJ_REF)) &&
  716. !(func->returnType.IsReference() ||
  717. func->returnType.IsObjectHandle()) )
  718. return asINVALID_DECLARATION;
  719. // Count number of parameters
  720. int paramCount = 0;
  721. n = n->next->firstChild;
  722. while( n )
  723. {
  724. paramCount++;
  725. n = n->next->next;
  726. if( n && n->nodeType == snIdentifier )
  727. n = n->next;
  728. if( n && n->nodeType == snExpression )
  729. n = n->next;
  730. }
  731. // Preallocate memory
  732. func->parameterTypes.Allocate(paramCount, false);
  733. func->inOutFlags.Allocate(paramCount, false);
  734. func->defaultArgs.Allocate(paramCount, false);
  735. if( paramAutoHandles ) paramAutoHandles->Allocate(paramCount, false);
  736. n = node->firstChild->next->next->next->firstChild;
  737. while( n )
  738. {
  739. asETypeModifiers inOutFlags;
  740. asCDataType type = CreateDataTypeFromNode(n, &source, false, objType);
  741. type = ModifyDataTypeFromNode(type, n->next, &source, &inOutFlags, &autoHandle);
  742. // Reference types cannot be passed by value to system functions
  743. if( isSystemFunction &&
  744. (type.GetObjectType() &&
  745. (type.GetObjectType()->flags & asOBJ_REF)) &&
  746. !(type.IsReference() ||
  747. type.IsObjectHandle()) )
  748. return asINVALID_DECLARATION;
  749. // Store the parameter type
  750. func->parameterTypes.PushLast(type);
  751. func->inOutFlags.PushLast(inOutFlags);
  752. // Don't permit void parameters
  753. if( type.GetTokenType() == ttVoid )
  754. return asINVALID_DECLARATION;
  755. if( autoHandle && (!type.IsObjectHandle() || type.IsReference()) )
  756. return asINVALID_DECLARATION;
  757. if( paramAutoHandles ) paramAutoHandles->PushLast(autoHandle);
  758. // Make sure that var type parameters are references
  759. if( type.GetTokenType() == ttQuestion &&
  760. !type.IsReference() )
  761. return asINVALID_DECLARATION;
  762. // Move to next parameter
  763. n = n->next->next;
  764. if( n && n->nodeType == snIdentifier )
  765. n = n->next;
  766. if( n && n->nodeType == snExpression )
  767. {
  768. // Strip out white space and comments to better share the string
  769. asCString *defaultArgStr = asNEW(asCString);
  770. *defaultArgStr = GetCleanExpressionString(n, &source);
  771. func->defaultArgs.PushLast(defaultArgStr);
  772. n = n->next;
  773. }
  774. else
  775. func->defaultArgs.PushLast(0);
  776. }
  777. // Set the read-only flag if const is declared after parameter list
  778. if( node->lastChild->nodeType == snUndefined && node->lastChild->tokenType == ttConst )
  779. {
  780. if( objType == 0 )
  781. return asINVALID_DECLARATION;
  782. func->isReadOnly = true;
  783. }
  784. else
  785. func->isReadOnly = false;
  786. // Make sure the default args are declared correctly
  787. ValidateDefaultArgs(&source, node, func);
  788. if( numErrors > 0 || numWarnings > 0 )
  789. return asINVALID_DECLARATION;
  790. return 0;
  791. }
  792. int asCBuilder::ParseVariableDeclaration(const char *decl, asCObjectProperty *var)
  793. {
  794. numErrors = 0;
  795. numWarnings = 0;
  796. preMessage.isSet = false;
  797. asCScriptCode source;
  798. source.SetCode(TXT_VARIABLE_DECL, decl, true);
  799. asCParser parser(this);
  800. int r = parser.ParsePropertyDeclaration(&source);
  801. if( r < 0 )
  802. return asINVALID_DECLARATION;
  803. asCScriptNode *node = parser.GetScriptNode();
  804. // Find name
  805. asCScriptNode *n = node->firstChild->next;
  806. var->name.Assign(&source.code[n->tokenPos], n->tokenLength);
  807. // Initialize a script variable object for registration
  808. var->type = CreateDataTypeFromNode(node->firstChild, &source);
  809. if( numErrors > 0 || numWarnings > 0 )
  810. return asINVALID_DECLARATION;
  811. return 0;
  812. }
  813. int asCBuilder::CheckNameConflictMember(asCObjectType *t, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty)
  814. {
  815. // It's not necessary to check against object types
  816. // TODO: optimize: Improve linear search
  817. asCArray<asCObjectProperty *> &props = t->properties;
  818. for( asUINT n = 0; n < props.GetLength(); n++ )
  819. {
  820. if( props[n]->name == name )
  821. {
  822. if( code )
  823. {
  824. int r, c;
  825. code->ConvertPosToRowCol(node->tokenPos, &r, &c);
  826. asCString str;
  827. str.Format(TXT_NAME_CONFLICT_s_OBJ_PROPERTY, name);
  828. WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
  829. }
  830. return -1;
  831. }
  832. }
  833. // Property names must be checked against method names
  834. if( isProperty )
  835. {
  836. asCArray<int> methods = t->methods;
  837. for( asUINT n = 0; n < methods.GetLength(); n++ )
  838. {
  839. if( engine->scriptFunctions[methods[n]]->name == name )
  840. {
  841. if( code )
  842. {
  843. int r, c;
  844. code->ConvertPosToRowCol(node->tokenPos, &r, &c);
  845. asCString str;
  846. str.Format(TXT_NAME_CONFLICT_s_METHOD, name);
  847. WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
  848. }
  849. return -1;
  850. }
  851. }
  852. }
  853. return 0;
  854. }
  855. int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code)
  856. {
  857. // TODO: Must verify object types in all config groups, whether the module has access or not
  858. // Check against object types
  859. if( engine->GetObjectType(name) != 0 )
  860. {
  861. if( code )
  862. {
  863. int r, c;
  864. code->ConvertPosToRowCol(node->tokenPos, &r, &c);
  865. asCString str;
  866. str.Format(TXT_NAME_CONFLICT_s_EXTENDED_TYPE, name);
  867. WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
  868. }
  869. return -1;
  870. }
  871. // TODO: Must verify global properties in all config groups, whether the module has access or not
  872. // Check against global properties
  873. asCGlobalProperty *prop = GetGlobalProperty(name, 0, 0, 0, 0);
  874. if( prop )
  875. {
  876. if( code )
  877. {
  878. int r, c;
  879. code->ConvertPosToRowCol(node->tokenPos, &r, &c);
  880. asCString str;
  881. str.Format(TXT_NAME_CONFLICT_s_GLOBAL_PROPERTY, name);
  882. WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
  883. }
  884. return -1;
  885. }
  886. // TODO: Property names must be checked against function names
  887. // Check against class types
  888. asUINT n;
  889. for( n = 0; n < classDeclarations.GetLength(); n++ )
  890. {
  891. if( classDeclarations[n]->name == name )
  892. {
  893. if( code )
  894. {
  895. int r, c;
  896. code->ConvertPosToRowCol(node->tokenPos, &r, &c);
  897. asCString str;
  898. str.Format(TXT_NAME_CONFLICT_s_STRUCT, name);
  899. WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
  900. }
  901. return -1;
  902. }
  903. }
  904. // Check against named types
  905. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  906. {
  907. if( namedTypeDeclarations[n]->name == name )
  908. {
  909. if( code )
  910. {
  911. int r, c;
  912. code->ConvertPosToRowCol(node->tokenPos, &r, &c);
  913. asCString str;
  914. str.Format(TXT_NAME_CONFLICT_s_IS_NAMED_TYPE, name);
  915. WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
  916. }
  917. return -1;
  918. }
  919. }
  920. // Must check for name conflicts with funcdefs
  921. for( n = 0; n < funcDefs.GetLength(); n++ )
  922. {
  923. if( funcDefs[n]->name == name )
  924. {
  925. if( code )
  926. {
  927. int r, c;
  928. code->ConvertPosToRowCol(node->tokenPos, &r, &c);
  929. asCString str;
  930. str.Format(TXT_NAME_CONFLICT_s_IS_FUNCDEF, name);
  931. WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
  932. }
  933. return -1;
  934. }
  935. }
  936. return 0;
  937. }
  938. int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file)
  939. {
  940. // Find the name
  941. asASSERT( node->firstChild->nodeType == snDataType );
  942. asCScriptNode *n = node->firstChild->next->next;
  943. asCString name;
  944. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  945. // Check for name conflict with other types
  946. int r = CheckNameConflict(name.AddressOf(), node, file);
  947. if( asSUCCESS != r )
  948. {
  949. node->Destroy(engine);
  950. return r;
  951. }
  952. // The function definition should be stored as a asCScriptFunction so that the application
  953. // can use the asIScriptFunction interface to enumerate the return type and parameters
  954. // The return type and parameter types aren't determined in this function. A second pass is
  955. // necessary after all type declarations have been identified.
  956. sFuncDef *fd = asNEW(sFuncDef);
  957. fd->name = name;
  958. fd->node = node;
  959. fd->script = file;
  960. fd->idx = module->AddFuncDef(name.AddressOf());
  961. funcDefs.PushLast(fd);
  962. return 0;
  963. }
  964. void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
  965. {
  966. asCDataType returnType;
  967. asCArray<asCDataType> parameterTypes;
  968. asCArray<asETypeModifiers> inOutFlags;
  969. asCArray<asCString *> defaultArgs;
  970. bool isConstMethod;
  971. bool isConstructor;
  972. bool isDestructor;
  973. bool isPrivate;
  974. bool isOverride;
  975. bool isFinal;
  976. GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, returnType, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal);
  977. asCScriptFunction *func = module->funcDefs[funcDef->idx];
  978. if( func )
  979. {
  980. func->returnType = returnType;
  981. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  982. {
  983. func->parameterTypes.PushLast(parameterTypes[p]);
  984. func->inOutFlags.PushLast(inOutFlags[p]);
  985. // Don't copy the default arg expression as it is not allowed for function definitions
  986. }
  987. }
  988. }
  989. int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file)
  990. {
  991. // Has the application disabled global vars?
  992. if( engine->ep.disallowGlobalVars )
  993. {
  994. int r, c;
  995. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  996. WriteError(file->name.AddressOf(), TXT_GLOBAL_VARS_NOT_ALLOWED, r, c);
  997. }
  998. // What data type is it?
  999. asCDataType type = CreateDataTypeFromNode(node->firstChild, file);
  1000. if( !type.CanBeInstanciated() )
  1001. {
  1002. asCString str;
  1003. // TODO: Change to "'type' cannot be declared as variable"
  1004. str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format().AddressOf());
  1005. int r, c;
  1006. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1007. WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
  1008. }
  1009. asCScriptNode *n = node->firstChild->next;
  1010. while( n )
  1011. {
  1012. // Verify that the name isn't taken
  1013. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1014. CheckNameConflict(name.AddressOf(), n, file);
  1015. // Register the global variable
  1016. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  1017. globVariables.PushLast(gvar);
  1018. gvar->script = file;
  1019. gvar->name = name;
  1020. gvar->isCompiled = false;
  1021. gvar->datatype = type;
  1022. gvar->isEnumValue = false;
  1023. // TODO: Give error message if wrong
  1024. asASSERT(!gvar->datatype.IsReference());
  1025. gvar->idNode = n;
  1026. gvar->nextNode = 0;
  1027. if( n->next &&
  1028. (n->next->nodeType == snAssignment ||
  1029. n->next->nodeType == snArgList ||
  1030. n->next->nodeType == snInitList ) )
  1031. {
  1032. gvar->nextNode = n->next;
  1033. n->next->DisconnectParent();
  1034. }
  1035. gvar->property = module->AllocateGlobalProperty(name.AddressOf(), gvar->datatype);
  1036. gvar->index = gvar->property->id;
  1037. n = n->next;
  1038. }
  1039. node->Destroy(engine);
  1040. return 0;
  1041. }
  1042. int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file)
  1043. {
  1044. asCScriptNode *n = node->firstChild;
  1045. bool isFinal = false;
  1046. bool isShared = false;
  1047. if( n->tokenType == ttIdentifier && file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) )
  1048. {
  1049. isFinal = true;
  1050. n = n->next;
  1051. }
  1052. if( n->tokenType == ttIdentifier && file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN) )
  1053. {
  1054. isShared = true;
  1055. n = n->next;
  1056. // Check for final again
  1057. if( n->tokenType == ttIdentifier && file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) )
  1058. {
  1059. isFinal = true;
  1060. n = n->next;
  1061. }
  1062. }
  1063. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1064. int r, c;
  1065. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1066. CheckNameConflict(name.AddressOf(), n, file);
  1067. sClassDeclaration *decl = asNEW(sClassDeclaration);
  1068. classDeclarations.PushLast(decl);
  1069. decl->name = name;
  1070. decl->script = file;
  1071. decl->node = node;
  1072. // If this type is shared and there already exist another shared
  1073. // type of the same name, then that one should be used instead of
  1074. // creating a new one.
  1075. if( isShared )
  1076. {
  1077. for( asUINT n = 0; n < engine->classTypes.GetLength(); n++ )
  1078. {
  1079. asCObjectType *st = engine->classTypes[n];
  1080. if( st &&
  1081. st->IsShared() &&
  1082. st->name == name &&
  1083. !st->IsInterface() )
  1084. {
  1085. // We'll use the existing type
  1086. decl->isExistingShared = true;
  1087. decl->objType = st;
  1088. module->classTypes.PushLast(st);
  1089. st->AddRef();
  1090. return 0;
  1091. }
  1092. }
  1093. }
  1094. // Create a new object type for this class
  1095. asCObjectType *st = asNEW(asCObjectType)(engine);
  1096. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
  1097. if( isShared )
  1098. st->flags |= asOBJ_SHARED;
  1099. if( isFinal )
  1100. st->flags |= asOBJ_NOINHERIT;
  1101. if( node->tokenType == ttHandle )
  1102. st->flags |= asOBJ_IMPLICIT_HANDLE;
  1103. st->size = sizeof(asCScriptObject);
  1104. st->name = name;
  1105. module->classTypes.PushLast(st);
  1106. engine->classTypes.PushLast(st);
  1107. st->AddRef();
  1108. decl->objType = st;
  1109. // Add script classes to the GC
  1110. // TODO: optimize: Only add the class to the GC when the module won't use the type anymore
  1111. engine->gc.AddScriptObjectToGC(st, &engine->objectTypeBehaviours);
  1112. // Use the default script class behaviours
  1113. st->beh = engine->scriptTypeBehaviours.beh;
  1114. // TODO: Move this to asCObjectType so that the asCRestore can reuse it
  1115. engine->scriptFunctions[st->beh.addref]->AddRef();
  1116. engine->scriptFunctions[st->beh.release]->AddRef();
  1117. engine->scriptFunctions[st->beh.gcEnumReferences]->AddRef();
  1118. engine->scriptFunctions[st->beh.gcGetFlag]->AddRef();
  1119. engine->scriptFunctions[st->beh.gcGetRefCount]->AddRef();
  1120. engine->scriptFunctions[st->beh.gcReleaseAllReferences]->AddRef();
  1121. engine->scriptFunctions[st->beh.gcSetFlag]->AddRef();
  1122. engine->scriptFunctions[st->beh.copy]->AddRef();
  1123. engine->scriptFunctions[st->beh.factory]->AddRef();
  1124. engine->scriptFunctions[st->beh.construct]->AddRef();
  1125. for( asUINT i = 1; i < st->beh.operators.GetLength(); i += 2 )
  1126. engine->scriptFunctions[st->beh.operators[i]]->AddRef();
  1127. return 0;
  1128. }
  1129. int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file)
  1130. {
  1131. asCScriptNode *n = node->firstChild;
  1132. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1133. bool isShared = false;
  1134. if( name == SHARED_TOKEN )
  1135. {
  1136. isShared = true;
  1137. n = n->next;
  1138. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  1139. }
  1140. int r, c;
  1141. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1142. CheckNameConflict(name.AddressOf(), n, file);
  1143. sClassDeclaration *decl = asNEW(sClassDeclaration);
  1144. interfaceDeclarations.PushLast(decl);
  1145. decl->name = name;
  1146. decl->script = file;
  1147. decl->node = node;
  1148. // If this type is shared and there already exist another shared
  1149. // type of the same name, then that one should be used instead of
  1150. // creating a new one.
  1151. if( isShared )
  1152. {
  1153. for( asUINT n = 0; n < engine->classTypes.GetLength(); n++ )
  1154. {
  1155. asCObjectType *st = engine->classTypes[n];
  1156. if( st &&
  1157. st->IsShared() &&
  1158. st->name == name &&
  1159. st->IsInterface() )
  1160. {
  1161. // We'll use the existing type
  1162. decl->isExistingShared = true;
  1163. decl->objType = st;
  1164. module->classTypes.PushLast(st);
  1165. st->AddRef();
  1166. return 0;
  1167. }
  1168. }
  1169. }
  1170. // Register the object type for the interface
  1171. asCObjectType *st = asNEW(asCObjectType)(engine);
  1172. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
  1173. if( isShared )
  1174. st->flags |= asOBJ_SHARED;
  1175. st->size = 0; // Cannot be instanciated
  1176. st->name = name;
  1177. module->classTypes.PushLast(st);
  1178. engine->classTypes.PushLast(st);
  1179. st->AddRef();
  1180. decl->objType = st;
  1181. // Use the default script class behaviours
  1182. st->beh.construct = 0;
  1183. st->beh.addref = engine->scriptTypeBehaviours.beh.addref;
  1184. engine->scriptFunctions[st->beh.addref]->AddRef();
  1185. st->beh.release = engine->scriptTypeBehaviours.beh.release;
  1186. engine->scriptFunctions[st->beh.release]->AddRef();
  1187. st->beh.copy = 0;
  1188. return 0;
  1189. }
  1190. void asCBuilder::CompileGlobalVariables()
  1191. {
  1192. bool compileSucceeded = true;
  1193. // Store state of compilation (errors, warning, output)
  1194. int currNumErrors = numErrors;
  1195. int currNumWarnings = numWarnings;
  1196. // Backup the original message stream
  1197. bool msgCallback = engine->msgCallback;
  1198. asSSystemFunctionInterface msgCallbackFunc = engine->msgCallbackFunc;
  1199. void *msgCallbackObj = engine->msgCallbackObj;
  1200. // Set the new temporary message stream
  1201. asCOutputBuffer outBuffer;
  1202. engine->SetMessageCallback(asMETHOD(asCOutputBuffer, Callback), &outBuffer, asCALL_THISCALL);
  1203. asCOutputBuffer finalOutput;
  1204. asCScriptFunction *initFunc = 0;
  1205. asCArray<asCGlobalProperty*> initOrder;
  1206. // We first try to compile all the primitive global variables, and only after that
  1207. // compile the non-primitive global variables. This permits the constructors
  1208. // for the complex types to use the already initialized variables of primitive
  1209. // type. Note, we currently don't know which global variables are used in the
  1210. // constructors, so we cannot guarantee that variables of complex types are
  1211. // initialized in the correct order, so we won't reorder those.
  1212. bool compilingPrimitives = true;
  1213. // Compile each global variable
  1214. while( compileSucceeded )
  1215. {
  1216. compileSucceeded = false;
  1217. int accumErrors = 0;
  1218. int accumWarnings = 0;
  1219. // Restore state of compilation
  1220. finalOutput.Clear();
  1221. for( asUINT n = 0; n < globVariables.GetLength(); n++ )
  1222. {
  1223. sGlobalVariableDescription *gvar = globVariables[n];
  1224. if( gvar->isCompiled )
  1225. continue;
  1226. asCByteCode init(engine);
  1227. numWarnings = 0;
  1228. numErrors = 0;
  1229. outBuffer.Clear();
  1230. // Skip this for now if we're not compiling complex types yet
  1231. if( compilingPrimitives && !gvar->datatype.IsPrimitive() )
  1232. continue;
  1233. if( gvar->nextNode )
  1234. {
  1235. int r, c;
  1236. gvar->script->ConvertPosToRowCol(gvar->nextNode->tokenPos, &r, &c);
  1237. asCString str = gvar->datatype.Format();
  1238. str += " " + gvar->name;
  1239. str.Format(TXT_COMPILING_s, str.AddressOf());
  1240. WriteInfo(gvar->script->name.AddressOf(), str.AddressOf(), r, c, true);
  1241. }
  1242. if( gvar->isEnumValue )
  1243. {
  1244. int r;
  1245. if( gvar->nextNode )
  1246. {
  1247. asCCompiler comp(engine);
  1248. asCScriptFunction func(engine, module, asFUNC_DUMMY);
  1249. // Temporarily switch the type of the variable to int so it can be compiled properly
  1250. asCDataType saveType;
  1251. saveType = gvar->datatype;
  1252. gvar->datatype = asCDataType::CreatePrimitive(ttInt, true);
  1253. r = comp.CompileGlobalVariable(this, gvar->script, gvar->nextNode, gvar, &func);
  1254. gvar->datatype = saveType;
  1255. }
  1256. else
  1257. {
  1258. r = 0;
  1259. // When there is no assignment the value is the last + 1
  1260. int enumVal = 0;
  1261. if( n > 0 )
  1262. {
  1263. sGlobalVariableDescription *gvar2 = globVariables[n-1];
  1264. if( gvar2->datatype == gvar->datatype )
  1265. {
  1266. // The integer value is stored in the lower bytes
  1267. enumVal = (*(int*)&gvar2->constantValue) + 1;
  1268. if( !gvar2->isCompiled )
  1269. {
  1270. // TODO: Need to get the correct script position
  1271. int row, col;
  1272. gvar->script->ConvertPosToRowCol(0, &row, &col);
  1273. asCString str = gvar->datatype.Format();
  1274. str += " " + gvar->name;
  1275. str.Format(TXT_COMPILING_s, str.AddressOf());
  1276. WriteInfo(gvar->script->name.AddressOf(), str.AddressOf(), row, col, true);
  1277. str.Format(TXT_UNINITIALIZED_GLOBAL_VAR_s, gvar2->name.AddressOf());
  1278. WriteError(gvar->script->name.AddressOf(), str.AddressOf(), row, col);
  1279. r = -1;
  1280. }
  1281. }
  1282. }
  1283. // The integer value is stored in the lower bytes
  1284. *(int*)&gvar->constantValue = enumVal;
  1285. }
  1286. if( r >= 0 )
  1287. {
  1288. // Set the value as compiled
  1289. gvar->isCompiled = true;
  1290. compileSucceeded = true;
  1291. }
  1292. }
  1293. else
  1294. {
  1295. // Compile the global variable
  1296. initFunc = asNEW(asCScriptFunction)(engine, module, asFUNC_DUMMY);
  1297. asCCompiler comp(engine);
  1298. int r = comp.CompileGlobalVariable(this, gvar->script, gvar->nextNode, gvar, initFunc);
  1299. if( r >= 0 )
  1300. {
  1301. // Compilation succeeded
  1302. gvar->isCompiled = true;
  1303. compileSucceeded = true;
  1304. }
  1305. else
  1306. {
  1307. // Compilation failed
  1308. asDELETE(initFunc, asCScriptFunction);
  1309. initFunc = 0;
  1310. }
  1311. }
  1312. if( gvar->isCompiled )
  1313. {
  1314. // Add warnings for this constant to the total build
  1315. if( numWarnings )
  1316. {
  1317. currNumWarnings += numWarnings;
  1318. if( msgCallback )
  1319. outBuffer.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  1320. }
  1321. // Determine order of variable initializations
  1322. if( gvar->property && !gvar->isEnumValue )
  1323. initOrder.PushLast(gvar->property);
  1324. // Does the function contain more than just a SUSPEND followed by a RET instruction?
  1325. if( initFunc && initFunc->byteCode.GetLength() > 2 )
  1326. {
  1327. // Create the init function for this variable
  1328. initFunc->id = engine->GetNextScriptFunctionId();
  1329. engine->SetScriptFunction(initFunc);
  1330. // Finalize the init function for this variable
  1331. initFunc->funcType = asFUNC_SCRIPT;
  1332. initFunc->returnType = asCDataType::CreatePrimitive(ttVoid, false);
  1333. initFunc->scriptSectionIdx = engine->GetScriptSectionNameIndex(gvar->script->name.AddressOf());
  1334. // Notify the GC of the new script function
  1335. engine->gc.AddScriptObjectToGC(initFunc, &engine->functionBehaviours);
  1336. gvar->property->SetInitFunc(initFunc);
  1337. initFunc->Release();
  1338. initFunc = 0;
  1339. }
  1340. else if( initFunc )
  1341. {
  1342. // Destroy the function as it won't be used
  1343. asDELETE(initFunc, asCScriptFunction);
  1344. initFunc = 0;
  1345. }
  1346. // Convert enums to true enum values, so subsequent compilations can access it as an enum
  1347. if( gvar->isEnumValue )
  1348. {
  1349. asCObjectType *objectType = gvar->datatype.GetObjectType();
  1350. asASSERT(NULL != objectType);
  1351. asSEnumValue *e = asNEW(asSEnumValue);
  1352. e->name = gvar->name;
  1353. e->value = *(int*)&gvar->constantValue;
  1354. objectType->enumValues.PushLast(e);
  1355. }
  1356. }
  1357. else
  1358. {
  1359. // Add output to final output
  1360. finalOutput.Append(outBuffer);
  1361. accumErrors += numErrors;
  1362. accumWarnings += numWarnings;
  1363. }
  1364. preMessage.isSet = false;
  1365. }
  1366. if( !compileSucceeded )
  1367. {
  1368. if( compilingPrimitives )
  1369. {
  1370. // No more primitives could be compiled, so
  1371. // switch to compiling the complex variables
  1372. compilingPrimitives = false;
  1373. compileSucceeded = true;
  1374. }
  1375. else
  1376. {
  1377. // No more variables can be compiled
  1378. // Add errors and warnings to total build
  1379. currNumWarnings += accumWarnings;
  1380. currNumErrors += accumErrors;
  1381. if( msgCallback )
  1382. finalOutput.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  1383. }
  1384. }
  1385. }
  1386. // Restore states
  1387. engine->msgCallback = msgCallback;
  1388. engine->msgCallbackFunc = msgCallbackFunc;
  1389. engine->msgCallbackObj = msgCallbackObj;
  1390. numWarnings = currNumWarnings;
  1391. numErrors = currNumErrors;
  1392. // Set the correct order of initialization
  1393. if( numErrors == 0 )
  1394. {
  1395. // If the length of the arrays are not the same, then this is the compilation
  1396. // of a single variable, in which case the initialization order of the previous
  1397. // variables must be preserved.
  1398. if( module->scriptGlobals.GetLength() == initOrder.GetLength() )
  1399. module->scriptGlobals = initOrder;
  1400. }
  1401. // Delete the enum expressions
  1402. for( asUINT n = 0; n < globVariables.GetLength(); n++ )
  1403. {
  1404. sGlobalVariableDescription *gvar = globVariables[n];
  1405. if( gvar->isEnumValue )
  1406. {
  1407. // Destroy the gvar property
  1408. if( gvar->nextNode )
  1409. {
  1410. gvar->nextNode->Destroy(engine);
  1411. gvar->nextNode = 0;
  1412. }
  1413. if( gvar->property )
  1414. {
  1415. asDELETE(gvar->property, asCGlobalProperty);
  1416. gvar->property = 0;
  1417. }
  1418. asDELETE(gvar, sGlobalVariableDescription);
  1419. globVariables[n] = 0;
  1420. }
  1421. }
  1422. }
  1423. void asCBuilder::CompileClasses()
  1424. {
  1425. asUINT n;
  1426. asCArray<sClassDeclaration*> toValidate((int)classDeclarations.GetLength());
  1427. // Determine class inheritances and interfaces
  1428. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1429. {
  1430. sClassDeclaration *decl = classDeclarations[n];
  1431. asCScriptCode *file = decl->script;
  1432. // Find the base class that this class inherits from
  1433. bool multipleInheritance = false;
  1434. asCScriptNode *node = decl->node->firstChild;
  1435. if( decl->objType->IsShared() )
  1436. {
  1437. // Skip the keyword 'shared'
  1438. asASSERT(node->tokenType == ttIdentifier);
  1439. node = node->next;
  1440. }
  1441. if( decl->objType->flags & asOBJ_NOINHERIT )
  1442. {
  1443. // skip the keyword 'final'
  1444. asASSERT(node->tokenType == ttIdentifier);
  1445. node = node->next;
  1446. }
  1447. // Skip the name of the class
  1448. asASSERT(node->tokenType == ttIdentifier);
  1449. node = node->next;
  1450. while( node && node->nodeType == snIdentifier )
  1451. {
  1452. // Get the interface name from the node
  1453. asCString name(&file->code[node->tokenPos], node->tokenLength);
  1454. // Find the object type for the interface
  1455. asCObjectType *objType = GetObjectType(name.AddressOf());
  1456. if( objType == 0 )
  1457. {
  1458. int r, c;
  1459. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1460. asCString str;
  1461. str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE, name.AddressOf());
  1462. WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
  1463. }
  1464. else if( !(objType->flags & asOBJ_SCRIPT_OBJECT) ||
  1465. objType->flags & asOBJ_NOINHERIT )
  1466. {
  1467. // Either the class is not a script class or interface
  1468. // or the class has been declared as 'final'
  1469. int r, c;
  1470. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1471. asCString str;
  1472. str.Format(TXT_CANNOT_INHERIT_FROM_s_FINAL, objType->name.AddressOf());
  1473. WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
  1474. }
  1475. else if( objType->size != 0 )
  1476. {
  1477. // The class inherits from another script class
  1478. if( !decl->isExistingShared && decl->objType->derivedFrom != 0 )
  1479. {
  1480. if( !multipleInheritance )
  1481. {
  1482. int r, c;
  1483. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1484. WriteError(file->name.AddressOf(), TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES, r, c);
  1485. multipleInheritance = true;
  1486. }
  1487. }
  1488. else
  1489. {
  1490. // Make sure none of the base classes inherit from this one
  1491. asCObjectType *base = objType;
  1492. bool error = false;
  1493. while( base != 0 )
  1494. {
  1495. if( base == decl->objType )
  1496. {
  1497. int r, c;
  1498. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1499. WriteError(file->name.AddressOf(), TXT_CANNOT_INHERIT_FROM_SELF, r, c);
  1500. error = true;
  1501. break;
  1502. }
  1503. base = base->derivedFrom;
  1504. }
  1505. if( !error )
  1506. {
  1507. // A shared type may only inherit from other shared types
  1508. if( (decl->objType->IsShared()) && !(objType->IsShared()) )
  1509. {
  1510. int r, c;
  1511. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1512. asCString msg;
  1513. msg.Format(TXT_SHARED_CANNOT_INHERIT_FROM_NON_SHARED_s, objType->name.AddressOf());
  1514. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  1515. error = true;
  1516. }
  1517. }
  1518. if( !error )
  1519. {
  1520. if( decl->isExistingShared )
  1521. {
  1522. // Verify that the base class is the same as the original shared type
  1523. if( decl->objType->derivedFrom != objType )
  1524. {
  1525. int r, c;
  1526. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1527. WriteError(file->name.AddressOf(), TXT_SHARED_DOESNT_MATCH_ORIGINAL, r, c);
  1528. }
  1529. }
  1530. else
  1531. {
  1532. // Set the base class
  1533. decl->objType->derivedFrom = objType;
  1534. objType->AddRef();
  1535. }
  1536. }
  1537. }
  1538. }
  1539. else
  1540. {
  1541. // The class implements an interface
  1542. if( !decl->isExistingShared && decl->objType->Implements(objType) )
  1543. {
  1544. int r, c;
  1545. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1546. asCString msg;
  1547. msg.Format(TXT_INTERFACE_s_ALREADY_IMPLEMENTED, objType->GetName());
  1548. WriteWarning(file->name.AddressOf(), msg.AddressOf(), r, c);
  1549. }
  1550. else
  1551. {
  1552. // A shared type may only implement from shared interfaces
  1553. if( (decl->objType->IsShared()) && !(objType->IsShared()) )
  1554. {
  1555. int r, c;
  1556. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1557. asCString msg;
  1558. msg.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, objType->name.AddressOf());
  1559. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  1560. }
  1561. else
  1562. {
  1563. if( decl->isExistingShared )
  1564. {
  1565. // Verify that the original implements the same interface
  1566. if( !decl->objType->Implements(objType) )
  1567. {
  1568. int r, c;
  1569. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1570. WriteError(file->name.AddressOf(), TXT_SHARED_DOESNT_MATCH_ORIGINAL, r, c);
  1571. }
  1572. }
  1573. else
  1574. {
  1575. decl->objType->interfaces.PushLast(objType);
  1576. }
  1577. }
  1578. }
  1579. }
  1580. node = node->next;
  1581. }
  1582. }
  1583. // Order class declarations so that base classes are compiled before derived classes.
  1584. // This will allow the derived classes to copy properties and methods in the next step.
  1585. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1586. {
  1587. sClassDeclaration *decl = classDeclarations[n];
  1588. asCObjectType *derived = decl->objType;
  1589. asCObjectType *base = derived->derivedFrom;
  1590. if( base == 0 ) continue;
  1591. // If the base class is found after the derived class, then move the derived class to the end of the list
  1592. for( asUINT m = n+1; m < classDeclarations.GetLength(); m++ )
  1593. {
  1594. sClassDeclaration *declBase = classDeclarations[m];
  1595. if( base == declBase->objType )
  1596. {
  1597. classDeclarations.RemoveIndex(n);
  1598. classDeclarations.PushLast(decl);
  1599. // Decrease index so that we don't skip an entry
  1600. n--;
  1601. break;
  1602. }
  1603. }
  1604. }
  1605. // Go through each of the classes and register the object type descriptions
  1606. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1607. {
  1608. sClassDeclaration *decl = classDeclarations[n];
  1609. if( decl->isExistingShared )
  1610. {
  1611. // TODO: shared: Should really validate against original
  1612. continue;
  1613. }
  1614. // Add all properties and methods from the base class
  1615. if( decl->objType->derivedFrom )
  1616. {
  1617. asCObjectType *baseType = decl->objType->derivedFrom;
  1618. // The derived class inherits all interfaces from the base class
  1619. for( unsigned int n = 0; n < baseType->interfaces.GetLength(); n++ )
  1620. {
  1621. if( !decl->objType->Implements(baseType->interfaces[n]) )
  1622. {
  1623. decl->objType->interfaces.PushLast(baseType->interfaces[n]);
  1624. }
  1625. else
  1626. {
  1627. // Warn if derived class already implements the interface
  1628. int r, c;
  1629. decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
  1630. asCString msg;
  1631. msg.Format(TXT_INTERFACE_s_ALREADY_IMPLEMENTED, baseType->interfaces[n]->GetName());
  1632. WriteWarning(decl->script->name.AddressOf(), msg.AddressOf(), r, c);
  1633. }
  1634. }
  1635. // TODO: Need to check for name conflict with new class methods
  1636. // Copy properties from base class to derived class
  1637. for( asUINT p = 0; p < baseType->properties.GetLength(); p++ )
  1638. {
  1639. asCObjectProperty *prop = AddPropertyToClass(decl, baseType->properties[p]->name, baseType->properties[p]->type, baseType->properties[p]->isPrivate);
  1640. // The properties must maintain the same offset
  1641. asASSERT(prop && prop->byteOffset == baseType->properties[p]->byteOffset); UNUSED_VAR(prop);
  1642. }
  1643. // Copy methods from base class to derived class
  1644. for( asUINT m = 0; m < baseType->methods.GetLength(); m++ )
  1645. {
  1646. // If the derived class implements the same method, then don't add the base class' method
  1647. asCScriptFunction *baseFunc = GetFunctionDescription(baseType->methods[m]);
  1648. asCScriptFunction *derivedFunc = 0;
  1649. bool found = false;
  1650. for( asUINT d = 0; d < decl->objType->methods.GetLength(); d++ )
  1651. {
  1652. derivedFunc = GetFunctionDescription(decl->objType->methods[d]);
  1653. if( derivedFunc->IsSignatureEqual(baseFunc) )
  1654. {
  1655. if( baseFunc->IsFinal() )
  1656. {
  1657. int r, c;
  1658. decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
  1659. asCString msg;
  1660. msg.Format(TXT_METHOD_CANNOT_OVERRIDE_s, baseFunc->GetDeclaration());
  1661. WriteError(decl->script->name.AddressOf(), msg.AddressOf(), r, c);
  1662. }
  1663. // Move the function from the methods array to the virtualFunctionTable
  1664. decl->objType->methods.RemoveIndex(d);
  1665. decl->objType->virtualFunctionTable.PushLast(derivedFunc);
  1666. found = true;
  1667. break;
  1668. }
  1669. }
  1670. if( !found )
  1671. {
  1672. // Push the base class function on the virtual function table
  1673. decl->objType->virtualFunctionTable.PushLast(baseType->virtualFunctionTable[m]);
  1674. baseType->virtualFunctionTable[m]->AddRef();
  1675. }
  1676. decl->objType->methods.PushLast(baseType->methods[m]);
  1677. engine->scriptFunctions[baseType->methods[m]]->AddRef();
  1678. }
  1679. }
  1680. // Move this class' methods into the virtual function table
  1681. for( asUINT m = 0; m < decl->objType->methods.GetLength(); m++ )
  1682. {
  1683. asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[m]);
  1684. if( func->funcType != asFUNC_VIRTUAL )
  1685. {
  1686. // Move the reference from the method list to the virtual function list
  1687. decl->objType->methods.RemoveIndex(m);
  1688. decl->objType->virtualFunctionTable.PushLast(func);
  1689. // Substitute the function description in the method list for a virtual method
  1690. // Make sure the methods are in the same order as the virtual function table
  1691. decl->objType->methods.PushLast(CreateVirtualFunction(func, (int)decl->objType->virtualFunctionTable.GetLength() - 1));
  1692. m--;
  1693. }
  1694. }
  1695. // Enumerate each of the declared properties
  1696. asCScriptNode *node = decl->node->firstChild->next;
  1697. if( decl->objType->IsShared() )
  1698. node = node->next;
  1699. if( decl->objType->flags & asOBJ_NOINHERIT )
  1700. node = node->next;
  1701. // Skip list of classes and interfaces
  1702. while( node && node->nodeType == snIdentifier )
  1703. node = node->next;
  1704. while( node )
  1705. {
  1706. if( node->nodeType == snDeclaration )
  1707. {
  1708. bool isPrivate = false;
  1709. if( node->firstChild && node->firstChild->tokenType == ttPrivate )
  1710. isPrivate = true;
  1711. asCScriptCode *file = decl->script;
  1712. asCDataType dt = CreateDataTypeFromNode(isPrivate ? node->firstChild->next : node->firstChild, file);
  1713. asCString name(&file->code[node->lastChild->tokenPos], node->lastChild->tokenLength);
  1714. if( decl->objType->IsShared() && dt.GetObjectType() && !dt.GetObjectType()->IsShared() )
  1715. {
  1716. int r, c;
  1717. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1718. asCString msg;
  1719. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf());
  1720. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  1721. }
  1722. if( dt.IsReadOnly() )
  1723. {
  1724. int r, c;
  1725. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1726. WriteError(file->name.AddressOf(), TXT_PROPERTY_CANT_BE_CONST, r, c);
  1727. }
  1728. CheckNameConflictMember(decl->objType, name.AddressOf(), node->lastChild, file, true);
  1729. AddPropertyToClass(decl, name, dt, isPrivate, file, node);
  1730. }
  1731. else
  1732. asASSERT(false);
  1733. node = node->next;
  1734. }
  1735. toValidate.PushLast(decl);
  1736. }
  1737. // TODO: Warn if a method overrides a base method without marking it as 'override'.
  1738. // It must be possible to turn off this warning through engine property.
  1739. // TODO: A base class should be able to mark a method as 'abstract'. This will
  1740. // allow a base class to provide a partial implementation, but still force
  1741. // derived classes to implement specific methods.
  1742. // Verify that all interface methods are implemented in the classes
  1743. // We do this here so the base class' methods have already been inherited
  1744. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1745. {
  1746. sClassDeclaration *decl = classDeclarations[n];
  1747. if( decl->isExistingShared ) continue;
  1748. asCArray<bool> overrideValidations(decl->objType->GetMethodCount());
  1749. for( asUINT k = 0; k < decl->objType->methods.GetLength(); k++ )
  1750. {
  1751. overrideValidations.PushLast( !static_cast<asCScriptFunction*>(decl->objType->GetMethodByIndex(k, false))->IsOverride() );
  1752. }
  1753. for( asUINT m = 0; m < decl->objType->interfaces.GetLength(); m++ )
  1754. {
  1755. asCObjectType *objType = decl->objType->interfaces[m];
  1756. for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
  1757. {
  1758. asUINT overrideIndex;
  1759. if( !DoesMethodExist(decl->objType, objType->methods[i], &overrideIndex) )
  1760. {
  1761. int r, c;
  1762. decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
  1763. asCString str;
  1764. str.Format(TXT_MISSING_IMPLEMENTATION_OF_s,
  1765. engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
  1766. WriteError(decl->script->name.AddressOf(), str.AddressOf(), r, c);
  1767. }
  1768. else
  1769. overrideValidations[overrideIndex] = true;
  1770. }
  1771. }
  1772. bool hasBaseClass = decl->objType->derivedFrom != 0;
  1773. for( asUINT j = 0; j < overrideValidations.GetLength(); j++ )
  1774. {
  1775. if( !overrideValidations[j] && (!hasBaseClass || !DoesMethodExist(decl->objType->derivedFrom, decl->objType->methods[j])) )
  1776. {
  1777. int r, c;
  1778. decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
  1779. asCString msg;
  1780. msg.Format(TXT_METHOD_s_DOES_NOT_OVERRIDE, decl->objType->GetMethodByIndex(j, false)->GetDeclaration());
  1781. WriteError(decl->script->name.AddressOf(), msg.AddressOf(), r, c);
  1782. }
  1783. }
  1784. }
  1785. // Verify that the declared structures are valid, e.g. that the structure
  1786. // doesn't contain a member of its own type directly or indirectly
  1787. while( toValidate.GetLength() > 0 )
  1788. {
  1789. asUINT numClasses = (asUINT)toValidate.GetLength();
  1790. asCArray<sClassDeclaration*> toValidateNext((int)toValidate.GetLength());
  1791. while( toValidate.GetLength() > 0 )
  1792. {
  1793. sClassDeclaration *decl = toValidate[toValidate.GetLength()-1];
  1794. int validState = 1;
  1795. for( asUINT n = 0; n < decl->objType->properties.GetLength(); n++ )
  1796. {
  1797. // A valid structure is one that uses only primitives or other valid objects
  1798. asCObjectProperty *prop = decl->objType->properties[n];
  1799. asCDataType dt = prop->type;
  1800. if( dt.IsTemplate() )
  1801. {
  1802. asCDataType sub = dt;
  1803. while( sub.IsTemplate() && !sub.IsObjectHandle() )
  1804. sub = sub.GetSubType();
  1805. dt = sub;
  1806. }
  1807. if( dt.IsObject() && !dt.IsObjectHandle() )
  1808. {
  1809. // Find the class declaration
  1810. sClassDeclaration *pdecl = 0;
  1811. for( asUINT p = 0; p < classDeclarations.GetLength(); p++ )
  1812. {
  1813. if( classDeclarations[p]->objType == dt.GetObjectType() )
  1814. {
  1815. pdecl = classDeclarations[p];
  1816. break;
  1817. }
  1818. }
  1819. if( pdecl )
  1820. {
  1821. if( pdecl->objType == decl->objType )
  1822. {
  1823. int r, c;
  1824. decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
  1825. WriteError(decl->script->name.AddressOf(), TXT_ILLEGAL_MEMBER_TYPE, r, c);
  1826. validState = 2;
  1827. break;
  1828. }
  1829. else if( pdecl->validState != 1 )
  1830. {
  1831. validState = pdecl->validState;
  1832. break;
  1833. }
  1834. }
  1835. }
  1836. }
  1837. if( validState == 1 )
  1838. {
  1839. decl->validState = 1;
  1840. toValidate.PopLast();
  1841. }
  1842. else if( validState == 2 )
  1843. {
  1844. decl->validState = 2;
  1845. toValidate.PopLast();
  1846. }
  1847. else
  1848. {
  1849. toValidateNext.PushLast(toValidate.PopLast());
  1850. }
  1851. }
  1852. toValidate = toValidateNext;
  1853. toValidateNext.SetLength(0);
  1854. if( numClasses == toValidate.GetLength() )
  1855. {
  1856. int r, c;
  1857. toValidate[0]->script->ConvertPosToRowCol(toValidate[0]->node->tokenPos, &r, &c);
  1858. WriteError(toValidate[0]->script->name.AddressOf(), TXT_ILLEGAL_MEMBER_TYPE, r, c);
  1859. break;
  1860. }
  1861. }
  1862. if( numErrors > 0 ) return;
  1863. // Urho3D: disable garbage collection from script classes
  1864. /*
  1865. // Verify potential circular references
  1866. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1867. {
  1868. sClassDeclaration *decl = classDeclarations[n];
  1869. if( decl->isExistingShared ) continue;
  1870. asCObjectType *ot = decl->objType;
  1871. // Is there some path in which this structure is involved in circular references?
  1872. for( asUINT p = 0; p < ot->properties.GetLength(); p++ )
  1873. {
  1874. asCDataType dt = ot->properties[p]->type;
  1875. if( dt.IsObject() )
  1876. {
  1877. if( dt.IsObjectHandle() )
  1878. {
  1879. // TODO: optimize: If it is known that the handle can't be involved in a circular reference
  1880. // then this object doesn't need to be marked as garbage collected.
  1881. // - The application could set a flag when registering the object.
  1882. // - The script classes can be marked as final, then the compiler will
  1883. // be able to determine whether the class is garbage collected or not.
  1884. ot->flags |= asOBJ_GC;
  1885. break;
  1886. }
  1887. else if( dt.GetObjectType()->flags & asOBJ_GC )
  1888. {
  1889. // TODO: optimize: Just because the member type is a potential circle doesn't mean that this one is
  1890. // Only if the object is of a type that can reference this type, either directly or indirectly
  1891. ot->flags |= asOBJ_GC;
  1892. break;
  1893. }
  1894. }
  1895. }
  1896. }
  1897. */
  1898. }
  1899. int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
  1900. {
  1901. asCScriptFunction *vf = asNEW(asCScriptFunction)(engine, module, asFUNC_VIRTUAL);
  1902. vf->funcType = asFUNC_VIRTUAL;
  1903. vf->name = func->name;
  1904. vf->returnType = func->returnType;
  1905. vf->parameterTypes = func->parameterTypes;
  1906. vf->inOutFlags = func->inOutFlags;
  1907. vf->id = engine->GetNextScriptFunctionId();
  1908. vf->scriptSectionIdx = func->scriptSectionIdx;
  1909. vf->isReadOnly = func->isReadOnly;
  1910. vf->objectType = func->objectType;
  1911. vf->signatureId = func->signatureId;
  1912. vf->isPrivate = func->isPrivate;
  1913. vf->isFinal = func->isFinal;
  1914. vf->isOverride = func->isOverride;
  1915. vf->vfTableIdx = idx;
  1916. vf->defaultArgs = func->defaultArgs;
  1917. // Copy the default arg strings to avoid multiple deletes on the same object
  1918. for( asUINT n = 0; n < vf->defaultArgs.GetLength(); n++ )
  1919. if( vf->defaultArgs[n] )
  1920. vf->defaultArgs[n] = asNEW(asCString)(*vf->defaultArgs[n]);
  1921. module->AddScriptFunction(vf);
  1922. // Add a dummy to the builder so that it doesn't mix up function ids
  1923. functions.PushLast(0);
  1924. return vf->id;
  1925. }
  1926. asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const asCString &name, const asCDataType &dt, bool isPrivate, asCScriptCode *file, asCScriptNode *node)
  1927. {
  1928. if( !dt.CanBeInstanciated() )
  1929. {
  1930. if( file && node )
  1931. {
  1932. int r, c;
  1933. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  1934. asCString str;
  1935. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
  1936. WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
  1937. }
  1938. return 0;
  1939. }
  1940. return decl->objType->AddPropertyToClass(name, dt, isPrivate);
  1941. }
  1942. bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex)
  1943. {
  1944. asCScriptFunction *method = GetFunctionDescription(methodId);
  1945. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  1946. {
  1947. asCScriptFunction *m = GetFunctionDescription(objType->methods[n]);
  1948. if( m->name != method->name ) continue;
  1949. if( m->returnType != method->returnType ) continue;
  1950. if( m->isReadOnly != method->isReadOnly ) continue;
  1951. if( m->parameterTypes != method->parameterTypes ) continue;
  1952. if( m->inOutFlags != method->inOutFlags ) continue;
  1953. if( methodIndex )
  1954. *methodIndex = n;
  1955. return true;
  1956. }
  1957. return false;
  1958. }
  1959. void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file)
  1960. {
  1961. int funcId = engine->GetNextScriptFunctionId();
  1962. asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false);
  1963. asCArray<asCDataType> parameterTypes;
  1964. asCArray<asETypeModifiers> inOutFlags;
  1965. asCArray<asCString *> defaultArgs;
  1966. // Add the script function
  1967. module->AddScriptFunction(file->idx, funcId, objType->name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), false, objType);
  1968. // Set it as default constructor
  1969. if( objType->beh.construct )
  1970. engine->scriptFunctions[objType->beh.construct]->Release();
  1971. objType->beh.construct = funcId;
  1972. objType->beh.constructors[0] = funcId;
  1973. engine->scriptFunctions[funcId]->AddRef();
  1974. // The bytecode for the default constructor will be generated
  1975. // only after the potential inheritance has been established
  1976. sFunctionDescription *func = asNEW(sFunctionDescription);
  1977. functions.PushLast(func);
  1978. func->script = file;
  1979. func->node = 0;
  1980. func->name = objType->name;
  1981. func->objType = objType;
  1982. func->funcId = funcId;
  1983. func->explicitSignature = 0;
  1984. // Add a default factory as well
  1985. funcId = engine->GetNextScriptFunctionId();
  1986. if( objType->beh.factory )
  1987. engine->scriptFunctions[objType->beh.factory]->Release();
  1988. objType->beh.factory = funcId;
  1989. objType->beh.factories[0] = funcId;
  1990. returnType = asCDataType::CreateObjectHandle(objType, false);
  1991. module->AddScriptFunction(file->idx, funcId, objType->name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), false);
  1992. functions.PushLast(0);
  1993. asCCompiler compiler(engine);
  1994. compiler.CompileFactory(this, file, engine->scriptFunctions[funcId]);
  1995. engine->scriptFunctions[funcId]->AddRef();
  1996. // If the object is shared, then the factory must also be marked as shared
  1997. if( objType->flags & asOBJ_SHARED )
  1998. engine->scriptFunctions[funcId]->isShared = true;
  1999. }
  2000. int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file)
  2001. {
  2002. // Grab the name of the enumeration
  2003. asCScriptNode *tmp = node->firstChild;
  2004. asASSERT(snDataType == tmp->nodeType);
  2005. asCString name;
  2006. asASSERT(snIdentifier == tmp->firstChild->nodeType);
  2007. name.Assign(&file->code[tmp->firstChild->tokenPos], tmp->firstChild->tokenLength);
  2008. // Check the name and add the enum
  2009. int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file);
  2010. if( asSUCCESS == r )
  2011. {
  2012. asCObjectType *st;
  2013. asCDataType dataType;
  2014. st = asNEW(asCObjectType)(engine);
  2015. dataType.CreatePrimitive(ttInt, false);
  2016. st->flags = asOBJ_ENUM;
  2017. st->size = 4;
  2018. st->name = name;
  2019. module->enumTypes.PushLast(st);
  2020. st->AddRef();
  2021. // TODO: cleanup: Should the enum type really be stored in the engine->classTypes?
  2022. // http://www.gamedev.net/topic/616912-c-header-file-shared-with-scripts/page__gopid__4895940
  2023. engine->classTypes.PushLast(st);
  2024. // Store the location of this declaration for reference in name collisions
  2025. sClassDeclaration *decl = asNEW(sClassDeclaration);
  2026. decl->name = name;
  2027. decl->script = file;
  2028. decl->objType = st;
  2029. namedTypeDeclarations.PushLast(decl);
  2030. asCDataType type = CreateDataTypeFromNode(tmp, file);
  2031. asASSERT(!type.IsReference());
  2032. tmp = tmp->next;
  2033. while( tmp )
  2034. {
  2035. asASSERT(snIdentifier == tmp->nodeType);
  2036. asCString name(&file->code[tmp->tokenPos], tmp->tokenLength);
  2037. // Check for name conflict errors with other values in the enum
  2038. r = 0;
  2039. for( size_t n = globVariables.GetLength(); n-- > 0; )
  2040. {
  2041. sGlobalVariableDescription *gvar = globVariables[n];
  2042. if( gvar->datatype != type )
  2043. break;
  2044. if( gvar->name == name )
  2045. {
  2046. r = asNAME_TAKEN;
  2047. break;
  2048. }
  2049. }
  2050. if( asSUCCESS != r )
  2051. {
  2052. int r, c;
  2053. file->ConvertPosToRowCol(tmp->tokenPos, &r, &c);
  2054. asCString str;
  2055. str.Format(TXT_NAME_CONFLICT_s_ALREADY_USED, name.AddressOf());
  2056. WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
  2057. tmp = tmp->next;
  2058. if( tmp && tmp->nodeType == snAssignment )
  2059. tmp = tmp->next;
  2060. continue;
  2061. }
  2062. // check for assignment
  2063. asCScriptNode *asnNode = tmp->next;
  2064. if( asnNode && snAssignment == asnNode->nodeType )
  2065. asnNode->DisconnectParent();
  2066. else
  2067. asnNode = 0;
  2068. // Create the global variable description so the enum value can be evaluated
  2069. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  2070. globVariables.PushLast(gvar);
  2071. gvar->script = file;
  2072. gvar->idNode = 0;
  2073. gvar->nextNode = asnNode;
  2074. gvar->name = name;
  2075. gvar->datatype = type;
  2076. // No need to allocate space on the global memory stack since the values are stored in the asCObjectType
  2077. gvar->index = 0;
  2078. gvar->isCompiled = false;
  2079. gvar->isPureConstant = true;
  2080. gvar->isEnumValue = true;
  2081. gvar->constantValue = 0xdeadbeef;
  2082. // Allocate dummy property so we can compile the value.
  2083. // This will be removed later on so we don't add it to the engine.
  2084. gvar->property = asNEW(asCGlobalProperty);
  2085. gvar->property->name = name;
  2086. gvar->property->type = gvar->datatype;
  2087. gvar->property->id = 0;
  2088. tmp = tmp->next;
  2089. }
  2090. }
  2091. node->Destroy(engine);
  2092. return r;
  2093. }
  2094. int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file)
  2095. {
  2096. // Get the native data type
  2097. asCScriptNode *tmp = node->firstChild;
  2098. asASSERT(NULL != tmp && snDataType == tmp->nodeType);
  2099. asCDataType dataType;
  2100. dataType.CreatePrimitive(tmp->tokenType, false);
  2101. dataType.SetTokenType(tmp->tokenType);
  2102. tmp = tmp->next;
  2103. // Grab the name of the typedef
  2104. asASSERT(NULL != tmp && NULL == tmp->next);
  2105. asCString name;
  2106. name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength);
  2107. // If the name is not already in use add it
  2108. int r = CheckNameConflict(name.AddressOf(), tmp, file);
  2109. if( asSUCCESS == r )
  2110. {
  2111. // Create the new type
  2112. asCObjectType *st = asNEW(asCObjectType)(engine);
  2113. st->flags = asOBJ_TYPEDEF;
  2114. st->size = dataType.GetSizeInMemoryBytes();
  2115. st->name = name;
  2116. st->templateSubType = dataType;
  2117. st->AddRef();
  2118. module->typeDefs.PushLast(st);
  2119. engine->classTypes.PushLast(st);
  2120. // Store the location of this declaration for reference in name collisions
  2121. sClassDeclaration *decl = asNEW(sClassDeclaration);
  2122. decl->name = name;
  2123. decl->script = file;
  2124. decl->objType = st;
  2125. namedTypeDeclarations.PushLast(decl);
  2126. }
  2127. node->Destroy(engine);
  2128. return r;
  2129. }
  2130. void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isOverride, bool &isFinal)
  2131. {
  2132. node = node->firstChild;
  2133. // Is the function a private class method?
  2134. isPrivate = false;
  2135. if( node->tokenType == ttPrivate )
  2136. {
  2137. isPrivate = true;
  2138. node = node->next;
  2139. }
  2140. // Find the name
  2141. isConstructor = false;
  2142. isDestructor = false;
  2143. asCScriptNode *n = 0;
  2144. if( node->nodeType == snDataType )
  2145. n = node->next->next;
  2146. else
  2147. {
  2148. // If the first node is a ~ token, then we know it is a destructor
  2149. if( node->tokenType == ttBitNot )
  2150. {
  2151. n = node->next;
  2152. isDestructor = true;
  2153. }
  2154. else
  2155. {
  2156. n = node;
  2157. isConstructor = true;
  2158. }
  2159. }
  2160. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  2161. // Initialize a script function object for registration
  2162. if( !isConstructor && !isDestructor )
  2163. {
  2164. returnType = CreateDataTypeFromNode(node, file);
  2165. returnType = ModifyDataTypeFromNode(returnType, node->next, file, 0, 0);
  2166. }
  2167. else
  2168. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  2169. isConstMethod = false;
  2170. isFinal = false;
  2171. isOverride = false;
  2172. if( objType && n->next->next )
  2173. {
  2174. asCScriptNode *decorator = n->next->next;
  2175. // Is this a const method?
  2176. if( decorator->tokenType == ttConst )
  2177. {
  2178. isConstMethod = true;
  2179. decorator = decorator->next;
  2180. }
  2181. while( decorator )
  2182. {
  2183. if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, FINAL_TOKEN) )
  2184. isFinal = true;
  2185. else if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, OVERRIDE_TOKEN) )
  2186. isOverride = true;
  2187. decorator = decorator->next;
  2188. }
  2189. }
  2190. // Count the number of parameters
  2191. int count = 0;
  2192. asCScriptNode *c = n->next->firstChild;
  2193. while( c )
  2194. {
  2195. count++;
  2196. c = c->next->next;
  2197. if( c && c->nodeType == snIdentifier )
  2198. c = c->next;
  2199. if( c && c->nodeType == snExpression )
  2200. c = c->next;
  2201. }
  2202. // Get the parameter types
  2203. parameterTypes.Allocate(count, false);
  2204. inOutFlags.Allocate(count, false);
  2205. defaultArgs.Allocate(count, false);
  2206. n = n->next->firstChild;
  2207. while( n )
  2208. {
  2209. asETypeModifiers inOutFlag;
  2210. asCDataType type = CreateDataTypeFromNode(n, file);
  2211. type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);
  2212. // Store the parameter type
  2213. parameterTypes.PushLast(type);
  2214. inOutFlags.PushLast(inOutFlag);
  2215. // Move to next parameter
  2216. n = n->next->next;
  2217. if( n && n->nodeType == snIdentifier )
  2218. n = n->next;
  2219. if( n && n->nodeType == snExpression )
  2220. {
  2221. // Strip out white space and comments to better share the string
  2222. asCString *defaultArgStr = asNEW(asCString);
  2223. *defaultArgStr = GetCleanExpressionString(n, file);
  2224. defaultArgs.PushLast(defaultArgStr);
  2225. n = n->next;
  2226. }
  2227. else
  2228. defaultArgs.PushLast(0);
  2229. }
  2230. }
  2231. asCString asCBuilder::GetCleanExpressionString(asCScriptNode *node, asCScriptCode *file)
  2232. {
  2233. asASSERT(node && node->nodeType == snExpression);
  2234. asCString str;
  2235. str.Assign(file->code + node->tokenPos, node->tokenLength);
  2236. asCString cleanStr;
  2237. for( asUINT n = 0; n < str.GetLength(); )
  2238. {
  2239. int len;
  2240. asETokenClass tok = engine->ParseToken(str.AddressOf() + n, str.GetLength() - n, &len);
  2241. if( tok != asTC_COMMENT && tok != asTC_WHITESPACE )
  2242. {
  2243. if( cleanStr.GetLength() ) cleanStr += " ";
  2244. cleanStr.Concatenate(str.AddressOf() + n, len);
  2245. }
  2246. n += len;
  2247. }
  2248. return cleanStr;
  2249. }
  2250. int asCBuilder::RegisterScriptFunction(int funcId, asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction)
  2251. {
  2252. asCString name;
  2253. asCDataType returnType;
  2254. asCArray<asCDataType> parameterTypes;
  2255. asCArray<asETypeModifiers> inOutFlags;
  2256. asCArray<asCString *> defaultArgs;
  2257. bool isConstMethod;
  2258. bool isOverride;
  2259. bool isFinal;
  2260. bool isConstructor;
  2261. bool isDestructor;
  2262. bool isPrivate;
  2263. GetParsedFunctionDetails(node, file, objType, name, returnType, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal);
  2264. // Check for name conflicts
  2265. if( !isConstructor && !isDestructor )
  2266. {
  2267. if( objType )
  2268. {
  2269. CheckNameConflictMember(objType, name.AddressOf(), node, file, false);
  2270. if( name == objType->name )
  2271. {
  2272. int r, c;
  2273. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2274. WriteError(file->name.AddressOf(), TXT_METHOD_CANT_HAVE_NAME_OF_CLASS, r, c);
  2275. }
  2276. }
  2277. else
  2278. CheckNameConflict(name.AddressOf(), node, file);
  2279. }
  2280. else
  2281. {
  2282. // Verify that the name of the constructor/destructor is the same as the class
  2283. if( name != objType->name )
  2284. {
  2285. int r, c;
  2286. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2287. WriteError(file->name.AddressOf(), TXT_CONSTRUCTOR_NAME_ERROR, r, c);
  2288. }
  2289. if( isDestructor )
  2290. name = "~" + name;
  2291. }
  2292. if( !isInterface )
  2293. {
  2294. sFunctionDescription *func = asNEW(sFunctionDescription);
  2295. functions.PushLast(func);
  2296. func->script = file;
  2297. func->node = node;
  2298. func->name = name;
  2299. func->objType = objType;
  2300. func->funcId = funcId;
  2301. func->explicitSignature = 0;
  2302. }
  2303. // Destructors may not have any parameters
  2304. if( isDestructor && parameterTypes.GetLength() > 0 )
  2305. {
  2306. int r, c;
  2307. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2308. WriteError(file->name.AddressOf(), TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, r, c);
  2309. }
  2310. // If class or interface is shared, then only shared types may be used in the method signature
  2311. if( objType && objType->IsShared() )
  2312. {
  2313. asCObjectType *ot = returnType.GetObjectType();
  2314. if( ot && !ot->IsShared() )
  2315. {
  2316. int r, c;
  2317. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2318. asCString msg;
  2319. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  2320. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  2321. }
  2322. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  2323. {
  2324. asCObjectType *ot = parameterTypes[p].GetObjectType();
  2325. if( ot && !ot->IsShared() )
  2326. {
  2327. int r, c;
  2328. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2329. asCString msg;
  2330. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  2331. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  2332. }
  2333. }
  2334. }
  2335. // TODO: Much of this can probably be reduced by using the IsSignatureEqual method
  2336. // Check that the same function hasn't been registered already
  2337. asCArray<int> funcs;
  2338. GetFunctionDescriptions(name.AddressOf(), funcs);
  2339. if( funcs.GetLength() )
  2340. {
  2341. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  2342. {
  2343. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  2344. if( parameterTypes.GetLength() == func->parameterTypes.GetLength() )
  2345. {
  2346. bool match = true;
  2347. if( func->objectType != objType )
  2348. {
  2349. match = false;
  2350. break;
  2351. }
  2352. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  2353. {
  2354. if( parameterTypes[p] != func->parameterTypes[p] )
  2355. {
  2356. match = false;
  2357. break;
  2358. }
  2359. }
  2360. if( match )
  2361. {
  2362. int r, c;
  2363. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2364. WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c);
  2365. break;
  2366. }
  2367. }
  2368. }
  2369. }
  2370. // Register the function
  2371. module->AddScriptFunction(file->idx, funcId, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType, isConstMethod, isGlobalFunction, isPrivate, isFinal, isOverride);
  2372. // Make sure the default args are declared correctly
  2373. ValidateDefaultArgs(file, node, engine->scriptFunctions[funcId]);
  2374. if( objType )
  2375. {
  2376. engine->scriptFunctions[funcId]->AddRef();
  2377. if( isConstructor )
  2378. {
  2379. int factoryId = engine->GetNextScriptFunctionId();
  2380. if( parameterTypes.GetLength() == 0 )
  2381. {
  2382. // Overload the default constructor
  2383. engine->scriptFunctions[objType->beh.construct]->Release();
  2384. objType->beh.construct = funcId;
  2385. objType->beh.constructors[0] = funcId;
  2386. // Register the default factory as well
  2387. engine->scriptFunctions[objType->beh.factory]->Release();
  2388. objType->beh.factory = factoryId;
  2389. objType->beh.factories[0] = factoryId;
  2390. }
  2391. else
  2392. {
  2393. objType->beh.constructors.PushLast(funcId);
  2394. // Register the factory as well
  2395. objType->beh.factories.PushLast(factoryId);
  2396. }
  2397. // We must copy the default arg strings to avoid deleting the same object multiple times
  2398. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  2399. if( defaultArgs[n] )
  2400. defaultArgs[n] = asNEW(asCString)(*defaultArgs[n]);
  2401. asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
  2402. module->AddScriptFunction(file->idx, factoryId, name.AddressOf(), dt, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), false);
  2403. // If the object is shared, then the factory must also be marked as shared
  2404. if( objType->flags & asOBJ_SHARED )
  2405. engine->scriptFunctions[factoryId]->isShared = true;
  2406. // Add a dummy function to the builder so that it doesn't mix up the fund Ids
  2407. functions.PushLast(0);
  2408. // Compile the factory immediately
  2409. asCCompiler compiler(engine);
  2410. compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
  2411. engine->scriptFunctions[factoryId]->AddRef();
  2412. }
  2413. else if( isDestructor )
  2414. objType->beh.destruct = funcId;
  2415. else
  2416. objType->methods.PushLast(funcId);
  2417. }
  2418. // We need to delete the node already if this is an interface method
  2419. if( isInterface && node )
  2420. {
  2421. node->Destroy(engine);
  2422. }
  2423. return 0;
  2424. }
  2425. int asCBuilder::RegisterScriptFunctionWithSignature(int funcId, asCScriptNode *node, asCScriptCode *file, asCString &name, sExplicitSignature *signature, asCObjectType *objType, bool isInterface, bool isGlobalFunction, bool isPrivate, bool isConst, bool isFinal, bool isOverride, bool treatAsProperty)
  2426. {
  2427. bool isConstructor = false;
  2428. bool isDestructor = false;
  2429. asCArray<asCDataType> &parameterTypes = signature->argTypes;
  2430. asCArray<asETypeModifiers> &inOutFlags = signature->argModifiers;
  2431. asCArray<asCString *> defaultArgs = signature->defaultArgs;
  2432. if( objType && asCDataType::CreatePrimitive(ttVoid, false) == signature->returnType )
  2433. {
  2434. if( 0 == name.Compare( objType->name ) )
  2435. isConstructor = true;
  2436. else if( 0 == name.Compare( "~" + objType->name ) )
  2437. isDestructor = true;
  2438. }
  2439. // Check for name conflicts
  2440. if( !isConstructor && !isDestructor )
  2441. {
  2442. if( objType )
  2443. CheckNameConflictMember(objType, name.AddressOf(), node, file, treatAsProperty);
  2444. else
  2445. CheckNameConflict(name.AddressOf(), node, file);
  2446. }
  2447. if( isInterface )
  2448. {
  2449. asASSERT(!isFinal);
  2450. asASSERT(!isOverride);
  2451. }
  2452. else
  2453. {
  2454. sFunctionDescription *func = asNEW(sFunctionDescription);
  2455. functions.PushLast(func);
  2456. func->script = file;
  2457. func->node = node;
  2458. func->name = name;
  2459. func->objType = objType;
  2460. func->funcId = funcId;
  2461. func->explicitSignature = signature;
  2462. }
  2463. // Destructors may not have any parameters
  2464. if( isDestructor && parameterTypes.GetLength() > 0 )
  2465. {
  2466. int r, c;
  2467. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2468. WriteError(file->name.AddressOf(), TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, r, c);
  2469. }
  2470. // If class or interface is shared, then only shared types may be used in the method signature
  2471. if( objType && (objType->flags & asOBJ_SHARED) )
  2472. {
  2473. asCObjectType *ot = signature->returnType.GetObjectType();
  2474. if( ot && (ot->flags & asOBJ_SCRIPT_OBJECT) && !(ot->flags & asOBJ_SHARED) )
  2475. {
  2476. int r, c;
  2477. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2478. asCString msg;
  2479. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  2480. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  2481. }
  2482. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  2483. {
  2484. asCObjectType *ot = parameterTypes[p].GetObjectType();
  2485. if( ot && (ot->flags & asOBJ_SCRIPT_OBJECT) && !(ot->flags & asOBJ_SHARED) )
  2486. {
  2487. int r, c;
  2488. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2489. asCString msg;
  2490. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  2491. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  2492. }
  2493. }
  2494. }
  2495. // TODO: Much of this can probably be reduced by using the IsSignatureEqual method
  2496. // Check that the same function hasn't been registered already
  2497. asCArray<int> funcs;
  2498. GetFunctionDescriptions(name.AddressOf(), funcs);
  2499. if( funcs.GetLength() )
  2500. {
  2501. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  2502. {
  2503. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  2504. if( parameterTypes.GetLength() == func->parameterTypes.GetLength() )
  2505. {
  2506. bool match = true;
  2507. if( func->objectType != objType )
  2508. {
  2509. match = false;
  2510. break;
  2511. }
  2512. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  2513. {
  2514. if( parameterTypes[p] != func->parameterTypes[p] )
  2515. {
  2516. match = false;
  2517. break;
  2518. }
  2519. }
  2520. if( match )
  2521. {
  2522. int r, c;
  2523. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2524. WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c);
  2525. break;
  2526. }
  2527. }
  2528. }
  2529. }
  2530. // Register the function
  2531. module->AddScriptFunction(file->idx, funcId, name.AddressOf(), signature->returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType, isConst, isGlobalFunction, isPrivate, isFinal, isOverride);
  2532. // Make sure the default args are declared correctly
  2533. ValidateDefaultArgs(file, node, engine->scriptFunctions[funcId]);
  2534. if( objType )
  2535. {
  2536. engine->scriptFunctions[funcId]->AddRef();
  2537. if( isConstructor )
  2538. {
  2539. int factoryId = engine->GetNextScriptFunctionId();
  2540. if( parameterTypes.GetLength() == 0 )
  2541. {
  2542. // Overload the default constructor
  2543. engine->scriptFunctions[objType->beh.construct]->Release();
  2544. objType->beh.construct = funcId;
  2545. objType->beh.constructors[0] = funcId;
  2546. // Register the default factory as well
  2547. engine->scriptFunctions[objType->beh.factory]->Release();
  2548. objType->beh.factory = factoryId;
  2549. objType->beh.factories[0] = factoryId;
  2550. }
  2551. else
  2552. {
  2553. objType->beh.constructors.PushLast(funcId);
  2554. // Register the factory as well
  2555. objType->beh.factories.PushLast(factoryId);
  2556. }
  2557. // We must copy the default arg strings to avoid deleting the same object multiple times
  2558. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  2559. if( defaultArgs[n] )
  2560. defaultArgs[n] = asNEW(asCString)(*defaultArgs[n]);
  2561. asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
  2562. module->AddScriptFunction(file->idx, factoryId, name.AddressOf(), dt, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), false);
  2563. // Add a dummy function to the builder so that it doesn't mix up the fund Ids
  2564. functions.PushLast(0);
  2565. // Compile the factory immediately
  2566. asCCompiler compiler(engine);
  2567. compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
  2568. engine->scriptFunctions[factoryId]->AddRef();
  2569. }
  2570. else if( isDestructor )
  2571. objType->beh.destruct = funcId;
  2572. else
  2573. objType->methods.PushLast(funcId);
  2574. }
  2575. // We need to delete the node already if this is an interface method
  2576. if( isInterface && node )
  2577. {
  2578. node->Destroy(engine);
  2579. }
  2580. return 0;
  2581. }
  2582. int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction)
  2583. {
  2584. if( engine->ep.propertyAccessorMode != 2 )
  2585. {
  2586. int r, c;
  2587. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2588. WriteError(file->name.AddressOf(), TXT_PROPERTY_ACCESSOR_DISABLED, r, c);
  2589. node->Destroy(engine);
  2590. return 0;
  2591. }
  2592. bool isPrivate = false;
  2593. asCString emulatedName;
  2594. asCDataType emulatedType;
  2595. if( !isGlobalFunction && node->tokenType == ttPrivate )
  2596. {
  2597. isPrivate = true;
  2598. node = node->next;
  2599. }
  2600. asCScriptNode *mainNode = node;
  2601. node = node->firstChild;
  2602. emulatedType = CreateDataTypeFromNode(node, file);
  2603. emulatedType = ModifyDataTypeFromNode(emulatedType, node->next, file, 0, 0);
  2604. node = node->next->next;
  2605. emulatedName.Assign(&file->code[node->tokenPos], node->tokenLength);
  2606. node = node->next;
  2607. while( node )
  2608. {
  2609. asCScriptNode *next = node->next;
  2610. asCScriptNode *funcNode = 0;
  2611. sExplicitSignature *signature = 0;
  2612. bool success = false;
  2613. bool isConst = false;
  2614. bool isFinal = false;
  2615. bool isOverride = false;
  2616. asCString name;
  2617. // TODO: getset: Allow private for individual property accessors
  2618. // TODO: getset: If the accessor uses its own name, then the property should be automatically declared
  2619. if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN) )
  2620. {
  2621. funcNode = node->firstChild->next;
  2622. if( funcNode && funcNode->tokenType == ttConst )
  2623. {
  2624. isConst = true;
  2625. funcNode = funcNode->next;
  2626. }
  2627. while( funcNode && funcNode->nodeType != snStatementBlock )
  2628. {
  2629. if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
  2630. isFinal = true;
  2631. else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
  2632. isOverride = true;
  2633. funcNode = funcNode->next;
  2634. }
  2635. if( funcNode )
  2636. funcNode->DisconnectParent();
  2637. if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
  2638. {
  2639. // TODO: getset: If no implementation is supplied the builder should provide an automatically generated implementation
  2640. // The compiler needs to be able to handle the different types, primitive, value type, and handle
  2641. // The code is also different for global property accessors
  2642. int r, c;
  2643. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2644. WriteError(file->name.AddressOf(), TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, r, c);
  2645. }
  2646. signature = asNEW(sExplicitSignature);
  2647. signature->returnType = emulatedType;
  2648. name = "get_" + emulatedName;
  2649. success = true;
  2650. }
  2651. else if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN) )
  2652. {
  2653. funcNode = node->firstChild->next;
  2654. if( funcNode && funcNode->tokenType == ttConst )
  2655. {
  2656. isConst = true;
  2657. funcNode = funcNode->next;
  2658. }
  2659. while( funcNode && funcNode->nodeType != snStatementBlock )
  2660. {
  2661. if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
  2662. isFinal = true;
  2663. else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
  2664. isOverride = true;
  2665. funcNode = funcNode->next;
  2666. }
  2667. if( funcNode )
  2668. funcNode->DisconnectParent();
  2669. if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
  2670. {
  2671. int r, c;
  2672. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2673. WriteError(file->name.AddressOf(), TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, r, c);
  2674. }
  2675. signature = asNEW(sExplicitSignature)(1);
  2676. signature->returnType = asCDataType::CreatePrimitive(ttVoid, false);
  2677. signature->argModifiers.PushLast(asTM_NONE);
  2678. signature->argNames.PushLast("value");
  2679. signature->argTypes.PushLast(emulatedType);
  2680. signature->defaultArgs.PushLast(0);
  2681. name = "set_" + emulatedName;
  2682. success = true;
  2683. }
  2684. else
  2685. {
  2686. int r, c;
  2687. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2688. WriteError(file->name.AddressOf(), TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, r, c);
  2689. }
  2690. if( success )
  2691. {
  2692. RegisterScriptFunctionWithSignature(engine->GetNextScriptFunctionId(), funcNode, file, name, signature, objType, isInterface, isGlobalFunction, isPrivate, isConst, isFinal, isOverride, true);
  2693. }
  2694. node = next;
  2695. };
  2696. mainNode->Destroy(engine);
  2697. return 0;
  2698. }
  2699. int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file)
  2700. {
  2701. // Find name
  2702. asCScriptNode *f = node->firstChild;
  2703. asCScriptNode *n = f->firstChild->next->next;
  2704. // Check for name conflicts
  2705. asCString name(&file->code[n->tokenPos], n->tokenLength);
  2706. CheckNameConflict(name.AddressOf(), n, file);
  2707. // Initialize a script function object for registration
  2708. asCDataType returnType;
  2709. returnType = CreateDataTypeFromNode(f->firstChild, file);
  2710. returnType = ModifyDataTypeFromNode(returnType, f->firstChild->next, file, 0, 0);
  2711. // Count the parameters
  2712. int count = 0;
  2713. asCScriptNode *c = n->next->firstChild;
  2714. while( c )
  2715. {
  2716. count++;
  2717. c = c->next->next;
  2718. if( c && c->nodeType == snIdentifier )
  2719. c = c->next;
  2720. }
  2721. asCArray<asCDataType> parameterTypes(count);
  2722. asCArray<asETypeModifiers> inOutFlags(count);
  2723. n = n->next->firstChild;
  2724. while( n )
  2725. {
  2726. asETypeModifiers inOutFlag;
  2727. asCDataType type = CreateDataTypeFromNode(n, file);
  2728. type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);
  2729. // Store the parameter type
  2730. parameterTypes.PushLast(type);
  2731. inOutFlags.PushLast(inOutFlag);
  2732. if( type.GetTokenType() == ttVoid )
  2733. {
  2734. int r, c;
  2735. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  2736. asCString str;
  2737. str.Format(TXT_PARAMETER_CANT_BE_s, type.Format().AddressOf());
  2738. WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
  2739. break;
  2740. }
  2741. // Move to next parameter
  2742. n = n->next->next;
  2743. if( n && n->nodeType == snIdentifier )
  2744. n = n->next;
  2745. }
  2746. // Check that the same function hasn't been registered already
  2747. asCArray<int> funcs;
  2748. GetFunctionDescriptions(name.AddressOf(), funcs);
  2749. if( funcs.GetLength() )
  2750. {
  2751. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  2752. {
  2753. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  2754. if( parameterTypes.GetLength() == func->parameterTypes.GetLength() )
  2755. {
  2756. bool match = true;
  2757. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  2758. {
  2759. if( parameterTypes[p] != func->parameterTypes[p] )
  2760. {
  2761. match = false;
  2762. break;
  2763. }
  2764. }
  2765. if( match )
  2766. {
  2767. int r, c;
  2768. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  2769. WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c);
  2770. break;
  2771. }
  2772. }
  2773. }
  2774. }
  2775. // Read the module name as well
  2776. n = node->firstChild->next;
  2777. asCString moduleName;
  2778. moduleName.Assign(&file->code[n->tokenPos+1], n->tokenLength-2);
  2779. node->Destroy(engine);
  2780. // Register the function
  2781. module->AddImportedFunction(importID, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), moduleName);
  2782. return 0;
  2783. }
  2784. asCScriptFunction *asCBuilder::GetFunctionDescription(int id)
  2785. {
  2786. // TODO: import: This should be improved when the imported functions are removed
  2787. // Get the description from the engine
  2788. if( (id & 0xFFFF0000) == 0 )
  2789. return engine->scriptFunctions[id];
  2790. else
  2791. return engine->importedFunctions[id & 0xFFFF]->importedFunctionSignature;
  2792. }
  2793. void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs)
  2794. {
  2795. // TODO: optimize: Improve linear searches in GetFunctionDescriptions
  2796. // A large part of the compilation time seems to be spent in this function
  2797. // I need to have a map with all global functions so that it will be
  2798. // quicker to find them by name. The key should be the function name, and
  2799. // the value a list with all the functions using that name
  2800. asUINT n;
  2801. for( n = 0; n < module->scriptFunctions.GetLength(); n++ )
  2802. {
  2803. if( module->scriptFunctions[n]->name == name &&
  2804. module->scriptFunctions[n]->objectType == 0 )
  2805. funcs.PushLast(module->scriptFunctions[n]->id);
  2806. }
  2807. for( n = 0; n < module->bindInformations.GetLength(); n++ )
  2808. {
  2809. if( module->bindInformations[n]->importedFunctionSignature->name == name )
  2810. funcs.PushLast(module->bindInformations[n]->importedFunctionSignature->id);
  2811. }
  2812. // TODO: optimize: Use the registeredGlobalFunctions array instead
  2813. for( n = 0; n < engine->scriptFunctions.GetLength(); n++ )
  2814. {
  2815. if( engine->scriptFunctions[n] &&
  2816. engine->scriptFunctions[n]->funcType == asFUNC_SYSTEM &&
  2817. engine->scriptFunctions[n]->objectType == 0 &&
  2818. engine->scriptFunctions[n]->name == name )
  2819. {
  2820. // Verify if the module has access to the function
  2821. if( module->accessMask & engine->scriptFunctions[n]->accessMask )
  2822. {
  2823. #ifdef AS_DEPRECATED
  2824. // deprecated since 2011-10-04
  2825. // Find the config group for the global function
  2826. asCConfigGroup *group = engine->FindConfigGroupForFunction(engine->scriptFunctions[n]->id);
  2827. if( !group || group->HasModuleAccess(module->name.AddressOf()) )
  2828. #endif
  2829. funcs.PushLast(engine->scriptFunctions[n]->id);
  2830. }
  2831. }
  2832. }
  2833. }
  2834. void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope)
  2835. {
  2836. if( scope != "" )
  2837. {
  2838. // Find the base class with the specified scope
  2839. while( objectType && objectType->name != scope )
  2840. objectType = objectType->derivedFrom;
  2841. // If the scope is not any of the base classes, then return no methods
  2842. if( objectType == 0 )
  2843. return;
  2844. }
  2845. // TODO: optimize: Improve linear search
  2846. if( objIsConst )
  2847. {
  2848. // Only add const methods to the list
  2849. for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
  2850. {
  2851. if( engine->scriptFunctions[objectType->methods[n]]->name == name &&
  2852. engine->scriptFunctions[objectType->methods[n]]->isReadOnly )
  2853. {
  2854. // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
  2855. if( scope == "" )
  2856. methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
  2857. else
  2858. {
  2859. asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
  2860. asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
  2861. methods.PushLast(realFunc->id);
  2862. }
  2863. }
  2864. }
  2865. }
  2866. else
  2867. {
  2868. // TODO: Prefer non-const over const
  2869. for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
  2870. {
  2871. if( engine->scriptFunctions[objectType->methods[n]]->name == name )
  2872. {
  2873. // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
  2874. if( scope == "" )
  2875. methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
  2876. else
  2877. {
  2878. asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
  2879. asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
  2880. methods.PushLast(realFunc->id);
  2881. }
  2882. }
  2883. }
  2884. }
  2885. }
  2886. void asCBuilder::WriteInfo(const char *scriptname, const char *message, int r, int c, bool pre)
  2887. {
  2888. // Need to store the pre message in a structure
  2889. if( pre )
  2890. {
  2891. preMessage.isSet = true;
  2892. preMessage.c = c;
  2893. preMessage.r = r;
  2894. preMessage.message = message;
  2895. }
  2896. else
  2897. {
  2898. preMessage.isSet = false;
  2899. engine->WriteMessage(scriptname, r, c, asMSGTYPE_INFORMATION, message);
  2900. }
  2901. }
  2902. void asCBuilder::WriteError(const char *scriptname, const char *message, int r, int c)
  2903. {
  2904. numErrors++;
  2905. // Need to pass the preMessage first
  2906. if( preMessage.isSet )
  2907. WriteInfo(scriptname, preMessage.message.AddressOf(), preMessage.r, preMessage.c, false);
  2908. engine->WriteMessage(scriptname, r, c, asMSGTYPE_ERROR, message);
  2909. }
  2910. void asCBuilder::WriteWarning(const char *scriptname, const char *message, int r, int c)
  2911. {
  2912. numWarnings++;
  2913. // Need to pass the preMessage first
  2914. if( preMessage.isSet )
  2915. WriteInfo(scriptname, preMessage.message.AddressOf(), preMessage.r, preMessage.c, false);
  2916. engine->WriteMessage(scriptname, r, c, asMSGTYPE_WARNING, message);
  2917. }
  2918. asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, bool acceptHandleForScope, asCObjectType *templateType)
  2919. {
  2920. asASSERT(node->nodeType == snDataType);
  2921. asCDataType dt;
  2922. asCScriptNode *n = node->firstChild;
  2923. bool isConst = false;
  2924. bool isImplicitHandle = false;
  2925. if( n->tokenType == ttConst )
  2926. {
  2927. isConst = true;
  2928. n = n->next;
  2929. }
  2930. if( n->tokenType == ttIdentifier )
  2931. {
  2932. asCString str;
  2933. str.Assign(&file->code[n->tokenPos], n->tokenLength);
  2934. asCObjectType *ot = 0;
  2935. // If this is for a template type, then we must first determine if the
  2936. // identifier matches any of the template subtypes
  2937. // TODO: template: it should be possible to have more than one subtypes
  2938. if( templateType && (templateType->flags & asOBJ_TEMPLATE) && str == templateType->templateSubType.GetObjectType()->name )
  2939. ot = templateType->templateSubType.GetObjectType();
  2940. if( ot == 0 )
  2941. ot = GetObjectType(str.AddressOf());
  2942. if( ot )
  2943. {
  2944. if( ot->flags & asOBJ_IMPLICIT_HANDLE )
  2945. isImplicitHandle = true;
  2946. // Make sure the module has access to the object type
  2947. #ifdef AS_DEPRECATED
  2948. // deprecated since 2011-10-04
  2949. // Find the config group for the object type
  2950. asCConfigGroup *group = engine->FindConfigGroupForObjectType(ot);
  2951. if( !module || ((module->accessMask & ot->accessMask) && (!group || group->HasModuleAccess(module->name.AddressOf()))) )
  2952. #else
  2953. if( !module || (module->accessMask & ot->accessMask) )
  2954. #endif
  2955. {
  2956. if(asOBJ_TYPEDEF == (ot->flags & asOBJ_TYPEDEF))
  2957. {
  2958. // TODO: typedef: A typedef should be considered different from the original type (though with implicit conversions between the two)
  2959. // Create primitive data type based on object flags
  2960. dt = ot->templateSubType;
  2961. dt.MakeReadOnly(isConst);
  2962. }
  2963. else
  2964. {
  2965. if( ot->flags & asOBJ_TEMPLATE )
  2966. {
  2967. n = n->next;
  2968. // Check if the subtype is a type or the template's subtype
  2969. // if it is the template's subtype then this is the actual template type,
  2970. // orderwise it is a template instance.
  2971. // Only do this for application registered interface, as the
  2972. // scripts cannot implement templates.
  2973. asCDataType subType = CreateDataTypeFromNode(n, file, false, module ? 0 : ot);
  2974. if( subType.GetObjectType() != ot->templateSubType.GetObjectType() )
  2975. {
  2976. // This is a template instance
  2977. // Need to find the correct object type
  2978. asCObjectType *otInstance = engine->GetTemplateInstanceType(ot, subType);
  2979. if( !otInstance )
  2980. {
  2981. asCString msg;
  2982. msg.Format(TXT_CANNOT_INSTANCIATE_TEMPLATE_s_WITH_s, ot->name.AddressOf(), subType.Format().AddressOf());
  2983. int r, c;
  2984. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  2985. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  2986. }
  2987. ot = otInstance;
  2988. }
  2989. }
  2990. // Create object data type
  2991. if( ot )
  2992. dt = asCDataType::CreateObject(ot, isConst);
  2993. else
  2994. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  2995. }
  2996. }
  2997. else
  2998. {
  2999. asCString msg;
  3000. msg.Format(TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE, (const char *)str.AddressOf());
  3001. int r, c;
  3002. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  3003. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  3004. dt.SetTokenType(ttInt);
  3005. }
  3006. }
  3007. else if( ot == 0 )
  3008. {
  3009. // It can still be a function definition
  3010. asCScriptFunction *funcdef = GetFuncDef(str.AddressOf());
  3011. if( funcdef )
  3012. {
  3013. dt = asCDataType::CreateFuncDef(funcdef);
  3014. }
  3015. else if( funcdef == 0 )
  3016. {
  3017. asCString msg;
  3018. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE, (const char *)str.AddressOf());
  3019. int r, c;
  3020. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  3021. WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
  3022. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  3023. return dt;
  3024. }
  3025. }
  3026. }
  3027. else
  3028. {
  3029. // Create primitive data type
  3030. dt = asCDataType::CreatePrimitive(n->tokenType, isConst);
  3031. }
  3032. // Determine array dimensions and object handles
  3033. n = n->next;
  3034. while( n && (n->tokenType == ttOpenBracket || n->tokenType == ttHandle) )
  3035. {
  3036. if( n->tokenType == ttOpenBracket )
  3037. {
  3038. // Make sure the sub type can be instanciated
  3039. if( !dt.CanBeInstanciated() )
  3040. {
  3041. int r, c;
  3042. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  3043. asCString str;
  3044. // TODO: Change to "Array sub type cannot be 'type'"
  3045. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
  3046. WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
  3047. }
  3048. // Make the type an array (or multidimensional array)
  3049. if( dt.MakeArray(engine) < 0 )
  3050. {
  3051. int r, c;
  3052. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  3053. WriteError(file->name.AddressOf(), TXT_NO_DEFAULT_ARRAY_TYPE, r, c);
  3054. break;
  3055. }
  3056. }
  3057. else
  3058. {
  3059. // Make the type a handle
  3060. if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
  3061. {
  3062. int r, c;
  3063. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  3064. WriteError(file->name.AddressOf(), TXT_OBJECT_HANDLE_NOT_SUPPORTED, r, c);
  3065. break;
  3066. }
  3067. }
  3068. n = n->next;
  3069. }
  3070. if( isImplicitHandle )
  3071. {
  3072. // Make the type a handle
  3073. if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
  3074. {
  3075. int r, c;
  3076. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  3077. WriteError(file->name.AddressOf(), TXT_OBJECT_HANDLE_NOT_SUPPORTED, r, c);
  3078. }
  3079. }
  3080. return dt;
  3081. }
  3082. asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlags, bool *autoHandle)
  3083. {
  3084. asCDataType dt = type;
  3085. if( inOutFlags ) *inOutFlags = asTM_NONE;
  3086. // Is the argument sent by reference?
  3087. asCScriptNode *n = node->firstChild;
  3088. if( n && n->tokenType == ttAmp )
  3089. {
  3090. dt.MakeReference(true);
  3091. n = n->next;
  3092. if( n )
  3093. {
  3094. if( inOutFlags )
  3095. {
  3096. if( n->tokenType == ttIn )
  3097. *inOutFlags = asTM_INREF;
  3098. else if( n->tokenType == ttOut )
  3099. *inOutFlags = asTM_OUTREF;
  3100. else if( n->tokenType == ttInOut )
  3101. *inOutFlags = asTM_INOUTREF;
  3102. else
  3103. asASSERT(false);
  3104. }
  3105. n = n->next;
  3106. }
  3107. else
  3108. {
  3109. if( inOutFlags )
  3110. *inOutFlags = asTM_INOUTREF; // ttInOut
  3111. }
  3112. if( !engine->ep.allowUnsafeReferences &&
  3113. inOutFlags && *inOutFlags == asTM_INOUTREF )
  3114. {
  3115. // Verify that the base type support &inout parameter types
  3116. if( !dt.IsObject() || dt.IsObjectHandle() || !dt.GetObjectType()->beh.addref || !dt.GetObjectType()->beh.release )
  3117. {
  3118. int r, c;
  3119. file->ConvertPosToRowCol(node->firstChild->tokenPos, &r, &c);
  3120. WriteError(file->name.AddressOf(), TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT, r, c);
  3121. }
  3122. }
  3123. }
  3124. if( autoHandle ) *autoHandle = false;
  3125. if( n && n->tokenType == ttPlus )
  3126. {
  3127. if( autoHandle ) *autoHandle = true;
  3128. }
  3129. return dt;
  3130. }
  3131. asCObjectType *asCBuilder::GetObjectType(const char *type)
  3132. {
  3133. asCObjectType *ot = engine->GetObjectType(type);
  3134. if( !ot && module )
  3135. ot = module->GetObjectType(type);
  3136. return ot;
  3137. }
  3138. asCScriptFunction *asCBuilder::GetFuncDef(const char *type)
  3139. {
  3140. for( asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++ )
  3141. {
  3142. // TODO: access: Only return the definitions that the module has access to
  3143. if( engine->registeredFuncDefs[n]->name == type )
  3144. {
  3145. return engine->registeredFuncDefs[n];
  3146. }
  3147. }
  3148. if( module )
  3149. {
  3150. for( asUINT n = 0; n < module->funcDefs.GetLength(); n++ )
  3151. {
  3152. if( module->funcDefs[n]->name == type )
  3153. {
  3154. return module->funcDefs[n];
  3155. }
  3156. }
  3157. }
  3158. return 0;
  3159. }
  3160. int asCBuilder::GetEnumValueFromObjectType(asCObjectType *objType, const char *name, asCDataType &outDt, asDWORD &outValue)
  3161. {
  3162. if( !objType || !(objType->flags & asOBJ_ENUM) )
  3163. return 0;
  3164. for( asUINT n = 0; n < objType->enumValues.GetLength(); ++n )
  3165. {
  3166. if( objType->enumValues[n]->name == name )
  3167. {
  3168. outDt = asCDataType::CreateObject(objType, true);
  3169. outValue = objType->enumValues[n]->value;
  3170. return 1;
  3171. }
  3172. }
  3173. return 0;
  3174. }
  3175. int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outValue)
  3176. {
  3177. bool found = false;
  3178. // Search all available enum types
  3179. asUINT t;
  3180. for( t = 0; t < engine->objectTypes.GetLength(); t++ )
  3181. {
  3182. asCObjectType *ot = engine->objectTypes[t];
  3183. if( GetEnumValueFromObjectType( ot, name, outDt, outValue ) )
  3184. {
  3185. if( !found )
  3186. {
  3187. found = true;
  3188. }
  3189. else
  3190. {
  3191. // Found more than one value in different enum types
  3192. return 2;
  3193. }
  3194. }
  3195. }
  3196. for( t = 0; t < module->enumTypes.GetLength(); t++ )
  3197. {
  3198. asCObjectType *ot = module->enumTypes[t];
  3199. if( GetEnumValueFromObjectType( ot, name, outDt, outValue ) )
  3200. {
  3201. if( !found )
  3202. {
  3203. found = true;
  3204. }
  3205. else
  3206. {
  3207. // Found more than one value in different enum types
  3208. return 2;
  3209. }
  3210. }
  3211. }
  3212. if( found )
  3213. return 1;
  3214. // Didn't find any value
  3215. return 0;
  3216. }
  3217. END_AS_NAMESPACE