as_builder.cpp 121 KB

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