as_builder.cpp 148 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2014 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. // Modified by Lasse Oorni 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. #include "as_debug.h"
  39. BEGIN_AS_NAMESPACE
  40. #ifndef AS_NO_COMPILER
  41. // asCSymbolTable template specializations for sGlobalVariableDescription entries
  42. template<>
  43. void asCSymbolTable<sGlobalVariableDescription>::GetKey(const sGlobalVariableDescription *entry, asSNameSpaceNamePair &key) const
  44. {
  45. asSNameSpace *ns = entry->ns;
  46. asCString name = entry->name;
  47. key = asSNameSpaceNamePair(ns, name);
  48. }
  49. // Comparator for exact variable search
  50. class asCCompGlobVarType : public asIFilter
  51. {
  52. public:
  53. const asCDataType &m_type;
  54. asCCompGlobVarType(const asCDataType &type) : m_type(type) {}
  55. bool operator()(const void *p) const
  56. {
  57. const sGlobalVariableDescription* desc = reinterpret_cast<const sGlobalVariableDescription*>(p);
  58. return desc->datatype == m_type;
  59. }
  60. private:
  61. // The assignment operator is required for MSVC9, otherwise it will complain that it is not possible to auto generate the operator
  62. asCCompGlobVarType &operator=(const asCCompGlobVarType &) {return *this;}
  63. };
  64. #endif
  65. asCBuilder::asCBuilder(asCScriptEngine *_engine, asCModule *_module)
  66. {
  67. this->engine = _engine;
  68. this->module = _module;
  69. silent = false;
  70. }
  71. asCBuilder::~asCBuilder()
  72. {
  73. #ifndef AS_NO_COMPILER
  74. asUINT n;
  75. // Free all functions
  76. for( n = 0; n < functions.GetLength(); n++ )
  77. {
  78. if( functions[n] )
  79. {
  80. if( functions[n]->node )
  81. functions[n]->node->Destroy(engine);
  82. asDELETE(functions[n],sFunctionDescription);
  83. }
  84. functions[n] = 0;
  85. }
  86. // Free all global variables
  87. asCSymbolTable<sGlobalVariableDescription>::iterator it = globVariables.List();
  88. while( it )
  89. {
  90. if( (*it)->declaredAtNode )
  91. (*it)->declaredAtNode->Destroy(engine);
  92. if( (*it)->initializationNode )
  93. (*it)->initializationNode->Destroy(engine);
  94. asDELETE((*it),sGlobalVariableDescription);
  95. it++;
  96. }
  97. globVariables.Clear();
  98. // Free all the loaded files
  99. for( n = 0; n < scripts.GetLength(); n++ )
  100. {
  101. if( scripts[n] )
  102. asDELETE(scripts[n],asCScriptCode);
  103. scripts[n] = 0;
  104. }
  105. // Free all class declarations
  106. for( n = 0; n < classDeclarations.GetLength(); n++ )
  107. {
  108. if( classDeclarations[n] )
  109. {
  110. if( classDeclarations[n]->node )
  111. classDeclarations[n]->node->Destroy(engine);
  112. asDELETE(classDeclarations[n],sClassDeclaration);
  113. classDeclarations[n] = 0;
  114. }
  115. }
  116. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  117. {
  118. if( interfaceDeclarations[n] )
  119. {
  120. if( interfaceDeclarations[n]->node )
  121. interfaceDeclarations[n]->node->Destroy(engine);
  122. asDELETE(interfaceDeclarations[n],sClassDeclaration);
  123. interfaceDeclarations[n] = 0;
  124. }
  125. }
  126. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  127. {
  128. if( namedTypeDeclarations[n] )
  129. {
  130. if( namedTypeDeclarations[n]->node )
  131. namedTypeDeclarations[n]->node->Destroy(engine);
  132. asDELETE(namedTypeDeclarations[n],sClassDeclaration);
  133. namedTypeDeclarations[n] = 0;
  134. }
  135. }
  136. for( n = 0; n < funcDefs.GetLength(); n++ )
  137. {
  138. if( funcDefs[n] )
  139. {
  140. if( funcDefs[n]->node )
  141. funcDefs[n]->node->Destroy(engine);
  142. asDELETE(funcDefs[n],sFuncDef);
  143. funcDefs[n] = 0;
  144. }
  145. }
  146. for( n = 0; n < mixinClasses.GetLength(); n++ )
  147. {
  148. if( mixinClasses[n] )
  149. {
  150. if( mixinClasses[n]->node )
  151. mixinClasses[n]->node->Destroy(engine);
  152. asDELETE(mixinClasses[n],sMixinClass);
  153. mixinClasses[n] = 0;
  154. }
  155. }
  156. #endif // AS_NO_COMPILER
  157. }
  158. void asCBuilder::Reset()
  159. {
  160. numErrors = 0;
  161. numWarnings = 0;
  162. engine->preMessage.isSet = false;
  163. #ifndef AS_NO_COMPILER
  164. // Clear the cache of known types
  165. hasCachedKnownTypes = false;
  166. knownTypes.EraseAll();
  167. #endif
  168. }
  169. #ifndef AS_NO_COMPILER
  170. int asCBuilder::AddCode(const char *name, const char *code, int codeLength, int lineOffset, int sectionIdx, bool makeCopy)
  171. {
  172. asCScriptCode *script = asNEW(asCScriptCode);
  173. if( script == 0 )
  174. return asOUT_OF_MEMORY;
  175. int r = script->SetCode(name, code, codeLength, makeCopy);
  176. if( r < 0 )
  177. {
  178. asDELETE(script, asCScriptCode);
  179. return r;
  180. }
  181. script->lineOffset = lineOffset;
  182. script->idx = sectionIdx;
  183. scripts.PushLast(script);
  184. return 0;
  185. }
  186. int asCBuilder::Build()
  187. {
  188. Reset();
  189. ParseScripts();
  190. // Compile the global variables first, so the auto types can be
  191. // resolved before the variables is used else where in the code
  192. CompileGlobalVariables();
  193. CompileInterfaces();
  194. CompileClasses();
  195. CompileFunctions();
  196. // TODO: Attempt to reorder the initialization of global variables so that
  197. // they do not access other uninitialized global variables out-of-order
  198. // The builder needs to check for each of the global variable, what functions
  199. // that are accessed, and what global variables are access by these functions.
  200. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  201. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  202. if( numErrors > 0 )
  203. return asERROR;
  204. // Make sure something was compiled, otherwise return an error
  205. if( module->IsEmpty() )
  206. {
  207. WriteError(TXT_NOTHING_WAS_BUILT, 0, 0);
  208. return asERROR;
  209. }
  210. return asSUCCESS;
  211. }
  212. int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  213. {
  214. Reset();
  215. // Add the string to the script code
  216. asCScriptCode *script = asNEW(asCScriptCode);
  217. if( script == 0 )
  218. return asOUT_OF_MEMORY;
  219. script->SetCode(sectionName, code, true);
  220. script->lineOffset = lineOffset;
  221. script->idx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  222. scripts.PushLast(script);
  223. // Parse the string
  224. asCParser parser(this);
  225. if( parser.ParseScript(scripts[0]) < 0 )
  226. return asERROR;
  227. asCScriptNode *node = parser.GetScriptNode();
  228. // Make sure there is nothing else than the global variable in the script code
  229. if( node == 0 ||
  230. node->firstChild == 0 ||
  231. node->firstChild != node->lastChild ||
  232. node->firstChild->nodeType != snDeclaration )
  233. {
  234. WriteError(TXT_ONLY_ONE_VARIABLE_ALLOWED, script, 0);
  235. return asERROR;
  236. }
  237. node = node->firstChild;
  238. node->DisconnectParent();
  239. RegisterGlobalVar(node, script, module->defaultNamespace);
  240. CompileGlobalVariables();
  241. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  242. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  243. if( numErrors > 0 )
  244. {
  245. // Remove the variable from the module, if it was registered
  246. if( globVariables.GetSize() > 0 )
  247. module->RemoveGlobalVar(module->GetGlobalVarCount()-1);
  248. return asERROR;
  249. }
  250. return 0;
  251. }
  252. #endif
  253. int asCBuilder::ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func)
  254. {
  255. int firstArgWithDefaultValue = -1;
  256. for( asUINT n = 0; n < func->defaultArgs.GetLength(); n++ )
  257. {
  258. if( func->defaultArgs[n] )
  259. firstArgWithDefaultValue = n;
  260. else if( firstArgWithDefaultValue >= 0 )
  261. {
  262. asCString str;
  263. str.Format(TXT_DEF_ARG_MISSING_IN_FUNC_s, func->GetDeclaration());
  264. WriteError(str, script, node);
  265. return asINVALID_DECLARATION;
  266. }
  267. }
  268. return 0;
  269. }
  270. #ifndef AS_NO_COMPILER
  271. int asCBuilder::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asCScriptFunction **outFunc)
  272. {
  273. asASSERT(outFunc != 0);
  274. Reset();
  275. // Add the string to the script code
  276. asCScriptCode *script = asNEW(asCScriptCode);
  277. if( script == 0 )
  278. return asOUT_OF_MEMORY;
  279. script->SetCode(sectionName, code, true);
  280. script->lineOffset = lineOffset;
  281. script->idx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  282. scripts.PushLast(script);
  283. // Parse the string
  284. asCParser parser(this);
  285. if( parser.ParseScript(scripts[0]) < 0 )
  286. return asERROR;
  287. asCScriptNode *node = parser.GetScriptNode();
  288. // Make sure there is nothing else than the function in the script code
  289. if( node == 0 ||
  290. node->firstChild == 0 ||
  291. node->firstChild != node->lastChild ||
  292. node->firstChild->nodeType != snFunction )
  293. {
  294. WriteError(TXT_ONLY_ONE_FUNCTION_ALLOWED, script, 0);
  295. return asERROR;
  296. }
  297. // Find the function node
  298. node = node->firstChild;
  299. // Create the function
  300. bool isConstructor, isDestructor, isPrivate, isFinal, isOverride, isShared;
  301. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, compileFlags & asCOMP_ADD_TO_MODULE ? module : 0, asFUNC_SCRIPT);
  302. if( func == 0 )
  303. return asOUT_OF_MEMORY;
  304. GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate, isFinal, isOverride, isShared, module->defaultNamespace);
  305. func->id = engine->GetNextScriptFunctionId();
  306. func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  307. int row, col;
  308. scripts[0]->ConvertPosToRowCol(node->tokenPos, &row, &col);
  309. func->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20);
  310. func->nameSpace = module->defaultNamespace;
  311. // Make sure the default args are declared correctly
  312. int r = ValidateDefaultArgs(script, node, func);
  313. if( r < 0 )
  314. {
  315. func->Release();
  316. return asERROR;
  317. }
  318. // Tell the engine that the function exists already so the compiler can access it
  319. if( compileFlags & asCOMP_ADD_TO_MODULE )
  320. {
  321. int r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->defaultNamespace);
  322. if( r < 0 )
  323. {
  324. func->Orphan(module);
  325. return asERROR;
  326. }
  327. module->globalFunctions.Put(func);
  328. func->AddRef();
  329. module->AddScriptFunction(func);
  330. }
  331. else
  332. engine->SetScriptFunction(func);
  333. // Fill in the function info for the builder too
  334. node->DisconnectParent();
  335. sFunctionDescription *funcDesc = asNEW(sFunctionDescription);
  336. if( funcDesc == 0 )
  337. {
  338. func->Release();
  339. return asOUT_OF_MEMORY;
  340. }
  341. functions.PushLast(funcDesc);
  342. funcDesc->script = scripts[0];
  343. funcDesc->node = node;
  344. funcDesc->name = func->name;
  345. funcDesc->funcId = func->id;
  346. funcDesc->paramNames = func->parameterNames;
  347. funcDesc->isExistingShared = false;
  348. asCCompiler compiler(engine);
  349. compiler.CompileFunction(this, functions[0]->script, func->parameterNames, functions[0]->node, func, 0);
  350. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  351. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  352. if( numErrors > 0 )
  353. {
  354. // If the function was added to the module then remove it again
  355. if( compileFlags & asCOMP_ADD_TO_MODULE )
  356. {
  357. module->globalFunctions.Erase(module->globalFunctions.GetIndex(func));
  358. module->scriptFunctions.RemoveValue(func);
  359. func->Release();
  360. func->Orphan(module);
  361. }
  362. func->Release();
  363. return asERROR;
  364. }
  365. // Return the function
  366. *outFunc = func;
  367. return asSUCCESS;
  368. }
  369. void asCBuilder::ParseScripts()
  370. {
  371. TimeIt("asCBuilder::ParseScripts");
  372. asCArray<asCParser*> parsers((int)scripts.GetLength());
  373. // Parse all the files as if they were one
  374. asUINT n = 0;
  375. for( n = 0; n < scripts.GetLength(); n++ )
  376. {
  377. asCParser *parser = asNEW(asCParser)(this);
  378. if( parser != 0 )
  379. {
  380. parsers.PushLast(parser);
  381. // Parse the script file
  382. parser->ParseScript(scripts[n]);
  383. }
  384. }
  385. if( numErrors == 0 )
  386. {
  387. // Find all type declarations
  388. for( n = 0; n < scripts.GetLength(); n++ )
  389. {
  390. asCScriptNode *node = parsers[n]->GetScriptNode();
  391. RegisterTypesFromScript(node, scripts[n], engine->nameSpaces[0]);
  392. }
  393. // Register the complete function definitions
  394. for( n = 0; n < funcDefs.GetLength(); n++ )
  395. CompleteFuncDef(funcDefs[n]);
  396. // Register script methods found in the interfaces
  397. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  398. {
  399. sClassDeclaration *decl = interfaceDeclarations[n];
  400. asCScriptNode *node = decl->node->firstChild->next;
  401. // Skip list of inherited interfaces
  402. while( node && node->nodeType == snIdentifier )
  403. node = node->next;
  404. while( node )
  405. {
  406. asCScriptNode *next = node->next;
  407. if( node->nodeType == snFunction )
  408. {
  409. node->DisconnectParent();
  410. RegisterScriptFunctionFromNode(node, decl->script, decl->objType, true, false, 0, decl->isExistingShared);
  411. }
  412. else if( node->nodeType == snVirtualProperty )
  413. {
  414. node->DisconnectParent();
  415. RegisterVirtualProperty(node, decl->script, decl->objType, true, false, 0, decl->isExistingShared);
  416. }
  417. node = next;
  418. }
  419. }
  420. // Register script methods found in the classes
  421. for( n = 0; n < classDeclarations.GetLength(); n++ )
  422. {
  423. sClassDeclaration *decl = classDeclarations[n];
  424. asCScriptNode *node = decl->node->firstChild->next;
  425. // Skip list of classes and interfaces
  426. while( node && node->nodeType == snIdentifier )
  427. node = node->next;
  428. while( node )
  429. {
  430. asCScriptNode *next = node->next;
  431. if( node->nodeType == snFunction )
  432. {
  433. node->DisconnectParent();
  434. RegisterScriptFunctionFromNode(node, decl->script, decl->objType, false, false, 0, decl->isExistingShared);
  435. }
  436. else if( node->nodeType == snVirtualProperty )
  437. {
  438. node->DisconnectParent();
  439. RegisterVirtualProperty(node, decl->script, decl->objType, false, false, 0, decl->isExistingShared);
  440. }
  441. node = next;
  442. }
  443. // Make sure the default factory & constructor exists for classes
  444. if( decl->objType->beh.construct == engine->scriptTypeBehaviours.beh.construct )
  445. {
  446. if( decl->objType->beh.constructors.GetLength() == 1 || engine->ep.alwaysImplDefaultConstruct )
  447. {
  448. AddDefaultConstructor(decl->objType, decl->script);
  449. }
  450. else
  451. {
  452. // As the class has another constructor we shouldn't provide the default constructor
  453. if( decl->objType->beh.construct )
  454. {
  455. engine->scriptFunctions[decl->objType->beh.construct]->Release();
  456. decl->objType->beh.construct = 0;
  457. decl->objType->beh.constructors.RemoveIndex(0);
  458. }
  459. if( decl->objType->beh.factory )
  460. {
  461. engine->scriptFunctions[decl->objType->beh.factory]->Release();
  462. decl->objType->beh.factory = 0;
  463. decl->objType->beh.factories.RemoveIndex(0);
  464. }
  465. // Only remove the opAssign method if the script hasn't provided one
  466. if( decl->objType->beh.copy == engine->scriptTypeBehaviours.beh.copy )
  467. {
  468. engine->scriptFunctions[decl->objType->beh.copy]->Release();
  469. decl->objType->beh.copy = 0;
  470. }
  471. }
  472. }
  473. }
  474. // Find other global nodes
  475. for( n = 0; n < scripts.GetLength(); n++ )
  476. {
  477. // Find other global nodes
  478. asCScriptNode *node = parsers[n]->GetScriptNode();
  479. RegisterNonTypesFromScript(node, scripts[n], engine->nameSpaces[0]);
  480. }
  481. }
  482. for( n = 0; n < parsers.GetLength(); n++ )
  483. {
  484. asDELETE(parsers[n],asCParser);
  485. }
  486. }
  487. void asCBuilder::RegisterTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns)
  488. {
  489. asASSERT(node->nodeType == snScript);
  490. // Find structure definitions first
  491. node = node->firstChild;
  492. while( node )
  493. {
  494. asCScriptNode *next = node->next;
  495. if( node->nodeType == snNamespace )
  496. {
  497. // Recursively register the entities defined in the namespace
  498. asCString nsName;
  499. nsName.Assign(&script->code[node->firstChild->tokenPos], node->firstChild->tokenLength);
  500. if( ns->name != "" )
  501. nsName = ns->name + "::" + nsName;
  502. asSNameSpace *nsChild = engine->AddNameSpace(nsName.AddressOf());
  503. RegisterTypesFromScript(node->lastChild, script, nsChild);
  504. }
  505. else
  506. {
  507. if( node->nodeType == snClass )
  508. {
  509. node->DisconnectParent();
  510. RegisterClass(node, script, ns);
  511. }
  512. else if( node->nodeType == snInterface )
  513. {
  514. node->DisconnectParent();
  515. RegisterInterface(node, script, ns);
  516. }
  517. else if( node->nodeType == snEnum )
  518. {
  519. node->DisconnectParent();
  520. RegisterEnum(node, script, ns);
  521. }
  522. else if( node->nodeType == snTypedef )
  523. {
  524. node->DisconnectParent();
  525. RegisterTypedef(node, script, ns);
  526. }
  527. else if( node->nodeType == snFuncDef )
  528. {
  529. node->DisconnectParent();
  530. RegisterFuncDef(node, script, ns);
  531. }
  532. else if( node->nodeType == snMixin )
  533. {
  534. node->DisconnectParent();
  535. RegisterMixinClass(node, script, ns);
  536. }
  537. }
  538. node = next;
  539. }
  540. }
  541. void asCBuilder::RegisterNonTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns)
  542. {
  543. node = node->firstChild;
  544. while( node )
  545. {
  546. asCScriptNode *next = node->next;
  547. if( node->nodeType == snNamespace )
  548. {
  549. // Determine the name of the namespace
  550. asCString nsName;
  551. nsName.Assign(&script->code[node->firstChild->tokenPos], node->firstChild->tokenLength);
  552. if( ns->name != "" )
  553. nsName = ns->name + "::" + nsName;
  554. // Declare the namespace, then add the entities
  555. asSNameSpace *nsChild = engine->AddNameSpace(nsName.AddressOf());
  556. RegisterNonTypesFromScript(node->lastChild, script, nsChild);
  557. }
  558. else
  559. {
  560. node->DisconnectParent();
  561. if( node->nodeType == snFunction )
  562. RegisterScriptFunctionFromNode(node, script, 0, false, true, ns);
  563. else if( node->nodeType == snDeclaration )
  564. RegisterGlobalVar(node, script, ns);
  565. else if( node->nodeType == snVirtualProperty )
  566. RegisterVirtualProperty(node, script, 0, false, true, ns);
  567. else if( node->nodeType == snImport )
  568. RegisterImportedFunction(module->GetNextImportedFunctionId(), node, script, ns);
  569. else
  570. {
  571. // Unused script node
  572. int r, c;
  573. script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  574. WriteWarning(script->name, TXT_UNUSED_SCRIPT_NODE, r, c);
  575. node->Destroy(engine);
  576. }
  577. }
  578. node = next;
  579. }
  580. }
  581. void asCBuilder::CompileFunctions()
  582. {
  583. // Compile each function
  584. for( asUINT n = 0; n < functions.GetLength(); n++ )
  585. {
  586. sFunctionDescription *current = functions[n];
  587. if( current == 0 ) continue;
  588. // Don't compile the function again if it was an existing shared function
  589. if( current->isExistingShared ) continue;
  590. asCCompiler compiler(engine);
  591. asCScriptFunction *func = engine->scriptFunctions[current->funcId];
  592. // Find the class declaration for constructors
  593. sClassDeclaration *classDecl = 0;
  594. if( current->objType && current->name == current->objType->name )
  595. {
  596. for( asUINT n = 0; n < classDeclarations.GetLength(); n++ )
  597. {
  598. if( classDeclarations[n]->objType == current->objType )
  599. {
  600. classDecl = classDeclarations[n];
  601. break;
  602. }
  603. }
  604. asASSERT( classDecl );
  605. }
  606. if( current->node )
  607. {
  608. int r, c;
  609. current->script->ConvertPosToRowCol(current->node->tokenPos, &r, &c);
  610. asCString str = func->GetDeclarationStr();
  611. str.Format(TXT_COMPILING_s, str.AddressOf());
  612. WriteInfo(current->script->name, str, r, c, true);
  613. // When compiling a constructor need to pass the class declaration for member initializations
  614. compiler.CompileFunction(this, current->script, current->paramNames, current->node, func, classDecl);
  615. engine->preMessage.isSet = false;
  616. }
  617. else if( current->objType && current->name == current->objType->name )
  618. {
  619. asCScriptNode *node = classDecl->node;
  620. int r = 0, c = 0;
  621. if( node )
  622. current->script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  623. asCString str = func->GetDeclarationStr();
  624. str.Format(TXT_COMPILING_s, str.AddressOf());
  625. WriteInfo(current->script->name, str, r, c, true);
  626. // This is the default constructor that is generated
  627. // automatically if not implemented by the user.
  628. compiler.CompileDefaultConstructor(this, current->script, node, func, classDecl);
  629. engine->preMessage.isSet = false;
  630. }
  631. else
  632. {
  633. asASSERT( false );
  634. }
  635. }
  636. }
  637. #endif
  638. // Called from module and engine
  639. int asCBuilder::ParseDataType(const char *datatype, asCDataType *result, asSNameSpace *implicitNamespace, bool isReturnType)
  640. {
  641. Reset();
  642. asCScriptCode source;
  643. source.SetCode("", datatype, true);
  644. asCParser parser(this);
  645. int r = parser.ParseDataType(&source, isReturnType);
  646. if( r < 0 )
  647. return asINVALID_TYPE;
  648. // Get data type and property name
  649. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  650. *result = CreateDataTypeFromNode(dataType, &source, implicitNamespace, true);
  651. if( isReturnType )
  652. *result = ModifyDataTypeFromNode(*result, dataType->next, &source, 0, 0);
  653. if( numErrors > 0 )
  654. return asINVALID_TYPE;
  655. return asSUCCESS;
  656. }
  657. int asCBuilder::ParseTemplateDecl(const char *decl, asCString *name, asCArray<asCString> &subtypeNames)
  658. {
  659. Reset();
  660. asCScriptCode source;
  661. source.SetCode("", decl, true);
  662. asCParser parser(this);
  663. int r = parser.ParseTemplateDecl(&source);
  664. if( r < 0 )
  665. return asINVALID_TYPE;
  666. // Get the template name and subtype names
  667. asCScriptNode *node = parser.GetScriptNode()->firstChild;
  668. name->Assign(&decl[node->tokenPos], node->tokenLength);
  669. while( (node = node->next) != 0 )
  670. {
  671. asCString subtypeName;
  672. subtypeName.Assign(&decl[node->tokenPos], node->tokenLength);
  673. subtypeNames.PushLast(subtypeName);
  674. }
  675. // TODO: template: check for name conflicts
  676. if( numErrors > 0 )
  677. return asINVALID_DECLARATION;
  678. return asSUCCESS;
  679. }
  680. int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &name, asCDataType &type, asSNameSpace *ns)
  681. {
  682. // Either datatype or namespace must be informed
  683. asASSERT( dt || ns );
  684. Reset();
  685. if( dt )
  686. {
  687. // Verify that the object type exist
  688. if( dt->GetObjectType() == 0 )
  689. return asINVALID_OBJECT;
  690. }
  691. // Check property declaration and type
  692. asCScriptCode source;
  693. source.SetCode(TXT_PROPERTY, decl, true);
  694. asCParser parser(this);
  695. int r = parser.ParsePropertyDeclaration(&source);
  696. if( r < 0 )
  697. return asINVALID_DECLARATION;
  698. // Get data type and property name
  699. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  700. asCScriptNode *nameNode = dataType->next;
  701. // If an object property is registered, then use the
  702. // object's namespace, otherwise use the specified namespace
  703. type = CreateDataTypeFromNode(dataType, &source, dt ? dt->GetObjectType()->nameSpace : ns);
  704. name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength);
  705. // Validate that the type really can be a registered property
  706. // We cannot use CanBeInstantiated, as it is allowed to register
  707. // properties of type that cannot otherwise be instantiated
  708. if( type.GetFuncDef() && !type.IsObjectHandle() )
  709. {
  710. // Function definitions must always be handles
  711. return asINVALID_DECLARATION;
  712. }
  713. // Verify property name
  714. if( dt )
  715. {
  716. if( CheckNameConflictMember(dt->GetObjectType(), name.AddressOf(), nameNode, &source, true) < 0 )
  717. return asNAME_TAKEN;
  718. }
  719. else
  720. {
  721. if( CheckNameConflict(name.AddressOf(), nameNode, &source, ns) < 0 )
  722. return asNAME_TAKEN;
  723. }
  724. if( numErrors > 0 )
  725. return asINVALID_DECLARATION;
  726. return asSUCCESS;
  727. }
  728. #ifndef AS_NO_COMPILER
  729. asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *prop)
  730. {
  731. asASSERT(obj.GetObjectType() != 0);
  732. // TODO: optimize: Improve linear search
  733. asCArray<asCObjectProperty *> &props = obj.GetObjectType()->properties;
  734. for( asUINT n = 0; n < props.GetLength(); n++ )
  735. {
  736. if( props[n]->name == prop )
  737. {
  738. if( module->accessMask & props[n]->accessMask )
  739. return props[n];
  740. else
  741. return 0;
  742. }
  743. }
  744. return 0;
  745. }
  746. #endif
  747. bool asCBuilder::DoesGlobalPropertyExist(const char *prop, asSNameSpace *ns, asCGlobalProperty **outProp, sGlobalVariableDescription **outDesc, bool *isAppProp)
  748. {
  749. if( outProp ) *outProp = 0;
  750. if( outDesc ) *outDesc = 0;
  751. if( isAppProp ) *isAppProp = false;
  752. // Check application registered properties
  753. asCString name(prop);
  754. asCGlobalProperty *globProp = engine->registeredGlobalProps.GetFirst(ns, name);
  755. if( globProp )
  756. {
  757. if( isAppProp ) *isAppProp = true;
  758. if( outProp ) *outProp = globProp;
  759. return true;
  760. }
  761. #ifndef AS_NO_COMPILER
  762. // Check properties being compiled now
  763. sGlobalVariableDescription* desc = globVariables.GetFirst(ns, prop);
  764. if( desc && !desc->isEnumValue )
  765. {
  766. if( outProp ) *outProp = desc->property;
  767. if( outDesc ) *outDesc = desc;
  768. return true;
  769. }
  770. #endif
  771. // Check previously compiled global variables
  772. if( module )
  773. {
  774. globProp = module->scriptGlobals.GetFirst(ns, prop);
  775. if( globProp )
  776. {
  777. if( outProp ) *outProp = globProp;
  778. return true;
  779. }
  780. }
  781. return false;
  782. }
  783. asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace *ns, bool *isCompiled, bool *isPureConstant, asQWORD *constantValue, bool *isAppProp)
  784. {
  785. if( isCompiled ) *isCompiled = true;
  786. if( isPureConstant ) *isPureConstant = false;
  787. if( isAppProp ) *isAppProp = false;
  788. if( constantValue ) *constantValue = 0;
  789. asCGlobalProperty *globProp = 0;
  790. sGlobalVariableDescription *globDesc = 0;
  791. if( DoesGlobalPropertyExist(prop, ns, &globProp, &globDesc, isAppProp) )
  792. {
  793. #ifndef AS_NO_COMPILER
  794. if( globDesc )
  795. {
  796. // The property was declared in this build call, check if it has been compiled successfully already
  797. if( isCompiled ) *isCompiled = globDesc->isCompiled;
  798. if( isPureConstant ) *isPureConstant = globDesc->isPureConstant;
  799. if( constantValue ) *constantValue = globDesc->constantValue;
  800. }
  801. else
  802. #endif
  803. if( isAppProp )
  804. {
  805. // Don't return the property if the module doesn't have access to it
  806. if( !(module->accessMask & globProp->accessMask) )
  807. globProp = 0;
  808. }
  809. return globProp;
  810. }
  811. return 0;
  812. }
  813. int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern)
  814. {
  815. asASSERT( objType || ns );
  816. // TODO: Can't we use GetParsedFunctionDetails to do most of what is done in this function?
  817. Reset();
  818. asCScriptCode source;
  819. source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);
  820. asCParser parser(this);
  821. int r = parser.ParseFunctionDefinition(&source, listPattern != 0);
  822. if( r < 0 )
  823. return asINVALID_DECLARATION;
  824. asCScriptNode *node = parser.GetScriptNode();
  825. // Determine scope
  826. asCScriptNode *n = node->firstChild->next->next;
  827. asCString scope = GetScopeFromNode(n, &source, &n);
  828. func->nameSpace = engine->FindNameSpace(scope.AddressOf());
  829. if( func->nameSpace == 0 )
  830. return asINVALID_DECLARATION;
  831. // Find name
  832. func->name.Assign(&source.code[n->tokenPos], n->tokenLength);
  833. // Initialize a script function object for registration
  834. bool autoHandle;
  835. // Scoped reference types are allowed to use handle when returned from application functions
  836. func->returnType = CreateDataTypeFromNode(node->firstChild, &source, objType ? objType->nameSpace : ns, true, objType);
  837. func->returnType = ModifyDataTypeFromNode(func->returnType, node->firstChild->next, &source, 0, &autoHandle);
  838. if( autoHandle && (!func->returnType.IsObjectHandle() || func->returnType.IsReference()) )
  839. return asINVALID_DECLARATION;
  840. if( returnAutoHandle ) *returnAutoHandle = autoHandle;
  841. // Reference types cannot be returned by value from system functions
  842. if( isSystemFunction &&
  843. (func->returnType.GetObjectType() &&
  844. (func->returnType.GetObjectType()->flags & asOBJ_REF)) &&
  845. !(func->returnType.IsReference() ||
  846. func->returnType.IsObjectHandle()) )
  847. return asINVALID_DECLARATION;
  848. // Count number of parameters
  849. int paramCount = 0;
  850. asCScriptNode *paramList = n->next;
  851. n = paramList->firstChild;
  852. while( n )
  853. {
  854. paramCount++;
  855. n = n->next->next;
  856. if( n && n->nodeType == snIdentifier )
  857. n = n->next;
  858. if( n && n->nodeType == snExpression )
  859. n = n->next;
  860. }
  861. // Preallocate memory
  862. func->parameterTypes.Allocate(paramCount, false);
  863. func->parameterNames.SetLength(paramCount);
  864. func->inOutFlags.Allocate(paramCount, false);
  865. func->defaultArgs.Allocate(paramCount, false);
  866. if( paramAutoHandles ) paramAutoHandles->Allocate(paramCount, false);
  867. n = paramList->firstChild;
  868. asUINT index = 0;
  869. while( n )
  870. {
  871. asETypeModifiers inOutFlags;
  872. asCDataType type = CreateDataTypeFromNode(n, &source, objType ? objType->nameSpace : ns, false, objType);
  873. type = ModifyDataTypeFromNode(type, n->next, &source, &inOutFlags, &autoHandle);
  874. // Reference types cannot be passed by value to system functions
  875. if( isSystemFunction &&
  876. (type.GetObjectType() &&
  877. (type.GetObjectType()->flags & asOBJ_REF)) &&
  878. !(type.IsReference() ||
  879. type.IsObjectHandle()) )
  880. return asINVALID_DECLARATION;
  881. // Store the parameter type
  882. func->parameterTypes.PushLast(type);
  883. func->inOutFlags.PushLast(inOutFlags);
  884. // Don't permit void parameters
  885. if( type.GetTokenType() == ttVoid )
  886. return asINVALID_DECLARATION;
  887. if( autoHandle && (!type.IsObjectHandle() || type.IsReference()) )
  888. return asINVALID_DECLARATION;
  889. if( paramAutoHandles ) paramAutoHandles->PushLast(autoHandle);
  890. // Make sure that var type parameters are references
  891. if( type.GetTokenType() == ttQuestion &&
  892. !type.IsReference() )
  893. return asINVALID_DECLARATION;
  894. // Move to next parameter
  895. n = n->next->next;
  896. if( n && n->nodeType == snIdentifier ) {
  897. func->parameterNames[index] = asCString(&source.code[n->tokenPos], n->tokenLength);
  898. n = n->next;
  899. }
  900. ++index;
  901. if( n && n->nodeType == snExpression )
  902. {
  903. // Strip out white space and comments to better share the string
  904. asCString *defaultArgStr = asNEW(asCString);
  905. if( defaultArgStr )
  906. {
  907. *defaultArgStr = GetCleanExpressionString(n, &source);
  908. func->defaultArgs.PushLast(defaultArgStr);
  909. }
  910. n = n->next;
  911. }
  912. else
  913. func->defaultArgs.PushLast(0);
  914. }
  915. // Set the read-only flag if const is declared after parameter list
  916. n = paramList->next;
  917. if( n && n->nodeType == snUndefined && n->tokenType == ttConst )
  918. {
  919. if( objType == 0 )
  920. return asINVALID_DECLARATION;
  921. func->isReadOnly = true;
  922. n = n->next;
  923. }
  924. else
  925. func->isReadOnly = false;
  926. // If the caller expects a list pattern, check for the existence, else report an error if not
  927. if( listPattern )
  928. {
  929. if( n == 0 || n->nodeType != snListPattern )
  930. return asINVALID_DECLARATION;
  931. else
  932. {
  933. *listPattern = n;
  934. n->DisconnectParent();
  935. }
  936. }
  937. else
  938. {
  939. if( n )
  940. return asINVALID_DECLARATION;
  941. }
  942. // Make sure the default args are declared correctly
  943. ValidateDefaultArgs(&source, node, func);
  944. if( numErrors > 0 || numWarnings > 0 )
  945. return asINVALID_DECLARATION;
  946. return 0;
  947. }
  948. int asCBuilder::ParseVariableDeclaration(const char *decl, asSNameSpace *implicitNamespace, asCString &outName, asSNameSpace *&outNamespace, asCDataType &outDt)
  949. {
  950. Reset();
  951. asCScriptCode source;
  952. source.SetCode(TXT_VARIABLE_DECL, decl, true);
  953. asCParser parser(this);
  954. int r = parser.ParsePropertyDeclaration(&source);
  955. if( r < 0 )
  956. return asINVALID_DECLARATION;
  957. asCScriptNode *node = parser.GetScriptNode();
  958. // Determine the scope from declaration
  959. asCScriptNode *n = node->firstChild->next;
  960. outNamespace = GetNameSpaceFromNode(n, &source, implicitNamespace, &n);
  961. if( outNamespace == 0 )
  962. return asINVALID_DECLARATION;
  963. // Find name
  964. outName.Assign(&source.code[n->tokenPos], n->tokenLength);
  965. // Initialize a script variable object for registration
  966. outDt = CreateDataTypeFromNode(node->firstChild, &source, implicitNamespace);
  967. if( numErrors > 0 || numWarnings > 0 )
  968. return asINVALID_DECLARATION;
  969. return 0;
  970. }
  971. int asCBuilder::CheckNameConflictMember(asCObjectType *t, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty)
  972. {
  973. // It's not necessary to check against object types
  974. // TODO: optimize: Improve linear search
  975. asCArray<asCObjectProperty *> &props = t->properties;
  976. for( asUINT n = 0; n < props.GetLength(); n++ )
  977. {
  978. if( props[n]->name == name )
  979. {
  980. if( code )
  981. {
  982. asCString str;
  983. str.Format(TXT_NAME_CONFLICT_s_OBJ_PROPERTY, name);
  984. WriteError(str, code, node);
  985. }
  986. return -1;
  987. }
  988. }
  989. // Property names must be checked against method names
  990. if( isProperty )
  991. {
  992. asCArray<int> methods = t->methods;
  993. for( asUINT n = 0; n < methods.GetLength(); n++ )
  994. {
  995. if( engine->scriptFunctions[methods[n]]->name == name )
  996. {
  997. if( code )
  998. {
  999. asCString str;
  1000. str.Format(TXT_NAME_CONFLICT_s_METHOD, name);
  1001. WriteError(str, code, node);
  1002. }
  1003. return -1;
  1004. }
  1005. }
  1006. }
  1007. return 0;
  1008. }
  1009. int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns)
  1010. {
  1011. // Check against registered object types
  1012. // TODO: Must check against registered funcdefs too
  1013. if( engine->GetRegisteredObjectType(name, ns) != 0 )
  1014. {
  1015. if( code )
  1016. {
  1017. asCString str;
  1018. str.Format(TXT_NAME_CONFLICT_s_EXTENDED_TYPE, name);
  1019. WriteError(str, code, node);
  1020. }
  1021. return -1;
  1022. }
  1023. // Check against global properties
  1024. if( DoesGlobalPropertyExist(name, ns) )
  1025. {
  1026. if( code )
  1027. {
  1028. asCString str;
  1029. str.Format(TXT_NAME_CONFLICT_s_GLOBAL_PROPERTY, name);
  1030. WriteError(str, code, node);
  1031. }
  1032. return -1;
  1033. }
  1034. // TODO: Property names must be checked against function names
  1035. #ifndef AS_NO_COMPILER
  1036. // Check against class types
  1037. asUINT n;
  1038. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1039. {
  1040. if( classDeclarations[n]->name == name &&
  1041. classDeclarations[n]->objType->nameSpace == ns )
  1042. {
  1043. if( code )
  1044. {
  1045. asCString str;
  1046. str.Format(TXT_NAME_CONFLICT_s_STRUCT, name);
  1047. WriteError(str, code, node);
  1048. }
  1049. return -1;
  1050. }
  1051. }
  1052. // Check against named types
  1053. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  1054. {
  1055. if( namedTypeDeclarations[n]->name == name &&
  1056. namedTypeDeclarations[n]->objType->nameSpace == ns )
  1057. {
  1058. if( code )
  1059. {
  1060. asCString str;
  1061. str.Format(TXT_NAME_CONFLICT_s_IS_NAMED_TYPE, name);
  1062. WriteError(str, code, node);
  1063. }
  1064. return -1;
  1065. }
  1066. }
  1067. // Must check for name conflicts with funcdefs
  1068. for( n = 0; n < funcDefs.GetLength(); n++ )
  1069. {
  1070. if( funcDefs[n]->name == name &&
  1071. module->funcDefs[funcDefs[n]->idx]->nameSpace == ns )
  1072. {
  1073. if( code )
  1074. {
  1075. asCString str;
  1076. str.Format(TXT_NAME_CONFLICT_s_IS_FUNCDEF, name);
  1077. WriteError(str, code, node);
  1078. }
  1079. return -1;
  1080. }
  1081. }
  1082. // Check against mixin classes
  1083. if( GetMixinClass(name, ns) )
  1084. {
  1085. if( code )
  1086. {
  1087. asCString str;
  1088. str.Format(TXT_NAME_CONFLICT_s_IS_MIXIN, name);
  1089. WriteError(str, code, node);
  1090. }
  1091. return -1;
  1092. }
  1093. #endif
  1094. return 0;
  1095. }
  1096. #ifndef AS_NO_COMPILER
  1097. sMixinClass *asCBuilder::GetMixinClass(const char *name, asSNameSpace *ns)
  1098. {
  1099. for( asUINT n = 0; n < mixinClasses.GetLength(); n++ )
  1100. if( mixinClasses[n]->name == name &&
  1101. mixinClasses[n]->ns == ns )
  1102. return mixinClasses[n];
  1103. return 0;
  1104. }
  1105. int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1106. {
  1107. // Find the name
  1108. asASSERT( node->firstChild->nodeType == snDataType );
  1109. asCScriptNode *n = node->firstChild->next->next;
  1110. asCString name;
  1111. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  1112. // Check for name conflict with other types
  1113. int r = CheckNameConflict(name.AddressOf(), node, file, ns);
  1114. if( asSUCCESS != r )
  1115. {
  1116. node->Destroy(engine);
  1117. return r;
  1118. }
  1119. // The function definition should be stored as a asCScriptFunction so that the application
  1120. // can use the asIScriptFunction interface to enumerate the return type and parameters
  1121. // The return type and parameter types aren't determined in this function. A second pass is
  1122. // necessary after all type declarations have been identified. The second pass is implemented
  1123. // in CompleteFuncDef().
  1124. sFuncDef *fd = asNEW(sFuncDef);
  1125. if( fd == 0 )
  1126. {
  1127. node->Destroy(engine);
  1128. return asOUT_OF_MEMORY;
  1129. }
  1130. fd->name = name;
  1131. fd->node = node;
  1132. fd->script = file;
  1133. fd->idx = module->AddFuncDef(name, ns);
  1134. funcDefs.PushLast(fd);
  1135. return 0;
  1136. }
  1137. void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
  1138. {
  1139. asCArray<asCString *> defaultArgs;
  1140. bool isConstMethod;
  1141. bool isConstructor;
  1142. bool isDestructor;
  1143. bool isPrivate;
  1144. bool isOverride;
  1145. bool isFinal;
  1146. bool isShared;
  1147. asCScriptFunction *func = module->funcDefs[funcDef->idx];
  1148. asASSERT( func );
  1149. GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal, isShared, func->nameSpace);
  1150. // There should not be any defaultArgs, but if there are any we need to delete them to avoid leaks
  1151. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1152. if( defaultArgs[n] )
  1153. asDELETE(defaultArgs[n], asCString);
  1154. // TODO: Should we force the use of 'shared' for this check to be done?
  1155. // Check if there is another identical funcdef from another module and if so reuse that instead
  1156. for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
  1157. {
  1158. asCScriptFunction *f2 = engine->funcDefs[n];
  1159. if( f2 == 0 || func == f2 )
  1160. continue;
  1161. if( f2->name == func->name &&
  1162. f2->nameSpace == func->nameSpace &&
  1163. f2->IsSignatureExceptNameEqual(func) )
  1164. {
  1165. // Replace our funcdef for the existing one
  1166. funcDef->idx = f2->id;
  1167. module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
  1168. f2->AddRef();
  1169. engine->funcDefs.RemoveValue(func);
  1170. func->Release();
  1171. // funcdefs aren't destroyed when the refCount reaches zero so we need to manually delete them
  1172. asDELETE(func, asCScriptFunction);
  1173. break;
  1174. }
  1175. }
  1176. }
  1177. int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1178. {
  1179. // Has the application disabled global vars?
  1180. if( engine->ep.disallowGlobalVars )
  1181. WriteError(TXT_GLOBAL_VARS_NOT_ALLOWED, file, node);
  1182. // What data type is it?
  1183. asCDataType type = CreateDataTypeFromNode(node->firstChild, file, ns);
  1184. if( !type.CanBeInstantiated() )
  1185. {
  1186. asCString str;
  1187. if( type.IsAbstractClass() )
  1188. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, type.Format().AddressOf());
  1189. else if( type.IsInterface() )
  1190. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, type.Format().AddressOf());
  1191. else
  1192. // TODO: Improve error message to explain why
  1193. str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format().AddressOf());
  1194. WriteError(str, file, node);
  1195. }
  1196. asCScriptNode *n = node->firstChild->next;
  1197. while( n )
  1198. {
  1199. // Verify that the name isn't taken
  1200. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1201. CheckNameConflict(name.AddressOf(), n, file, ns);
  1202. // Register the global variable
  1203. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  1204. if( gvar == 0 )
  1205. {
  1206. node->Destroy(engine);
  1207. return asOUT_OF_MEMORY;
  1208. }
  1209. gvar->script = file;
  1210. gvar->name = name;
  1211. gvar->isCompiled = false;
  1212. gvar->datatype = type;
  1213. gvar->isEnumValue = false;
  1214. gvar->ns = ns;
  1215. // TODO: Give error message if wrong
  1216. asASSERT(!gvar->datatype.IsReference());
  1217. // Allocation is done when the variable is compiled, to allow for autos
  1218. gvar->property = 0;
  1219. gvar->index = 0;
  1220. globVariables.Put(gvar);
  1221. gvar->declaredAtNode = n;
  1222. n = n->next;
  1223. gvar->declaredAtNode->DisconnectParent();
  1224. gvar->initializationNode = 0;
  1225. if( n &&
  1226. ( n->nodeType == snAssignment ||
  1227. n->nodeType == snArgList ||
  1228. n->nodeType == snInitList ) )
  1229. {
  1230. gvar->initializationNode = n;
  1231. n = n->next;
  1232. gvar->initializationNode->DisconnectParent();
  1233. }
  1234. }
  1235. node->Destroy(engine);
  1236. return 0;
  1237. }
  1238. int asCBuilder::RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1239. {
  1240. asCScriptNode *cl = node->firstChild;
  1241. asASSERT( cl->nodeType == snClass );
  1242. asCScriptNode *n = cl->firstChild;
  1243. // Skip potential 'final' and 'shared' tokens
  1244. while( n->tokenType == ttIdentifier &&
  1245. (file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) ||
  1246. file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN)) )
  1247. {
  1248. // Report error, because mixin class cannot be final or shared
  1249. asCString msg;
  1250. msg.Format(TXT_MIXIN_CANNOT_BE_DECLARED_AS_s, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1251. WriteError(msg, file, n);
  1252. asCScriptNode *tmp = n;
  1253. n = n->next;
  1254. // Remove the invalid node, so compilation can continue as if it wasn't there
  1255. tmp->DisconnectParent();
  1256. tmp->Destroy(engine);
  1257. }
  1258. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1259. int r, c;
  1260. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1261. CheckNameConflict(name.AddressOf(), n, file, ns);
  1262. sMixinClass *decl = asNEW(sMixinClass);
  1263. if( decl == 0 )
  1264. {
  1265. node->Destroy(engine);
  1266. return asOUT_OF_MEMORY;
  1267. }
  1268. mixinClasses.PushLast(decl);
  1269. decl->name = name;
  1270. decl->ns = ns;
  1271. decl->node = cl;
  1272. decl->script = file;
  1273. // Clean up memory
  1274. cl->DisconnectParent();
  1275. node->Destroy(engine);
  1276. return 0;
  1277. }
  1278. int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1279. {
  1280. asCScriptNode *n = node->firstChild;
  1281. bool isFinal = false;
  1282. bool isShared = false;
  1283. bool isAbstract = false;
  1284. // Check the class modifiers
  1285. while( n->tokenType == ttIdentifier )
  1286. {
  1287. if( file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) )
  1288. {
  1289. if( isAbstract )
  1290. WriteError(TXT_CLASS_CANT_BE_FINAL_AND_ABSTRACT, file, n);
  1291. else
  1292. {
  1293. if( isFinal )
  1294. {
  1295. asCString msg;
  1296. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1297. WriteWarning(msg, file, n);
  1298. }
  1299. isFinal = true;
  1300. }
  1301. }
  1302. else if( file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN) )
  1303. {
  1304. if( isShared )
  1305. {
  1306. asCString msg;
  1307. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1308. WriteWarning(msg, file, n);
  1309. }
  1310. isShared = true;
  1311. }
  1312. else if( file->TokenEquals(n->tokenPos, n->tokenLength, ABSTRACT_TOKEN) )
  1313. {
  1314. if( isFinal )
  1315. WriteError(TXT_CLASS_CANT_BE_FINAL_AND_ABSTRACT, file, n);
  1316. else
  1317. {
  1318. if( isAbstract )
  1319. {
  1320. asCString msg;
  1321. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1322. WriteWarning(msg, file, n);
  1323. }
  1324. isAbstract = true;
  1325. }
  1326. }
  1327. else
  1328. {
  1329. // This is the name of the class
  1330. break;
  1331. }
  1332. n = n->next;
  1333. }
  1334. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1335. int r, c;
  1336. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1337. CheckNameConflict(name.AddressOf(), n, file, ns);
  1338. sClassDeclaration *decl = asNEW(sClassDeclaration);
  1339. if( decl == 0 )
  1340. {
  1341. node->Destroy(engine);
  1342. return asOUT_OF_MEMORY;
  1343. }
  1344. classDeclarations.PushLast(decl);
  1345. decl->name = name;
  1346. decl->script = file;
  1347. decl->node = node;
  1348. // If this type is shared and there already exist another shared
  1349. // type of the same name, then that one should be used instead of
  1350. // creating a new one.
  1351. if( isShared )
  1352. {
  1353. for( asUINT n = 0; n < engine->classTypes.GetLength(); n++ )
  1354. {
  1355. asCObjectType *st = engine->classTypes[n];
  1356. if( st &&
  1357. st->IsShared() &&
  1358. st->name == name &&
  1359. st->nameSpace == ns &&
  1360. !st->IsInterface() )
  1361. {
  1362. // We'll use the existing type
  1363. decl->isExistingShared = true;
  1364. decl->objType = st;
  1365. module->classTypes.PushLast(st);
  1366. st->AddRef();
  1367. return 0;
  1368. }
  1369. }
  1370. }
  1371. // Create a new object type for this class
  1372. asCObjectType *st = asNEW(asCObjectType)(engine);
  1373. if( st == 0 )
  1374. return asOUT_OF_MEMORY;
  1375. // By default all script classes are marked as garbage collected.
  1376. // Only after the complete structure and relationship between classes
  1377. // is known, can the flag be cleared for those objects that truly cannot
  1378. // form circular references. This is important because a template
  1379. // callback may be called with a script class before the compilation
  1380. // completes, and until it is known, the callback must assume the class
  1381. // is garbage collected.
  1382. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_GC;
  1383. if( isShared )
  1384. st->flags |= asOBJ_SHARED;
  1385. if( isFinal )
  1386. st->flags |= asOBJ_NOINHERIT;
  1387. if( isAbstract )
  1388. st->flags |= asOBJ_ABSTRACT;
  1389. if( node->tokenType == ttHandle )
  1390. st->flags |= asOBJ_IMPLICIT_HANDLE;
  1391. st->size = sizeof(asCScriptObject);
  1392. st->name = name;
  1393. st->nameSpace = ns;
  1394. st->module = module;
  1395. module->classTypes.PushLast(st);
  1396. engine->classTypes.PushLast(st);
  1397. st->AddRef();
  1398. decl->objType = st;
  1399. // Use the default script class behaviours
  1400. st->beh = engine->scriptTypeBehaviours.beh;
  1401. // TODO: Move this to asCObjectType so that the asCRestore can reuse it
  1402. engine->scriptFunctions[st->beh.addref]->AddRef();
  1403. engine->scriptFunctions[st->beh.release]->AddRef();
  1404. engine->scriptFunctions[st->beh.gcEnumReferences]->AddRef();
  1405. engine->scriptFunctions[st->beh.gcGetFlag]->AddRef();
  1406. engine->scriptFunctions[st->beh.gcGetRefCount]->AddRef();
  1407. engine->scriptFunctions[st->beh.gcReleaseAllReferences]->AddRef();
  1408. engine->scriptFunctions[st->beh.gcSetFlag]->AddRef();
  1409. engine->scriptFunctions[st->beh.copy]->AddRef();
  1410. engine->scriptFunctions[st->beh.factory]->AddRef();
  1411. engine->scriptFunctions[st->beh.construct]->AddRef();
  1412. // TODO: weak: Should not do this if the class has been declared with noweak
  1413. engine->scriptFunctions[st->beh.getWeakRefFlag]->AddRef();
  1414. for( asUINT i = 1; i < st->beh.operators.GetLength(); i += 2 )
  1415. engine->scriptFunctions[st->beh.operators[i]]->AddRef();
  1416. return 0;
  1417. }
  1418. int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1419. {
  1420. asCScriptNode *n = node->firstChild;
  1421. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1422. bool isShared = false;
  1423. if( name == SHARED_TOKEN )
  1424. {
  1425. isShared = true;
  1426. n = n->next;
  1427. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  1428. }
  1429. int r, c;
  1430. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1431. CheckNameConflict(name.AddressOf(), n, file, ns);
  1432. sClassDeclaration *decl = asNEW(sClassDeclaration);
  1433. if( decl == 0 )
  1434. {
  1435. node->Destroy(engine);
  1436. return asOUT_OF_MEMORY;
  1437. }
  1438. interfaceDeclarations.PushLast(decl);
  1439. decl->name = name;
  1440. decl->script = file;
  1441. decl->node = node;
  1442. // If this type is shared and there already exist another shared
  1443. // type of the same name, then that one should be used instead of
  1444. // creating a new one.
  1445. if( isShared )
  1446. {
  1447. for( asUINT n = 0; n < engine->classTypes.GetLength(); n++ )
  1448. {
  1449. asCObjectType *st = engine->classTypes[n];
  1450. if( st &&
  1451. st->IsShared() &&
  1452. st->name == name &&
  1453. st->nameSpace == ns &&
  1454. st->IsInterface() )
  1455. {
  1456. // We'll use the existing type
  1457. decl->isExistingShared = true;
  1458. decl->objType = st;
  1459. module->classTypes.PushLast(st);
  1460. st->AddRef();
  1461. return 0;
  1462. }
  1463. }
  1464. }
  1465. // Register the object type for the interface
  1466. asCObjectType *st = asNEW(asCObjectType)(engine);
  1467. if( st == 0 )
  1468. return asOUT_OF_MEMORY;
  1469. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
  1470. if( isShared )
  1471. st->flags |= asOBJ_SHARED;
  1472. st->size = 0; // Cannot be instantiated
  1473. st->name = name;
  1474. st->nameSpace = ns;
  1475. module->classTypes.PushLast(st);
  1476. engine->classTypes.PushLast(st);
  1477. st->AddRef();
  1478. decl->objType = st;
  1479. // Use the default script class behaviours
  1480. st->beh.construct = 0;
  1481. st->beh.addref = engine->scriptTypeBehaviours.beh.addref;
  1482. engine->scriptFunctions[st->beh.addref]->AddRef();
  1483. st->beh.release = engine->scriptTypeBehaviours.beh.release;
  1484. engine->scriptFunctions[st->beh.release]->AddRef();
  1485. st->beh.copy = 0;
  1486. return 0;
  1487. }
  1488. void asCBuilder::CompileGlobalVariables()
  1489. {
  1490. bool compileSucceeded = true;
  1491. // Store state of compilation (errors, warning, output)
  1492. int currNumErrors = numErrors;
  1493. int currNumWarnings = numWarnings;
  1494. // Backup the original message stream
  1495. bool msgCallback = engine->msgCallback;
  1496. asSSystemFunctionInterface msgCallbackFunc = engine->msgCallbackFunc;
  1497. void *msgCallbackObj = engine->msgCallbackObj;
  1498. // Set the new temporary message stream
  1499. asCOutputBuffer outBuffer;
  1500. engine->SetMessageCallback(asMETHOD(asCOutputBuffer, Callback), &outBuffer, asCALL_THISCALL);
  1501. asCOutputBuffer finalOutput;
  1502. asCScriptFunction *initFunc = 0;
  1503. asCSymbolTable<asCGlobalProperty> initOrder;
  1504. // We first try to compile all the primitive global variables, and only after that
  1505. // compile the non-primitive global variables. This permits the constructors
  1506. // for the complex types to use the already initialized variables of primitive
  1507. // type. Note, we currently don't know which global variables are used in the
  1508. // constructors, so we cannot guarantee that variables of complex types are
  1509. // initialized in the correct order, so we won't reorder those.
  1510. bool compilingPrimitives = true;
  1511. // Compile each global variable
  1512. while( compileSucceeded )
  1513. {
  1514. compileSucceeded = false;
  1515. int accumErrors = 0;
  1516. int accumWarnings = 0;
  1517. // Restore state of compilation
  1518. finalOutput.Clear();
  1519. asCSymbolTable<sGlobalVariableDescription>::iterator it = globVariables.List();
  1520. for( ; it; it++ )
  1521. {
  1522. sGlobalVariableDescription *gvar = *it;
  1523. if( gvar->isCompiled )
  1524. continue;
  1525. asCByteCode init(engine);
  1526. numWarnings = 0;
  1527. numErrors = 0;
  1528. outBuffer.Clear();
  1529. // Skip this for now if we're not compiling complex types yet
  1530. if( compilingPrimitives && !gvar->datatype.IsPrimitive() )
  1531. continue;
  1532. if( gvar->declaredAtNode )
  1533. {
  1534. int r, c;
  1535. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &r, &c);
  1536. asCString str = gvar->datatype.Format();
  1537. str += " " + gvar->name;
  1538. str.Format(TXT_COMPILING_s, str.AddressOf());
  1539. WriteInfo(gvar->script->name, str, r, c, true);
  1540. }
  1541. if( gvar->isEnumValue )
  1542. {
  1543. int r;
  1544. if( gvar->initializationNode )
  1545. {
  1546. asCCompiler comp(engine);
  1547. asCScriptFunction func(engine, module, asFUNC_SCRIPT);
  1548. // Set the namespace that should be used during the compilation
  1549. func.nameSpace = gvar->datatype.GetObjectType()->nameSpace;
  1550. // Temporarily switch the type of the variable to int so it can be compiled properly
  1551. asCDataType saveType;
  1552. saveType = gvar->datatype;
  1553. gvar->datatype = asCDataType::CreatePrimitive(ttInt, true);
  1554. r = comp.CompileGlobalVariable(this, gvar->script, gvar->initializationNode, gvar, &func);
  1555. gvar->datatype = saveType;
  1556. // Make the function a dummy so it doesn't try to release objects while destroying the function
  1557. func.funcType = asFUNC_DUMMY;
  1558. }
  1559. else
  1560. {
  1561. r = 0;
  1562. // When there is no assignment the value is the last + 1
  1563. int enumVal = 0;
  1564. asCSymbolTable<sGlobalVariableDescription>::iterator prev_it = it;
  1565. prev_it--;
  1566. if( prev_it )
  1567. {
  1568. sGlobalVariableDescription *gvar2 = *prev_it;
  1569. if(gvar2->datatype == gvar->datatype )
  1570. {
  1571. // The integer value is stored in the lower bytes
  1572. enumVal = (*(int*)&gvar2->constantValue) + 1;
  1573. if( !gvar2->isCompiled )
  1574. {
  1575. int row, col;
  1576. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &row, &col);
  1577. asCString str = gvar->datatype.Format();
  1578. str += " " + gvar->name;
  1579. str.Format(TXT_COMPILING_s, str.AddressOf());
  1580. WriteInfo(gvar->script->name, str, row, col, true);
  1581. str.Format(TXT_UNINITIALIZED_GLOBAL_VAR_s, gvar2->name.AddressOf());
  1582. WriteError(gvar->script->name, str, row, col);
  1583. r = -1;
  1584. }
  1585. }
  1586. }
  1587. // The integer value is stored in the lower bytes
  1588. *(int*)&gvar->constantValue = enumVal;
  1589. }
  1590. if( r >= 0 )
  1591. {
  1592. // Set the value as compiled
  1593. gvar->isCompiled = true;
  1594. compileSucceeded = true;
  1595. }
  1596. }
  1597. else
  1598. {
  1599. // Compile the global variable
  1600. initFunc = asNEW(asCScriptFunction)(engine, module, asFUNC_SCRIPT);
  1601. if( initFunc == 0 )
  1602. {
  1603. // Out of memory
  1604. return;
  1605. }
  1606. // Set the namespace that should be used for this function
  1607. initFunc->nameSpace = gvar->ns;
  1608. asCCompiler comp(engine);
  1609. int r = comp.CompileGlobalVariable(this, gvar->script, gvar->initializationNode, gvar, initFunc);
  1610. if( r >= 0 )
  1611. {
  1612. // Compilation succeeded
  1613. gvar->isCompiled = true;
  1614. compileSucceeded = true;
  1615. }
  1616. else
  1617. {
  1618. // Compilation failed
  1619. initFunc->funcType = asFUNC_DUMMY;
  1620. asDELETE(initFunc, asCScriptFunction);
  1621. initFunc = 0;
  1622. }
  1623. }
  1624. if( gvar->isCompiled )
  1625. {
  1626. // Add warnings for this constant to the total build
  1627. if( numWarnings )
  1628. {
  1629. currNumWarnings += numWarnings;
  1630. if( msgCallback )
  1631. outBuffer.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  1632. }
  1633. // Determine order of variable initializations
  1634. if( gvar->property && !gvar->isEnumValue )
  1635. initOrder.Put(gvar->property);
  1636. // Does the function contain more than just a SUSPEND followed by a RET instruction?
  1637. if( initFunc && initFunc->scriptData->byteCode.GetLength() > 2 )
  1638. {
  1639. // Create the init function for this variable
  1640. initFunc->id = engine->GetNextScriptFunctionId();
  1641. engine->SetScriptFunction(initFunc);
  1642. // Finalize the init function for this variable
  1643. initFunc->returnType = asCDataType::CreatePrimitive(ttVoid, false);
  1644. initFunc->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(gvar->script->name.AddressOf());
  1645. if( gvar->declaredAtNode )
  1646. {
  1647. int row, col;
  1648. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &row, &col);
  1649. initFunc->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20);
  1650. }
  1651. gvar->property->SetInitFunc(initFunc);
  1652. initFunc->Release();
  1653. initFunc = 0;
  1654. }
  1655. else if( initFunc )
  1656. {
  1657. // Destroy the function as it won't be used
  1658. initFunc->funcType = asFUNC_DUMMY;
  1659. asDELETE(initFunc, asCScriptFunction);
  1660. initFunc = 0;
  1661. }
  1662. // Convert enums to true enum values, so subsequent compilations can access it as an enum
  1663. if( gvar->isEnumValue )
  1664. {
  1665. asCObjectType *objectType = gvar->datatype.GetObjectType();
  1666. asASSERT(NULL != objectType);
  1667. asSEnumValue *e = asNEW(asSEnumValue);
  1668. if( e == 0 )
  1669. {
  1670. // Out of memory
  1671. numErrors++;
  1672. return;
  1673. }
  1674. e->name = gvar->name;
  1675. e->value = *(int*)&gvar->constantValue;
  1676. objectType->enumValues.PushLast(e);
  1677. }
  1678. }
  1679. else
  1680. {
  1681. // Add output to final output
  1682. finalOutput.Append(outBuffer);
  1683. accumErrors += numErrors;
  1684. accumWarnings += numWarnings;
  1685. }
  1686. engine->preMessage.isSet = false;
  1687. }
  1688. if( !compileSucceeded )
  1689. {
  1690. if( compilingPrimitives )
  1691. {
  1692. // No more primitives could be compiled, so
  1693. // switch to compiling the complex variables
  1694. compilingPrimitives = false;
  1695. compileSucceeded = true;
  1696. }
  1697. else
  1698. {
  1699. // No more variables can be compiled
  1700. // Add errors and warnings to total build
  1701. currNumWarnings += accumWarnings;
  1702. currNumErrors += accumErrors;
  1703. if( msgCallback )
  1704. finalOutput.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  1705. }
  1706. }
  1707. }
  1708. // Restore states
  1709. engine->msgCallback = msgCallback;
  1710. engine->msgCallbackFunc = msgCallbackFunc;
  1711. engine->msgCallbackObj = msgCallbackObj;
  1712. numWarnings = currNumWarnings;
  1713. numErrors = currNumErrors;
  1714. // Set the correct order of initialization
  1715. if( numErrors == 0 )
  1716. {
  1717. // If the length of the arrays are not the same, then this is the compilation
  1718. // of a single variable, in which case the initialization order of the previous
  1719. // variables must be preserved.
  1720. if( module->scriptGlobals.GetSize() == initOrder.GetSize() )
  1721. module->scriptGlobals.SwapWith(initOrder);
  1722. }
  1723. // Delete the enum expressions
  1724. asCSymbolTableIterator<sGlobalVariableDescription> it = globVariables.List();
  1725. while( it )
  1726. {
  1727. sGlobalVariableDescription *gvar = *it;
  1728. if( gvar->isEnumValue )
  1729. {
  1730. // Remove from symboltable. This has to be done prior to freeing the memeory
  1731. globVariables.Erase(it.GetIndex());
  1732. // Destroy the gvar property
  1733. if( gvar->declaredAtNode )
  1734. {
  1735. gvar->declaredAtNode->Destroy(engine);
  1736. gvar->declaredAtNode = 0;
  1737. }
  1738. if( gvar->initializationNode )
  1739. {
  1740. gvar->initializationNode->Destroy(engine);
  1741. gvar->initializationNode = 0;
  1742. }
  1743. if( gvar->property )
  1744. {
  1745. asDELETE(gvar->property, asCGlobalProperty);
  1746. gvar->property = 0;
  1747. }
  1748. asDELETE(gvar, sGlobalVariableDescription);
  1749. }
  1750. else
  1751. it++;
  1752. }
  1753. }
  1754. int asCBuilder::GetNamespaceAndNameFromNode(asCScriptNode *n, asCScriptCode *script, asSNameSpace *implicitNs, asSNameSpace *&outNs, asCString &outName)
  1755. {
  1756. asASSERT( n->nodeType == snIdentifier );
  1757. // Get the optional scope from the node
  1758. asSNameSpace *ns = GetNameSpaceFromNode(n->firstChild, script, implicitNs, 0);
  1759. if( ns == 0 )
  1760. return -1;
  1761. // Get the name
  1762. asCString name(&script->code[n->lastChild->tokenPos], n->lastChild->tokenLength);
  1763. outNs = ns;
  1764. outName = name;
  1765. return 0;
  1766. }
  1767. void asCBuilder::AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScriptNode *errNode, sMixinClass *mixin)
  1768. {
  1769. // Determine what interfaces that the mixin implements
  1770. asCScriptNode *node = mixin->node;
  1771. asASSERT(node->nodeType == snClass);
  1772. // Skip the name of the mixin
  1773. node = node->firstChild->next;
  1774. while( node && node->nodeType == snIdentifier )
  1775. {
  1776. bool ok = true;
  1777. asSNameSpace *ns;
  1778. asCString name;
  1779. if( GetNamespaceAndNameFromNode(node, mixin->script, mixin->ns, ns, name) < 0 )
  1780. ok = false;
  1781. else
  1782. {
  1783. // Find the object type for the interface
  1784. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  1785. // Check that the object type is an interface
  1786. if( objType && objType->IsInterface() )
  1787. {
  1788. // Only add the interface if the class doesn't already implement it
  1789. if( !decl->objType->Implements(objType) )
  1790. AddInterfaceToClass(decl, errNode, objType);
  1791. }
  1792. else
  1793. {
  1794. WriteError(TXT_MIXIN_CLASS_CANNOT_INHERIT, mixin->script, node);
  1795. ok = false;
  1796. }
  1797. }
  1798. if( !ok )
  1799. {
  1800. // Remove this node so the error isn't reported again
  1801. asCScriptNode *delNode = node;
  1802. node = node->prev;
  1803. delNode->DisconnectParent();
  1804. delNode->Destroy(engine);
  1805. }
  1806. node = node->next;
  1807. }
  1808. }
  1809. void asCBuilder::AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *errNode, asCObjectType *intfType)
  1810. {
  1811. // A shared type may only implement from shared interfaces
  1812. if( decl->objType->IsShared() && !intfType->IsShared() )
  1813. {
  1814. asCString msg;
  1815. msg.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, intfType->name.AddressOf());
  1816. WriteError(msg, decl->script, errNode);
  1817. return;
  1818. }
  1819. if( decl->isExistingShared )
  1820. {
  1821. // If the class is an existing shared class, then just check if the
  1822. // interface exists in the original declaration too
  1823. if( !decl->objType->Implements(intfType) )
  1824. {
  1825. asCString str;
  1826. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  1827. WriteError(str, decl->script, errNode);
  1828. return;
  1829. }
  1830. }
  1831. else
  1832. {
  1833. // If the interface is already in the class then don't add it again
  1834. if( decl->objType->Implements(intfType) )
  1835. return;
  1836. // Add the interface to the class
  1837. decl->objType->interfaces.PushLast(intfType);
  1838. // Add the inherited interfaces too
  1839. // For interfaces this will be done outside to handle out-of-order declarations
  1840. if( !decl->objType->IsInterface() )
  1841. {
  1842. for( asUINT n = 0; n < intfType->interfaces.GetLength(); n++ )
  1843. AddInterfaceToClass(decl, errNode, intfType->interfaces[n]);
  1844. }
  1845. }
  1846. }
  1847. void asCBuilder::CompileInterfaces()
  1848. {
  1849. asUINT n;
  1850. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  1851. {
  1852. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  1853. asCObjectType *intfType = intfDecl->objType;
  1854. asCScriptNode *node = intfDecl->node;
  1855. asASSERT(node && node->nodeType == snInterface);
  1856. node = node->firstChild;
  1857. // Skip the 'shared' keyword
  1858. if( intfType->IsShared() )
  1859. node = node->next;
  1860. // Skip the name
  1861. node = node->next;
  1862. // Verify the inherited interfaces
  1863. while( node && node->nodeType == snIdentifier )
  1864. {
  1865. asSNameSpace *ns;
  1866. asCString name;
  1867. if( GetNamespaceAndNameFromNode(node, intfDecl->script, intfType->nameSpace, ns, name) < 0 )
  1868. {
  1869. node = node->next;
  1870. continue;
  1871. }
  1872. // Find the object type for the interface
  1873. asCObjectType *objType = 0;
  1874. while( ns )
  1875. {
  1876. objType = GetObjectType(name.AddressOf(), ns);
  1877. if( objType ) break;
  1878. ns = GetParentNameSpace(ns);
  1879. }
  1880. // Check that the object type is an interface
  1881. bool ok = true;
  1882. if( objType && objType->IsInterface() )
  1883. {
  1884. // Check that the implemented interface is shared if the base interface is shared
  1885. if( intfType->IsShared() && !objType->IsShared() )
  1886. {
  1887. asCString str;
  1888. str.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, objType->GetName());
  1889. WriteError(str, intfDecl->script, node);
  1890. ok = false;
  1891. }
  1892. }
  1893. else
  1894. {
  1895. WriteError(TXT_INTERFACE_CAN_ONLY_IMPLEMENT_INTERFACE, intfDecl->script, node);
  1896. ok = false;
  1897. }
  1898. if( ok )
  1899. {
  1900. // Make sure none of the implemented interfaces implement from this one
  1901. asCObjectType *base = objType;
  1902. while( base != 0 )
  1903. {
  1904. if( base == intfType )
  1905. {
  1906. WriteError(TXT_CANNOT_IMPLEMENT_SELF, intfDecl->script, node);
  1907. ok = false;
  1908. break;
  1909. }
  1910. // At this point there is at most one implemented interface
  1911. if( base->interfaces.GetLength() )
  1912. base = base->interfaces[0];
  1913. else
  1914. break;
  1915. }
  1916. }
  1917. if( ok )
  1918. AddInterfaceToClass(intfDecl, node, objType);
  1919. // Remove the nodes so they aren't parsed again
  1920. asCScriptNode *delNode = node;
  1921. node = node->next;
  1922. delNode->DisconnectParent();
  1923. delNode->Destroy(engine);
  1924. }
  1925. }
  1926. // Order the interfaces with inheritances so that the inherited
  1927. // of inherited interfaces can be added properly
  1928. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  1929. {
  1930. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  1931. asCObjectType *intfType = intfDecl->objType;
  1932. if( intfType->interfaces.GetLength() == 0 ) continue;
  1933. // If any of the derived interfaces are found after this interface, then move this to the end of the list
  1934. for( asUINT m = n+1; m < interfaceDeclarations.GetLength(); m++ )
  1935. {
  1936. if( intfType->Implements(interfaceDeclarations[m]->objType) )
  1937. {
  1938. interfaceDeclarations.RemoveIndex(n);
  1939. interfaceDeclarations.PushLast(intfDecl);
  1940. // Decrease index so that we don't skip an entry
  1941. n--;
  1942. break;
  1943. }
  1944. }
  1945. }
  1946. // Now recursively add the additional inherited interfaces
  1947. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  1948. {
  1949. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  1950. asCObjectType *intfType = intfDecl->objType;
  1951. // TODO: 2.28.1: Is this really at the correct place? Hasn't the vfTableIdx already been set here?
  1952. // Co-opt the vfTableIdx value in our own methods to indicate the
  1953. // index the function should have in the table chunk for this interface.
  1954. for( asUINT d = 0; d < intfType->methods.GetLength(); d++ )
  1955. {
  1956. asCScriptFunction *func = GetFunctionDescription(intfType->methods[d]);
  1957. func->vfTableIdx = d;
  1958. asASSERT(func->objectType == intfType);
  1959. }
  1960. // As new interfaces will be added to the end of the list, all
  1961. // interfaces will be traversed the same as recursively
  1962. for( asUINT m = 0; m < intfType->interfaces.GetLength(); m++ )
  1963. {
  1964. asCObjectType *base = intfType->interfaces[m];
  1965. // Add any interfaces not already implemented
  1966. for( asUINT l = 0; l < base->interfaces.GetLength(); l++ )
  1967. AddInterfaceToClass(intfDecl, intfDecl->node, base->interfaces[l]);
  1968. // Add the methods from the implemented interface
  1969. for( asUINT m = 0; m < base->methods.GetLength(); m++ )
  1970. {
  1971. // If the derived interface implements the same method, then don't add the base interface' method
  1972. asCScriptFunction *baseFunc = GetFunctionDescription(base->methods[m]);
  1973. asCScriptFunction *derivedFunc = 0;
  1974. bool found = false;
  1975. for( asUINT d = 0; d < intfType->methods.GetLength(); d++ )
  1976. {
  1977. derivedFunc = GetFunctionDescription(intfType->methods[d]);
  1978. if( derivedFunc->IsSignatureEqual(baseFunc) )
  1979. {
  1980. found = true;
  1981. break;
  1982. }
  1983. }
  1984. if( !found )
  1985. {
  1986. // Add the method
  1987. intfType->methods.PushLast(baseFunc->id);
  1988. baseFunc->AddRef();
  1989. }
  1990. }
  1991. }
  1992. }
  1993. }
  1994. void asCBuilder::CompileClasses()
  1995. {
  1996. asUINT n;
  1997. asCArray<sClassDeclaration*> toValidate((int)classDeclarations.GetLength());
  1998. // Determine class inheritances and interfaces
  1999. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2000. {
  2001. sClassDeclaration *decl = classDeclarations[n];
  2002. asCScriptCode *file = decl->script;
  2003. // Find the base class that this class inherits from
  2004. bool multipleInheritance = false;
  2005. asCScriptNode *node = decl->node->firstChild;
  2006. while( file->TokenEquals(node->tokenPos, node->tokenLength, FINAL_TOKEN) ||
  2007. file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) ||
  2008. file->TokenEquals(node->tokenPos, node->tokenLength, ABSTRACT_TOKEN) )
  2009. {
  2010. node = node->next;
  2011. }
  2012. // Skip the name of the class
  2013. asASSERT(node->tokenType == ttIdentifier);
  2014. node = node->next;
  2015. while( node && node->nodeType == snIdentifier )
  2016. {
  2017. asSNameSpace *ns;
  2018. asCString name;
  2019. if( GetNamespaceAndNameFromNode(node, file, decl->objType->nameSpace, ns, name) < 0 )
  2020. {
  2021. node = node->next;
  2022. continue;
  2023. }
  2024. // Find the object type for the interface
  2025. asCObjectType *objType = 0;
  2026. sMixinClass *mixin = 0;
  2027. asSNameSpace *origNs = ns;
  2028. while( ns )
  2029. {
  2030. objType = GetObjectType(name.AddressOf(), ns);
  2031. if( objType == 0 )
  2032. mixin = GetMixinClass(name.AddressOf(), ns);
  2033. if( objType || mixin )
  2034. break;
  2035. ns = GetParentNameSpace(ns);
  2036. }
  2037. if( objType == 0 && mixin == 0 )
  2038. {
  2039. asCString str;
  2040. if( origNs->name == "" )
  2041. str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, name.AddressOf());
  2042. else
  2043. str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, name.AddressOf(), origNs->name.AddressOf());
  2044. WriteError(str, file, node);
  2045. }
  2046. else if( mixin )
  2047. {
  2048. AddInterfaceFromMixinToClass(decl, node, mixin);
  2049. }
  2050. else if( !(objType->flags & asOBJ_SCRIPT_OBJECT) ||
  2051. objType->flags & asOBJ_NOINHERIT )
  2052. {
  2053. // Either the class is not a script class or interface
  2054. // or the class has been declared as 'final'
  2055. asCString str;
  2056. str.Format(TXT_CANNOT_INHERIT_FROM_s_FINAL, objType->name.AddressOf());
  2057. WriteError(str, file, node);
  2058. }
  2059. else if( objType->size != 0 )
  2060. {
  2061. // The class inherits from another script class
  2062. if( !decl->isExistingShared && decl->objType->derivedFrom != 0 )
  2063. {
  2064. if( !multipleInheritance )
  2065. {
  2066. WriteError(TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES, file, node);
  2067. multipleInheritance = true;
  2068. }
  2069. }
  2070. else
  2071. {
  2072. // Make sure none of the base classes inherit from this one
  2073. asCObjectType *base = objType;
  2074. bool error = false;
  2075. while( base != 0 )
  2076. {
  2077. if( base == decl->objType )
  2078. {
  2079. WriteError(TXT_CANNOT_INHERIT_FROM_SELF, file, node);
  2080. error = true;
  2081. break;
  2082. }
  2083. base = base->derivedFrom;
  2084. }
  2085. if( !error )
  2086. {
  2087. // A shared type may only inherit from other shared types
  2088. if( (decl->objType->IsShared()) && !(objType->IsShared()) )
  2089. {
  2090. asCString msg;
  2091. msg.Format(TXT_SHARED_CANNOT_INHERIT_FROM_NON_SHARED_s, objType->name.AddressOf());
  2092. WriteError(msg, file, node);
  2093. error = true;
  2094. }
  2095. }
  2096. if( !error )
  2097. {
  2098. if( decl->isExistingShared )
  2099. {
  2100. // Verify that the base class is the same as the original shared type
  2101. if( decl->objType->derivedFrom != objType )
  2102. {
  2103. asCString str;
  2104. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  2105. WriteError(str, file, node);
  2106. }
  2107. }
  2108. else
  2109. {
  2110. // Set the base class
  2111. decl->objType->derivedFrom = objType;
  2112. objType->AddRef();
  2113. }
  2114. }
  2115. }
  2116. }
  2117. else
  2118. {
  2119. // The class implements an interface
  2120. AddInterfaceToClass(decl, node, objType);
  2121. }
  2122. node = node->next;
  2123. }
  2124. }
  2125. // Order class declarations so that base classes are compiled before derived classes.
  2126. // This will allow the derived classes to copy properties and methods in the next step.
  2127. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2128. {
  2129. sClassDeclaration *decl = classDeclarations[n];
  2130. asCObjectType *derived = decl->objType;
  2131. asCObjectType *base = derived->derivedFrom;
  2132. if( base == 0 ) continue;
  2133. // If the base class is found after the derived class, then move the derived class to the end of the list
  2134. for( asUINT m = n+1; m < classDeclarations.GetLength(); m++ )
  2135. {
  2136. sClassDeclaration *declBase = classDeclarations[m];
  2137. if( base == declBase->objType )
  2138. {
  2139. classDeclarations.RemoveIndex(n);
  2140. classDeclarations.PushLast(decl);
  2141. // Decrease index so that we don't skip an entry
  2142. n--;
  2143. break;
  2144. }
  2145. }
  2146. }
  2147. // Go through each of the classes and register the object type descriptions
  2148. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2149. {
  2150. sClassDeclaration *decl = classDeclarations[n];
  2151. if( decl->isExistingShared )
  2152. {
  2153. // Set the declaration as validated already, so that other
  2154. // types that contain this will accept this type
  2155. decl->validState = 1;
  2156. // We'll still validate the declaration to make sure nothing new is
  2157. // added to the shared class that wasn't there in the previous
  2158. // compilation. We do not care if something that is there in the previous
  2159. // declaration is not included in the new declaration though.
  2160. asASSERT( decl->objType->interfaces.GetLength() == decl->objType->interfaceVFTOffsets.GetLength() );
  2161. }
  2162. // Methods included from mixin classes should take precedence over inherited methods
  2163. IncludeMethodsFromMixins(decl);
  2164. // Add all properties and methods from the base class
  2165. if( !decl->isExistingShared && decl->objType->derivedFrom )
  2166. {
  2167. asCObjectType *baseType = decl->objType->derivedFrom;
  2168. // The derived class inherits all interfaces from the base class
  2169. for( unsigned int n = 0; n < baseType->interfaces.GetLength(); n++ )
  2170. {
  2171. if( !decl->objType->Implements(baseType->interfaces[n]) )
  2172. decl->objType->interfaces.PushLast(baseType->interfaces[n]);
  2173. }
  2174. // TODO: Need to check for name conflict with new class methods
  2175. // Copy properties from base class to derived class
  2176. for( asUINT p = 0; p < baseType->properties.GetLength(); p++ )
  2177. {
  2178. asCObjectProperty *prop = AddPropertyToClass(decl, baseType->properties[p]->name, baseType->properties[p]->type, baseType->properties[p]->isPrivate);
  2179. // The properties must maintain the same offset
  2180. asASSERT(prop && prop->byteOffset == baseType->properties[p]->byteOffset); UNUSED_VAR(prop);
  2181. }
  2182. // Copy methods from base class to derived class
  2183. for( asUINT m = 0; m < baseType->methods.GetLength(); m++ )
  2184. {
  2185. // If the derived class implements the same method, then don't add the base class' method
  2186. asCScriptFunction *baseFunc = GetFunctionDescription(baseType->methods[m]);
  2187. asCScriptFunction *derivedFunc = 0;
  2188. bool found = false;
  2189. for( asUINT d = 0; d < decl->objType->methods.GetLength(); d++ )
  2190. {
  2191. derivedFunc = GetFunctionDescription(decl->objType->methods[d]);
  2192. if( derivedFunc->name == baseFunc->name &&
  2193. derivedFunc->IsSignatureExceptNameAndReturnTypeEqual(baseFunc) )
  2194. {
  2195. if( baseFunc->returnType != derivedFunc->returnType )
  2196. {
  2197. asCString msg;
  2198. msg.Format(TXT_DERIVED_METHOD_MUST_HAVE_SAME_RETTYPE_s, baseFunc->GetDeclaration());
  2199. WriteError(msg, decl->script, decl->node);
  2200. }
  2201. if( baseFunc->IsFinal() )
  2202. {
  2203. asCString msg;
  2204. msg.Format(TXT_METHOD_CANNOT_OVERRIDE_s, baseFunc->GetDeclaration());
  2205. WriteError(msg, decl->script, decl->node);
  2206. }
  2207. // Move the function from the methods array to the virtualFunctionTable
  2208. decl->objType->methods.RemoveIndex(d);
  2209. decl->objType->virtualFunctionTable.PushLast(derivedFunc);
  2210. found = true;
  2211. break;
  2212. }
  2213. }
  2214. if( !found )
  2215. {
  2216. // Push the base class function on the virtual function table
  2217. decl->objType->virtualFunctionTable.PushLast(baseType->virtualFunctionTable[m]);
  2218. baseType->virtualFunctionTable[m]->AddRef();
  2219. }
  2220. decl->objType->methods.PushLast(baseType->methods[m]);
  2221. engine->scriptFunctions[baseType->methods[m]]->AddRef();
  2222. }
  2223. }
  2224. if( !decl->isExistingShared )
  2225. {
  2226. // Move this class' methods into the virtual function table
  2227. for( asUINT m = 0; m < decl->objType->methods.GetLength(); m++ )
  2228. {
  2229. asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[m]);
  2230. if( func->funcType != asFUNC_VIRTUAL )
  2231. {
  2232. // Move the reference from the method list to the virtual function list
  2233. decl->objType->methods.RemoveIndex(m);
  2234. decl->objType->virtualFunctionTable.PushLast(func);
  2235. // Substitute the function description in the method list for a virtual method
  2236. // Make sure the methods are in the same order as the virtual function table
  2237. decl->objType->methods.PushLast(CreateVirtualFunction(func, (int)decl->objType->virtualFunctionTable.GetLength() - 1));
  2238. m--;
  2239. }
  2240. }
  2241. // Make virtual function table chunks for each implemented interface
  2242. for( asUINT n = 0; n < decl->objType->interfaces.GetLength(); n++ )
  2243. {
  2244. asCObjectType *intf = decl->objType->interfaces[n];
  2245. // Add all the interface's functions to the virtual function table
  2246. asUINT offset = asUINT(decl->objType->virtualFunctionTable.GetLength());
  2247. decl->objType->interfaceVFTOffsets.PushLast(offset);
  2248. for( asUINT j = 0; j < intf->methods.GetLength(); j++ )
  2249. {
  2250. asCScriptFunction *intfFunc = GetFunctionDescription(intf->methods[j]);
  2251. // Only create the table for functions that are explicitly from this interface,
  2252. // inherited interface methods will be put in that interface's table.
  2253. if( intfFunc->objectType != intf )
  2254. continue;
  2255. asASSERT((asUINT)intfFunc->vfTableIdx == j);
  2256. //Find the interface function in the list of methods
  2257. asCScriptFunction *realFunc = 0;
  2258. for( asUINT p = 0; p < decl->objType->methods.GetLength(); p++ )
  2259. {
  2260. asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[p]);
  2261. if( func->signatureId == intfFunc->signatureId )
  2262. {
  2263. if( func->funcType == asFUNC_VIRTUAL )
  2264. {
  2265. realFunc = decl->objType->virtualFunctionTable[func->vfTableIdx];
  2266. }
  2267. else
  2268. {
  2269. // This should not happen, all methods were moved into the virtual table
  2270. asASSERT(false);
  2271. }
  2272. break;
  2273. }
  2274. }
  2275. // If realFunc is still null, the interface was not
  2276. // implemented and we error out later in the checks.
  2277. decl->objType->virtualFunctionTable.PushLast(realFunc);
  2278. if( realFunc )
  2279. realFunc->AddRef();
  2280. }
  2281. }
  2282. }
  2283. // Enumerate each of the declared properties
  2284. asCScriptNode *node = decl->node->firstChild->next;
  2285. // Skip list of classes and interfaces
  2286. while( node && node->nodeType == snIdentifier )
  2287. node = node->next;
  2288. while( node )
  2289. {
  2290. if( node->nodeType == snDeclaration )
  2291. {
  2292. asCScriptNode *n = node->firstChild;
  2293. // Is the property declared as private?
  2294. bool isPrivate = false;
  2295. if( n && n->tokenType == ttPrivate )
  2296. {
  2297. isPrivate = true;
  2298. n = n->next;
  2299. }
  2300. // Determine the type of the property
  2301. asCScriptCode *file = decl->script;
  2302. asCDataType dt = CreateDataTypeFromNode(n, file, decl->objType->nameSpace);
  2303. if( decl->objType->IsShared() && dt.GetObjectType() && !dt.GetObjectType()->IsShared() )
  2304. {
  2305. asCString msg;
  2306. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf());
  2307. WriteError(msg, file, node);
  2308. }
  2309. if( dt.IsReadOnly() )
  2310. WriteError(TXT_PROPERTY_CANT_BE_CONST, file, node);
  2311. // Multiple properties can be declared separated by ,
  2312. n = n->next;
  2313. while( n )
  2314. {
  2315. asCString name(&file->code[n->tokenPos], n->tokenLength);
  2316. if( !decl->isExistingShared )
  2317. {
  2318. CheckNameConflictMember(decl->objType, name.AddressOf(), n, file, true);
  2319. AddPropertyToClass(decl, name, dt, isPrivate, file, n);
  2320. }
  2321. else
  2322. {
  2323. // Verify that the property exists in the original declaration
  2324. bool found = false;
  2325. for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ )
  2326. {
  2327. asCObjectProperty *prop = decl->objType->properties[p];
  2328. if( prop->isPrivate == isPrivate &&
  2329. prop->name == name &&
  2330. prop->type.IsEqualExceptRef(dt) )
  2331. {
  2332. found = true;
  2333. break;
  2334. }
  2335. }
  2336. if( !found )
  2337. {
  2338. asCString str;
  2339. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  2340. WriteError(str, file, n);
  2341. }
  2342. }
  2343. // Skip the initialization node
  2344. if( n->next && n->next->nodeType != snIdentifier )
  2345. n = n->next;
  2346. n = n->next;
  2347. }
  2348. }
  2349. else
  2350. asASSERT(false);
  2351. node = node->next;
  2352. }
  2353. // Add properties from included mixin classes that don't conflict with existing properties
  2354. IncludePropertiesFromMixins(decl);
  2355. if( !decl->isExistingShared )
  2356. toValidate.PushLast(decl);
  2357. asASSERT( decl->objType->interfaces.GetLength() == decl->objType->interfaceVFTOffsets.GetLength() );
  2358. }
  2359. // TODO: Warn if a method overrides a base method without marking it as 'override'.
  2360. // It must be possible to turn off this warning through engine property.
  2361. // TODO: A base class should be able to mark a method as 'abstract'. This will
  2362. // allow a base class to provide a partial implementation, but still force
  2363. // derived classes to implement specific methods.
  2364. // Verify that all interface methods are implemented in the classes
  2365. // We do this here so the base class' methods have already been inherited
  2366. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2367. {
  2368. sClassDeclaration *decl = classDeclarations[n];
  2369. if( decl->isExistingShared ) continue;
  2370. asCArray<bool> overrideValidations(decl->objType->GetMethodCount());
  2371. for( asUINT k = 0; k < decl->objType->methods.GetLength(); k++ )
  2372. overrideValidations.PushLast( !static_cast<asCScriptFunction*>(decl->objType->GetMethodByIndex(k, false))->IsOverride() );
  2373. for( asUINT m = 0; m < decl->objType->interfaces.GetLength(); m++ )
  2374. {
  2375. asCObjectType *objType = decl->objType->interfaces[m];
  2376. for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
  2377. {
  2378. // Only check the interface methods that was explicitly declared in this interface
  2379. // Methods that was inherited from other interfaces will be checked in those interfaces
  2380. if( objType != engine->scriptFunctions[objType->methods[i]]->objectType )
  2381. continue;
  2382. asUINT overrideIndex;
  2383. if( !DoesMethodExist(decl->objType, objType->methods[i], &overrideIndex) )
  2384. {
  2385. asCString str;
  2386. str.Format(TXT_MISSING_IMPLEMENTATION_OF_s,
  2387. engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
  2388. WriteError(str, decl->script, decl->node);
  2389. }
  2390. else
  2391. overrideValidations[overrideIndex] = true;
  2392. }
  2393. }
  2394. bool hasBaseClass = decl->objType->derivedFrom != 0;
  2395. for( asUINT j = 0; j < overrideValidations.GetLength(); j++ )
  2396. {
  2397. if( !overrideValidations[j] && (!hasBaseClass || !DoesMethodExist(decl->objType->derivedFrom, decl->objType->methods[j])) )
  2398. {
  2399. asCString msg;
  2400. msg.Format(TXT_METHOD_s_DOES_NOT_OVERRIDE, decl->objType->GetMethodByIndex(j, false)->GetDeclaration());
  2401. WriteError(msg, decl->script, decl->node);
  2402. }
  2403. }
  2404. }
  2405. // Verify that the declared structures are valid, e.g. that the structure
  2406. // doesn't contain a member of its own type directly or indirectly
  2407. while( toValidate.GetLength() > 0 )
  2408. {
  2409. asUINT numClasses = (asUINT)toValidate.GetLength();
  2410. asCArray<sClassDeclaration*> toValidateNext((int)toValidate.GetLength());
  2411. while( toValidate.GetLength() > 0 )
  2412. {
  2413. sClassDeclaration *decl = toValidate[toValidate.GetLength()-1];
  2414. int validState = 1;
  2415. for( asUINT n = 0; n < decl->objType->properties.GetLength(); n++ )
  2416. {
  2417. // A valid structure is one that uses only primitives or other valid objects
  2418. asCObjectProperty *prop = decl->objType->properties[n];
  2419. asCDataType dt = prop->type;
  2420. if( dt.IsTemplate() )
  2421. {
  2422. asCDataType sub = dt;
  2423. while( sub.IsTemplate() && !sub.IsObjectHandle() )
  2424. sub = sub.GetSubType();
  2425. dt = sub;
  2426. }
  2427. if( dt.IsObject() && !dt.IsObjectHandle() )
  2428. {
  2429. // Find the class declaration
  2430. sClassDeclaration *pdecl = 0;
  2431. for( asUINT p = 0; p < classDeclarations.GetLength(); p++ )
  2432. {
  2433. if( classDeclarations[p]->objType == dt.GetObjectType() )
  2434. {
  2435. pdecl = classDeclarations[p];
  2436. break;
  2437. }
  2438. }
  2439. if( pdecl )
  2440. {
  2441. if( pdecl->objType == decl->objType )
  2442. {
  2443. WriteError(TXT_ILLEGAL_MEMBER_TYPE, decl->script, decl->node);
  2444. validState = 2;
  2445. break;
  2446. }
  2447. else if( pdecl->validState != 1 )
  2448. {
  2449. validState = pdecl->validState;
  2450. break;
  2451. }
  2452. }
  2453. }
  2454. }
  2455. if( validState == 1 )
  2456. {
  2457. decl->validState = 1;
  2458. toValidate.PopLast();
  2459. }
  2460. else if( validState == 2 )
  2461. {
  2462. decl->validState = 2;
  2463. toValidate.PopLast();
  2464. }
  2465. else
  2466. {
  2467. toValidateNext.PushLast(toValidate.PopLast());
  2468. }
  2469. }
  2470. toValidate = toValidateNext;
  2471. toValidateNext.SetLength(0);
  2472. if( numClasses == toValidate.GetLength() )
  2473. {
  2474. WriteError(TXT_ILLEGAL_MEMBER_TYPE, toValidate[0]->script, toValidate[0]->node);
  2475. break;
  2476. }
  2477. }
  2478. if( numErrors > 0 ) return;
  2479. // Verify which script classes can really form circular references, and mark only those as garbage collected.
  2480. // TODO: runtime optimize: This algorithm can be further improved by checking the types that inherits from
  2481. // a base class. If the base class is not shared all the classes that derive from it
  2482. // are known at compile time, and can thus be checked for potential circular references too.
  2483. //
  2484. // Observe, that doing this would conflict with another potential future feature, which is to
  2485. // allow incremental builds, i.e. allow application to add or replace classes in an
  2486. // existing module. However, the applications that want to use that should use a special
  2487. // build flag to not finalize the module.
  2488. // Urho3D: disable garbage collection from script classes
  2489. /*
  2490. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2491. {
  2492. sClassDeclaration *decl = classDeclarations[n];
  2493. // Existing shared classes won't be re-evaluated
  2494. if( decl->isExistingShared ) continue;
  2495. asCObjectType *ot = decl->objType;
  2496. // Is there some path in which this structure is involved in circular references?
  2497. bool gc = false;
  2498. for( asUINT p = 0; p < ot->properties.GetLength(); p++ )
  2499. {
  2500. asCDataType dt = ot->properties[p]->type;
  2501. if( !dt.IsObject() )
  2502. continue;
  2503. if( dt.IsObjectHandle() )
  2504. {
  2505. // If it is known that the handle can't be involved in a circular reference
  2506. // then this object doesn't need to be marked as garbage collected.
  2507. asCObjectType *prop = dt.GetObjectType();
  2508. if( prop->flags & asOBJ_SCRIPT_OBJECT )
  2509. {
  2510. // For script objects, treat non-final classes as if they can contain references
  2511. // as it is not known what derived classes might do. For final types, check all
  2512. // properties to determine if any of those can cause a circular reference.
  2513. if( prop->flags & asOBJ_NOINHERIT )
  2514. {
  2515. for( asUINT sp = 0; sp < prop->properties.GetLength(); sp++ )
  2516. {
  2517. asCDataType sdt = prop->properties[sp]->type;
  2518. if( sdt.IsObject() )
  2519. {
  2520. if( sdt.IsObjectHandle() )
  2521. {
  2522. // TODO: runtime optimize: If the handle is again to a final class, then we can recursively check if the circular reference can occur
  2523. if( sdt.GetObjectType()->flags & (asOBJ_SCRIPT_OBJECT | asOBJ_GC) )
  2524. {
  2525. gc = true;
  2526. break;
  2527. }
  2528. }
  2529. else if( sdt.GetObjectType()->flags & asOBJ_GC )
  2530. {
  2531. // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is.
  2532. // Only if the object is of a type that can reference this type, either directly or indirectly
  2533. gc = true;
  2534. break;
  2535. }
  2536. }
  2537. }
  2538. if( gc )
  2539. break;
  2540. }
  2541. else
  2542. {
  2543. // Assume it is garbage collected as it is not known at compile time what might inherit from this type
  2544. gc = true;
  2545. break;
  2546. }
  2547. }
  2548. else if( prop->flags & asOBJ_GC )
  2549. {
  2550. // If a type is not a script object, adopt its GC flag
  2551. gc = true;
  2552. break;
  2553. }
  2554. }
  2555. else if( dt.GetObjectType()->flags & asOBJ_GC )
  2556. {
  2557. // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is.
  2558. // Only if the object is of a type that can reference this type, either directly or indirectly
  2559. gc = true;
  2560. break;
  2561. }
  2562. }
  2563. // Update the flag in the object type
  2564. if( gc )
  2565. ot->flags |= asOBJ_GC;
  2566. else
  2567. ot->flags &= ~asOBJ_GC;
  2568. }
  2569. */
  2570. }
  2571. void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl)
  2572. {
  2573. asCScriptNode *node = decl->node->firstChild;
  2574. // Skip the class attributes
  2575. while( node->nodeType == snIdentifier &&
  2576. !decl->script->TokenEquals(node->tokenPos, node->tokenLength, decl->name.AddressOf()) )
  2577. node = node->next;
  2578. // Skip the name of the class
  2579. node = node->next;
  2580. // Find the included mixin classes
  2581. while( node && node->nodeType == snIdentifier )
  2582. {
  2583. asSNameSpace *ns;
  2584. asCString name;
  2585. if( GetNamespaceAndNameFromNode(node, decl->script, decl->objType->nameSpace, ns, name) < 0 )
  2586. {
  2587. node = node->next;
  2588. continue;
  2589. }
  2590. sMixinClass *mixin = 0;
  2591. while( ns )
  2592. {
  2593. // Need to make sure the name is not an object type
  2594. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  2595. if( objType == 0 )
  2596. mixin = GetMixinClass(name.AddressOf(), ns);
  2597. if( objType || mixin )
  2598. break;
  2599. ns = GetParentNameSpace(ns);
  2600. }
  2601. if( mixin )
  2602. {
  2603. // Find methods from mixin declaration
  2604. asCScriptNode *n = mixin->node->firstChild;
  2605. // Skip to the member declarations
  2606. // Possible keywords 'final' and 'shared' are removed in RegisterMixinClass so we don't need to worry about those here
  2607. while( n && n->nodeType == snIdentifier )
  2608. n = n->next;
  2609. // Add methods from the mixin that are not already existing in the class
  2610. while( n )
  2611. {
  2612. if( n->nodeType == snFunction )
  2613. {
  2614. // Instead of disconnecting the node, we need to clone it, otherwise other
  2615. // classes that include the same mixin will not see the methods
  2616. asCScriptNode *copy = n->CreateCopy(engine);
  2617. // Register the method, but only if it doesn't already exist in the class
  2618. RegisterScriptFunctionFromNode(copy, mixin->script, decl->objType, false, false, 0, false, true);
  2619. }
  2620. else if( n->nodeType == snVirtualProperty )
  2621. {
  2622. // TODO: mixin: Support virtual properties too
  2623. WriteError("The virtual property syntax is currently not supported for mixin classes", mixin->script, n);
  2624. //RegisterVirtualProperty(node, decl->script, decl->objType, false, false);
  2625. }
  2626. n = n->next;
  2627. }
  2628. }
  2629. node = node->next;
  2630. }
  2631. }
  2632. void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl)
  2633. {
  2634. asCScriptNode *node = decl->node->firstChild;
  2635. // Skip the class attributes
  2636. while( node->nodeType == snIdentifier &&
  2637. !decl->script->TokenEquals(node->tokenPos, node->tokenLength, decl->name.AddressOf()) )
  2638. node = node->next;
  2639. // Skip the name of the class
  2640. node = node->next;
  2641. // Find the included mixin classes
  2642. while( node && node->nodeType == snIdentifier )
  2643. {
  2644. asSNameSpace *ns;
  2645. asCString name;
  2646. if( GetNamespaceAndNameFromNode(node, decl->script, decl->objType->nameSpace, ns, name) < 0 )
  2647. {
  2648. node = node->next;
  2649. continue;
  2650. }
  2651. sMixinClass *mixin = 0;
  2652. while( ns )
  2653. {
  2654. // Need to make sure the name is not an object type
  2655. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  2656. if( objType == 0 )
  2657. mixin = GetMixinClass(name.AddressOf(), ns);
  2658. if( objType || mixin )
  2659. break;
  2660. ns = GetParentNameSpace(ns);
  2661. }
  2662. if( mixin )
  2663. {
  2664. // Find properties from mixin declaration
  2665. asCScriptNode *n = mixin->node->firstChild;
  2666. // Skip to the member declarations
  2667. // Possible keywords 'final' and 'shared' are removed in RegisterMixinClass so we don't need to worry about those here
  2668. while( n && n->nodeType == snIdentifier )
  2669. n = n->next;
  2670. // Add properties from the mixin that are not already existing in the class
  2671. while( n )
  2672. {
  2673. if( n->nodeType == snDeclaration )
  2674. {
  2675. asCScriptNode *n2 = n->firstChild;
  2676. bool isPrivate = false;
  2677. if( n2 && n2->tokenType == ttPrivate )
  2678. {
  2679. isPrivate = true;
  2680. n2 = n2->next;
  2681. }
  2682. asCScriptCode *file = mixin->script;
  2683. asCDataType dt = CreateDataTypeFromNode(n2, file, mixin->ns);
  2684. if( decl->objType->IsShared() && dt.GetObjectType() && !dt.GetObjectType()->IsShared() )
  2685. {
  2686. asCString msg;
  2687. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf());
  2688. WriteError(msg, file, n);
  2689. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  2690. }
  2691. if( dt.IsReadOnly() )
  2692. WriteError(TXT_PROPERTY_CANT_BE_CONST, file, n);
  2693. n2 = n2->next;
  2694. while( n2 )
  2695. {
  2696. asCString name(&file->code[n2->tokenPos], n2->tokenLength);
  2697. // Add the property only if it doesn't already exist in the class
  2698. bool exists = false;
  2699. for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ )
  2700. if( decl->objType->properties[p]->name == name )
  2701. {
  2702. exists = true;
  2703. break;
  2704. }
  2705. if( !exists )
  2706. {
  2707. if( !decl->isExistingShared )
  2708. {
  2709. // It must not conflict with the name of methods
  2710. int r = CheckNameConflictMember(decl->objType, name.AddressOf(), n2, file, true);
  2711. if( r < 0 )
  2712. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  2713. AddPropertyToClass(decl, name, dt, isPrivate, file, n2);
  2714. }
  2715. else
  2716. {
  2717. // Verify that the property exists in the original declaration
  2718. bool found = false;
  2719. for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ )
  2720. {
  2721. asCObjectProperty *prop = decl->objType->properties[p];
  2722. if( prop->isPrivate == isPrivate &&
  2723. prop->name == name &&
  2724. prop->type == dt )
  2725. {
  2726. found = true;
  2727. break;
  2728. }
  2729. }
  2730. if( !found )
  2731. {
  2732. asCString str;
  2733. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  2734. WriteError(str, decl->script, decl->node);
  2735. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  2736. }
  2737. }
  2738. }
  2739. // Skip the initialization expression
  2740. if( n2->next && n2->next->nodeType != snIdentifier )
  2741. n2 = n2->next;
  2742. n2 = n2->next;
  2743. }
  2744. }
  2745. n = n->next;
  2746. }
  2747. }
  2748. node = node->next;
  2749. }
  2750. }
  2751. int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
  2752. {
  2753. asCScriptFunction *vf = asNEW(asCScriptFunction)(engine, module, asFUNC_VIRTUAL);
  2754. if( vf == 0 )
  2755. return asOUT_OF_MEMORY;
  2756. vf->name = func->name;
  2757. vf->returnType = func->returnType;
  2758. vf->parameterTypes = func->parameterTypes;
  2759. vf->inOutFlags = func->inOutFlags;
  2760. vf->id = engine->GetNextScriptFunctionId();
  2761. vf->isReadOnly = func->isReadOnly;
  2762. vf->objectType = func->objectType;
  2763. vf->signatureId = func->signatureId;
  2764. vf->isPrivate = func->isPrivate;
  2765. vf->isFinal = func->isFinal;
  2766. vf->isOverride = func->isOverride;
  2767. vf->vfTableIdx = idx;
  2768. // It is not necessary to copy the default args, as they have no meaning in the virtual function
  2769. module->AddScriptFunction(vf);
  2770. // Add a dummy to the builder so that it doesn't mix up function ids
  2771. functions.PushLast(0);
  2772. return vf->id;
  2773. }
  2774. asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const asCString &name, const asCDataType &dt, bool isPrivate, asCScriptCode *file, asCScriptNode *node)
  2775. {
  2776. // If the declaration node is not given, then
  2777. // this property is inherited from a base class
  2778. if( node )
  2779. {
  2780. // Check if the property is allowed
  2781. if( !dt.CanBeInstantiated() )
  2782. {
  2783. if( file && node )
  2784. {
  2785. asCString str;
  2786. if( dt.IsAbstractClass() )
  2787. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format().AddressOf());
  2788. else if( dt.IsInterface() )
  2789. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format().AddressOf());
  2790. else
  2791. // TODO: Improve error message to explain why
  2792. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
  2793. WriteError(str, file, node);
  2794. }
  2795. return 0;
  2796. }
  2797. // Register the initialization expression (if any) to be compiled later
  2798. asCScriptNode *declNode = node;
  2799. asCScriptNode *initNode = 0;
  2800. if( node->next && node->next->nodeType != snIdentifier )
  2801. {
  2802. asASSERT( node->next->nodeType == snAssignment );
  2803. initNode = node->next;
  2804. }
  2805. sPropertyInitializer p(name, declNode, initNode, file);
  2806. decl->propInits.PushLast(p);
  2807. }
  2808. // Add the property to the object type
  2809. return decl->objType->AddPropertyToClass(name, dt, isPrivate);
  2810. }
  2811. bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex)
  2812. {
  2813. asCScriptFunction *method = GetFunctionDescription(methodId);
  2814. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  2815. {
  2816. asCScriptFunction *m = GetFunctionDescription(objType->methods[n]);
  2817. if( m->name != method->name ) continue;
  2818. if( m->returnType != method->returnType ) continue;
  2819. if( m->isReadOnly != method->isReadOnly ) continue;
  2820. if( m->parameterTypes != method->parameterTypes ) continue;
  2821. if( m->inOutFlags != method->inOutFlags ) continue;
  2822. if( methodIndex )
  2823. *methodIndex = n;
  2824. return true;
  2825. }
  2826. return false;
  2827. }
  2828. void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file)
  2829. {
  2830. int funcId = engine->GetNextScriptFunctionId();
  2831. asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false);
  2832. asCArray<asCDataType> parameterTypes;
  2833. asCArray<asETypeModifiers> inOutFlags;
  2834. asCArray<asCString *> defaultArgs;
  2835. asCArray<asCString> parameterNames;
  2836. // Add the script function
  2837. // TODO: declaredAt should be set to where the class has been declared
  2838. module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, objType);
  2839. // Set it as default constructor
  2840. if( objType->beh.construct )
  2841. engine->scriptFunctions[objType->beh.construct]->Release();
  2842. objType->beh.construct = funcId;
  2843. objType->beh.constructors[0] = funcId;
  2844. engine->scriptFunctions[funcId]->AddRef();
  2845. // The bytecode for the default constructor will be generated
  2846. // only after the potential inheritance has been established
  2847. sFunctionDescription *func = asNEW(sFunctionDescription);
  2848. if( func == 0 )
  2849. {
  2850. // Out of memory
  2851. return;
  2852. }
  2853. functions.PushLast(func);
  2854. func->script = file;
  2855. func->node = 0;
  2856. func->name = objType->name;
  2857. func->objType = objType;
  2858. func->funcId = funcId;
  2859. func->isExistingShared = false;
  2860. // Add a default factory as well
  2861. funcId = engine->GetNextScriptFunctionId();
  2862. if( objType->beh.factory )
  2863. engine->scriptFunctions[objType->beh.factory]->Release();
  2864. objType->beh.factory = funcId;
  2865. objType->beh.factories[0] = funcId;
  2866. returnType = asCDataType::CreateObjectHandle(objType, false);
  2867. // TODO: should be the same as the constructor
  2868. module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false);
  2869. functions.PushLast(0);
  2870. asCCompiler compiler(engine);
  2871. compiler.CompileFactory(this, file, engine->scriptFunctions[funcId]);
  2872. engine->scriptFunctions[funcId]->AddRef();
  2873. // If the object is shared, then the factory must also be marked as shared
  2874. if( objType->flags & asOBJ_SHARED )
  2875. engine->scriptFunctions[funcId]->isShared = true;
  2876. }
  2877. int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  2878. {
  2879. // Is it a shared enum?
  2880. bool isShared = false;
  2881. asCObjectType *existingSharedType = 0;
  2882. asCScriptNode *tmp = node->firstChild;
  2883. if( tmp->nodeType == snIdentifier && file->TokenEquals(tmp->tokenPos, tmp->tokenLength, SHARED_TOKEN) )
  2884. {
  2885. isShared = true;
  2886. tmp = tmp->next;
  2887. }
  2888. // Grab the name of the enumeration
  2889. asCString name;
  2890. asASSERT(snDataType == tmp->nodeType);
  2891. asASSERT(snIdentifier == tmp->firstChild->nodeType);
  2892. name.Assign(&file->code[tmp->firstChild->tokenPos], tmp->firstChild->tokenLength);
  2893. if( isShared )
  2894. {
  2895. // Look for a pre-existing shared enum with the same signature
  2896. for( asUINT n = 0; n < engine->classTypes.GetLength(); n++ )
  2897. {
  2898. asCObjectType *o = engine->classTypes[n];
  2899. if( o &&
  2900. o->IsShared() &&
  2901. (o->flags & asOBJ_ENUM) &&
  2902. o->name == name &&
  2903. o->nameSpace == ns )
  2904. {
  2905. existingSharedType = o;
  2906. break;
  2907. }
  2908. }
  2909. }
  2910. // Check the name and add the enum
  2911. int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns);
  2912. if( asSUCCESS == r )
  2913. {
  2914. asCObjectType *st;
  2915. if( existingSharedType )
  2916. st = existingSharedType;
  2917. else
  2918. {
  2919. st = asNEW(asCObjectType)(engine);
  2920. if( st == 0 )
  2921. return asOUT_OF_MEMORY;
  2922. st->flags = asOBJ_ENUM;
  2923. if( isShared )
  2924. st->flags |= asOBJ_SHARED;
  2925. st->size = 4;
  2926. st->name = name;
  2927. st->nameSpace = ns;
  2928. }
  2929. module->enumTypes.PushLast(st);
  2930. st->AddRef();
  2931. // TODO: cleanup: Should the enum type really be stored in the engine->classTypes?
  2932. // http://www.gamedev.net/topic/616912-c-header-file-shared-with-scripts/page__gopid__4895940
  2933. if( !existingSharedType )
  2934. engine->classTypes.PushLast(st);
  2935. // Store the location of this declaration for reference in name collisions
  2936. sClassDeclaration *decl = asNEW(sClassDeclaration);
  2937. if( decl == 0 )
  2938. return asOUT_OF_MEMORY;
  2939. decl->name = name;
  2940. decl->script = file;
  2941. decl->objType = st;
  2942. namedTypeDeclarations.PushLast(decl);
  2943. asCDataType type = CreateDataTypeFromNode(tmp, file, ns);
  2944. asASSERT(!type.IsReference());
  2945. // Register the enum values
  2946. tmp = tmp->next;
  2947. while( tmp )
  2948. {
  2949. asASSERT(snIdentifier == tmp->nodeType);
  2950. asCString name(&file->code[tmp->tokenPos], tmp->tokenLength);
  2951. if( existingSharedType )
  2952. {
  2953. // If this is a pre-existent shared enum, then just double check
  2954. // that the value is already defined in the original declaration
  2955. bool found = false;
  2956. for( size_t n = 0; n < st->enumValues.GetLength(); n++ )
  2957. if( st->enumValues[n]->name == name )
  2958. {
  2959. found = true;
  2960. break;
  2961. }
  2962. if( !found )
  2963. {
  2964. asCString str;
  2965. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, st->GetName());
  2966. WriteError(str, file, tmp);
  2967. break;
  2968. }
  2969. tmp = tmp->next;
  2970. if( tmp && tmp->nodeType == snAssignment )
  2971. tmp = tmp->next;
  2972. continue;
  2973. }
  2974. else
  2975. {
  2976. // Check for name conflict errors with other values in the enum
  2977. if( globVariables.GetFirst(ns, name, asCCompGlobVarType(type)) )
  2978. {
  2979. asCString str;
  2980. str.Format(TXT_NAME_CONFLICT_s_ALREADY_USED, name.AddressOf());
  2981. WriteError(str, file, tmp);
  2982. tmp = tmp->next;
  2983. if( tmp && tmp->nodeType == snAssignment )
  2984. tmp = tmp->next;
  2985. continue;
  2986. }
  2987. // Check for assignment
  2988. asCScriptNode *asnNode = tmp->next;
  2989. if( asnNode && snAssignment == asnNode->nodeType )
  2990. asnNode->DisconnectParent();
  2991. else
  2992. asnNode = 0;
  2993. // Create the global variable description so the enum value can be evaluated
  2994. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  2995. if( gvar == 0 )
  2996. return asOUT_OF_MEMORY;
  2997. gvar->script = file;
  2998. gvar->declaredAtNode = tmp;
  2999. tmp = tmp->next;
  3000. gvar->declaredAtNode->DisconnectParent();
  3001. gvar->initializationNode = asnNode;
  3002. gvar->name = name;
  3003. gvar->datatype = type;
  3004. gvar->ns = ns;
  3005. // No need to allocate space on the global memory stack since the values are stored in the asCObjectType
  3006. // Set the index to a negative to allow compiler to diferentiate from ordinary global var when compiling the initialization
  3007. gvar->index = -1;
  3008. gvar->isCompiled = false;
  3009. gvar->isPureConstant = true;
  3010. gvar->isEnumValue = true;
  3011. gvar->constantValue = 0xdeadbeef;
  3012. // Allocate dummy property so we can compile the value.
  3013. // This will be removed later on so we don't add it to the engine.
  3014. gvar->property = asNEW(asCGlobalProperty);
  3015. if( gvar->property == 0 )
  3016. return asOUT_OF_MEMORY;
  3017. gvar->property->name = name;
  3018. gvar->property->nameSpace = ns;
  3019. gvar->property->type = gvar->datatype;
  3020. gvar->property->id = 0;
  3021. globVariables.Put(gvar);
  3022. }
  3023. }
  3024. }
  3025. node->Destroy(engine);
  3026. return r;
  3027. }
  3028. int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  3029. {
  3030. // Get the native data type
  3031. asCScriptNode *tmp = node->firstChild;
  3032. asASSERT(NULL != tmp && snDataType == tmp->nodeType);
  3033. asCDataType dataType;
  3034. dataType.CreatePrimitive(tmp->tokenType, false);
  3035. dataType.SetTokenType(tmp->tokenType);
  3036. tmp = tmp->next;
  3037. // Grab the name of the typedef
  3038. asASSERT(NULL != tmp && NULL == tmp->next);
  3039. asCString name;
  3040. name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength);
  3041. // If the name is not already in use add it
  3042. int r = CheckNameConflict(name.AddressOf(), tmp, file, ns);
  3043. asCObjectType *st = 0;
  3044. if( asSUCCESS == r )
  3045. {
  3046. // Create the new type
  3047. st = asNEW(asCObjectType)(engine);
  3048. if( st == 0 )
  3049. r = asOUT_OF_MEMORY;
  3050. }
  3051. if( asSUCCESS == r )
  3052. {
  3053. st->flags = asOBJ_TYPEDEF;
  3054. st->size = dataType.GetSizeInMemoryBytes();
  3055. st->name = name;
  3056. st->nameSpace = ns;
  3057. st->templateSubTypes.PushLast(dataType);
  3058. st->AddRef();
  3059. module->typeDefs.PushLast(st);
  3060. engine->classTypes.PushLast(st);
  3061. // Store the location of this declaration for reference in name collisions
  3062. sClassDeclaration *decl = asNEW(sClassDeclaration);
  3063. if( decl == 0 )
  3064. r = asOUT_OF_MEMORY;
  3065. else
  3066. {
  3067. decl->name = name;
  3068. decl->script = file;
  3069. decl->objType = st;
  3070. namedTypeDeclarations.PushLast(decl);
  3071. }
  3072. }
  3073. node->Destroy(engine);
  3074. return r;
  3075. }
  3076. void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isOverride, bool &isFinal, bool &isShared, asSNameSpace *implicitNamespace)
  3077. {
  3078. node = node->firstChild;
  3079. // Is the function a private class method?
  3080. isPrivate = false;
  3081. if( node->tokenType == ttPrivate )
  3082. {
  3083. isPrivate = true;
  3084. node = node->next;
  3085. }
  3086. // Is the function shared?
  3087. isShared = false;
  3088. if( node->tokenType == ttIdentifier && file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) )
  3089. {
  3090. isShared = true;
  3091. node = node->next;
  3092. }
  3093. // Find the name
  3094. isConstructor = false;
  3095. isDestructor = false;
  3096. asCScriptNode *n = 0;
  3097. if( node->nodeType == snDataType )
  3098. n = node->next->next;
  3099. else
  3100. {
  3101. // If the first node is a ~ token, then we know it is a destructor
  3102. if( node->tokenType == ttBitNot )
  3103. {
  3104. n = node->next;
  3105. isDestructor = true;
  3106. }
  3107. else
  3108. {
  3109. n = node;
  3110. isConstructor = true;
  3111. }
  3112. }
  3113. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  3114. // Initialize a script function object for registration
  3115. if( !isConstructor && !isDestructor )
  3116. {
  3117. returnType = CreateDataTypeFromNode(node, file, implicitNamespace);
  3118. returnType = ModifyDataTypeFromNode(returnType, node->next, file, 0, 0);
  3119. if( engine->ep.disallowValueAssignForRefType &&
  3120. returnType.GetObjectType() &&
  3121. (returnType.GetObjectType()->flags & asOBJ_REF) &&
  3122. !(returnType.GetObjectType()->flags & asOBJ_SCOPED) &&
  3123. !returnType.IsReference() &&
  3124. !returnType.IsObjectHandle() )
  3125. {
  3126. WriteError(TXT_REF_TYPE_CANT_BE_RETURNED_BY_VAL, file, node);
  3127. }
  3128. }
  3129. else
  3130. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  3131. isConstMethod = false;
  3132. isFinal = false;
  3133. isOverride = false;
  3134. if( objType && n->next->next )
  3135. {
  3136. asCScriptNode *decorator = n->next->next;
  3137. // Is this a const method?
  3138. if( decorator->tokenType == ttConst )
  3139. {
  3140. isConstMethod = true;
  3141. decorator = decorator->next;
  3142. }
  3143. while( decorator )
  3144. {
  3145. if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, FINAL_TOKEN) )
  3146. isFinal = true;
  3147. else if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, OVERRIDE_TOKEN) )
  3148. isOverride = true;
  3149. decorator = decorator->next;
  3150. }
  3151. }
  3152. // Count the number of parameters
  3153. int count = 0;
  3154. asCScriptNode *c = n->next->firstChild;
  3155. while( c )
  3156. {
  3157. count++;
  3158. c = c->next->next;
  3159. if( c && c->nodeType == snIdentifier )
  3160. c = c->next;
  3161. if( c && c->nodeType == snExpression )
  3162. c = c->next;
  3163. }
  3164. // Get the parameter types
  3165. parameterNames.Allocate(count, false);
  3166. parameterTypes.Allocate(count, false);
  3167. inOutFlags.Allocate(count, false);
  3168. defaultArgs.Allocate(count, false);
  3169. n = n->next->firstChild;
  3170. while( n )
  3171. {
  3172. asETypeModifiers inOutFlag;
  3173. asCDataType type = CreateDataTypeFromNode(n, file, implicitNamespace);
  3174. type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);
  3175. if( engine->ep.disallowValueAssignForRefType &&
  3176. type.GetObjectType() &&
  3177. (type.GetObjectType()->flags & asOBJ_REF) &&
  3178. !(type.GetObjectType()->flags & asOBJ_SCOPED) &&
  3179. !type.IsReference() &&
  3180. !type.IsObjectHandle() )
  3181. {
  3182. WriteError(TXT_REF_TYPE_CANT_BE_PASSED_BY_VAL, file, node);
  3183. }
  3184. // Store the parameter type
  3185. parameterTypes.PushLast(type);
  3186. inOutFlags.PushLast(inOutFlag);
  3187. // Move to next parameter
  3188. n = n->next->next;
  3189. if( n && n->nodeType == snIdentifier )
  3190. {
  3191. asCString name;
  3192. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  3193. parameterNames.PushLast(name);
  3194. n = n->next;
  3195. }
  3196. else
  3197. {
  3198. // No name was given for the parameter
  3199. parameterNames.PushLast(asCString());
  3200. }
  3201. if( n && n->nodeType == snExpression )
  3202. {
  3203. // Strip out white space and comments to better share the string
  3204. asCString *defaultArgStr = asNEW(asCString);
  3205. if( defaultArgStr )
  3206. *defaultArgStr = GetCleanExpressionString(n, file);
  3207. defaultArgs.PushLast(defaultArgStr);
  3208. n = n->next;
  3209. }
  3210. else
  3211. defaultArgs.PushLast(0);
  3212. }
  3213. }
  3214. #endif
  3215. asCString asCBuilder::GetCleanExpressionString(asCScriptNode *node, asCScriptCode *file)
  3216. {
  3217. asASSERT(node && node->nodeType == snExpression);
  3218. asCString str;
  3219. str.Assign(file->code + node->tokenPos, node->tokenLength);
  3220. asCString cleanStr;
  3221. for( asUINT n = 0; n < str.GetLength(); )
  3222. {
  3223. int len;
  3224. asETokenClass tok = engine->ParseToken(str.AddressOf() + n, str.GetLength() - n, &len);
  3225. if( tok != asTC_COMMENT && tok != asTC_WHITESPACE )
  3226. {
  3227. if( cleanStr.GetLength() ) cleanStr += " ";
  3228. cleanStr.Concatenate(str.AddressOf() + n, len);
  3229. }
  3230. n += len;
  3231. }
  3232. return cleanStr;
  3233. }
  3234. #ifndef AS_NO_COMPILER
  3235. int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin)
  3236. {
  3237. asCString name;
  3238. asCDataType returnType;
  3239. asCArray<asCString> parameterNames;
  3240. asCArray<asCDataType> parameterTypes;
  3241. asCArray<asETypeModifiers> inOutFlags;
  3242. asCArray<asCString *> defaultArgs;
  3243. bool isConstMethod;
  3244. bool isOverride;
  3245. bool isFinal;
  3246. bool isConstructor;
  3247. bool isDestructor;
  3248. bool isPrivate;
  3249. bool isShared;
  3250. asASSERT( (objType && ns == 0) || isGlobalFunction );
  3251. // Set the default namespace
  3252. if( ns == 0 )
  3253. {
  3254. if( objType )
  3255. ns = objType->nameSpace;
  3256. else
  3257. ns = engine->nameSpaces[0];
  3258. }
  3259. GetParsedFunctionDetails(node, file, objType, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal, isShared, ns);
  3260. return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal, isShared);
  3261. }
  3262. int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isOverride, bool isFinal, bool isShared)
  3263. {
  3264. // Determine default namespace if not specified
  3265. if( ns == 0 )
  3266. {
  3267. if( objType )
  3268. ns = objType->nameSpace;
  3269. else
  3270. ns = engine->nameSpaces[0];
  3271. }
  3272. if( isExistingShared )
  3273. {
  3274. asASSERT( objType );
  3275. // Should validate that the function really exists in the class/interface
  3276. bool found = false;
  3277. if( isConstructor || isDestructor )
  3278. {
  3279. // TODO: shared: Should check the existance of these too
  3280. found = true;
  3281. }
  3282. else
  3283. {
  3284. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  3285. {
  3286. asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
  3287. if( func->name == name &&
  3288. func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, isConstMethod) )
  3289. {
  3290. found = true;
  3291. break;
  3292. }
  3293. }
  3294. }
  3295. if( !found )
  3296. {
  3297. asCString str;
  3298. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, objType->GetName());
  3299. WriteError(str, file, node);
  3300. }
  3301. // Free the default args
  3302. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3303. if( defaultArgs[n] )
  3304. asDELETE(defaultArgs[n], asCString);
  3305. node->Destroy(engine);
  3306. return 0;
  3307. }
  3308. // Check for name conflicts
  3309. if( !isConstructor && !isDestructor )
  3310. {
  3311. if( objType )
  3312. {
  3313. CheckNameConflictMember(objType, name.AddressOf(), node, file, false);
  3314. if( name == objType->name )
  3315. WriteError(TXT_METHOD_CANT_HAVE_NAME_OF_CLASS, file, node);
  3316. }
  3317. else
  3318. CheckNameConflict(name.AddressOf(), node, file, ns);
  3319. }
  3320. else
  3321. {
  3322. if( isMixin )
  3323. {
  3324. // Mixins cannot implement constructors/destructors
  3325. WriteError(TXT_MIXIN_CANNOT_HAVE_CONSTRUCTOR, file, node);
  3326. // Free the default args
  3327. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3328. if( defaultArgs[n] )
  3329. asDELETE(defaultArgs[n], asCString);
  3330. node->Destroy(engine);
  3331. return 0;
  3332. }
  3333. // Verify that the name of the constructor/destructor is the same as the class
  3334. if( name != objType->name )
  3335. WriteError(TXT_CONSTRUCTOR_NAME_ERROR, file, node);
  3336. if( isDestructor )
  3337. name = "~" + name;
  3338. }
  3339. isExistingShared = false;
  3340. int funcId = engine->GetNextScriptFunctionId();
  3341. if( !isInterface )
  3342. {
  3343. sFunctionDescription *func = asNEW(sFunctionDescription);
  3344. if( func == 0 )
  3345. {
  3346. // Free the default args
  3347. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3348. if( defaultArgs[n] )
  3349. asDELETE(defaultArgs[n], asCString);
  3350. return asOUT_OF_MEMORY;
  3351. }
  3352. functions.PushLast(func);
  3353. func->script = file;
  3354. func->node = node;
  3355. func->name = name;
  3356. func->objType = objType;
  3357. func->funcId = funcId;
  3358. func->isExistingShared = false;
  3359. func->paramNames = parameterNames;
  3360. if( isShared )
  3361. {
  3362. // Look for a pre-existing shared function with the same signature
  3363. for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
  3364. {
  3365. asCScriptFunction *f = engine->scriptFunctions[n];
  3366. if( f &&
  3367. f->isShared &&
  3368. f->name == name &&
  3369. f->nameSpace == ns &&
  3370. f->objectType == objType &&
  3371. f->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, 0, false) )
  3372. {
  3373. funcId = func->funcId = f->id;
  3374. isExistingShared = func->isExistingShared = true;
  3375. break;
  3376. }
  3377. }
  3378. }
  3379. }
  3380. // Destructors may not have any parameters
  3381. if( isDestructor && parameterTypes.GetLength() > 0 )
  3382. WriteError(TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, file, node);
  3383. // If a function, class, or interface is shared then only shared types may be used in the signature
  3384. if( (objType && objType->IsShared()) || isShared )
  3385. {
  3386. asCObjectType *ot = returnType.GetObjectType();
  3387. if( ot && !ot->IsShared() )
  3388. {
  3389. asCString msg;
  3390. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  3391. WriteError(msg, file, node);
  3392. }
  3393. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  3394. {
  3395. asCObjectType *ot = parameterTypes[p].GetObjectType();
  3396. if( ot && !ot->IsShared() )
  3397. {
  3398. asCString msg;
  3399. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  3400. WriteError(msg, file, node);
  3401. }
  3402. }
  3403. }
  3404. // Check that the same function hasn't been registered already in the namespace
  3405. asCArray<int> funcs;
  3406. if( objType )
  3407. GetObjectMethodDescriptions(name.AddressOf(), objType, funcs, false);
  3408. else
  3409. GetFunctionDescriptions(name.AddressOf(), funcs, ns);
  3410. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  3411. {
  3412. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  3413. if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, objType, isConstMethod) )
  3414. {
  3415. if( isMixin )
  3416. {
  3417. // Clean up the memory, as the function will not be registered
  3418. if( node )
  3419. node->Destroy(engine);
  3420. sFunctionDescription *func = functions.PopLast();
  3421. asDELETE(func, sFunctionDescription);
  3422. // Free the default args
  3423. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3424. if( defaultArgs[n] )
  3425. asDELETE(defaultArgs[n], asCString);
  3426. return 0;
  3427. }
  3428. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  3429. break;
  3430. }
  3431. }
  3432. // Register the function
  3433. if( isExistingShared )
  3434. {
  3435. // Delete the default args as they won't be used anymore
  3436. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3437. if( defaultArgs[n] )
  3438. asDELETE(defaultArgs[n], asCString);
  3439. asCScriptFunction *f = engine->scriptFunctions[funcId];
  3440. module->AddScriptFunction(f);
  3441. // TODO: clean up: This should be done by AddScriptFunction() itself
  3442. module->globalFunctions.Put(f);
  3443. f->AddRef();
  3444. }
  3445. else
  3446. {
  3447. int row = 0, col = 0;
  3448. if( node )
  3449. file->ConvertPosToRowCol(node->tokenPos, &row, &col);
  3450. module->AddScriptFunction(file->idx, (row&0xFFFFF)|((col&0xFFF)<<20), funcId, name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, isInterface, objType, isConstMethod, isGlobalFunction, isPrivate, isFinal, isOverride, isShared, ns);
  3451. }
  3452. // Make sure the default args are declared correctly
  3453. ValidateDefaultArgs(file, node, engine->scriptFunctions[funcId]);
  3454. if( objType )
  3455. {
  3456. asASSERT( !isExistingShared );
  3457. engine->scriptFunctions[funcId]->AddRef();
  3458. if( isConstructor )
  3459. {
  3460. int factoryId = engine->GetNextScriptFunctionId();
  3461. if( parameterTypes.GetLength() == 0 )
  3462. {
  3463. // Overload the default constructor
  3464. engine->scriptFunctions[objType->beh.construct]->Release();
  3465. objType->beh.construct = funcId;
  3466. objType->beh.constructors[0] = funcId;
  3467. // Register the default factory as well
  3468. engine->scriptFunctions[objType->beh.factory]->Release();
  3469. objType->beh.factory = factoryId;
  3470. objType->beh.factories[0] = factoryId;
  3471. }
  3472. else
  3473. {
  3474. objType->beh.constructors.PushLast(funcId);
  3475. // Register the factory as well
  3476. objType->beh.factories.PushLast(factoryId);
  3477. }
  3478. // We must copy the default arg strings to avoid deleting the same object multiple times
  3479. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3480. if( defaultArgs[n] )
  3481. defaultArgs[n] = asNEW(asCString)(*defaultArgs[n]);
  3482. asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
  3483. module->AddScriptFunction(file->idx, engine->scriptFunctions[funcId]->scriptData->declaredAt, factoryId, name, dt, parameterTypes, parameterNames, inOutFlags, defaultArgs, false);
  3484. // If the object is shared, then the factory must also be marked as shared
  3485. if( objType->flags & asOBJ_SHARED )
  3486. engine->scriptFunctions[factoryId]->isShared = true;
  3487. // Add a dummy function to the builder so that it doesn't mix up the fund Ids
  3488. functions.PushLast(0);
  3489. // Compile the factory immediately
  3490. asCCompiler compiler(engine);
  3491. compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
  3492. engine->scriptFunctions[factoryId]->AddRef();
  3493. }
  3494. else if( isDestructor )
  3495. objType->beh.destruct = funcId;
  3496. else
  3497. {
  3498. // If the method is the assignment operator we need to replace the default implementation
  3499. asCScriptFunction *f = engine->scriptFunctions[funcId];
  3500. if( f->name == "opAssign" && f->parameterTypes.GetLength() == 1 &&
  3501. f->parameterTypes[0].GetObjectType() == f->objectType &&
  3502. (f->inOutFlags[0] & asTM_INREF) )
  3503. {
  3504. engine->scriptFunctions[objType->beh.copy]->Release();
  3505. objType->beh.copy = funcId;
  3506. f->AddRef();
  3507. }
  3508. objType->methods.PushLast(funcId);
  3509. }
  3510. }
  3511. // We need to delete the node already if this is an interface method
  3512. if( isInterface && node )
  3513. node->Destroy(engine);
  3514. return 0;
  3515. }
  3516. int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared)
  3517. {
  3518. if( engine->ep.propertyAccessorMode != 2 )
  3519. {
  3520. WriteError(TXT_PROPERTY_ACCESSOR_DISABLED, file, node);
  3521. node->Destroy(engine);
  3522. return 0;
  3523. }
  3524. asASSERT( (objType && ns == 0) || isGlobalFunction );
  3525. if( ns == 0 )
  3526. {
  3527. if( objType )
  3528. ns = objType->nameSpace;
  3529. else
  3530. ns = engine->nameSpaces[0];
  3531. }
  3532. bool isPrivate = false;
  3533. asCString emulatedName;
  3534. asCDataType emulatedType;
  3535. asCScriptNode *mainNode = node;
  3536. node = node->firstChild;
  3537. if( !isGlobalFunction && node->tokenType == ttPrivate )
  3538. {
  3539. isPrivate = true;
  3540. node = node->next;
  3541. }
  3542. emulatedType = CreateDataTypeFromNode(node, file, ns);
  3543. emulatedType = ModifyDataTypeFromNode(emulatedType, node->next, file, 0, 0);
  3544. node = node->next->next;
  3545. emulatedName.Assign(&file->code[node->tokenPos], node->tokenLength);
  3546. if( node->next == 0 )
  3547. WriteError(TXT_PROPERTY_WITHOUT_ACCESSOR, file, node);
  3548. node = node->next;
  3549. while( node )
  3550. {
  3551. asCScriptNode *next = node->next;
  3552. asCScriptNode *funcNode = 0;
  3553. bool success = false;
  3554. bool isConst = false;
  3555. bool isFinal = false;
  3556. bool isOverride = false;
  3557. asCDataType returnType;
  3558. asCArray<asCString> paramNames;
  3559. asCArray<asCDataType> paramTypes;
  3560. asCArray<asETypeModifiers> paramModifiers;
  3561. asCArray<asCString*> defaultArgs;
  3562. asCString name;
  3563. // TODO: getset: Allow private for individual property accessors
  3564. // TODO: getset: If the accessor uses its own name, then the property should be automatically declared
  3565. if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN) )
  3566. {
  3567. funcNode = node->firstChild->next;
  3568. if( funcNode && funcNode->tokenType == ttConst )
  3569. {
  3570. isConst = true;
  3571. funcNode = funcNode->next;
  3572. }
  3573. while( funcNode && funcNode->nodeType != snStatementBlock )
  3574. {
  3575. if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
  3576. isFinal = true;
  3577. else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
  3578. isOverride = true;
  3579. funcNode = funcNode->next;
  3580. }
  3581. if( funcNode )
  3582. funcNode->DisconnectParent();
  3583. if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
  3584. {
  3585. // TODO: getset: If no implementation is supplied the builder should provide an automatically generated implementation
  3586. // The compiler needs to be able to handle the different types, primitive, value type, and handle
  3587. // The code is also different for global property accessors
  3588. WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node);
  3589. }
  3590. // Setup the signature for the get accessor method
  3591. returnType = emulatedType;
  3592. name = "get_" + emulatedName;
  3593. success = true;
  3594. }
  3595. else if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN) )
  3596. {
  3597. funcNode = node->firstChild->next;
  3598. if( funcNode && funcNode->tokenType == ttConst )
  3599. {
  3600. isConst = true;
  3601. funcNode = funcNode->next;
  3602. }
  3603. while( funcNode && funcNode->nodeType != snStatementBlock )
  3604. {
  3605. if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
  3606. isFinal = true;
  3607. else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
  3608. isOverride = true;
  3609. funcNode = funcNode->next;
  3610. }
  3611. if( funcNode )
  3612. funcNode->DisconnectParent();
  3613. if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
  3614. WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node);
  3615. // Setup the signature for the set accessor method
  3616. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  3617. paramModifiers.PushLast(asTM_NONE);
  3618. paramNames.PushLast("value");
  3619. paramTypes.PushLast(emulatedType);
  3620. defaultArgs.PushLast(0);
  3621. name = "set_" + emulatedName;
  3622. success = true;
  3623. }
  3624. else
  3625. WriteError(TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, file, node);
  3626. if( success )
  3627. {
  3628. if( !isExistingShared )
  3629. RegisterScriptFunction(funcNode, file, objType, isInterface, isGlobalFunction, ns, false, false, name, returnType, paramNames, paramTypes, paramModifiers, defaultArgs, isConst, false, false, isPrivate, isOverride, isFinal, false);
  3630. else
  3631. {
  3632. // Free the funcNode as it won't be used
  3633. if( funcNode ) funcNode->Destroy(engine);
  3634. // Should validate that the function really exists in the class/interface
  3635. bool found = false;
  3636. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  3637. {
  3638. asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
  3639. if( func->name == name &&
  3640. func->IsSignatureExceptNameEqual(returnType, paramTypes, paramModifiers, objType, isConst) )
  3641. {
  3642. found = true;
  3643. break;
  3644. }
  3645. }
  3646. if( !found )
  3647. {
  3648. asCString str;
  3649. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, objType->GetName());
  3650. WriteError(str, file, node);
  3651. }
  3652. }
  3653. }
  3654. node = next;
  3655. };
  3656. mainNode->Destroy(engine);
  3657. return 0;
  3658. }
  3659. int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  3660. {
  3661. asCString name;
  3662. asCDataType returnType;
  3663. asCArray<asCString> parameterNames;
  3664. asCArray<asCDataType> parameterTypes;
  3665. asCArray<asETypeModifiers> inOutFlags;
  3666. asCArray<asCString *> defaultArgs;
  3667. bool isConstMethod, isOverride, isFinal, isConstructor, isDestructor, isPrivate, isShared;
  3668. if( ns == 0 )
  3669. ns = engine->nameSpaces[0];
  3670. GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal, isShared, ns);
  3671. CheckNameConflict(name.AddressOf(), node, file, ns);
  3672. // Check that the same function hasn't been registered already in the namespace
  3673. asCArray<int> funcs;
  3674. GetFunctionDescriptions(name.AddressOf(), funcs, ns);
  3675. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  3676. {
  3677. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  3678. if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, 0, false) )
  3679. {
  3680. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  3681. break;
  3682. }
  3683. }
  3684. // Read the module name as well
  3685. asCScriptNode *nd = node->lastChild;
  3686. asASSERT( nd->nodeType == snConstant && nd->tokenType == ttStringConstant );
  3687. asCString moduleName;
  3688. moduleName.Assign(&file->code[nd->tokenPos+1], nd->tokenLength-2);
  3689. node->Destroy(engine);
  3690. // Register the function
  3691. module->AddImportedFunction(importID, name, returnType, parameterTypes, inOutFlags, defaultArgs, ns, moduleName);
  3692. return 0;
  3693. }
  3694. asCScriptFunction *asCBuilder::GetFunctionDescription(int id)
  3695. {
  3696. // TODO: import: This should be improved when the imported functions are removed
  3697. // Get the description from the engine
  3698. if( (id & FUNC_IMPORTED) == 0 )
  3699. return engine->scriptFunctions[id];
  3700. else
  3701. return engine->importedFunctions[id & ~FUNC_IMPORTED]->importedFunctionSignature;
  3702. }
  3703. void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs, asSNameSpace *ns)
  3704. {
  3705. asUINT n;
  3706. // Get the script declared global functions
  3707. const asCArray<unsigned int> &idxs = module->globalFunctions.GetIndexes(ns, name);
  3708. for( n = 0; n < idxs.GetLength(); n++ )
  3709. {
  3710. const asCScriptFunction *f = module->globalFunctions.Get(idxs[n]);
  3711. asASSERT( f->objectType == 0 );
  3712. funcs.PushLast(f->id);
  3713. }
  3714. // Add the imported functions
  3715. // TODO: optimize: Linear search: This is probably not that critial. Also bindInformation will probably be removed in near future
  3716. for( n = 0; n < module->bindInformations.GetLength(); n++ )
  3717. {
  3718. if( module->bindInformations[n]->importedFunctionSignature->name == name )
  3719. funcs.PushLast(module->bindInformations[n]->importedFunctionSignature->id);
  3720. }
  3721. // Add the registered global functions
  3722. const asCArray<unsigned int> &idxs2 = engine->registeredGlobalFuncs.GetIndexes(ns, name);
  3723. for( n = 0; n < idxs2.GetLength(); n++ )
  3724. {
  3725. asCScriptFunction *f = engine->registeredGlobalFuncs.Get(idxs2[n]);
  3726. // Verify if the module has access to the function
  3727. if( module->accessMask & f->accessMask )
  3728. {
  3729. funcs.PushLast(f->id);
  3730. }
  3731. }
  3732. }
  3733. void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope)
  3734. {
  3735. if( scope != "" )
  3736. {
  3737. // Find the base class with the specified scope
  3738. while( objectType && objectType->name != scope )
  3739. objectType = objectType->derivedFrom;
  3740. // If the scope is not any of the base classes, then return no methods
  3741. if( objectType == 0 )
  3742. return;
  3743. }
  3744. // TODO: optimize: Improve linear search
  3745. if( objIsConst )
  3746. {
  3747. // Only add const methods to the list
  3748. for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
  3749. {
  3750. if( engine->scriptFunctions[objectType->methods[n]]->name == name &&
  3751. engine->scriptFunctions[objectType->methods[n]]->isReadOnly )
  3752. {
  3753. // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
  3754. if( scope == "" )
  3755. methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
  3756. else
  3757. {
  3758. asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
  3759. asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
  3760. methods.PushLast(realFunc->id);
  3761. }
  3762. }
  3763. }
  3764. }
  3765. else
  3766. {
  3767. // TODO: Prefer non-const over const
  3768. for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
  3769. {
  3770. if( engine->scriptFunctions[objectType->methods[n]]->name == name )
  3771. {
  3772. // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
  3773. if( scope == "" )
  3774. methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
  3775. else
  3776. {
  3777. asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
  3778. asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
  3779. methods.PushLast(realFunc->id);
  3780. }
  3781. }
  3782. }
  3783. }
  3784. }
  3785. #endif
  3786. void asCBuilder::WriteInfo(const asCString &scriptname, const asCString &message, int r, int c, bool pre)
  3787. {
  3788. // Need to store the pre message in a structure
  3789. if( pre )
  3790. {
  3791. engine->preMessage.isSet = true;
  3792. engine->preMessage.c = c;
  3793. engine->preMessage.r = r;
  3794. engine->preMessage.message = message;
  3795. engine->preMessage.scriptname = scriptname;
  3796. }
  3797. else
  3798. {
  3799. engine->preMessage.isSet = false;
  3800. if( !silent )
  3801. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_INFORMATION, message.AddressOf());
  3802. }
  3803. }
  3804. void asCBuilder::WriteInfo(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  3805. {
  3806. int r = 0, c = 0;
  3807. if( node )
  3808. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  3809. WriteInfo(file->name, message, r, c, false);
  3810. }
  3811. void asCBuilder::WriteError(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  3812. {
  3813. int r = 0, c = 0;
  3814. if( node && file )
  3815. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  3816. WriteError(file ? file->name : asCString(""), message, r, c);
  3817. }
  3818. void asCBuilder::WriteError(const asCString &scriptname, const asCString &message, int r, int c)
  3819. {
  3820. numErrors++;
  3821. if( !silent )
  3822. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_ERROR, message.AddressOf());
  3823. }
  3824. void asCBuilder::WriteWarning(const asCString &scriptname, const asCString &message, int r, int c)
  3825. {
  3826. if( engine->ep.compilerWarnings )
  3827. {
  3828. numWarnings++;
  3829. if( !silent )
  3830. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_WARNING, message.AddressOf());
  3831. }
  3832. }
  3833. void asCBuilder::WriteWarning(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  3834. {
  3835. int r = 0, c = 0;
  3836. if( node && file )
  3837. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  3838. WriteWarning(file ? file->name : asCString(""), message, r, c);
  3839. }
  3840. asCString asCBuilder::GetScopeFromNode(asCScriptNode *node, asCScriptCode *script, asCScriptNode **next)
  3841. {
  3842. asCString scope;
  3843. asCScriptNode *sn = node;
  3844. if( sn->tokenType == ttScope )
  3845. {
  3846. scope = "::";
  3847. sn = sn->next;
  3848. }
  3849. while( sn && sn->next && sn->next->tokenType == ttScope )
  3850. {
  3851. asCString tmp;
  3852. tmp.Assign(&script->code[sn->tokenPos], sn->tokenLength);
  3853. if( scope != "" && scope != "::" )
  3854. scope += "::";
  3855. scope += tmp;
  3856. sn = sn->next->next;
  3857. }
  3858. if( next )
  3859. *next = sn;
  3860. return scope;
  3861. }
  3862. asSNameSpace *asCBuilder::GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next)
  3863. {
  3864. asCString scope = GetScopeFromNode(node, script, next);
  3865. asSNameSpace *ns = implicitNs;
  3866. if( scope == "::" )
  3867. ns = engine->nameSpaces[0];
  3868. else if( scope != "" )
  3869. {
  3870. ns = engine->FindNameSpace(scope.AddressOf());
  3871. if( ns == 0 )
  3872. {
  3873. asCString msg;
  3874. msg.Format(TXT_NAMESPACE_s_DOESNT_EXIST, scope.AddressOf());
  3875. WriteError(msg, script, node);
  3876. }
  3877. }
  3878. return ns;
  3879. }
  3880. asSNameSpace *asCBuilder::GetParentNameSpace(asSNameSpace *ns)
  3881. {
  3882. if( ns == 0 ) return 0;
  3883. if( ns == engine->nameSpaces[0] ) return 0;
  3884. asCString scope = ns->name;
  3885. int pos = scope.FindLast("::");
  3886. if( pos >= 0 )
  3887. {
  3888. scope = scope.SubString(0, pos);
  3889. return engine->FindNameSpace(scope.AddressOf());
  3890. }
  3891. return engine->nameSpaces[0];
  3892. }
  3893. asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope, asCObjectType *currentType)
  3894. {
  3895. asASSERT(node->nodeType == snDataType);
  3896. asCDataType dt;
  3897. asCScriptNode *n = node->firstChild;
  3898. bool isConst = false;
  3899. bool isImplicitHandle = false;
  3900. if( n->tokenType == ttConst )
  3901. {
  3902. isConst = true;
  3903. n = n->next;
  3904. }
  3905. // Determine namespace
  3906. asSNameSpace *ns = GetNameSpaceFromNode(n, file, implicitNamespace, &n);
  3907. if( ns == 0 )
  3908. {
  3909. // The namespace doesn't exist. Return a dummy type instead.
  3910. dt = asCDataType::CreatePrimitive(ttInt, false);
  3911. return dt;
  3912. }
  3913. if( n->tokenType == ttIdentifier )
  3914. {
  3915. bool found = false;
  3916. asCScriptNode *nameToken = n;
  3917. asCString str;
  3918. str.Assign(&file->code[n->tokenPos], n->tokenLength);
  3919. // Recursively search parent namespaces for matching type
  3920. asSNameSpace *origNs = ns;
  3921. while( ns && !found )
  3922. {
  3923. asCObjectType *ot = 0;
  3924. // If this is for a template type, then we must first determine if the
  3925. // identifier matches any of the template subtypes
  3926. if( currentType && (currentType->flags & asOBJ_TEMPLATE))
  3927. {
  3928. for( asUINT subtypeIndex = 0; subtypeIndex < currentType->templateSubTypes.GetLength(); subtypeIndex++)
  3929. {
  3930. asCObjectType *type = currentType->templateSubTypes[subtypeIndex].GetObjectType();
  3931. if( type && str == type->name )
  3932. {
  3933. ot = type;
  3934. break;
  3935. }
  3936. }
  3937. }
  3938. if( ot == 0 )
  3939. ot = GetObjectType(str.AddressOf(), ns);
  3940. if( ot == 0 && !module && currentType )
  3941. ot = GetObjectTypeFromTypesKnownByObject(str.AddressOf(), currentType);
  3942. if( ot )
  3943. {
  3944. found = true;
  3945. if( ot->flags & asOBJ_IMPLICIT_HANDLE )
  3946. isImplicitHandle = true;
  3947. // Make sure the module has access to the object type
  3948. if( !module || (module->accessMask & ot->accessMask) )
  3949. {
  3950. if(asOBJ_TYPEDEF == (ot->flags & asOBJ_TYPEDEF))
  3951. {
  3952. // TODO: typedef: A typedef should be considered different from the original type (though with implicit conversions between the two)
  3953. // Create primitive data type based on object flags
  3954. dt = ot->templateSubTypes[0];
  3955. dt.MakeReadOnly(isConst);
  3956. }
  3957. else
  3958. {
  3959. if( ot->flags & asOBJ_TEMPLATE )
  3960. {
  3961. // Check if the subtype is a type or the template's subtype
  3962. // if it is the template's subtype then this is the actual template type,
  3963. // orderwise it is a template instance.
  3964. // Only do this for application registered interface, as the
  3965. // scripts cannot implement templates.
  3966. asCArray<asCDataType> subTypes;
  3967. asUINT subtypeIndex;
  3968. while( n && n->next && n->next->nodeType == snDataType )
  3969. {
  3970. n = n->next;
  3971. asCDataType subType = CreateDataTypeFromNode(n, file, implicitNamespace, false, module ? 0 : ot);
  3972. subTypes.PushLast(subType);
  3973. if( subType.IsReadOnly() )
  3974. {
  3975. asCString msg;
  3976. msg.Format(TXT_TMPL_SUBTYPE_MUST_NOT_BE_READ_ONLY);
  3977. WriteError(msg, file, n);
  3978. // Return a dummy
  3979. return asCDataType::CreatePrimitive(ttInt, false);
  3980. }
  3981. }
  3982. if( subTypes.GetLength() != ot->templateSubTypes.GetLength() )
  3983. {
  3984. asCString msg;
  3985. msg.Format(TXT_TMPL_s_EXPECTS_d_SUBTYPES, ot->name.AddressOf(), int(ot->templateSubTypes.GetLength()));
  3986. WriteError(msg, file, nameToken);
  3987. // Return a dummy
  3988. return asCDataType::CreatePrimitive(ttInt, false);
  3989. }
  3990. // Check if any of the given subtypes are different from the template's declared subtypes
  3991. bool isDifferent = false;
  3992. for( subtypeIndex = 0; subtypeIndex < subTypes.GetLength(); subtypeIndex++ )
  3993. {
  3994. if( subTypes[subtypeIndex].GetObjectType() != ot->templateSubTypes[subtypeIndex].GetObjectType() )
  3995. {
  3996. isDifferent = true;
  3997. break;
  3998. }
  3999. }
  4000. if( isDifferent )
  4001. {
  4002. // This is a template instance
  4003. // Need to find the correct object type
  4004. asCObjectType *otInstance = engine->GetTemplateInstanceType(ot, subTypes);
  4005. if( !otInstance )
  4006. {
  4007. asCString msg;
  4008. // TODO: Should name all subtypes
  4009. msg.Format(TXT_CANNOT_INSTANTIATE_TEMPLATE_s_WITH_s, ot->name.AddressOf(), subTypes[0].Format().AddressOf());
  4010. WriteError(msg, file, n);
  4011. }
  4012. ot = otInstance;
  4013. }
  4014. }
  4015. // Create object data type
  4016. if( ot )
  4017. dt = asCDataType::CreateObject(ot, isConst);
  4018. else
  4019. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  4020. }
  4021. }
  4022. else
  4023. {
  4024. asCString msg;
  4025. msg.Format(TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE, (const char *)str.AddressOf());
  4026. WriteError(msg, file, n);
  4027. dt.SetTokenType(ttInt);
  4028. }
  4029. }
  4030. else if( ot == 0 )
  4031. {
  4032. // It can still be a function definition
  4033. asCScriptFunction *funcdef = GetFuncDef(str.AddressOf());
  4034. if( funcdef )
  4035. {
  4036. dt = asCDataType::CreateFuncDef(funcdef);
  4037. found = true;
  4038. }
  4039. }
  4040. if( !found )
  4041. {
  4042. // Try to find it in the parent namespace
  4043. ns = GetParentNameSpace(ns);
  4044. }
  4045. }
  4046. if( !found )
  4047. {
  4048. asCString msg;
  4049. if( origNs->name == "" )
  4050. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, str.AddressOf());
  4051. else
  4052. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, str.AddressOf(), origNs->name.AddressOf());
  4053. WriteError(msg, file, n);
  4054. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  4055. return dt;
  4056. }
  4057. }
  4058. else if( n->tokenType == ttAuto )
  4059. {
  4060. dt = asCDataType::CreateAuto(isConst);
  4061. }
  4062. else
  4063. {
  4064. // Create primitive data type
  4065. dt = asCDataType::CreatePrimitive(n->tokenType, isConst);
  4066. }
  4067. // Determine array dimensions and object handles
  4068. n = n->next;
  4069. while( n && (n->tokenType == ttOpenBracket || n->tokenType == ttHandle) )
  4070. {
  4071. if( n->tokenType == ttOpenBracket )
  4072. {
  4073. // Make sure the sub type can be instantiated
  4074. if( !dt.CanBeInstantiated() )
  4075. {
  4076. asCString str;
  4077. if( dt.IsAbstractClass() )
  4078. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format().AddressOf());
  4079. else if( dt.IsInterface() )
  4080. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format().AddressOf());
  4081. else
  4082. // TODO: Improve error message to explain why
  4083. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
  4084. WriteError(str, file, n);
  4085. }
  4086. // Make the type an array (or multidimensional array)
  4087. if( dt.MakeArray(engine) < 0 )
  4088. {
  4089. WriteError(TXT_NO_DEFAULT_ARRAY_TYPE, file, n);
  4090. break;
  4091. }
  4092. }
  4093. else
  4094. {
  4095. // Make the type a handle
  4096. if( dt.IsObjectHandle() )
  4097. {
  4098. WriteError(TXT_HANDLE_OF_HANDLE_IS_NOT_ALLOWED, file, n);
  4099. break;
  4100. }
  4101. else if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
  4102. {
  4103. WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
  4104. break;
  4105. }
  4106. }
  4107. n = n->next;
  4108. }
  4109. if( isImplicitHandle )
  4110. {
  4111. // Make the type a handle
  4112. if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
  4113. WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
  4114. }
  4115. return dt;
  4116. }
  4117. asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlags, bool *autoHandle)
  4118. {
  4119. asCDataType dt = type;
  4120. if( inOutFlags ) *inOutFlags = asTM_NONE;
  4121. // Is the argument sent by reference?
  4122. asCScriptNode *n = node->firstChild;
  4123. if( n && n->tokenType == ttAmp )
  4124. {
  4125. dt.MakeReference(true);
  4126. n = n->next;
  4127. if( n )
  4128. {
  4129. if( inOutFlags )
  4130. {
  4131. if( n->tokenType == ttIn )
  4132. *inOutFlags = asTM_INREF;
  4133. else if( n->tokenType == ttOut )
  4134. *inOutFlags = asTM_OUTREF;
  4135. else if( n->tokenType == ttInOut )
  4136. *inOutFlags = asTM_INOUTREF;
  4137. else
  4138. asASSERT(false);
  4139. }
  4140. n = n->next;
  4141. }
  4142. else
  4143. {
  4144. if( inOutFlags )
  4145. *inOutFlags = asTM_INOUTREF; // ttInOut
  4146. }
  4147. if( !engine->ep.allowUnsafeReferences &&
  4148. inOutFlags && *inOutFlags == asTM_INOUTREF )
  4149. {
  4150. // Verify that the base type support &inout parameter types
  4151. if( !dt.IsObject() || dt.IsObjectHandle() || !((dt.GetObjectType()->flags & asOBJ_NOCOUNT) || (dt.GetObjectType()->beh.addref && dt.GetObjectType()->beh.release)) )
  4152. WriteError(TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT, file, node->firstChild);
  4153. }
  4154. }
  4155. if( autoHandle ) *autoHandle = false;
  4156. if( n && n->tokenType == ttPlus )
  4157. {
  4158. // Autohandles are not supported for types with NOCOUNT
  4159. // If the type is not a handle then there was an error with building the type, but
  4160. // this error would already have been reported so no need to report another error here
  4161. if( dt.IsObjectHandle() && (dt.GetObjectType()->flags & asOBJ_NOCOUNT) )
  4162. WriteError(TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT, file, node->firstChild);
  4163. if( autoHandle ) *autoHandle = true;
  4164. }
  4165. return dt;
  4166. }
  4167. asCObjectType *asCBuilder::GetObjectType(const char *type, asSNameSpace *ns)
  4168. {
  4169. asCObjectType *ot = engine->GetRegisteredObjectType(type, ns);
  4170. if( !ot && module )
  4171. ot = module->GetObjectType(type, ns);
  4172. return ot;
  4173. }
  4174. #ifndef AS_NO_COMPILER
  4175. // This function will return true if there are any types in the engine or module
  4176. // with the given name. The namespace is ignored in this verification.
  4177. bool asCBuilder::DoesTypeExist(const asCString &type)
  4178. {
  4179. asUINT n;
  4180. // This function is only used when parsing expressions for building bytecode
  4181. // and this is only done after all types are known. For this reason the types
  4182. // can be safely cached in a map for quick lookup. Once the builder is released
  4183. // the cache will also be destroyed thus avoiding unnecessary memory consumption.
  4184. if( !hasCachedKnownTypes )
  4185. {
  4186. // Only do this once
  4187. hasCachedKnownTypes = true;
  4188. // Add registered object types
  4189. asSMapNode<asSNameSpaceNamePair, asCObjectType*> *cursor;
  4190. engine->allRegisteredTypes.MoveFirst(&cursor);
  4191. while( cursor )
  4192. {
  4193. if( !knownTypes.MoveTo(0, cursor->key.name) )
  4194. knownTypes.Insert(cursor->key.name, true);
  4195. engine->allRegisteredTypes.MoveNext(&cursor, cursor);
  4196. }
  4197. // Add registered funcdefs
  4198. for( n = 0; n < engine->registeredFuncDefs.GetLength(); n++ )
  4199. if( !knownTypes.MoveTo(0, engine->registeredFuncDefs[n]->name) )
  4200. knownTypes.Insert(engine->registeredFuncDefs[n]->name, true);
  4201. if( module )
  4202. {
  4203. // Add script classes and interfaces
  4204. for( n = 0; n < module->classTypes.GetLength(); n++ )
  4205. if( !knownTypes.MoveTo(0, module->classTypes[n]->name) )
  4206. knownTypes.Insert(module->classTypes[n]->name, true);
  4207. // Add script enums
  4208. for( n = 0; n < module->enumTypes.GetLength(); n++ )
  4209. if( !knownTypes.MoveTo(0, module->enumTypes[n]->name) )
  4210. knownTypes.Insert(module->enumTypes[n]->name, true);
  4211. // Add script typedefs
  4212. for( n = 0; n < module->typeDefs.GetLength(); n++ )
  4213. if( !knownTypes.MoveTo(0, module->typeDefs[n]->name) )
  4214. knownTypes.Insert(module->typeDefs[n]->name, true);
  4215. // Add script funcdefs
  4216. for( n = 0; n < module->funcDefs.GetLength(); n++ )
  4217. if( !knownTypes.MoveTo(0, module->funcDefs[n]->name) )
  4218. knownTypes.Insert(module->funcDefs[n]->name, true);
  4219. }
  4220. }
  4221. // Check if the type is known
  4222. return knownTypes.MoveTo(0, type);
  4223. }
  4224. #endif
  4225. asCObjectType *asCBuilder::GetObjectTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType)
  4226. {
  4227. if( currentType->name == type )
  4228. return currentType;
  4229. asUINT n;
  4230. asCObjectType *found = 0;
  4231. for( n = 0; found == 0 && n < currentType->properties.GetLength(); n++ )
  4232. if( currentType->properties[n]->type.GetObjectType() &&
  4233. currentType->properties[n]->type.GetObjectType()->name == type )
  4234. found = currentType->properties[n]->type.GetObjectType();
  4235. for( n = 0; found == 0 && n < currentType->methods.GetLength(); n++ )
  4236. {
  4237. asCScriptFunction *func = engine->scriptFunctions[currentType->methods[n]];
  4238. if( func->returnType.GetObjectType() &&
  4239. func->returnType.GetObjectType()->name == type )
  4240. found = func->returnType.GetObjectType();
  4241. for( asUINT f = 0; found == 0 && f < func->parameterTypes.GetLength(); f++ )
  4242. if( func->parameterTypes[f].GetObjectType() &&
  4243. func->parameterTypes[f].GetObjectType()->name == type )
  4244. found = func->parameterTypes[f].GetObjectType();
  4245. }
  4246. if( found )
  4247. {
  4248. // In case we find a template instance it mustn't be returned
  4249. // because it is not known if the subtype is really matching
  4250. if( found->flags & asOBJ_TEMPLATE )
  4251. return 0;
  4252. }
  4253. return found;
  4254. }
  4255. asCScriptFunction *asCBuilder::GetFuncDef(const char *type)
  4256. {
  4257. for( asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++ )
  4258. // TODO: access: Only return the definitions that the module has access to
  4259. if( engine->registeredFuncDefs[n]->name == type )
  4260. return engine->registeredFuncDefs[n];
  4261. if( module )
  4262. {
  4263. for( asUINT n = 0; n < module->funcDefs.GetLength(); n++ )
  4264. if( module->funcDefs[n]->name == type )
  4265. return module->funcDefs[n];
  4266. }
  4267. return 0;
  4268. }
  4269. #ifndef AS_NO_COMPILER
  4270. int asCBuilder::GetEnumValueFromObjectType(asCObjectType *objType, const char *name, asCDataType &outDt, asDWORD &outValue)
  4271. {
  4272. if( !objType || !(objType->flags & asOBJ_ENUM) )
  4273. return 0;
  4274. for( asUINT n = 0; n < objType->enumValues.GetLength(); ++n )
  4275. {
  4276. if( objType->enumValues[n]->name == name )
  4277. {
  4278. outDt = asCDataType::CreateObject(objType, true);
  4279. outValue = objType->enumValues[n]->value;
  4280. return 1;
  4281. }
  4282. }
  4283. return 0;
  4284. }
  4285. int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outValue, asSNameSpace *ns)
  4286. {
  4287. bool found = false;
  4288. // Search all available enum types
  4289. asUINT t;
  4290. for( t = 0; t < engine->registeredEnums.GetLength(); t++ )
  4291. {
  4292. asCObjectType *ot = engine->registeredEnums[t];
  4293. if( ns != ot->nameSpace ) continue;
  4294. // Don't bother with types the module doesn't have access to
  4295. if( (ot->accessMask & module->accessMask) == 0 )
  4296. continue;
  4297. if( GetEnumValueFromObjectType(ot, name, outDt, outValue) )
  4298. {
  4299. if( !found )
  4300. found = true;
  4301. else
  4302. {
  4303. // Found more than one value in different enum types
  4304. return 2;
  4305. }
  4306. }
  4307. }
  4308. for( t = 0; t < module->enumTypes.GetLength(); t++ )
  4309. {
  4310. asCObjectType *ot = module->enumTypes[t];
  4311. if( ns != ot->nameSpace ) continue;
  4312. if( GetEnumValueFromObjectType(ot, name, outDt, outValue) )
  4313. {
  4314. if( !found )
  4315. found = true;
  4316. else
  4317. {
  4318. // Found more than one value in different enum types
  4319. return 2;
  4320. }
  4321. }
  4322. }
  4323. if( found )
  4324. return 1;
  4325. // Didn't find any value
  4326. return 0;
  4327. }
  4328. #endif // AS_NO_COMPILER
  4329. END_AS_NAMESPACE