as_builder.cpp 187 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2022 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 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. CleanupEnumValues();
  88. asCSymbolTable<sGlobalVariableDescription>::iterator it = globVariables.List();
  89. while( it )
  90. {
  91. if( (*it)->declaredAtNode )
  92. (*it)->declaredAtNode->Destroy(engine);
  93. if( (*it)->initializationNode )
  94. (*it)->initializationNode->Destroy(engine);
  95. asDELETE((*it),sGlobalVariableDescription);
  96. it++;
  97. }
  98. globVariables.Clear();
  99. // Free all the loaded files
  100. for( n = 0; n < scripts.GetLength(); n++ )
  101. {
  102. if( scripts[n] )
  103. asDELETE(scripts[n],asCScriptCode);
  104. scripts[n] = 0;
  105. }
  106. // Free all class declarations
  107. for( n = 0; n < classDeclarations.GetLength(); n++ )
  108. {
  109. if( classDeclarations[n] )
  110. {
  111. if( classDeclarations[n]->node )
  112. classDeclarations[n]->node->Destroy(engine);
  113. asDELETE(classDeclarations[n],sClassDeclaration);
  114. classDeclarations[n] = 0;
  115. }
  116. }
  117. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  118. {
  119. if( interfaceDeclarations[n] )
  120. {
  121. if( interfaceDeclarations[n]->node )
  122. interfaceDeclarations[n]->node->Destroy(engine);
  123. asDELETE(interfaceDeclarations[n],sClassDeclaration);
  124. interfaceDeclarations[n] = 0;
  125. }
  126. }
  127. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  128. {
  129. if( namedTypeDeclarations[n] )
  130. {
  131. if( namedTypeDeclarations[n]->node )
  132. namedTypeDeclarations[n]->node->Destroy(engine);
  133. asDELETE(namedTypeDeclarations[n],sClassDeclaration);
  134. namedTypeDeclarations[n] = 0;
  135. }
  136. }
  137. for( n = 0; n < funcDefs.GetLength(); n++ )
  138. {
  139. if( funcDefs[n] )
  140. {
  141. if( funcDefs[n]->node )
  142. funcDefs[n]->node->Destroy(engine);
  143. asDELETE(funcDefs[n],sFuncDef);
  144. funcDefs[n] = 0;
  145. }
  146. }
  147. for( n = 0; n < mixinClasses.GetLength(); n++ )
  148. {
  149. if( mixinClasses[n] )
  150. {
  151. if( mixinClasses[n]->node )
  152. mixinClasses[n]->node->Destroy(engine);
  153. asDELETE(mixinClasses[n],sMixinClass);
  154. mixinClasses[n] = 0;
  155. }
  156. }
  157. #endif // AS_NO_COMPILER
  158. }
  159. void asCBuilder::Reset()
  160. {
  161. numErrors = 0;
  162. numWarnings = 0;
  163. engine->preMessage.isSet = false;
  164. #ifndef AS_NO_COMPILER
  165. // Clear the cache of known types
  166. hasCachedKnownTypes = false;
  167. knownTypes.EraseAll();
  168. #endif
  169. }
  170. #ifndef AS_NO_COMPILER
  171. int asCBuilder::AddCode(const char *name, const char *code, int codeLength, int lineOffset, int sectionIdx, bool makeCopy)
  172. {
  173. asCScriptCode *script = asNEW(asCScriptCode);
  174. if( script == 0 )
  175. return asOUT_OF_MEMORY;
  176. int r = script->SetCode(name, code, codeLength, makeCopy);
  177. if( r < 0 )
  178. {
  179. asDELETE(script, asCScriptCode);
  180. return r;
  181. }
  182. script->lineOffset = lineOffset;
  183. script->idx = sectionIdx;
  184. scripts.PushLast(script);
  185. return 0;
  186. }
  187. asCScriptCode *asCBuilder::FindOrAddCode(const char *name, const char *code, size_t length)
  188. {
  189. for (asUINT n = 0; n < scripts.GetLength(); n++)
  190. if( scripts[n]->name == name && scripts[n]->codeLength == length && memcmp(scripts[n]->code, code, length) == 0 )
  191. return scripts[n];
  192. asCScriptCode *script = asNEW(asCScriptCode);
  193. if (script == 0)
  194. return 0;
  195. int r = script->SetCode(name, code, length, true);
  196. if (r < 0)
  197. {
  198. asDELETE(script, asCScriptCode);
  199. return 0;
  200. }
  201. script->idx = engine->GetScriptSectionNameIndex(name);
  202. scripts.PushLast(script);
  203. return script;
  204. }
  205. void asCBuilder::EvaluateTemplateInstances(asUINT startIdx, bool keepSilent)
  206. {
  207. // Backup the original message stream
  208. bool msgCallback = engine->msgCallback;
  209. asSSystemFunctionInterface msgCallbackFunc = engine->msgCallbackFunc;
  210. void *msgCallbackObj = engine->msgCallbackObj;
  211. // Set the new temporary message stream
  212. asCOutputBuffer outBuffer;
  213. if( keepSilent )
  214. engine->SetMessageCallback(asMETHOD(asCOutputBuffer, Callback), &outBuffer, asCALL_THISCALL);
  215. // Evaluate each of the template instances that have been created since the start of the build
  216. // TODO: This is not exactly correct, since another thread may have created template instances in parallel
  217. for( asUINT n = startIdx; n < engine->templateInstanceTypes.GetLength(); n++ )
  218. {
  219. bool dontGarbageCollect = false;
  220. asCObjectType *tmpl = engine->templateInstanceTypes[n];
  221. asCScriptFunction *callback = engine->scriptFunctions[tmpl->beh.templateCallback];
  222. if( callback && !engine->CallGlobalFunctionRetBool(tmpl, &dontGarbageCollect, callback->sysFuncIntf, callback) )
  223. {
  224. asCString sub = tmpl->templateSubTypes[0].Format(engine->nameSpaces[0]);
  225. for( asUINT m = 1; m < tmpl->templateSubTypes.GetLength(); m++ )
  226. {
  227. sub += ",";
  228. sub += tmpl->templateSubTypes[m].Format(engine->nameSpaces[0]);
  229. }
  230. asCString str;
  231. str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, tmpl->name.AddressOf(), sub.AddressOf());
  232. WriteError(tmpl->scriptSectionIdx >= 0 ? engine->scriptSectionNames[tmpl->scriptSectionIdx]->AddressOf() : "", str, tmpl->declaredAt&0xFFFFF, (tmpl->declaredAt>>20)&0xFFF);
  233. }
  234. else
  235. {
  236. // If the callback said this template instance won't be garbage collected then remove the flag
  237. if( dontGarbageCollect )
  238. tmpl->flags &= ~asOBJ_GC;
  239. }
  240. }
  241. // Restore message callback
  242. if( keepSilent )
  243. {
  244. engine->msgCallback = msgCallback;
  245. engine->msgCallbackFunc = msgCallbackFunc;
  246. engine->msgCallbackObj = msgCallbackObj;
  247. }
  248. }
  249. int asCBuilder::Build()
  250. {
  251. Reset();
  252. // The template callbacks must only be called after the subtypes have a known structure,
  253. // otherwise the callback may think it is not possible to create the template instance,
  254. // even though it is.
  255. // TODO: This flag shouldn't be set globally in the engine, as it would mean that another
  256. // thread requesting a template instance in parallel to the compilation wouldn't
  257. // evaluate the template instance.
  258. engine->deferValidationOfTemplateTypes = true;
  259. asUINT numTempl = (asUINT)engine->templateInstanceTypes.GetLength();
  260. ParseScripts();
  261. if (numErrors > 0)
  262. return asERROR;
  263. // Compile the types first
  264. CompileInterfaces();
  265. CompileClasses(numTempl);
  266. // Evaluate the template instances one last time, this time with error messages, as we know
  267. // all classes have been fully built and it is known which ones will need garbage collection.
  268. EvaluateTemplateInstances(numTempl, false);
  269. engine->deferValidationOfTemplateTypes = false;
  270. if (numErrors > 0)
  271. return asERROR;
  272. // Then the global variables. Here the variables declared with auto
  273. // will be resolved, so they can be accessed properly in the functions
  274. CompileGlobalVariables();
  275. // Finally the global functions and class methods
  276. CompileFunctions();
  277. // TODO: Attempt to reorder the initialization of global variables so that
  278. // they do not access other uninitialized global variables out-of-order
  279. // The builder needs to check for each of the global variable, what functions
  280. // that are accessed, and what global variables are access by these functions.
  281. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  282. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  283. if( numErrors > 0 )
  284. return asERROR;
  285. // Make sure something was compiled, otherwise return an error
  286. if( module->IsEmpty() )
  287. {
  288. WriteError(TXT_NOTHING_WAS_BUILT, 0, 0);
  289. return asERROR;
  290. }
  291. return asSUCCESS;
  292. }
  293. int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  294. {
  295. Reset();
  296. // Add the string to the script code
  297. asCScriptCode *script = asNEW(asCScriptCode);
  298. if( script == 0 )
  299. return asOUT_OF_MEMORY;
  300. script->SetCode(sectionName, code, true);
  301. script->lineOffset = lineOffset;
  302. script->idx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  303. scripts.PushLast(script);
  304. // Parse the string
  305. asCParser parser(this);
  306. if( parser.ParseScript(scripts[0]) < 0 )
  307. return asERROR;
  308. asCScriptNode *node = parser.GetScriptNode();
  309. // Make sure there is nothing else than the global variable in the script code
  310. if( node == 0 ||
  311. node->firstChild == 0 ||
  312. node->firstChild != node->lastChild ||
  313. node->firstChild->nodeType != snDeclaration )
  314. {
  315. WriteError(TXT_ONLY_ONE_VARIABLE_ALLOWED, script, 0);
  316. return asERROR;
  317. }
  318. node = node->firstChild;
  319. node->DisconnectParent();
  320. RegisterGlobalVar(node, script, module->m_defaultNamespace);
  321. CompileGlobalVariables();
  322. // It is possible that the global variable initialization included anonymous functions that must be compiled too
  323. for( asUINT n = 0; n < functions.GetLength(); n++ )
  324. {
  325. asCCompiler compiler(engine);
  326. asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
  327. int r = compiler.CompileFunction(this, functions[n]->script, func->parameterNames, functions[n]->node, func, 0);
  328. if( r < 0 )
  329. break;
  330. }
  331. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  332. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  333. // None of the functions should be added to the module if any error occurred,
  334. // or it was requested that the functions wouldn't be added to the scope
  335. if( numErrors > 0 )
  336. {
  337. for( asUINT n = 0; n < functions.GetLength(); n++ )
  338. {
  339. asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
  340. if( module->m_globalFunctions.GetIndex(func) >= 0 )
  341. {
  342. module->m_globalFunctions.Erase(module->m_globalFunctions.GetIndex(func));
  343. module->m_scriptFunctions.RemoveValue(func);
  344. func->ReleaseInternal();
  345. }
  346. }
  347. }
  348. if( numErrors > 0 )
  349. {
  350. // Remove the variable from the module, if it was registered
  351. if( globVariables.GetSize() > 0 )
  352. module->RemoveGlobalVar(module->GetGlobalVarCount()-1);
  353. return asERROR;
  354. }
  355. return 0;
  356. }
  357. #endif
  358. int asCBuilder::ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func)
  359. {
  360. int firstArgWithDefaultValue = -1;
  361. for( asUINT n = 0; n < func->defaultArgs.GetLength(); n++ )
  362. {
  363. if( func->defaultArgs[n] )
  364. firstArgWithDefaultValue = n;
  365. else if( firstArgWithDefaultValue >= 0 )
  366. {
  367. asCString str;
  368. str.Format(TXT_DEF_ARG_MISSING_IN_FUNC_s, func->GetDeclaration());
  369. WriteError(str, script, node);
  370. return asINVALID_DECLARATION;
  371. }
  372. }
  373. return 0;
  374. }
  375. #ifndef AS_NO_COMPILER
  376. // This function will verify if the newly created function will conflict another overload due to having
  377. // identical function arguments that are not default args, e.g: foo(int) and foo(int, int=0)
  378. int asCBuilder::CheckForConflictsDueToDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func, asCObjectType *objType)
  379. {
  380. // TODO: Implement for global functions too
  381. if( func->objectType == 0 || objType == 0 ) return 0;
  382. asCArray<int> funcs;
  383. GetObjectMethodDescriptions(func->name.AddressOf(), objType, funcs, false);
  384. for( asUINT n = 0; n < funcs.GetLength(); n++ )
  385. {
  386. asCScriptFunction *func2 = engine->scriptFunctions[funcs[n]];
  387. if( func == func2 )
  388. continue;
  389. if( func->IsReadOnly() != func2->IsReadOnly() )
  390. continue;
  391. bool match = true;
  392. asUINT p = 0;
  393. for( ; p < func->parameterTypes.GetLength() && p < func2->parameterTypes.GetLength(); p++ )
  394. {
  395. // Only verify until the first argument with default args
  396. if( (func->defaultArgs.GetLength() > p && func->defaultArgs[p]) ||
  397. (func2->defaultArgs.GetLength() > p && func2->defaultArgs[p]) )
  398. break;
  399. if( func->parameterTypes[p] != func2->parameterTypes[p] ||
  400. func->inOutFlags[p] != func2->inOutFlags[p] )
  401. {
  402. match = false;
  403. break;
  404. }
  405. }
  406. if( match )
  407. {
  408. if( !((p >= func->parameterTypes.GetLength() && p < func2->defaultArgs.GetLength() && func2->defaultArgs[p]) ||
  409. (p >= func2->parameterTypes.GetLength() && p < func->defaultArgs.GetLength() && func->defaultArgs[p])) )
  410. {
  411. // The argument lists match for the full length of the shorter, but the next
  412. // argument on the longer does not have a default arg so there is no conflict
  413. match = false;
  414. }
  415. }
  416. if( match )
  417. {
  418. WriteWarning(TXT_OVERLOAD_CONFLICTS_DUE_TO_DEFAULT_ARGS, script, node);
  419. WriteInfo(func->GetDeclaration(), script, node);
  420. WriteInfo(func2->GetDeclaration(), script, node);
  421. break;
  422. }
  423. }
  424. return 0;
  425. }
  426. int asCBuilder::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asCScriptFunction **outFunc)
  427. {
  428. asASSERT(outFunc != 0);
  429. Reset();
  430. // Add the string to the script code
  431. asCScriptCode *script = asNEW(asCScriptCode);
  432. if( script == 0 )
  433. return asOUT_OF_MEMORY;
  434. script->SetCode(sectionName, code, true);
  435. script->lineOffset = lineOffset;
  436. script->idx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  437. scripts.PushLast(script);
  438. // Parse the string
  439. asCParser parser(this);
  440. if( parser.ParseScript(scripts[0]) < 0 )
  441. return asERROR;
  442. asCScriptNode *node = parser.GetScriptNode();
  443. // Make sure there is nothing else than the function in the script code
  444. if( node == 0 ||
  445. node->firstChild == 0 ||
  446. node->firstChild != node->lastChild ||
  447. node->firstChild->nodeType != snFunction )
  448. {
  449. WriteError(TXT_ONLY_ONE_FUNCTION_ALLOWED, script, 0);
  450. return asERROR;
  451. }
  452. // Find the function node
  453. node = node->firstChild;
  454. // Create the function
  455. asSFunctionTraits funcTraits;
  456. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, compileFlags & asCOMP_ADD_TO_MODULE ? module : 0, asFUNC_SCRIPT);
  457. if( func == 0 )
  458. return asOUT_OF_MEMORY;
  459. GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, funcTraits, module->m_defaultNamespace);
  460. func->id = engine->GetNextScriptFunctionId();
  461. func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  462. int row, col;
  463. scripts[0]->ConvertPosToRowCol(node->tokenPos, &row, &col);
  464. func->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20);
  465. func->nameSpace = module->m_defaultNamespace;
  466. // Make sure the default args are declared correctly
  467. int r = ValidateDefaultArgs(script, node, func);
  468. if( r < 0 )
  469. {
  470. func->ReleaseInternal();
  471. return asERROR;
  472. }
  473. // Tell the engine that the function exists already so the compiler can access it
  474. if( compileFlags & asCOMP_ADD_TO_MODULE )
  475. {
  476. r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->m_defaultNamespace, false, false, false);
  477. if( r < 0 )
  478. {
  479. func->ReleaseInternal();
  480. return asERROR;
  481. }
  482. module->m_globalFunctions.Put(func);
  483. module->AddScriptFunction(func);
  484. }
  485. else
  486. engine->AddScriptFunction(func);
  487. // Fill in the function info for the builder too
  488. node->DisconnectParent();
  489. sFunctionDescription *funcDesc = asNEW(sFunctionDescription);
  490. if( funcDesc == 0 )
  491. {
  492. func->ReleaseInternal();
  493. return asOUT_OF_MEMORY;
  494. }
  495. functions.PushLast(funcDesc);
  496. funcDesc->script = scripts[0];
  497. funcDesc->node = node;
  498. funcDesc->name = func->name;
  499. funcDesc->funcId = func->id;
  500. funcDesc->paramNames = func->parameterNames;
  501. funcDesc->isExistingShared = false;
  502. // This must be done in a loop, as it is possible that additional functions get declared as lambda's in the code
  503. for( asUINT n = 0; n < functions.GetLength(); n++ )
  504. {
  505. asCCompiler compiler(engine);
  506. asCScriptFunction *f = engine->scriptFunctions[functions[n]->funcId];
  507. r = compiler.CompileFunction(this, functions[n]->script, f->parameterNames, functions[n]->node, f, 0);
  508. if( r < 0 )
  509. break;
  510. }
  511. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  512. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  513. // None of the functions should be added to the module if any error occurred,
  514. // or it was requested that the functions wouldn't be added to the scope
  515. if( !(compileFlags & asCOMP_ADD_TO_MODULE) || numErrors > 0 )
  516. {
  517. for( asUINT n = 0; n < functions.GetLength(); n++ )
  518. {
  519. asCScriptFunction *f = engine->scriptFunctions[functions[n]->funcId];
  520. if( module->m_globalFunctions.GetIndex(f) >= 0 )
  521. {
  522. module->m_globalFunctions.Erase(module->m_globalFunctions.GetIndex(f));
  523. module->m_scriptFunctions.RemoveValue(f);
  524. f->ReleaseInternal();
  525. }
  526. }
  527. }
  528. if( numErrors > 0 )
  529. {
  530. // Release the function pointer that would otherwise be returned if no errors occured
  531. func->ReleaseInternal();
  532. return asERROR;
  533. }
  534. // Return the function
  535. *outFunc = func;
  536. return asSUCCESS;
  537. }
  538. void asCBuilder::ParseScripts()
  539. {
  540. TimeIt("asCBuilder::ParseScripts");
  541. asCArray<asCParser*> parsers((int)scripts.GetLength());
  542. // Parse all the files as if they were one
  543. asUINT n = 0;
  544. for( n = 0; n < scripts.GetLength(); n++ )
  545. {
  546. asCParser *parser = asNEW(asCParser)(this);
  547. if( parser != 0 )
  548. {
  549. parsers.PushLast(parser);
  550. // Parse the script file
  551. parser->ParseScript(scripts[n]);
  552. }
  553. }
  554. if (numErrors == 0)
  555. {
  556. // Find all type declarations
  557. for (n = 0; n < scripts.GetLength(); n++)
  558. {
  559. asCScriptNode *node = parsers[n]->GetScriptNode();
  560. RegisterTypesFromScript(node, scripts[n], engine->nameSpaces[0]);
  561. }
  562. // Before moving forward the builder must establish the relationship between types
  563. // so that a derived type can see the child types of the parent type.
  564. DetermineTypeRelations();
  565. // Complete function definitions (defining returntype and parameters)
  566. for( n = 0; n < funcDefs.GetLength(); n++ )
  567. CompleteFuncDef(funcDefs[n]);
  568. // Find other global nodes
  569. for (n = 0; n < scripts.GetLength(); n++)
  570. {
  571. // Find other global nodes
  572. asCScriptNode *node = parsers[n]->GetScriptNode();
  573. RegisterNonTypesFromScript(node, scripts[n], engine->nameSpaces[0]);
  574. }
  575. // Register script methods found in the interfaces
  576. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  577. {
  578. sClassDeclaration *decl = interfaceDeclarations[n];
  579. asCScriptNode *node = decl->node->firstChild->next;
  580. // Skip list of inherited interfaces
  581. while( node && node->nodeType == snIdentifier )
  582. node = node->next;
  583. while( node )
  584. {
  585. asCScriptNode *next = node->next;
  586. if( node->nodeType == snFunction )
  587. {
  588. node->DisconnectParent();
  589. RegisterScriptFunctionFromNode(node, decl->script, CastToObjectType(decl->typeInfo), true, false, 0, decl->isExistingShared);
  590. }
  591. else if( node->nodeType == snVirtualProperty )
  592. {
  593. node->DisconnectParent();
  594. RegisterVirtualProperty(node, decl->script, CastToObjectType(decl->typeInfo), true, false, 0, decl->isExistingShared);
  595. }
  596. node = next;
  597. }
  598. }
  599. // Register script methods found in the classes
  600. for( n = 0; n < classDeclarations.GetLength(); n++ )
  601. {
  602. sClassDeclaration *decl = classDeclarations[n];
  603. asCScriptNode *node = decl->node->firstChild->next;
  604. // Skip list of classes and interfaces
  605. while( node && node->nodeType == snIdentifier )
  606. node = node->next;
  607. while( node )
  608. {
  609. asCScriptNode *next = node->next;
  610. if( node->nodeType == snFunction )
  611. {
  612. node->DisconnectParent();
  613. RegisterScriptFunctionFromNode(node, decl->script, CastToObjectType(decl->typeInfo), false, false, 0, decl->isExistingShared);
  614. }
  615. else if( node->nodeType == snVirtualProperty )
  616. {
  617. node->DisconnectParent();
  618. RegisterVirtualProperty(node, decl->script, CastToObjectType(decl->typeInfo), false, false, 0, decl->isExistingShared);
  619. }
  620. node = next;
  621. }
  622. // Make sure the default factory & constructor exists for classes
  623. asCObjectType *ot = CastToObjectType(decl->typeInfo);
  624. if( ot->beh.construct == engine->scriptTypeBehaviours.beh.construct )
  625. {
  626. if( ot->beh.constructors.GetLength() == 1 || engine->ep.alwaysImplDefaultConstruct )
  627. {
  628. AddDefaultConstructor(ot, decl->script);
  629. }
  630. else
  631. {
  632. // As the class has another constructor we shouldn't provide the default constructor
  633. if( ot->beh.construct )
  634. {
  635. engine->scriptFunctions[ot->beh.construct]->ReleaseInternal();
  636. ot->beh.construct = 0;
  637. ot->beh.constructors.RemoveIndex(0);
  638. }
  639. if( ot->beh.factory )
  640. {
  641. engine->scriptFunctions[ot->beh.factory]->ReleaseInternal();
  642. ot->beh.factory = 0;
  643. ot->beh.factories.RemoveIndex(0);
  644. }
  645. // Only remove the opAssign method if the script hasn't provided one
  646. if( ot->beh.copy == engine->scriptTypeBehaviours.beh.copy )
  647. {
  648. engine->scriptFunctions[ot->beh.copy]->ReleaseInternal();
  649. ot->beh.copy = 0;
  650. }
  651. }
  652. }
  653. }
  654. }
  655. for( n = 0; n < parsers.GetLength(); n++ )
  656. {
  657. asDELETE(parsers[n],asCParser);
  658. }
  659. }
  660. void asCBuilder::RegisterTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns)
  661. {
  662. asASSERT(node->nodeType == snScript);
  663. // Find structure definitions first
  664. node = node->firstChild;
  665. while( node )
  666. {
  667. asCScriptNode *next = node->next;
  668. if( node->nodeType == snNamespace )
  669. {
  670. // Recursively register the entities defined in the namespace
  671. asCString nsName;
  672. nsName.Assign(&script->code[node->firstChild->tokenPos], node->firstChild->tokenLength);
  673. if( ns->name != "" )
  674. nsName = ns->name + "::" + nsName;
  675. asSNameSpace *nsChild = engine->AddNameSpace(nsName.AddressOf());
  676. RegisterTypesFromScript(node->lastChild, script, nsChild);
  677. }
  678. else
  679. {
  680. if( node->nodeType == snClass )
  681. {
  682. node->DisconnectParent();
  683. RegisterClass(node, script, ns);
  684. }
  685. else if( node->nodeType == snInterface )
  686. {
  687. node->DisconnectParent();
  688. RegisterInterface(node, script, ns);
  689. }
  690. else if( node->nodeType == snEnum )
  691. {
  692. node->DisconnectParent();
  693. RegisterEnum(node, script, ns);
  694. }
  695. else if( node->nodeType == snTypedef )
  696. {
  697. node->DisconnectParent();
  698. RegisterTypedef(node, script, ns);
  699. }
  700. else if( node->nodeType == snFuncDef )
  701. {
  702. node->DisconnectParent();
  703. RegisterFuncDef(node, script, ns, 0);
  704. }
  705. else if( node->nodeType == snMixin )
  706. {
  707. node->DisconnectParent();
  708. RegisterMixinClass(node, script, ns);
  709. }
  710. }
  711. node = next;
  712. }
  713. }
  714. void asCBuilder::RegisterNonTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns)
  715. {
  716. node = node->firstChild;
  717. while( node )
  718. {
  719. asCScriptNode *next = node->next;
  720. if( node->nodeType == snNamespace )
  721. {
  722. // Determine the name of the namespace
  723. asCString nsName;
  724. nsName.Assign(&script->code[node->firstChild->tokenPos], node->firstChild->tokenLength);
  725. if( ns->name != "" )
  726. nsName = ns->name + "::" + nsName;
  727. // Declare the namespace, then add the entities
  728. asSNameSpace *nsChild = engine->AddNameSpace(nsName.AddressOf());
  729. RegisterNonTypesFromScript(node->lastChild, script, nsChild);
  730. }
  731. else
  732. {
  733. node->DisconnectParent();
  734. if( node->nodeType == snFunction )
  735. RegisterScriptFunctionFromNode(node, script, 0, false, true, ns);
  736. else if( node->nodeType == snDeclaration )
  737. RegisterGlobalVar(node, script, ns);
  738. else if( node->nodeType == snVirtualProperty )
  739. RegisterVirtualProperty(node, script, 0, false, true, ns);
  740. else if( node->nodeType == snImport )
  741. RegisterImportedFunction(module->GetNextImportedFunctionId(), node, script, ns);
  742. else
  743. {
  744. // Unused script node
  745. int r, c;
  746. script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  747. WriteWarning(script->name, TXT_UNUSED_SCRIPT_NODE, r, c);
  748. node->Destroy(engine);
  749. }
  750. }
  751. node = next;
  752. }
  753. }
  754. void asCBuilder::CompileFunctions()
  755. {
  756. // Compile each function
  757. for( asUINT n = 0; n < functions.GetLength(); n++ )
  758. {
  759. sFunctionDescription *current = functions[n];
  760. if( current == 0 ) continue;
  761. // Don't compile the function again if it was an existing shared function
  762. if( current->isExistingShared ) continue;
  763. // Don't compile if there is no statement block
  764. if (current->node && !(current->node->nodeType == snStatementBlock || current->node->lastChild->nodeType == snStatementBlock))
  765. continue;
  766. asCCompiler compiler(engine);
  767. asCScriptFunction *func = engine->scriptFunctions[current->funcId];
  768. // Find the class declaration for constructors
  769. sClassDeclaration *classDecl = 0;
  770. if( current->objType && current->name == current->objType->name )
  771. {
  772. for( asUINT c = 0; c < classDeclarations.GetLength(); c++ )
  773. {
  774. if( classDeclarations[c]->typeInfo == current->objType )
  775. {
  776. classDecl = classDeclarations[c];
  777. break;
  778. }
  779. }
  780. asASSERT( classDecl );
  781. }
  782. if( current->node )
  783. {
  784. int r, c;
  785. current->script->ConvertPosToRowCol(current->node->tokenPos, &r, &c);
  786. asCString str = func->GetDeclarationStr();
  787. str.Format(TXT_COMPILING_s, str.AddressOf());
  788. WriteInfo(current->script->name, str, r, c, true);
  789. // When compiling a constructor need to pass the class declaration for member initializations
  790. compiler.CompileFunction(this, current->script, current->paramNames, current->node, func, classDecl);
  791. engine->preMessage.isSet = false;
  792. }
  793. else if( current->objType && current->name == current->objType->name )
  794. {
  795. asCScriptNode *node = classDecl->node;
  796. int r = 0, c = 0;
  797. if( node )
  798. current->script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  799. asCString str = func->GetDeclarationStr();
  800. str.Format(TXT_COMPILING_s, str.AddressOf());
  801. WriteInfo(current->script->name, str, r, c, true);
  802. // This is the default constructor that is generated
  803. // automatically if not implemented by the user.
  804. compiler.CompileDefaultConstructor(this, current->script, node, func, classDecl);
  805. engine->preMessage.isSet = false;
  806. }
  807. else
  808. {
  809. asASSERT( false );
  810. }
  811. }
  812. }
  813. #endif
  814. // Called from module and engine
  815. int asCBuilder::ParseDataType(const char *datatype, asCDataType *result, asSNameSpace *implicitNamespace, bool isReturnType)
  816. {
  817. Reset();
  818. asCScriptCode source;
  819. source.SetCode("", datatype, true);
  820. asCParser parser(this);
  821. int r = parser.ParseDataType(&source, isReturnType);
  822. if( r < 0 )
  823. return asINVALID_TYPE;
  824. // Get data type and property name
  825. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  826. *result = CreateDataTypeFromNode(dataType, &source, implicitNamespace, true);
  827. if( isReturnType )
  828. *result = ModifyDataTypeFromNode(*result, dataType->next, &source, 0, 0);
  829. if( numErrors > 0 )
  830. return asINVALID_TYPE;
  831. return asSUCCESS;
  832. }
  833. int asCBuilder::ParseTemplateDecl(const char *decl, asCString *name, asCArray<asCString> &subtypeNames)
  834. {
  835. Reset();
  836. asCScriptCode source;
  837. source.SetCode("", decl, true);
  838. asCParser parser(this);
  839. int r = parser.ParseTemplateDecl(&source);
  840. if( r < 0 )
  841. return asINVALID_TYPE;
  842. // Get the template name and subtype names
  843. asCScriptNode *node = parser.GetScriptNode()->firstChild;
  844. name->Assign(&decl[node->tokenPos], node->tokenLength);
  845. while( (node = node->next) != 0 )
  846. {
  847. asCString subtypeName;
  848. subtypeName.Assign(&decl[node->tokenPos], node->tokenLength);
  849. subtypeNames.PushLast(subtypeName);
  850. }
  851. // TODO: template: check for name conflicts
  852. if( numErrors > 0 )
  853. return asINVALID_DECLARATION;
  854. return asSUCCESS;
  855. }
  856. int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &name, asCDataType &type, asSNameSpace *ns)
  857. {
  858. // Either datatype or namespace must be informed
  859. asASSERT( dt || ns );
  860. Reset();
  861. if( dt )
  862. {
  863. // Verify that the object type exist
  864. if( CastToObjectType(dt->GetTypeInfo()) == 0 )
  865. return asINVALID_OBJECT;
  866. }
  867. // Check property declaration and type
  868. asCScriptCode source;
  869. source.SetCode(TXT_PROPERTY, decl, true);
  870. asCParser parser(this);
  871. int r = parser.ParsePropertyDeclaration(&source);
  872. if( r < 0 )
  873. return asINVALID_DECLARATION;
  874. // Get data type
  875. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  876. // Check if the property is declared 'by reference'
  877. bool isReference = (dataType->next->tokenType == ttAmp);
  878. // Get the name of the property
  879. asCScriptNode *nameNode = isReference ? dataType->next->next : dataType->next;
  880. // If an object property is registered, then use the
  881. // object's namespace, otherwise use the specified namespace
  882. type = CreateDataTypeFromNode(dataType, &source, dt ? dt->GetTypeInfo()->nameSpace : ns);
  883. name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength);
  884. type.MakeReference(isReference);
  885. // Validate that the type really can be a registered property
  886. // We cannot use CanBeInstantiated, as it is allowed to register
  887. // properties of type that cannot otherwise be instantiated
  888. if( type.IsFuncdef() && !type.IsObjectHandle() )
  889. {
  890. // Function definitions must always be handles
  891. return asINVALID_DECLARATION;
  892. }
  893. // Verify property name
  894. if( dt )
  895. {
  896. if( CheckNameConflictMember(dt->GetTypeInfo(), name.AddressOf(), nameNode, &source, true, false) < 0 )
  897. return asNAME_TAKEN;
  898. }
  899. else
  900. {
  901. if( CheckNameConflict(name.AddressOf(), nameNode, &source, ns, true, false, false) < 0 )
  902. return asNAME_TAKEN;
  903. }
  904. if( numErrors > 0 )
  905. return asINVALID_DECLARATION;
  906. return asSUCCESS;
  907. }
  908. #ifndef AS_NO_COMPILER
  909. asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *prop)
  910. {
  911. asASSERT(CastToObjectType(obj.GetTypeInfo()) != 0);
  912. // TODO: optimize: Improve linear search
  913. asCArray<asCObjectProperty *> &props = CastToObjectType(obj.GetTypeInfo())->properties;
  914. for( asUINT n = 0; n < props.GetLength(); n++ )
  915. {
  916. if( props[n]->name == prop )
  917. {
  918. if( module->m_accessMask & props[n]->accessMask )
  919. return props[n];
  920. else
  921. return 0;
  922. }
  923. }
  924. return 0;
  925. }
  926. #endif
  927. bool asCBuilder::DoesGlobalPropertyExist(const char *prop, asSNameSpace *ns, asCGlobalProperty **outProp, sGlobalVariableDescription **outDesc, bool *isAppProp)
  928. {
  929. if( outProp ) *outProp = 0;
  930. if( outDesc ) *outDesc = 0;
  931. if( isAppProp ) *isAppProp = false;
  932. // Check application registered properties
  933. asCString name(prop);
  934. asCGlobalProperty *globProp = engine->registeredGlobalProps.GetFirst(ns, name);
  935. if( globProp )
  936. {
  937. if( isAppProp ) *isAppProp = true;
  938. if( outProp ) *outProp = globProp;
  939. return true;
  940. }
  941. #ifndef AS_NO_COMPILER
  942. // Check properties being compiled now
  943. sGlobalVariableDescription* desc = globVariables.GetFirst(ns, prop);
  944. if( desc && !desc->isEnumValue )
  945. {
  946. if( outProp ) *outProp = desc->property;
  947. if( outDesc ) *outDesc = desc;
  948. return true;
  949. }
  950. #endif
  951. // Check previously compiled global variables
  952. if( module )
  953. {
  954. globProp = module->m_scriptGlobals.GetFirst(ns, prop);
  955. if( globProp )
  956. {
  957. if( outProp ) *outProp = globProp;
  958. return true;
  959. }
  960. }
  961. return false;
  962. }
  963. asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace *ns, bool *isCompiled, bool *isPureConstant, asQWORD *constantValue, bool *isAppProp)
  964. {
  965. if( isCompiled ) *isCompiled = true;
  966. if( isPureConstant ) *isPureConstant = false;
  967. if( isAppProp ) *isAppProp = false;
  968. if( constantValue ) *constantValue = 0;
  969. asCGlobalProperty *globProp = 0;
  970. sGlobalVariableDescription *globDesc = 0;
  971. if( DoesGlobalPropertyExist(prop, ns, &globProp, &globDesc, isAppProp) )
  972. {
  973. #ifndef AS_NO_COMPILER
  974. if( globDesc )
  975. {
  976. // The property was declared in this build call, check if it has been compiled successfully already
  977. if( isCompiled ) *isCompiled = globDesc->isCompiled;
  978. if( isPureConstant ) *isPureConstant = globDesc->isPureConstant;
  979. if( constantValue ) *constantValue = globDesc->constantValue;
  980. }
  981. else
  982. #endif
  983. if( isAppProp )
  984. {
  985. // Don't return the property if the module doesn't have access to it
  986. if( !(module->m_accessMask & globProp->accessMask) )
  987. globProp = 0;
  988. }
  989. return globProp;
  990. }
  991. return 0;
  992. }
  993. int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern, asCObjectType **outParentClass)
  994. {
  995. asASSERT( objType || ns );
  996. if (listPattern)
  997. *listPattern = 0;
  998. if (outParentClass)
  999. *outParentClass = 0;
  1000. // TODO: Can't we use GetParsedFunctionDetails to do most of what is done in this function?
  1001. Reset();
  1002. asCScriptCode source;
  1003. source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);
  1004. asCParser parser(this);
  1005. int r = parser.ParseFunctionDefinition(&source, listPattern != 0);
  1006. if( r < 0 )
  1007. return asINVALID_DECLARATION;
  1008. asCScriptNode *node = parser.GetScriptNode();
  1009. // Determine scope
  1010. asCScriptNode *n = node->firstChild->next->next;
  1011. asCObjectType *parentClass = 0;
  1012. func->nameSpace = GetNameSpaceFromNode(n, &source, ns, &n, &parentClass);
  1013. if( func->nameSpace == 0 && parentClass == 0 )
  1014. return asINVALID_DECLARATION;
  1015. if (parentClass && func->funcType != asFUNC_FUNCDEF)
  1016. return asINVALID_DECLARATION;
  1017. if (outParentClass)
  1018. *outParentClass = parentClass;
  1019. // Find name
  1020. func->name.Assign(&source.code[n->tokenPos], n->tokenLength);
  1021. // Initialize a script function object for registration
  1022. bool autoHandle;
  1023. // Scoped reference types are allowed to use handle when returned from application functions
  1024. func->returnType = CreateDataTypeFromNode(node->firstChild, &source, objType ? objType->nameSpace : ns, true, parentClass ? parentClass : objType);
  1025. func->returnType = ModifyDataTypeFromNode(func->returnType, node->firstChild->next, &source, 0, &autoHandle);
  1026. if( autoHandle && (!func->returnType.IsObjectHandle() || func->returnType.IsReference()) )
  1027. return asINVALID_DECLARATION;
  1028. if( returnAutoHandle ) *returnAutoHandle = autoHandle;
  1029. // Reference types cannot be returned by value from system functions
  1030. if( isSystemFunction &&
  1031. (func->returnType.GetTypeInfo() &&
  1032. (func->returnType.GetTypeInfo()->flags & asOBJ_REF)) &&
  1033. !(func->returnType.IsReference() ||
  1034. func->returnType.IsObjectHandle()) )
  1035. return asINVALID_DECLARATION;
  1036. // Count number of parameters
  1037. int paramCount = 0;
  1038. asCScriptNode *paramList = n->next;
  1039. n = paramList->firstChild;
  1040. while( n )
  1041. {
  1042. paramCount++;
  1043. n = n->next->next;
  1044. if( n && n->nodeType == snIdentifier )
  1045. n = n->next;
  1046. if( n && n->nodeType == snExpression )
  1047. n = n->next;
  1048. }
  1049. // Preallocate memory
  1050. func->parameterTypes.Allocate(paramCount, false);
  1051. func->parameterNames.SetLength(paramCount);
  1052. func->inOutFlags.Allocate(paramCount, false);
  1053. func->defaultArgs.Allocate(paramCount, false);
  1054. if( paramAutoHandles ) paramAutoHandles->Allocate(paramCount, false);
  1055. n = paramList->firstChild;
  1056. asUINT index = 0;
  1057. while( n )
  1058. {
  1059. asETypeModifiers inOutFlags;
  1060. asCDataType type = CreateDataTypeFromNode(n, &source, objType ? objType->nameSpace : ns, false, parentClass ? parentClass : objType);
  1061. type = ModifyDataTypeFromNode(type, n->next, &source, &inOutFlags, &autoHandle);
  1062. // Reference types cannot be passed by value to system functions
  1063. if( isSystemFunction &&
  1064. (type.GetTypeInfo() &&
  1065. (type.GetTypeInfo()->flags & asOBJ_REF)) &&
  1066. !(type.IsReference() ||
  1067. type.IsObjectHandle()) )
  1068. return asINVALID_DECLARATION;
  1069. // Store the parameter type
  1070. func->parameterTypes.PushLast(type);
  1071. func->inOutFlags.PushLast(inOutFlags);
  1072. // Don't permit void parameters
  1073. if( type.GetTokenType() == ttVoid )
  1074. return asINVALID_DECLARATION;
  1075. if( autoHandle && (!type.IsObjectHandle() || type.IsReference()) )
  1076. return asINVALID_DECLARATION;
  1077. if( paramAutoHandles ) paramAutoHandles->PushLast(autoHandle);
  1078. // Make sure that var type parameters are references
  1079. if( type.GetTokenType() == ttQuestion &&
  1080. !type.IsReference() )
  1081. return asINVALID_DECLARATION;
  1082. // Move to next parameter
  1083. n = n->next->next;
  1084. if( n && n->nodeType == snIdentifier )
  1085. {
  1086. func->parameterNames[index] = asCString(&source.code[n->tokenPos], n->tokenLength);
  1087. n = n->next;
  1088. }
  1089. ++index;
  1090. if( n && n->nodeType == snExpression )
  1091. {
  1092. // Strip out white space and comments to better share the string
  1093. asCString *defaultArgStr = asNEW(asCString);
  1094. if( defaultArgStr )
  1095. {
  1096. *defaultArgStr = GetCleanExpressionString(n, &source);
  1097. func->defaultArgs.PushLast(defaultArgStr);
  1098. }
  1099. n = n->next;
  1100. }
  1101. else
  1102. func->defaultArgs.PushLast(0);
  1103. }
  1104. // Set the read-only flag if const is declared after parameter list
  1105. n = paramList->next;
  1106. if( n && n->nodeType == snUndefined && n->tokenType == ttConst )
  1107. {
  1108. if( objType == 0 )
  1109. return asINVALID_DECLARATION;
  1110. func->SetReadOnly(true);
  1111. n = n->next;
  1112. }
  1113. else
  1114. func->SetReadOnly(false);
  1115. // Check for additional function traits
  1116. while (n && n->nodeType == snIdentifier)
  1117. {
  1118. if (source.TokenEquals(n->tokenPos, n->tokenLength, EXPLICIT_TOKEN))
  1119. func->SetExplicit(true);
  1120. else if( source.TokenEquals(n->tokenPos, n->tokenLength, PROPERTY_TOKEN))
  1121. func->SetProperty(true);
  1122. else
  1123. return asINVALID_DECLARATION;
  1124. n = n->next;
  1125. }
  1126. // If the caller expects a list pattern, check for the existence, else report an error if not
  1127. if( listPattern )
  1128. {
  1129. if( n == 0 || n->nodeType != snListPattern )
  1130. return asINVALID_DECLARATION;
  1131. else
  1132. {
  1133. *listPattern = n;
  1134. n->DisconnectParent();
  1135. }
  1136. }
  1137. else
  1138. {
  1139. if( n )
  1140. return asINVALID_DECLARATION;
  1141. }
  1142. // Make sure the default args are declared correctly
  1143. ValidateDefaultArgs(&source, node, func);
  1144. if( numErrors > 0 || numWarnings > 0 )
  1145. return asINVALID_DECLARATION;
  1146. return 0;
  1147. }
  1148. int asCBuilder::ParseVariableDeclaration(const char *decl, asSNameSpace *implicitNamespace, asCString &outName, asSNameSpace *&outNamespace, asCDataType &outDt)
  1149. {
  1150. Reset();
  1151. asCScriptCode source;
  1152. source.SetCode(TXT_VARIABLE_DECL, decl, true);
  1153. asCParser parser(this);
  1154. int r = parser.ParsePropertyDeclaration(&source);
  1155. if( r < 0 )
  1156. return asINVALID_DECLARATION;
  1157. asCScriptNode *node = parser.GetScriptNode();
  1158. // Determine the scope from declaration
  1159. asCScriptNode *n = node->firstChild->next;
  1160. // TODO: child funcdef: The parentType will be set if the scope is actually a type rather than a namespace
  1161. outNamespace = GetNameSpaceFromNode(n, &source, implicitNamespace, &n);
  1162. if( outNamespace == 0 )
  1163. return asINVALID_DECLARATION;
  1164. // Find name
  1165. outName.Assign(&source.code[n->tokenPos], n->tokenLength);
  1166. // Initialize a script variable object for registration
  1167. outDt = CreateDataTypeFromNode(node->firstChild, &source, implicitNamespace);
  1168. if( numErrors > 0 || numWarnings > 0 )
  1169. return asINVALID_DECLARATION;
  1170. return 0;
  1171. }
  1172. // TODO: This should use SymbolLookupMember, which should be available in the TypeInfo class
  1173. int asCBuilder::CheckNameConflictMember(asCTypeInfo *t, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty, bool isVirtualProperty)
  1174. {
  1175. // It's not necessary to check against object types
  1176. asCObjectType *ot = CastToObjectType(t);
  1177. if (!ot)
  1178. return 0;
  1179. // Check against properties
  1180. // TODO: optimize: Improve linear search
  1181. // Properties are allowed to have the same name as virtual properties
  1182. if( !isVirtualProperty )
  1183. {
  1184. asCArray<asCObjectProperty *> &props = ot->properties;
  1185. for( asUINT n = 0; n < props.GetLength(); n++ )
  1186. {
  1187. if( props[n]->name == name )
  1188. {
  1189. if( code )
  1190. {
  1191. asCString str;
  1192. str.Format(TXT_NAME_CONFLICT_s_OBJ_PROPERTY, name);
  1193. WriteError(str, code, node);
  1194. }
  1195. return -1;
  1196. }
  1197. }
  1198. }
  1199. // Check against virtual properties
  1200. // Don't do this when the check is for a virtual property, as it is allowed to have multiple overloads for virtual properties
  1201. // Properties are allowed to have the same name as virtual properties
  1202. if( !isProperty && !isVirtualProperty )
  1203. {
  1204. asCArray<int> methods = ot->methods;
  1205. for( asUINT n = 0; n < methods.GetLength(); n++ )
  1206. {
  1207. asCScriptFunction *func = engine->scriptFunctions[methods[n]];
  1208. if( func->IsProperty() && func->name.SubString(4) == name )
  1209. {
  1210. if( code )
  1211. {
  1212. asCString str;
  1213. str.Format(TXT_NAME_CONFLICT_s_OBJ_PROPERTY, name);
  1214. WriteError(str, code, node);
  1215. }
  1216. return -1;
  1217. }
  1218. }
  1219. }
  1220. // Check against child types
  1221. asCArray<asCFuncdefType*> &funcdefs = ot->childFuncDefs;
  1222. for (asUINT n = 0; n < funcdefs.GetLength(); n++)
  1223. {
  1224. if (funcdefs[n]->name == name)
  1225. {
  1226. if (code)
  1227. {
  1228. asCString str;
  1229. str.Format(TXT_NAME_CONFLICT_s_IS_FUNCDEF, name);
  1230. WriteError(str, code, node);
  1231. }
  1232. return -1;
  1233. }
  1234. }
  1235. // Property names must be checked against method names
  1236. if( isProperty )
  1237. {
  1238. asCArray<int> methods = ot->methods;
  1239. for( asUINT n = 0; n < methods.GetLength(); n++ )
  1240. {
  1241. if( engine->scriptFunctions[methods[n]]->name == name )
  1242. {
  1243. if( code )
  1244. {
  1245. asCString str;
  1246. str.Format(TXT_NAME_CONFLICT_s_METHOD, name);
  1247. WriteError(str, code, node);
  1248. }
  1249. return -1;
  1250. }
  1251. }
  1252. }
  1253. // If there is a namespace at the same level with the same name as the class, then need to check for conflicts with symbols in that namespace too
  1254. // TODO: When classes can have static members, the code should change so that class name cannot be the same as a namespace
  1255. asCString scope;
  1256. if (ot->nameSpace->name != "")
  1257. scope = ot->nameSpace->name + "::" + ot->name;
  1258. else
  1259. scope = ot->name;
  1260. asSNameSpace *ns = engine->FindNameSpace(scope.AddressOf());
  1261. if (ns)
  1262. {
  1263. // Check as if not a function as it doesn't matter the function signature
  1264. return CheckNameConflict(name, node, code, ns, true, isVirtualProperty, false);
  1265. }
  1266. return 0;
  1267. }
  1268. // TODO: This should use SymbolLookup
  1269. int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns, bool isProperty, bool isVirtualProperty, bool isSharedIntf)
  1270. {
  1271. // Check against registered object types
  1272. if( engine->GetRegisteredType(name, ns) != 0 )
  1273. {
  1274. if( code )
  1275. {
  1276. asCString str;
  1277. if (ns->name != "")
  1278. str = ns->name + "::" + name;
  1279. else
  1280. str = name;
  1281. str.Format(TXT_NAME_CONFLICT_s_EXTENDED_TYPE, str.AddressOf());
  1282. WriteError(str, code, node);
  1283. }
  1284. return -1;
  1285. }
  1286. // Check against global properties
  1287. // Virtual properties are allowed to have the same name as a real property
  1288. if( !isVirtualProperty && DoesGlobalPropertyExist(name, ns) )
  1289. {
  1290. if( code )
  1291. {
  1292. asCString str;
  1293. if (ns->name != "")
  1294. str = ns->name + "::" + name;
  1295. else
  1296. str = name;
  1297. str.Format(TXT_NAME_CONFLICT_s_GLOBAL_PROPERTY, str.AddressOf());
  1298. WriteError(str, code, node);
  1299. }
  1300. return -1;
  1301. }
  1302. // Check against registered global virtual properties
  1303. // Don't do this when the check is for a virtual property, as it is allowed to have multiple overloads for virtual properties
  1304. if( !isProperty || !isVirtualProperty )
  1305. {
  1306. for (asUINT n = 0; n < engine->registeredGlobalFuncs.GetSize(); n++)
  1307. {
  1308. asCScriptFunction *func = engine->registeredGlobalFuncs.Get(n);
  1309. if (func->IsProperty() &&
  1310. func->nameSpace == ns &&
  1311. func->name.SubString(4) == name)
  1312. {
  1313. if (code)
  1314. {
  1315. asCString str;
  1316. if (ns->name != "")
  1317. str = ns->name + "::" + name;
  1318. else
  1319. str = name;
  1320. str.Format(TXT_NAME_CONFLICT_s_IS_VIRTPROP, str.AddressOf());
  1321. WriteError(str, code, node);
  1322. }
  1323. return -1;
  1324. }
  1325. }
  1326. }
  1327. // Property names must be checked against function names
  1328. if (isProperty)
  1329. {
  1330. for (asUINT n = 0; n < engine->registeredGlobalFuncs.GetSize(); n++)
  1331. {
  1332. if (engine->registeredGlobalFuncs.Get(n)->name == name &&
  1333. engine->registeredGlobalFuncs.Get(n)->nameSpace == ns)
  1334. {
  1335. if (code)
  1336. {
  1337. asCString str;
  1338. if (ns->name != "")
  1339. str = ns->name + "::" + name;
  1340. else
  1341. str = name;
  1342. str.Format(TXT_NAME_CONFLICT_s_IS_FUNCTION, str.AddressOf());
  1343. WriteError(str, code, node);
  1344. }
  1345. return -1;
  1346. }
  1347. }
  1348. }
  1349. #ifndef AS_NO_COMPILER
  1350. // Check against interface types
  1351. asUINT n;
  1352. for (n = 0; n < interfaceDeclarations.GetLength(); n++)
  1353. {
  1354. if (interfaceDeclarations[n]->name == name &&
  1355. interfaceDeclarations[n]->typeInfo->nameSpace == ns)
  1356. {
  1357. // Don't report an error if the application wants to ignore duplicate declarations of shared interfaces
  1358. if (!(isSharedIntf && engine->ep.ignoreDuplicateSharedIntf))
  1359. {
  1360. if (code)
  1361. {
  1362. asCString str;
  1363. if (ns->name != "")
  1364. str = ns->name + "::" + name;
  1365. else
  1366. str = name;
  1367. str.Format(TXT_NAME_CONFLICT_s_INTF, str.AddressOf());
  1368. WriteError(str, code, node);
  1369. }
  1370. return -1;
  1371. }
  1372. }
  1373. }
  1374. // Check against class types
  1375. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1376. {
  1377. if( classDeclarations[n]->name == name &&
  1378. classDeclarations[n]->typeInfo->nameSpace == ns )
  1379. {
  1380. if( code )
  1381. {
  1382. asCString str;
  1383. if (ns->name != "")
  1384. str = ns->name + "::" + name;
  1385. else
  1386. str = name;
  1387. str.Format(TXT_NAME_CONFLICT_s_STRUCT, str.AddressOf());
  1388. WriteError(str, code, node);
  1389. }
  1390. return -1;
  1391. }
  1392. }
  1393. // Check against named types
  1394. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  1395. {
  1396. if( namedTypeDeclarations[n]->name == name &&
  1397. namedTypeDeclarations[n]->typeInfo->nameSpace == ns )
  1398. {
  1399. if( code )
  1400. {
  1401. asCString str;
  1402. if (ns->name != "")
  1403. str = ns->name + "::" + name;
  1404. else
  1405. str = name;
  1406. str.Format(TXT_NAME_CONFLICT_s_IS_NAMED_TYPE, str.AddressOf());
  1407. WriteError(str, code, node);
  1408. }
  1409. return -1;
  1410. }
  1411. }
  1412. // Must check for name conflicts with funcdefs
  1413. for( n = 0; n < funcDefs.GetLength(); n++ )
  1414. {
  1415. if( funcDefs[n]->name == name &&
  1416. module->m_funcDefs[funcDefs[n]->idx]->nameSpace == ns )
  1417. {
  1418. if( code )
  1419. {
  1420. asCString str;
  1421. if (ns->name != "")
  1422. str = ns->name + "::" + name;
  1423. else
  1424. str = name;
  1425. str.Format(TXT_NAME_CONFLICT_s_IS_FUNCDEF, str.AddressOf());
  1426. WriteError(str, code, node);
  1427. }
  1428. return -1;
  1429. }
  1430. }
  1431. // Check against mixin classes
  1432. if( GetMixinClass(name, ns) )
  1433. {
  1434. if( code )
  1435. {
  1436. asCString str;
  1437. if (ns->name != "")
  1438. str = ns->name + "::" + name;
  1439. else
  1440. str = name;
  1441. str.Format(TXT_NAME_CONFLICT_s_IS_MIXIN, str.AddressOf());
  1442. WriteError(str, code, node);
  1443. }
  1444. return -1;
  1445. }
  1446. // Check against virtual properties
  1447. // Don't do this when the check is for a virtual property, as it is allowed to have multiple overloads for virtual properties
  1448. if( !isProperty && !isVirtualProperty )
  1449. {
  1450. for (n = 0; n < functions.GetLength(); n++)
  1451. {
  1452. asCScriptFunction *func = engine->scriptFunctions[functions[n] ? functions[n]->funcId : 0];
  1453. if (func &&
  1454. func->IsProperty() &&
  1455. func->objectType == 0 &&
  1456. func->nameSpace == ns &&
  1457. func->name.SubString(4) == name)
  1458. {
  1459. if (code)
  1460. {
  1461. asCString str;
  1462. if (ns->name != "")
  1463. str = ns->name + "::" + name;
  1464. else
  1465. str = name;
  1466. str.Format(TXT_NAME_CONFLICT_s_IS_VIRTPROP, str.AddressOf());
  1467. WriteError(str, code, node);
  1468. }
  1469. return -1;
  1470. }
  1471. }
  1472. }
  1473. // Property names must be checked against function names
  1474. if (isProperty)
  1475. {
  1476. for (n = 0; n < functions.GetLength(); n++)
  1477. {
  1478. if (functions[n] &&
  1479. functions[n]->objType == 0 &&
  1480. functions[n]->name == name &&
  1481. engine->scriptFunctions[functions[n]->funcId]->nameSpace == ns )
  1482. {
  1483. if (code)
  1484. {
  1485. asCString str;
  1486. if (ns->name != "")
  1487. str = ns->name + "::" + name;
  1488. else
  1489. str = name;
  1490. str.Format(TXT_NAME_CONFLICT_s_IS_FUNCTION, str.AddressOf());
  1491. WriteError(str, code, node);
  1492. }
  1493. return -1;
  1494. }
  1495. }
  1496. }
  1497. #else
  1498. UNUSED_VAR(isSharedIntf);
  1499. #endif
  1500. return 0;
  1501. }
  1502. // Returns a negative value on invalid property
  1503. // -2 incorrect prefix
  1504. // -3 invalid signature
  1505. // -4 mismatching type for get/set
  1506. // -5 name conflict
  1507. int asCBuilder::ValidateVirtualProperty(asCScriptFunction *func)
  1508. {
  1509. asASSERT( func->IsProperty() );
  1510. // A virtual property must have the prefix "get_" or "set_"
  1511. asCString prefix = func->name.SubString(0, 4);
  1512. if( prefix != "get_" && prefix != "set_" )
  1513. return -2;
  1514. // A getter must return a non-void type and have at most 1 argument (indexed property)
  1515. if( prefix == "get_" && (func->returnType == asCDataType::CreatePrimitive(ttVoid, false) || func->parameterTypes.GetLength() > 1) )
  1516. return -3;
  1517. // A setter must return a void and have 1 or 2 arguments (indexed property)
  1518. if( prefix == "set_" && (func->returnType != asCDataType::CreatePrimitive(ttVoid, false) || func->parameterTypes.GetLength() < 1 || func->parameterTypes.GetLength() > 2) )
  1519. return -3;
  1520. // Check matching getter/setter
  1521. asCDataType getType, setType;
  1522. bool found = false;
  1523. if( prefix == "get_" )
  1524. {
  1525. getType = func->returnType;
  1526. // Find if there is a set accessor in the same scope, and then validate the type of it
  1527. // TODO: optimize search
  1528. asCString setName = "set_" + func->name.SubString(4);
  1529. for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
  1530. {
  1531. asCScriptFunction *setFunc = engine->scriptFunctions[n];
  1532. if( setFunc == 0 || setFunc->name != setName || !setFunc->IsProperty() )
  1533. continue;
  1534. // Is it the same scope?
  1535. if( func->module != setFunc->module || func->nameSpace != setFunc->nameSpace || func->objectType != setFunc->objectType )
  1536. continue;
  1537. setType = setFunc->parameterTypes[setFunc->parameterTypes.GetLength() - 1];
  1538. found = true;
  1539. break;
  1540. }
  1541. }
  1542. else
  1543. {
  1544. setType = func->parameterTypes[func->parameterTypes.GetLength() - 1];
  1545. // Find if there is a get accessor in the same scope and then validate the type of it
  1546. // TODO: optimize search
  1547. asCString getName = "get_" + func->name.SubString(4);
  1548. for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
  1549. {
  1550. asCScriptFunction *getFunc = engine->scriptFunctions[n];
  1551. if( getFunc == 0 || getFunc->name != getName || !getFunc->IsProperty() )
  1552. continue;
  1553. // Is it the same scope?
  1554. if( func->module != getFunc->module || func->nameSpace != getFunc->nameSpace || func->objectType != getFunc->objectType )
  1555. continue;
  1556. getType = getFunc->returnType;
  1557. found = true;
  1558. break;
  1559. }
  1560. }
  1561. if( found )
  1562. {
  1563. // Check that the type matches
  1564. // It is permitted for a getter to return a handle and the setter to take a reference
  1565. if( !getType.IsEqualExceptRefAndConst(setType) &&
  1566. !((getType.IsObjectHandle() && !setType.IsObjectHandle()) &&
  1567. (getType.GetTypeInfo() == setType.GetTypeInfo())) )
  1568. {
  1569. return -4;
  1570. }
  1571. }
  1572. // Check name conflict with other entities in the same scope
  1573. // It is allowed to have a real property of the same name, in which case the virtual property hides the real one.
  1574. int r;
  1575. if( func->objectType )
  1576. r = CheckNameConflictMember(func->objectType, func->name.SubString(4).AddressOf(), 0, 0, true, true);
  1577. else
  1578. r = CheckNameConflict(func->name.SubString(4).AddressOf(), 0, 0, func->nameSpace, true, true, false);
  1579. if( r < 0 )
  1580. return -5;
  1581. // Everything is OK
  1582. return 0;
  1583. }
  1584. #ifndef AS_NO_COMPILER
  1585. sMixinClass *asCBuilder::GetMixinClass(const char *name, asSNameSpace *ns)
  1586. {
  1587. for( asUINT n = 0; n < mixinClasses.GetLength(); n++ )
  1588. if( mixinClasses[n]->name == name &&
  1589. mixinClasses[n]->ns == ns )
  1590. return mixinClasses[n];
  1591. return 0;
  1592. }
  1593. int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns, asCObjectType *parent)
  1594. {
  1595. // namespace and parent are exclusively mutual
  1596. asASSERT((ns == 0 && parent) || (ns && parent == 0));
  1597. // Skip leading 'shared' and 'external' keywords
  1598. asCScriptNode *n = node->firstChild;
  1599. while (n->nodeType == snIdentifier)
  1600. n = n->next;
  1601. // Find the name
  1602. asASSERT( n->nodeType == snDataType );
  1603. n = n->next->next;
  1604. asCString name;
  1605. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  1606. // Check for name conflict with other types
  1607. if (ns)
  1608. {
  1609. int r = CheckNameConflict(name.AddressOf(), node, file, ns, true, false, false);
  1610. if (asSUCCESS != r)
  1611. {
  1612. node->Destroy(engine);
  1613. return r;
  1614. }
  1615. }
  1616. else
  1617. {
  1618. int r = CheckNameConflictMember(parent, name.AddressOf(), node, file, false, false);
  1619. if (asSUCCESS != r)
  1620. {
  1621. node->Destroy(engine);
  1622. return r;
  1623. }
  1624. }
  1625. // The function definition should be stored as a asCScriptFunction so that the application
  1626. // can use the asIScriptFunction interface to enumerate the return type and parameters
  1627. // The return type and parameter types aren't determined in this function. A second pass is
  1628. // necessary after all type declarations have been identified. The second pass is implemented
  1629. // in CompleteFuncDef().
  1630. sFuncDef *fd = asNEW(sFuncDef);
  1631. if( fd == 0 )
  1632. {
  1633. node->Destroy(engine);
  1634. return asOUT_OF_MEMORY;
  1635. }
  1636. fd->name = name;
  1637. fd->node = node;
  1638. fd->script = file;
  1639. fd->idx = module->AddFuncDef(name, ns, parent);
  1640. funcDefs.PushLast(fd);
  1641. return 0;
  1642. }
  1643. void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
  1644. {
  1645. asCArray<asCString *> defaultArgs;
  1646. asSFunctionTraits funcTraits;
  1647. asCFuncdefType *fdt = module->m_funcDefs[funcDef->idx];
  1648. asASSERT( fdt );
  1649. asCScriptFunction *func = fdt->funcdef;
  1650. asSNameSpace *implicitNs = func->nameSpace ? func->nameSpace : fdt->parentClass->nameSpace;
  1651. GetParsedFunctionDetails(funcDef->node, funcDef->script, fdt->parentClass, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, funcTraits, implicitNs);
  1652. // There should not be any defaultArgs, but if there are any we need to delete them to avoid leaks
  1653. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1654. if( defaultArgs[n] )
  1655. asDELETE(defaultArgs[n], asCString);
  1656. // All funcdefs are shared, unless one of the parameter types or return type is not shared
  1657. bool declaredShared = funcTraits.GetTrait(asTRAIT_SHARED);
  1658. funcTraits.SetTrait(asTRAIT_SHARED, true);
  1659. if (func->returnType.GetTypeInfo() && !func->returnType.GetTypeInfo()->IsShared())
  1660. {
  1661. if (declaredShared)
  1662. {
  1663. asCString s;
  1664. s.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, func->returnType.GetTypeInfo()->name.AddressOf());
  1665. WriteError(s.AddressOf(), funcDef->script, funcDef->node);
  1666. }
  1667. funcTraits.SetTrait(asTRAIT_SHARED, false);
  1668. }
  1669. for( asUINT n = 0; funcTraits.GetTrait(asTRAIT_SHARED) && n < func->parameterTypes.GetLength(); n++ )
  1670. if (func->parameterTypes[n].GetTypeInfo() && !func->parameterTypes[n].GetTypeInfo()->IsShared())
  1671. {
  1672. if (declaredShared)
  1673. {
  1674. asCString s;
  1675. s.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, func->parameterTypes[n].GetTypeInfo()->name.AddressOf());
  1676. WriteError(s.AddressOf(), funcDef->script, funcDef->node);
  1677. }
  1678. funcTraits.SetTrait(asTRAIT_SHARED, false);
  1679. }
  1680. func->SetShared(funcTraits.GetTrait(asTRAIT_SHARED));
  1681. // Check if there is another identical funcdef from another module and if so reuse that instead
  1682. bool found = false;
  1683. if( func->IsShared() )
  1684. {
  1685. for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
  1686. {
  1687. asCFuncdefType *fdt2 = engine->funcDefs[n];
  1688. if( fdt2 == 0 || fdt == fdt2 )
  1689. continue;
  1690. if( !fdt2->funcdef->IsShared() )
  1691. continue;
  1692. if( fdt2->name == fdt->name &&
  1693. fdt2->nameSpace == fdt->nameSpace &&
  1694. fdt2->parentClass == fdt->parentClass &&
  1695. fdt2->funcdef->IsSignatureExceptNameEqual(func) )
  1696. {
  1697. // Replace our funcdef for the existing one
  1698. funcDef->idx = fdt2->funcdef->id;
  1699. module->ReplaceFuncDef(fdt, fdt2);
  1700. fdt2->AddRefInternal();
  1701. engine->funcDefs.RemoveValue(fdt);
  1702. fdt->ReleaseInternal();
  1703. found = true;
  1704. break;
  1705. }
  1706. }
  1707. }
  1708. // If the funcdef was declared as external then the existing shared declaration must have been found
  1709. if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !found)
  1710. {
  1711. asCString str;
  1712. str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, funcDef->name.AddressOf());
  1713. WriteError(str, funcDef->script, funcDef->node);
  1714. }
  1715. // Remember if the type was declared as external so the saved bytecode can be flagged accordingly
  1716. if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && found)
  1717. module->m_externalTypes.PushLast(engine->scriptFunctions[funcDef->idx]->funcdefType);
  1718. }
  1719. int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1720. {
  1721. // Has the application disabled global vars?
  1722. if( engine->ep.disallowGlobalVars )
  1723. WriteError(TXT_GLOBAL_VARS_NOT_ALLOWED, file, node);
  1724. // What data type is it?
  1725. asCDataType type = CreateDataTypeFromNode(node->firstChild, file, ns);
  1726. if( !type.CanBeInstantiated() )
  1727. {
  1728. asCString str;
  1729. if( type.IsAbstractClass() )
  1730. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, type.Format(ns).AddressOf());
  1731. else if( type.IsInterface() )
  1732. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, type.Format(ns).AddressOf());
  1733. else
  1734. // TODO: Improve error message to explain why
  1735. str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format(ns).AddressOf());
  1736. WriteError(str, file, node);
  1737. }
  1738. asCScriptNode *n = node->firstChild->next;
  1739. while( n )
  1740. {
  1741. // Verify that the name isn't taken
  1742. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1743. CheckNameConflict(name.AddressOf(), n, file, ns, true, false, false);
  1744. // Register the global variable
  1745. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  1746. if( gvar == 0 )
  1747. {
  1748. node->Destroy(engine);
  1749. return asOUT_OF_MEMORY;
  1750. }
  1751. gvar->script = file;
  1752. gvar->name = name;
  1753. gvar->isCompiled = false;
  1754. gvar->datatype = type;
  1755. gvar->isEnumValue = false;
  1756. gvar->ns = ns;
  1757. // TODO: Give error message if wrong
  1758. asASSERT(!gvar->datatype.IsReference());
  1759. // Allocation is done when the variable is compiled, to allow for autos
  1760. gvar->property = 0;
  1761. gvar->index = 0;
  1762. globVariables.Put(gvar);
  1763. gvar->declaredAtNode = n;
  1764. n = n->next;
  1765. gvar->declaredAtNode->DisconnectParent();
  1766. gvar->initializationNode = 0;
  1767. if( n &&
  1768. ( n->nodeType == snAssignment ||
  1769. n->nodeType == snArgList ||
  1770. n->nodeType == snInitList ) )
  1771. {
  1772. gvar->initializationNode = n;
  1773. n = n->next;
  1774. gvar->initializationNode->DisconnectParent();
  1775. }
  1776. }
  1777. node->Destroy(engine);
  1778. return 0;
  1779. }
  1780. int asCBuilder::RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1781. {
  1782. asCScriptNode *cl = node->firstChild;
  1783. asASSERT( cl->nodeType == snClass );
  1784. asCScriptNode *n = cl->firstChild;
  1785. // Skip potential decorator tokens
  1786. while( n->tokenType == ttIdentifier &&
  1787. (file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) ||
  1788. file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN) ||
  1789. file->TokenEquals(n->tokenPos, n->tokenLength, ABSTRACT_TOKEN) ||
  1790. file->TokenEquals(n->tokenPos, n->tokenLength, EXTERNAL_TOKEN)) )
  1791. {
  1792. // Report error, because mixin class cannot be final or shared
  1793. asCString msg;
  1794. msg.Format(TXT_MIXIN_CANNOT_BE_DECLARED_AS_s, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1795. WriteError(msg, file, n);
  1796. asCScriptNode *tmp = n;
  1797. n = n->next;
  1798. // Remove the invalid node, so compilation can continue as if it wasn't there
  1799. tmp->DisconnectParent();
  1800. tmp->Destroy(engine);
  1801. }
  1802. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1803. int r, c;
  1804. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1805. CheckNameConflict(name.AddressOf(), n, file, ns, true, false, false);
  1806. sMixinClass *decl = asNEW(sMixinClass);
  1807. if( decl == 0 )
  1808. {
  1809. node->Destroy(engine);
  1810. return asOUT_OF_MEMORY;
  1811. }
  1812. mixinClasses.PushLast(decl);
  1813. decl->name = name;
  1814. decl->ns = ns;
  1815. decl->node = cl;
  1816. decl->script = file;
  1817. // Clean up memory
  1818. cl->DisconnectParent();
  1819. node->Destroy(engine);
  1820. // Check that the mixin class doesn't contain any child types
  1821. // TODO: Add support for child types in mixin classes
  1822. n = cl->firstChild;
  1823. while (n)
  1824. {
  1825. if (n->nodeType == snFuncDef)
  1826. {
  1827. WriteError(TXT_MIXIN_CANNOT_HAVE_CHILD_TYPES, file, n);
  1828. break;
  1829. }
  1830. n = n->next;
  1831. }
  1832. return 0;
  1833. }
  1834. int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1835. {
  1836. asCScriptNode *n = node->firstChild;
  1837. bool isFinal = false;
  1838. bool isShared = false;
  1839. bool isAbstract = false;
  1840. bool isExternal = false;
  1841. // Check the class modifiers
  1842. while( n->tokenType == ttIdentifier )
  1843. {
  1844. if( file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) )
  1845. {
  1846. if( isAbstract )
  1847. WriteError(TXT_CLASS_CANT_BE_FINAL_AND_ABSTRACT, file, n);
  1848. else
  1849. {
  1850. if( isFinal )
  1851. {
  1852. asCString msg;
  1853. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1854. WriteWarning(msg, file, n);
  1855. }
  1856. isFinal = true;
  1857. }
  1858. }
  1859. else if( file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN) )
  1860. {
  1861. if( isShared )
  1862. {
  1863. asCString msg;
  1864. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1865. WriteWarning(msg, file, n);
  1866. }
  1867. isShared = true;
  1868. }
  1869. else if (file->TokenEquals(n->tokenPos, n->tokenLength, EXTERNAL_TOKEN))
  1870. {
  1871. if (isExternal)
  1872. {
  1873. asCString msg;
  1874. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1875. WriteWarning(msg, file, n);
  1876. }
  1877. isExternal = true;
  1878. }
  1879. else if( file->TokenEquals(n->tokenPos, n->tokenLength, ABSTRACT_TOKEN) )
  1880. {
  1881. if( isFinal )
  1882. WriteError(TXT_CLASS_CANT_BE_FINAL_AND_ABSTRACT, file, n);
  1883. else
  1884. {
  1885. if( isAbstract )
  1886. {
  1887. asCString msg;
  1888. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1889. WriteWarning(msg, file, n);
  1890. }
  1891. isAbstract = true;
  1892. }
  1893. }
  1894. else
  1895. {
  1896. // This is the name of the class
  1897. break;
  1898. }
  1899. n = n->next;
  1900. }
  1901. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1902. int r, c;
  1903. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1904. CheckNameConflict(name.AddressOf(), n, file, ns, true, false, false);
  1905. sClassDeclaration *decl = asNEW(sClassDeclaration);
  1906. if( decl == 0 )
  1907. {
  1908. node->Destroy(engine);
  1909. return asOUT_OF_MEMORY;
  1910. }
  1911. classDeclarations.PushLast(decl);
  1912. decl->name = name;
  1913. decl->script = file;
  1914. decl->node = node;
  1915. // External shared interfaces must not try to redefine the interface
  1916. if (isExternal && (n->next == 0 || n->next->tokenType != ttEndStatement))
  1917. {
  1918. asCString str;
  1919. str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf());
  1920. WriteError(str, file, n);
  1921. }
  1922. else if (!isExternal && n->next && n->next->tokenType == ttEndStatement)
  1923. {
  1924. asCString str;
  1925. str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf());
  1926. WriteError(str, file, n);
  1927. }
  1928. // If this type is shared and there already exist another shared
  1929. // type of the same name, then that one should be used instead of
  1930. // creating a new one.
  1931. asCObjectType *st = 0;
  1932. if( isShared )
  1933. {
  1934. for( asUINT i = 0; i < engine->sharedScriptTypes.GetLength(); i++ )
  1935. {
  1936. st = CastToObjectType(engine->sharedScriptTypes[i]);
  1937. if( st &&
  1938. st->IsShared() &&
  1939. st->name == name &&
  1940. st->nameSpace == ns &&
  1941. !st->IsInterface() )
  1942. {
  1943. // We'll use the existing type
  1944. decl->isExistingShared = true;
  1945. decl->typeInfo = st;
  1946. module->AddClassType(st);
  1947. st->AddRefInternal();
  1948. break;
  1949. }
  1950. }
  1951. }
  1952. // If the class was declared as external then it must have been compiled in a different module first
  1953. if (isExternal && decl->typeInfo == 0)
  1954. {
  1955. asCString str;
  1956. str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf());
  1957. WriteError(str, file, n);
  1958. }
  1959. // Remember if the class was declared as external so the saved bytecode can be flagged accordingly
  1960. if (isExternal)
  1961. module->m_externalTypes.PushLast(st);
  1962. if (!decl->isExistingShared)
  1963. {
  1964. // Create a new object type for this class
  1965. st = asNEW(asCObjectType)(engine);
  1966. if (st == 0)
  1967. return asOUT_OF_MEMORY;
  1968. // By default all script classes are marked as garbage collected.
  1969. // Only after the complete structure and relationship between classes
  1970. // is known, can the flag be cleared for those objects that truly cannot
  1971. // form circular references. This is important because a template
  1972. // callback may be called with a script class before the compilation
  1973. // completes, and until it is known, the callback must assume the class
  1974. // is garbage collected.
  1975. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_GC;
  1976. if (isShared)
  1977. st->flags |= asOBJ_SHARED;
  1978. if (isFinal)
  1979. st->flags |= asOBJ_NOINHERIT;
  1980. if (isAbstract)
  1981. st->flags |= asOBJ_ABSTRACT;
  1982. if (node->tokenType == ttHandle)
  1983. st->flags |= asOBJ_IMPLICIT_HANDLE;
  1984. st->size = sizeof(asCScriptObject);
  1985. st->name = name;
  1986. st->nameSpace = ns;
  1987. st->module = module;
  1988. module->AddClassType(st);
  1989. if (isShared)
  1990. {
  1991. engine->sharedScriptTypes.PushLast(st);
  1992. st->AddRefInternal();
  1993. }
  1994. decl->typeInfo = st;
  1995. // Use the default script class behaviours
  1996. st->beh = engine->scriptTypeBehaviours.beh;
  1997. // TODO: Move this to asCObjectType so that the asCRestore can reuse it
  1998. engine->scriptFunctions[st->beh.addref]->AddRefInternal();
  1999. engine->scriptFunctions[st->beh.release]->AddRefInternal();
  2000. engine->scriptFunctions[st->beh.gcEnumReferences]->AddRefInternal();
  2001. engine->scriptFunctions[st->beh.gcGetFlag]->AddRefInternal();
  2002. engine->scriptFunctions[st->beh.gcGetRefCount]->AddRefInternal();
  2003. engine->scriptFunctions[st->beh.gcReleaseAllReferences]->AddRefInternal();
  2004. engine->scriptFunctions[st->beh.gcSetFlag]->AddRefInternal();
  2005. engine->scriptFunctions[st->beh.copy]->AddRefInternal();
  2006. engine->scriptFunctions[st->beh.factory]->AddRefInternal();
  2007. engine->scriptFunctions[st->beh.construct]->AddRefInternal();
  2008. // TODO: weak: Should not do this if the class has been declared with noweak
  2009. engine->scriptFunctions[st->beh.getWeakRefFlag]->AddRefInternal();
  2010. // Skip to the content of the class
  2011. while (n && n->nodeType == snIdentifier)
  2012. n = n->next;
  2013. }
  2014. // Register possible child types
  2015. while (n)
  2016. {
  2017. node = n->next;
  2018. if (n->nodeType == snFuncDef)
  2019. {
  2020. n->DisconnectParent();
  2021. if (!decl->isExistingShared)
  2022. RegisterFuncDef(n, file, 0, st);
  2023. else
  2024. {
  2025. // Destroy the node, since it won't be used
  2026. // TODO: Should verify that the funcdef is identical to the one in the existing shared class
  2027. n->Destroy(engine);
  2028. }
  2029. }
  2030. n = node;
  2031. }
  2032. return 0;
  2033. }
  2034. int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  2035. {
  2036. asCScriptNode *n = node->firstChild;
  2037. bool isShared = false;
  2038. bool isExternal = false;
  2039. while( n->nodeType == snIdentifier )
  2040. {
  2041. if (file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN))
  2042. isShared = true;
  2043. else if (file->TokenEquals(n->tokenPos, n->tokenLength, EXTERNAL_TOKEN))
  2044. isExternal = true;
  2045. else
  2046. break;
  2047. n = n->next;
  2048. }
  2049. int r, c;
  2050. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  2051. asCString name;
  2052. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  2053. CheckNameConflict(name.AddressOf(), n, file, ns, true, false, isShared);
  2054. sClassDeclaration *decl = asNEW(sClassDeclaration);
  2055. if( decl == 0 )
  2056. {
  2057. node->Destroy(engine);
  2058. return asOUT_OF_MEMORY;
  2059. }
  2060. interfaceDeclarations.PushLast(decl);
  2061. decl->name = name;
  2062. decl->script = file;
  2063. decl->node = node;
  2064. // External shared interfaces must not try to redefine the interface
  2065. if (isExternal && (n->next == 0 || n->next->tokenType != ttEndStatement) )
  2066. {
  2067. asCString str;
  2068. str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf());
  2069. WriteError(str, file, n);
  2070. }
  2071. else if (!isExternal && n->next && n->next->tokenType == ttEndStatement)
  2072. {
  2073. asCString str;
  2074. str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf());
  2075. WriteError(str, file, n);
  2076. }
  2077. // If this type is shared and there already exist another shared
  2078. // type of the same name, then that one should be used instead of
  2079. // creating a new one.
  2080. if( isShared )
  2081. {
  2082. for( asUINT i = 0; i < engine->sharedScriptTypes.GetLength(); i++ )
  2083. {
  2084. asCObjectType *st = CastToObjectType(engine->sharedScriptTypes[i]);
  2085. if( st &&
  2086. st->IsShared() &&
  2087. st->name == name &&
  2088. st->nameSpace == ns &&
  2089. st->IsInterface() )
  2090. {
  2091. // We'll use the existing type
  2092. decl->isExistingShared = true;
  2093. decl->typeInfo = st;
  2094. module->AddClassType(st);
  2095. st->AddRefInternal();
  2096. // Remember if the interface was declared as external so the saved bytecode can be flagged accordingly
  2097. if (isExternal)
  2098. module->m_externalTypes.PushLast(st);
  2099. return 0;
  2100. }
  2101. }
  2102. }
  2103. // If the interface was declared as external then it must have been compiled in a different module first
  2104. if (isExternal)
  2105. {
  2106. asCString str;
  2107. str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf());
  2108. WriteError(str, file, n);
  2109. }
  2110. // Register the object type for the interface
  2111. asCObjectType *st = asNEW(asCObjectType)(engine);
  2112. if( st == 0 )
  2113. return asOUT_OF_MEMORY;
  2114. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
  2115. if( isShared )
  2116. st->flags |= asOBJ_SHARED;
  2117. st->size = 0; // Cannot be instantiated
  2118. st->name = name;
  2119. st->nameSpace = ns;
  2120. st->module = module;
  2121. module->AddClassType(st);
  2122. if( isShared )
  2123. {
  2124. engine->sharedScriptTypes.PushLast(st);
  2125. st->AddRefInternal();
  2126. }
  2127. decl->typeInfo = st;
  2128. // Use the default script class behaviours
  2129. st->beh.construct = 0;
  2130. st->beh.addref = engine->scriptTypeBehaviours.beh.addref;
  2131. engine->scriptFunctions[st->beh.addref]->AddRefInternal();
  2132. st->beh.release = engine->scriptTypeBehaviours.beh.release;
  2133. engine->scriptFunctions[st->beh.release]->AddRefInternal();
  2134. st->beh.copy = 0;
  2135. return 0;
  2136. }
  2137. void asCBuilder::CompileGlobalVariables()
  2138. {
  2139. bool compileSucceeded = true;
  2140. // Store state of compilation (errors, warning, output)
  2141. int currNumErrors = numErrors;
  2142. int currNumWarnings = numWarnings;
  2143. // Backup the original message stream
  2144. bool msgCallback = engine->msgCallback;
  2145. asSSystemFunctionInterface msgCallbackFunc = engine->msgCallbackFunc;
  2146. void *msgCallbackObj = engine->msgCallbackObj;
  2147. // Set the new temporary message stream
  2148. asCOutputBuffer outBuffer;
  2149. engine->SetMessageCallback(asMETHOD(asCOutputBuffer, Callback), &outBuffer, asCALL_THISCALL);
  2150. asCOutputBuffer finalOutput;
  2151. asCScriptFunction *initFunc = 0;
  2152. asCSymbolTable<asCGlobalProperty> initOrder;
  2153. // We first try to compile all the primitive global variables, and only after that
  2154. // compile the non-primitive global variables. This permits the constructors
  2155. // for the complex types to use the already initialized variables of primitive
  2156. // type. Note, we currently don't know which global variables are used in the
  2157. // constructors, so we cannot guarantee that variables of complex types are
  2158. // initialized in the correct order, so we won't reorder those.
  2159. bool compilingPrimitives = true;
  2160. // Compile each global variable
  2161. while( compileSucceeded )
  2162. {
  2163. compileSucceeded = false;
  2164. int accumErrors = 0;
  2165. int accumWarnings = 0;
  2166. // Restore state of compilation
  2167. finalOutput.Clear();
  2168. asCSymbolTable<sGlobalVariableDescription>::iterator it = globVariables.List();
  2169. for( ; it; it++ )
  2170. {
  2171. sGlobalVariableDescription *gvar = *it;
  2172. if( gvar->isCompiled )
  2173. continue;
  2174. asCByteCode init(engine);
  2175. numWarnings = 0;
  2176. numErrors = 0;
  2177. outBuffer.Clear();
  2178. // Skip this for now if we're not compiling complex types yet
  2179. if( compilingPrimitives && !gvar->datatype.IsPrimitive() )
  2180. continue;
  2181. if( gvar->declaredAtNode )
  2182. {
  2183. int r, c;
  2184. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &r, &c);
  2185. asCString str = gvar->datatype.Format(gvar->ns);
  2186. str += " " + gvar->name;
  2187. str.Format(TXT_COMPILING_s, str.AddressOf());
  2188. WriteInfo(gvar->script->name, str, r, c, true);
  2189. }
  2190. if( gvar->isEnumValue )
  2191. {
  2192. int r;
  2193. if( gvar->initializationNode )
  2194. {
  2195. asCCompiler comp(engine);
  2196. asCScriptFunction func(engine, module, asFUNC_SCRIPT);
  2197. // Set the namespace that should be used during the compilation
  2198. func.nameSpace = gvar->datatype.GetTypeInfo()->nameSpace;
  2199. // Temporarily switch the type of the variable to int so it can be compiled properly
  2200. asCDataType saveType;
  2201. saveType = gvar->datatype;
  2202. gvar->datatype = asCDataType::CreatePrimitive(ttInt, true);
  2203. r = comp.CompileGlobalVariable(this, gvar->script, gvar->initializationNode, gvar, &func);
  2204. gvar->datatype = saveType;
  2205. // Make the function a dummy so it doesn't try to release objects while destroying the function
  2206. func.funcType = asFUNC_DUMMY;
  2207. }
  2208. else
  2209. {
  2210. r = 0;
  2211. // When there is no assignment the value is the last + 1
  2212. int enumVal = 0;
  2213. asCSymbolTable<sGlobalVariableDescription>::iterator prev_it = it;
  2214. prev_it--;
  2215. if( prev_it )
  2216. {
  2217. sGlobalVariableDescription *gvar2 = *prev_it;
  2218. if(gvar2->datatype == gvar->datatype )
  2219. {
  2220. enumVal = int(gvar2->constantValue) + 1;
  2221. if( !gvar2->isCompiled )
  2222. {
  2223. int row, col;
  2224. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &row, &col);
  2225. asCString str = gvar->datatype.Format(gvar->ns);
  2226. str += " " + gvar->name;
  2227. str.Format(TXT_COMPILING_s, str.AddressOf());
  2228. WriteInfo(gvar->script->name, str, row, col, true);
  2229. str.Format(TXT_UNINITIALIZED_GLOBAL_VAR_s, gvar2->name.AddressOf());
  2230. WriteError(gvar->script->name, str, row, col);
  2231. r = -1;
  2232. }
  2233. }
  2234. }
  2235. gvar->constantValue = enumVal;
  2236. }
  2237. if( r >= 0 )
  2238. {
  2239. // Set the value as compiled
  2240. gvar->isCompiled = true;
  2241. compileSucceeded = true;
  2242. }
  2243. }
  2244. else
  2245. {
  2246. // Compile the global variable
  2247. initFunc = asNEW(asCScriptFunction)(engine, module, asFUNC_SCRIPT);
  2248. if( initFunc == 0 )
  2249. {
  2250. // Out of memory
  2251. return;
  2252. }
  2253. // Set the namespace that should be used for this function
  2254. initFunc->nameSpace = gvar->ns;
  2255. asCCompiler comp(engine);
  2256. int r = comp.CompileGlobalVariable(this, gvar->script, gvar->initializationNode, gvar, initFunc);
  2257. if( r >= 0 )
  2258. {
  2259. // Compilation succeeded
  2260. gvar->isCompiled = true;
  2261. compileSucceeded = true;
  2262. }
  2263. else
  2264. {
  2265. // Compilation failed
  2266. initFunc->funcType = asFUNC_DUMMY;
  2267. asDELETE(initFunc, asCScriptFunction);
  2268. initFunc = 0;
  2269. }
  2270. }
  2271. if( gvar->isCompiled )
  2272. {
  2273. // Add warnings for this constant to the total build
  2274. if( numWarnings )
  2275. {
  2276. currNumWarnings += numWarnings;
  2277. if( msgCallback )
  2278. outBuffer.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  2279. }
  2280. // Determine order of variable initializations
  2281. if( gvar->property && !gvar->isEnumValue )
  2282. initOrder.Put(gvar->property);
  2283. // Does the function contain more than just a SUSPEND followed by a RET instruction?
  2284. if( initFunc && initFunc->scriptData->byteCode.GetLength() > 2 )
  2285. {
  2286. // Create the init function for this variable
  2287. initFunc->id = engine->GetNextScriptFunctionId();
  2288. engine->AddScriptFunction(initFunc);
  2289. // Finalize the init function for this variable
  2290. initFunc->returnType = asCDataType::CreatePrimitive(ttVoid, false);
  2291. initFunc->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(gvar->script->name.AddressOf());
  2292. if( gvar->declaredAtNode )
  2293. {
  2294. int row, col;
  2295. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &row, &col);
  2296. initFunc->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20);
  2297. }
  2298. gvar->property->SetInitFunc(initFunc);
  2299. initFunc->ReleaseInternal();
  2300. initFunc = 0;
  2301. }
  2302. else if( initFunc )
  2303. {
  2304. // Destroy the function as it won't be used
  2305. initFunc->funcType = asFUNC_DUMMY;
  2306. asDELETE(initFunc, asCScriptFunction);
  2307. initFunc = 0;
  2308. }
  2309. // Convert enums to true enum values, so subsequent compilations can access it as an enum
  2310. if( gvar->isEnumValue )
  2311. {
  2312. asCEnumType *enumType = CastToEnumType(gvar->datatype.GetTypeInfo());
  2313. asASSERT(NULL != enumType);
  2314. asSEnumValue *e = asNEW(asSEnumValue);
  2315. if( e == 0 )
  2316. {
  2317. // Out of memory
  2318. numErrors++;
  2319. return;
  2320. }
  2321. e->name = gvar->name;
  2322. e->value = int(gvar->constantValue);
  2323. enumType->enumValues.PushLast(e);
  2324. }
  2325. }
  2326. else
  2327. {
  2328. // Add output to final output
  2329. finalOutput.Append(outBuffer);
  2330. accumErrors += numErrors;
  2331. accumWarnings += numWarnings;
  2332. }
  2333. engine->preMessage.isSet = false;
  2334. }
  2335. if( !compileSucceeded )
  2336. {
  2337. if( compilingPrimitives )
  2338. {
  2339. // No more primitives could be compiled, so
  2340. // switch to compiling the complex variables
  2341. compilingPrimitives = false;
  2342. compileSucceeded = true;
  2343. }
  2344. else
  2345. {
  2346. // No more variables can be compiled
  2347. // Add errors and warnings to total build
  2348. currNumWarnings += accumWarnings;
  2349. currNumErrors += accumErrors;
  2350. if( msgCallback )
  2351. finalOutput.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  2352. }
  2353. }
  2354. }
  2355. // Restore states
  2356. engine->msgCallback = msgCallback;
  2357. engine->msgCallbackFunc = msgCallbackFunc;
  2358. engine->msgCallbackObj = msgCallbackObj;
  2359. numWarnings = currNumWarnings;
  2360. numErrors = currNumErrors;
  2361. // Set the correct order of initialization
  2362. if( numErrors == 0 )
  2363. {
  2364. // If the length of the arrays are not the same, then this is the compilation
  2365. // of a single variable, in which case the initialization order of the previous
  2366. // variables must be preserved.
  2367. if( module->m_scriptGlobals.GetSize() == initOrder.GetSize() )
  2368. module->m_scriptGlobals.SwapWith(initOrder);
  2369. }
  2370. CleanupEnumValues();
  2371. }
  2372. void asCBuilder::CleanupEnumValues()
  2373. {
  2374. // Delete the enum expressions
  2375. asCSymbolTableIterator<sGlobalVariableDescription> it = globVariables.List();
  2376. while (it)
  2377. {
  2378. sGlobalVariableDescription *gvar = *it;
  2379. if (gvar->isEnumValue)
  2380. {
  2381. // Remove from symboltable. This has to be done prior to freeing the memeory
  2382. globVariables.Erase(it.GetIndex());
  2383. // Destroy the gvar property
  2384. if (gvar->declaredAtNode)
  2385. {
  2386. gvar->declaredAtNode->Destroy(engine);
  2387. gvar->declaredAtNode = 0;
  2388. }
  2389. if (gvar->initializationNode)
  2390. {
  2391. gvar->initializationNode->Destroy(engine);
  2392. gvar->initializationNode = 0;
  2393. }
  2394. if (gvar->property)
  2395. {
  2396. asDELETE(gvar->property, asCGlobalProperty);
  2397. gvar->property = 0;
  2398. }
  2399. asDELETE(gvar, sGlobalVariableDescription);
  2400. }
  2401. else
  2402. it++;
  2403. }
  2404. }
  2405. int asCBuilder::GetNamespaceAndNameFromNode(asCScriptNode *n, asCScriptCode *script, asSNameSpace *implicitNs, asSNameSpace *&outNs, asCString &outName)
  2406. {
  2407. // TODO: child funcdef: The node might be a snScope now
  2408. asASSERT( n->nodeType == snIdentifier );
  2409. // Get the optional scope from the node
  2410. // TODO: child funcdef: The parentType will be set if the scope is actually a type rather than a namespace
  2411. asSNameSpace *ns = GetNameSpaceFromNode(n->firstChild, script, implicitNs, 0);
  2412. if( ns == 0 )
  2413. return -1;
  2414. // Get the name
  2415. asCString name(&script->code[n->lastChild->tokenPos], n->lastChild->tokenLength);
  2416. outNs = ns;
  2417. outName = name;
  2418. return 0;
  2419. }
  2420. void asCBuilder::AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScriptNode *errNode, sMixinClass *mixin)
  2421. {
  2422. // Determine what interfaces that the mixin implements
  2423. asCScriptNode *node = mixin->node;
  2424. asASSERT(node->nodeType == snClass);
  2425. // Skip the name of the mixin
  2426. node = node->firstChild->next;
  2427. while( node && node->nodeType == snIdentifier )
  2428. {
  2429. bool ok = true;
  2430. asSNameSpace *ns;
  2431. asCString name;
  2432. if( GetNamespaceAndNameFromNode(node, mixin->script, mixin->ns, ns, name) < 0 )
  2433. ok = false;
  2434. else
  2435. {
  2436. // Find the object type for the interface
  2437. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  2438. // Check that the object type is an interface
  2439. if( objType && objType->IsInterface() )
  2440. {
  2441. // Only add the interface if the class doesn't already implement it
  2442. if( !decl->typeInfo->Implements(objType) )
  2443. AddInterfaceToClass(decl, errNode, objType);
  2444. }
  2445. else
  2446. {
  2447. WriteError(TXT_MIXIN_CLASS_CANNOT_INHERIT, mixin->script, node);
  2448. ok = false;
  2449. }
  2450. }
  2451. if( !ok )
  2452. {
  2453. // Remove this node so the error isn't reported again
  2454. asCScriptNode *delNode = node;
  2455. node = node->prev;
  2456. delNode->DisconnectParent();
  2457. delNode->Destroy(engine);
  2458. }
  2459. node = node->next;
  2460. }
  2461. }
  2462. void asCBuilder::AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *errNode, asCObjectType *intfType)
  2463. {
  2464. // A shared type may only implement from shared interfaces
  2465. if( decl->typeInfo->IsShared() && !intfType->IsShared() )
  2466. {
  2467. asCString msg;
  2468. msg.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, intfType->name.AddressOf());
  2469. WriteError(msg, decl->script, errNode);
  2470. return;
  2471. }
  2472. if( decl->isExistingShared )
  2473. {
  2474. // If the class is an existing shared class, then just check if the
  2475. // interface exists in the original declaration too
  2476. if( !decl->typeInfo->Implements(intfType) )
  2477. {
  2478. asCString str;
  2479. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->typeInfo->GetName());
  2480. WriteError(str, decl->script, errNode);
  2481. return;
  2482. }
  2483. }
  2484. else
  2485. {
  2486. // If the interface is already in the class then don't add it again
  2487. if( decl->typeInfo->Implements(intfType) )
  2488. return;
  2489. // Add the interface to the class
  2490. CastToObjectType(decl->typeInfo)->interfaces.PushLast(intfType);
  2491. // Add the inherited interfaces too
  2492. // For interfaces this will be done outside to handle out-of-order declarations
  2493. if( !CastToObjectType(decl->typeInfo)->IsInterface() )
  2494. {
  2495. for( asUINT n = 0; n < intfType->interfaces.GetLength(); n++ )
  2496. AddInterfaceToClass(decl, errNode, intfType->interfaces[n]);
  2497. }
  2498. }
  2499. }
  2500. void asCBuilder::CompileInterfaces()
  2501. {
  2502. asUINT n;
  2503. // Order the interfaces with inheritances so that the inherited
  2504. // of inherited interfaces can be added properly
  2505. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  2506. {
  2507. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  2508. asCObjectType *intfType = CastToObjectType(intfDecl->typeInfo);
  2509. if( intfType->interfaces.GetLength() == 0 ) continue;
  2510. // If any of the derived interfaces are found after this interface, then move this to the end of the list
  2511. for( asUINT m = n+1; m < interfaceDeclarations.GetLength(); m++ )
  2512. {
  2513. if( intfType != interfaceDeclarations[m]->typeInfo &&
  2514. intfType->Implements(interfaceDeclarations[m]->typeInfo) )
  2515. {
  2516. interfaceDeclarations.RemoveIndex(n);
  2517. interfaceDeclarations.PushLast(intfDecl);
  2518. // Decrease index so that we don't skip an entry
  2519. n--;
  2520. break;
  2521. }
  2522. }
  2523. }
  2524. // Now recursively add the additional inherited interfaces
  2525. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  2526. {
  2527. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  2528. if( intfDecl->isExistingShared )
  2529. {
  2530. // Set the declaration as validated already, so that other
  2531. // types that contain this will accept this type
  2532. intfDecl->validState = 1;
  2533. continue;
  2534. }
  2535. asCObjectType *intfType = CastToObjectType(intfDecl->typeInfo);
  2536. // TODO: Is this really at the correct place? Hasn't the vfTableIdx already been set here?
  2537. // Co-opt the vfTableIdx value in our own methods to indicate the
  2538. // index the function should have in the table chunk for this interface.
  2539. for( asUINT d = 0; d < intfType->methods.GetLength(); d++ )
  2540. {
  2541. asCScriptFunction *func = GetFunctionDescription(intfType->methods[d]);
  2542. func->vfTableIdx = d;
  2543. asASSERT(func->objectType == intfType);
  2544. }
  2545. // As new interfaces will be added to the end of the list, all
  2546. // interfaces will be traversed the same as recursively
  2547. for( asUINT m = 0; m < intfType->interfaces.GetLength(); m++ )
  2548. {
  2549. asCObjectType *base = intfType->interfaces[m];
  2550. // Add any interfaces not already implemented
  2551. for( asUINT l = 0; l < base->interfaces.GetLength(); l++ )
  2552. AddInterfaceToClass(intfDecl, intfDecl->node, base->interfaces[l]);
  2553. // Add the methods from the implemented interface
  2554. for( asUINT l = 0; l < base->methods.GetLength(); l++ )
  2555. {
  2556. // If the derived interface implements the same method, then don't add the base interface' method
  2557. asCScriptFunction *baseFunc = GetFunctionDescription(base->methods[l]);
  2558. asCScriptFunction *derivedFunc = 0;
  2559. bool found = false;
  2560. for( asUINT d = 0; d < intfType->methods.GetLength(); d++ )
  2561. {
  2562. derivedFunc = GetFunctionDescription(intfType->methods[d]);
  2563. if( derivedFunc->IsSignatureEqual(baseFunc) )
  2564. {
  2565. found = true;
  2566. break;
  2567. }
  2568. }
  2569. if( !found )
  2570. {
  2571. // Add the method
  2572. intfType->methods.PushLast(baseFunc->id);
  2573. baseFunc->AddRefInternal();
  2574. }
  2575. }
  2576. }
  2577. }
  2578. }
  2579. void asCBuilder::DetermineTypeRelations()
  2580. {
  2581. // Determine inheritance between interfaces
  2582. for (asUINT n = 0; n < interfaceDeclarations.GetLength(); n++)
  2583. {
  2584. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  2585. asCObjectType *intfType = CastToObjectType(intfDecl->typeInfo);
  2586. asCScriptNode *node = intfDecl->node;
  2587. asASSERT(node && node->nodeType == snInterface);
  2588. node = node->firstChild;
  2589. // Skip the 'shared' & 'external' keywords
  2590. while( node->nodeType == snIdentifier &&
  2591. (intfDecl->script->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) ||
  2592. intfDecl->script->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN)) )
  2593. node = node->next;
  2594. // Skip the name
  2595. node = node->next;
  2596. // Verify the inherited interfaces
  2597. while (node && node->nodeType == snIdentifier)
  2598. {
  2599. asSNameSpace *ns;
  2600. asCString name;
  2601. if (GetNamespaceAndNameFromNode(node, intfDecl->script, intfType->nameSpace, ns, name) < 0)
  2602. {
  2603. node = node->next;
  2604. continue;
  2605. }
  2606. // Find the object type for the interface
  2607. asCObjectType *objType = 0;
  2608. while (ns)
  2609. {
  2610. objType = GetObjectType(name.AddressOf(), ns);
  2611. if (objType) break;
  2612. ns = engine->GetParentNameSpace(ns);
  2613. }
  2614. // Check that the object type is an interface
  2615. bool ok = true;
  2616. if (objType && objType->IsInterface())
  2617. {
  2618. // Check that the implemented interface is shared if the base interface is shared
  2619. if (intfType->IsShared() && !objType->IsShared())
  2620. {
  2621. asCString str;
  2622. str.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, objType->GetName());
  2623. WriteError(str, intfDecl->script, node);
  2624. ok = false;
  2625. }
  2626. }
  2627. else
  2628. {
  2629. WriteError(TXT_INTERFACE_CAN_ONLY_IMPLEMENT_INTERFACE, intfDecl->script, node);
  2630. ok = false;
  2631. }
  2632. if (ok)
  2633. {
  2634. // Make sure none of the implemented interfaces implement from this one
  2635. asCObjectType *base = objType;
  2636. while (base != 0)
  2637. {
  2638. if (base == intfType)
  2639. {
  2640. WriteError(TXT_CANNOT_IMPLEMENT_SELF, intfDecl->script, node);
  2641. ok = false;
  2642. break;
  2643. }
  2644. // At this point there is at most one implemented interface
  2645. if (base->interfaces.GetLength())
  2646. base = base->interfaces[0];
  2647. else
  2648. break;
  2649. }
  2650. }
  2651. if (ok)
  2652. AddInterfaceToClass(intfDecl, node, objType);
  2653. // Remove the nodes so they aren't parsed again
  2654. asCScriptNode *delNode = node;
  2655. node = node->next;
  2656. delNode->DisconnectParent();
  2657. delNode->Destroy(engine);
  2658. }
  2659. }
  2660. // Determine class inheritances and interfaces
  2661. for (asUINT n = 0; n < classDeclarations.GetLength(); n++)
  2662. {
  2663. sClassDeclaration *decl = classDeclarations[n];
  2664. asCScriptCode *file = decl->script;
  2665. // Find the base class that this class inherits from
  2666. bool multipleInheritance = false;
  2667. asCScriptNode *node = decl->node->firstChild;
  2668. while (file->TokenEquals(node->tokenPos, node->tokenLength, FINAL_TOKEN) ||
  2669. file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) ||
  2670. file->TokenEquals(node->tokenPos, node->tokenLength, ABSTRACT_TOKEN) ||
  2671. file->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN))
  2672. {
  2673. node = node->next;
  2674. }
  2675. // Skip the name of the class
  2676. asASSERT(node->tokenType == ttIdentifier);
  2677. node = node->next;
  2678. while (node && node->nodeType == snIdentifier)
  2679. {
  2680. asSNameSpace *ns;
  2681. asCString name;
  2682. if (GetNamespaceAndNameFromNode(node, file, decl->typeInfo->nameSpace, ns, name) < 0)
  2683. {
  2684. node = node->next;
  2685. continue;
  2686. }
  2687. // Find the object type for the interface
  2688. asCObjectType *objType = 0;
  2689. sMixinClass *mixin = 0;
  2690. asSNameSpace *origNs = ns;
  2691. while (ns)
  2692. {
  2693. objType = GetObjectType(name.AddressOf(), ns);
  2694. if (objType == 0)
  2695. mixin = GetMixinClass(name.AddressOf(), ns);
  2696. if (objType || mixin)
  2697. break;
  2698. ns = engine->GetParentNameSpace(ns);
  2699. }
  2700. if (objType == 0 && mixin == 0)
  2701. {
  2702. asCString str;
  2703. if (origNs->name == "")
  2704. str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, name.AddressOf());
  2705. else
  2706. str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, name.AddressOf(), origNs->name.AddressOf());
  2707. WriteError(str, file, node);
  2708. }
  2709. else if (mixin)
  2710. {
  2711. AddInterfaceFromMixinToClass(decl, node, mixin);
  2712. }
  2713. else if (!(objType->flags & asOBJ_SCRIPT_OBJECT) ||
  2714. (objType->flags & asOBJ_NOINHERIT))
  2715. {
  2716. // Either the class is not a script class or interface
  2717. // or the class has been declared as 'final'
  2718. asCString str;
  2719. str.Format(TXT_CANNOT_INHERIT_FROM_s_FINAL, objType->name.AddressOf());
  2720. WriteError(str, file, node);
  2721. }
  2722. else if (objType->size != 0)
  2723. {
  2724. // The class inherits from another script class
  2725. if (!decl->isExistingShared && CastToObjectType(decl->typeInfo)->derivedFrom != 0)
  2726. {
  2727. if (!multipleInheritance)
  2728. {
  2729. WriteError(TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES, file, node);
  2730. multipleInheritance = true;
  2731. }
  2732. }
  2733. else
  2734. {
  2735. // Make sure none of the base classes inherit from this one
  2736. asCObjectType *base = objType;
  2737. bool error = false;
  2738. while (base != 0)
  2739. {
  2740. if (base == decl->typeInfo)
  2741. {
  2742. WriteError(TXT_CANNOT_INHERIT_FROM_SELF, file, node);
  2743. error = true;
  2744. break;
  2745. }
  2746. base = base->derivedFrom;
  2747. }
  2748. if (!error)
  2749. {
  2750. // A shared type may only inherit from other shared types
  2751. if ((decl->typeInfo->IsShared()) && !(objType->IsShared()))
  2752. {
  2753. asCString msg;
  2754. msg.Format(TXT_SHARED_CANNOT_INHERIT_FROM_NON_SHARED_s, objType->name.AddressOf());
  2755. WriteError(msg, file, node);
  2756. error = true;
  2757. }
  2758. }
  2759. if (!error)
  2760. {
  2761. if (decl->isExistingShared)
  2762. {
  2763. // Verify that the base class is the same as the original shared type
  2764. if (CastToObjectType(decl->typeInfo)->derivedFrom != objType)
  2765. {
  2766. asCString str;
  2767. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->typeInfo->GetName());
  2768. WriteError(str, file, node);
  2769. }
  2770. }
  2771. else
  2772. {
  2773. // Set the base class
  2774. CastToObjectType(decl->typeInfo)->derivedFrom = objType;
  2775. objType->AddRefInternal();
  2776. }
  2777. }
  2778. }
  2779. }
  2780. else
  2781. {
  2782. // The class implements an interface
  2783. AddInterfaceToClass(decl, node, objType);
  2784. }
  2785. node = node->next;
  2786. }
  2787. }
  2788. }
  2789. // numTempl is the number of template instances that existed in the engine before the build begun
  2790. void asCBuilder::CompileClasses(asUINT numTempl)
  2791. {
  2792. asUINT n;
  2793. asCArray<sClassDeclaration*> toValidate((int)classDeclarations.GetLength());
  2794. // Order class declarations so that base classes are compiled before derived classes.
  2795. // This will allow the derived classes to copy properties and methods in the next step.
  2796. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2797. {
  2798. sClassDeclaration *decl = classDeclarations[n];
  2799. asCObjectType *derived = CastToObjectType(decl->typeInfo);
  2800. asCObjectType *base = derived->derivedFrom;
  2801. if( base == 0 ) continue;
  2802. // If the base class is found after the derived class, then move the derived class to the end of the list
  2803. for( asUINT m = n+1; m < classDeclarations.GetLength(); m++ )
  2804. {
  2805. sClassDeclaration *declBase = classDeclarations[m];
  2806. if( base == declBase->typeInfo )
  2807. {
  2808. classDeclarations.RemoveIndex(n);
  2809. classDeclarations.PushLast(decl);
  2810. // Decrease index so that we don't skip an entry
  2811. n--;
  2812. break;
  2813. }
  2814. }
  2815. }
  2816. // Go through each of the classes and register the object type descriptions
  2817. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2818. {
  2819. sClassDeclaration *decl = classDeclarations[n];
  2820. asCObjectType *ot = CastToObjectType(decl->typeInfo);
  2821. if( decl->isExistingShared )
  2822. {
  2823. // Set the declaration as validated already, so that other
  2824. // types that contain this will accept this type
  2825. decl->validState = 1;
  2826. // We'll still validate the declaration to make sure nothing new is
  2827. // added to the shared class that wasn't there in the previous
  2828. // compilation. We do not care if something that is there in the previous
  2829. // declaration is not included in the new declaration though.
  2830. asASSERT( ot->interfaces.GetLength() == ot->interfaceVFTOffsets.GetLength() );
  2831. }
  2832. // Methods included from mixin classes should take precedence over inherited methods
  2833. IncludeMethodsFromMixins(decl);
  2834. // Add all properties and methods from the base class
  2835. if( !decl->isExistingShared && ot->derivedFrom )
  2836. {
  2837. asCObjectType *baseType = ot->derivedFrom;
  2838. // The derived class inherits all interfaces from the base class
  2839. for( unsigned int m = 0; m < baseType->interfaces.GetLength(); m++ )
  2840. {
  2841. if( !ot->Implements(baseType->interfaces[m]) )
  2842. ot->interfaces.PushLast(baseType->interfaces[m]);
  2843. }
  2844. // TODO: Need to check for name conflict with new class methods
  2845. // Copy properties from base class to derived class
  2846. for( asUINT p = 0; p < baseType->properties.GetLength(); p++ )
  2847. {
  2848. asCObjectProperty *prop = AddPropertyToClass(decl, baseType->properties[p]->name, baseType->properties[p]->type, baseType->properties[p]->isPrivate, baseType->properties[p]->isProtected, true);
  2849. // The properties must maintain the same offset
  2850. asASSERT(prop && prop->byteOffset == baseType->properties[p]->byteOffset); UNUSED_VAR(prop);
  2851. }
  2852. // Copy methods from base class to derived class
  2853. for( asUINT m = 0; m < baseType->methods.GetLength(); m++ )
  2854. {
  2855. // If the derived class implements the same method, then don't add the base class' method
  2856. asCScriptFunction *baseFunc = GetFunctionDescription(baseType->methods[m]);
  2857. asCScriptFunction *derivedFunc = 0;
  2858. bool found = false;
  2859. for( asUINT d = 0; d < ot->methods.GetLength(); d++ )
  2860. {
  2861. derivedFunc = GetFunctionDescription(ot->methods[d]);
  2862. if( baseFunc->name == "opConv" || baseFunc->name == "opImplConv" ||
  2863. baseFunc->name == "opCast" || baseFunc->name == "opImplCast" )
  2864. {
  2865. // For the opConv and opCast methods, the return type can differ if they are different methods
  2866. if( derivedFunc->name == baseFunc->name &&
  2867. derivedFunc->IsSignatureExceptNameEqual(baseFunc) )
  2868. {
  2869. if( baseFunc->IsFinal() )
  2870. {
  2871. asCString msg;
  2872. msg.Format(TXT_METHOD_CANNOT_OVERRIDE_s, baseFunc->GetDeclaration());
  2873. WriteError(msg, decl->script, decl->node);
  2874. }
  2875. // Move the function from the methods array to the virtualFunctionTable
  2876. ot->methods.RemoveIndex(d);
  2877. ot->virtualFunctionTable.PushLast(derivedFunc);
  2878. found = true;
  2879. break;
  2880. }
  2881. }
  2882. else
  2883. {
  2884. if( derivedFunc->name == baseFunc->name &&
  2885. derivedFunc->IsSignatureExceptNameAndReturnTypeEqual(baseFunc) )
  2886. {
  2887. if( baseFunc->returnType != derivedFunc->returnType )
  2888. {
  2889. asCString msg;
  2890. msg.Format(TXT_DERIVED_METHOD_MUST_HAVE_SAME_RETTYPE_s, baseFunc->GetDeclaration());
  2891. WriteError(msg, decl->script, decl->node);
  2892. }
  2893. if( baseFunc->IsFinal() )
  2894. {
  2895. asCString msg;
  2896. msg.Format(TXT_METHOD_CANNOT_OVERRIDE_s, baseFunc->GetDeclaration());
  2897. WriteError(msg, decl->script, decl->node);
  2898. }
  2899. // Move the function from the methods array to the virtualFunctionTable
  2900. ot->methods.RemoveIndex(d);
  2901. ot->virtualFunctionTable.PushLast(derivedFunc);
  2902. found = true;
  2903. break;
  2904. }
  2905. }
  2906. }
  2907. if( !found )
  2908. {
  2909. // Push the base class function on the virtual function table
  2910. ot->virtualFunctionTable.PushLast(baseType->virtualFunctionTable[m]);
  2911. baseType->virtualFunctionTable[m]->AddRefInternal();
  2912. CheckForConflictsDueToDefaultArgs(decl->script, decl->node, baseType->virtualFunctionTable[m], ot);
  2913. }
  2914. ot->methods.PushLast(baseType->methods[m]);
  2915. engine->scriptFunctions[baseType->methods[m]]->AddRefInternal();
  2916. }
  2917. }
  2918. if( !decl->isExistingShared )
  2919. {
  2920. // Move this class' methods into the virtual function table
  2921. for( asUINT m = 0; m < ot->methods.GetLength(); m++ )
  2922. {
  2923. asCScriptFunction *func = GetFunctionDescription(ot->methods[m]);
  2924. if( func->funcType != asFUNC_VIRTUAL )
  2925. {
  2926. // Move the reference from the method list to the virtual function list
  2927. ot->methods.RemoveIndex(m);
  2928. ot->virtualFunctionTable.PushLast(func);
  2929. // Substitute the function description in the method list for a virtual method
  2930. // Make sure the methods are in the same order as the virtual function table
  2931. ot->methods.PushLast(CreateVirtualFunction(func, (int)ot->virtualFunctionTable.GetLength() - 1));
  2932. m--;
  2933. }
  2934. }
  2935. // Make virtual function table chunks for each implemented interface
  2936. for( asUINT m = 0; m < ot->interfaces.GetLength(); m++ )
  2937. {
  2938. asCObjectType *intf = ot->interfaces[m];
  2939. // Add all the interface's functions to the virtual function table
  2940. asUINT offset = asUINT(ot->virtualFunctionTable.GetLength());
  2941. ot->interfaceVFTOffsets.PushLast(offset);
  2942. for( asUINT j = 0; j < intf->methods.GetLength(); j++ )
  2943. {
  2944. asCScriptFunction *intfFunc = GetFunctionDescription(intf->methods[j]);
  2945. // Only create the table for functions that are explicitly from this interface,
  2946. // inherited interface methods will be put in that interface's table.
  2947. if( intfFunc->objectType != intf )
  2948. continue;
  2949. asASSERT((asUINT)intfFunc->vfTableIdx == j);
  2950. //Find the interface function in the list of methods
  2951. asCScriptFunction *realFunc = 0;
  2952. for( asUINT p = 0; p < ot->methods.GetLength(); p++ )
  2953. {
  2954. asCScriptFunction *func = GetFunctionDescription(ot->methods[p]);
  2955. if( func->signatureId == intfFunc->signatureId )
  2956. {
  2957. if( func->funcType == asFUNC_VIRTUAL )
  2958. {
  2959. realFunc = ot->virtualFunctionTable[func->vfTableIdx];
  2960. }
  2961. else
  2962. {
  2963. // This should not happen, all methods were moved into the virtual table
  2964. asASSERT(false);
  2965. }
  2966. break;
  2967. }
  2968. }
  2969. // If realFunc is still null, the interface was not
  2970. // implemented and we error out later in the checks.
  2971. ot->virtualFunctionTable.PushLast(realFunc);
  2972. if( realFunc )
  2973. realFunc->AddRefInternal();
  2974. }
  2975. }
  2976. }
  2977. // Enumerate each of the declared properties
  2978. asCScriptNode *node = decl->node->firstChild->next;
  2979. // Skip list of classes and interfaces
  2980. while( node && node->nodeType == snIdentifier )
  2981. node = node->next;
  2982. while( node && node->nodeType == snDeclaration )
  2983. {
  2984. asCScriptNode *nd = node->firstChild;
  2985. // Is the property declared as private or protected?
  2986. bool isPrivate = false, isProtected = false;
  2987. if( nd && nd->tokenType == ttPrivate )
  2988. {
  2989. isPrivate = true;
  2990. nd = nd->next;
  2991. }
  2992. else if( nd && nd->tokenType == ttProtected )
  2993. {
  2994. isProtected = true;
  2995. nd = nd->next;
  2996. }
  2997. // Determine the type of the property
  2998. asCScriptCode *file = decl->script;
  2999. asCDataType dt = CreateDataTypeFromNode(nd, file, ot->nameSpace, false, ot);
  3000. if( ot->IsShared() && dt.GetTypeInfo() && !dt.GetTypeInfo()->IsShared() )
  3001. {
  3002. asCString msg;
  3003. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetTypeInfo()->name.AddressOf());
  3004. WriteError(msg, file, node);
  3005. }
  3006. if( dt.IsReadOnly() )
  3007. WriteError(TXT_PROPERTY_CANT_BE_CONST, file, node);
  3008. // Multiple properties can be declared separated by ,
  3009. nd = nd->next;
  3010. while( nd )
  3011. {
  3012. asCString name(&file->code[nd->tokenPos], nd->tokenLength);
  3013. if( !decl->isExistingShared )
  3014. {
  3015. CheckNameConflictMember(ot, name.AddressOf(), nd, file, true, false);
  3016. AddPropertyToClass(decl, name, dt, isPrivate, isProtected, false, file, nd);
  3017. }
  3018. else
  3019. {
  3020. // Verify that the property exists in the original declaration
  3021. bool found = false;
  3022. for( asUINT p = 0; p < ot->properties.GetLength(); p++ )
  3023. {
  3024. asCObjectProperty *prop = ot->properties[p];
  3025. if( prop->isPrivate == isPrivate &&
  3026. prop->isProtected == isProtected &&
  3027. prop->name == name &&
  3028. prop->type.IsEqualExceptRef(dt) )
  3029. {
  3030. found = true;
  3031. break;
  3032. }
  3033. }
  3034. if( !found )
  3035. {
  3036. asCString str;
  3037. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  3038. WriteError(str, file, nd);
  3039. }
  3040. }
  3041. // Skip the initialization node
  3042. if( nd->next && nd->next->nodeType != snIdentifier )
  3043. nd = nd->next;
  3044. nd = nd->next;
  3045. }
  3046. node = node->next;
  3047. }
  3048. // Add properties from included mixin classes that don't conflict with existing properties
  3049. IncludePropertiesFromMixins(decl);
  3050. if( !decl->isExistingShared )
  3051. toValidate.PushLast(decl);
  3052. asASSERT( ot->interfaces.GetLength() == ot->interfaceVFTOffsets.GetLength() );
  3053. }
  3054. // TODO: Warn if a method overrides a base method without marking it as 'override'.
  3055. // It must be possible to turn off this warning through engine property.
  3056. // TODO: A base class should be able to mark a method as 'abstract'. This will
  3057. // allow a base class to provide a partial implementation, but still force
  3058. // derived classes to implement specific methods.
  3059. // Verify that all interface methods are implemented in the classes
  3060. // We do this here so the base class' methods have already been inherited
  3061. for( n = 0; n < classDeclarations.GetLength(); n++ )
  3062. {
  3063. sClassDeclaration *decl = classDeclarations[n];
  3064. if( decl->isExistingShared ) continue;
  3065. asCObjectType *ot = CastToObjectType(decl->typeInfo);
  3066. asCArray<bool> overrideValidations(ot->GetMethodCount());
  3067. for( asUINT k = 0; k < ot->methods.GetLength(); k++ )
  3068. overrideValidations.PushLast( !static_cast<asCScriptFunction*>(ot->GetMethodByIndex(k, false))->IsOverride() );
  3069. for( asUINT m = 0; m < ot->interfaces.GetLength(); m++ )
  3070. {
  3071. asCObjectType *objType = ot->interfaces[m];
  3072. for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
  3073. {
  3074. // Only check the interface methods that was explicitly declared in this interface
  3075. // Methods that was inherited from other interfaces will be checked in those interfaces
  3076. if( objType != engine->scriptFunctions[objType->methods[i]]->objectType )
  3077. continue;
  3078. asUINT overrideIndex;
  3079. if( !DoesMethodExist(ot, objType->methods[i], &overrideIndex) )
  3080. {
  3081. asCString str;
  3082. str.Format(TXT_MISSING_IMPLEMENTATION_OF_s,
  3083. engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
  3084. WriteError(str, decl->script, decl->node);
  3085. }
  3086. else
  3087. overrideValidations[overrideIndex] = true;
  3088. }
  3089. }
  3090. bool hasBaseClass = ot->derivedFrom != 0;
  3091. for( asUINT j = 0; j < overrideValidations.GetLength(); j++ )
  3092. {
  3093. if( !overrideValidations[j] && (!hasBaseClass || !DoesMethodExist(ot->derivedFrom, ot->methods[j])) )
  3094. {
  3095. asCString msg;
  3096. msg.Format(TXT_METHOD_s_DOES_NOT_OVERRIDE, ot->GetMethodByIndex(j, false)->GetDeclaration());
  3097. WriteError(msg, decl->script, decl->node);
  3098. }
  3099. }
  3100. }
  3101. // Verify that the declared structures are valid, e.g. that the structure
  3102. // doesn't contain a member of its own type directly or indirectly
  3103. while( toValidate.GetLength() > 0 )
  3104. {
  3105. asUINT numClasses = (asUINT)toValidate.GetLength();
  3106. asCArray<sClassDeclaration*> toValidateNext((int)toValidate.GetLength());
  3107. while( toValidate.GetLength() > 0 )
  3108. {
  3109. sClassDeclaration *decl = toValidate[toValidate.GetLength()-1];
  3110. asCObjectType *ot = CastToObjectType(decl->typeInfo);
  3111. int validState = 1;
  3112. for( n = 0; n < ot->properties.GetLength(); n++ )
  3113. {
  3114. // A valid structure is one that uses only primitives or other valid objects
  3115. asCObjectProperty *prop = ot->properties[n];
  3116. asCDataType dt = prop->type;
  3117. // TODO: Add this check again, once solving the issues commented below
  3118. /*
  3119. if( dt.IsTemplate() )
  3120. {
  3121. // TODO: This must verify all sub types, not just the first one
  3122. // TODO: Just because the subtype is not a handle doesn't mean the template will actually instance the object
  3123. // this it shouldn't automatically raise an error for this, e.g. weakref<Object> should be legal as member
  3124. // of the Object class
  3125. asCDataType sub = dt;
  3126. while( sub.IsTemplate() && !sub.IsObjectHandle() )
  3127. sub = sub.GetSubType();
  3128. dt = sub;
  3129. }
  3130. */
  3131. if( dt.IsObject() && !dt.IsObjectHandle() )
  3132. {
  3133. // Find the class declaration
  3134. sClassDeclaration *pdecl = 0;
  3135. for( asUINT p = 0; p < classDeclarations.GetLength(); p++ )
  3136. {
  3137. if( classDeclarations[p]->typeInfo == dt.GetTypeInfo() )
  3138. {
  3139. pdecl = classDeclarations[p];
  3140. break;
  3141. }
  3142. }
  3143. if( pdecl )
  3144. {
  3145. if( pdecl->typeInfo == decl->typeInfo )
  3146. {
  3147. WriteError(TXT_ILLEGAL_MEMBER_TYPE, decl->script, decl->node);
  3148. validState = 2;
  3149. break;
  3150. }
  3151. else if( pdecl->validState != 1 )
  3152. {
  3153. validState = pdecl->validState;
  3154. break;
  3155. }
  3156. }
  3157. }
  3158. }
  3159. if( validState == 1 )
  3160. {
  3161. decl->validState = 1;
  3162. toValidate.PopLast();
  3163. }
  3164. else if( validState == 2 )
  3165. {
  3166. decl->validState = 2;
  3167. toValidate.PopLast();
  3168. }
  3169. else
  3170. {
  3171. toValidateNext.PushLast(toValidate.PopLast());
  3172. }
  3173. }
  3174. toValidate = toValidateNext;
  3175. toValidateNext.SetLength(0);
  3176. if( numClasses == toValidate.GetLength() )
  3177. {
  3178. WriteError(TXT_ILLEGAL_MEMBER_TYPE, toValidate[0]->script, toValidate[0]->node);
  3179. break;
  3180. }
  3181. }
  3182. if( numErrors > 0 ) return;
  3183. // Verify which script classes can really form circular references, and mark only those as garbage collected.
  3184. // This must be done in the correct order, so that a class that contains another class isn't needlessly marked
  3185. // as garbage collected, just because the contained class was evaluated afterwards.
  3186. // TODO: runtime optimize: This algorithm can be further improved by checking the types that inherits from
  3187. // a base class. If the base class is not shared all the classes that derive from it
  3188. // are known at compile time, and can thus be checked for potential circular references too.
  3189. //
  3190. // Observe, that doing this would conflict with another potential future feature, which is to
  3191. // allow incremental builds, i.e. allow application to add or replace classes in an
  3192. // existing module. However, the applications that want to use that should use a special
  3193. // build flag to not finalize the module.
  3194. // Urho3D: disable garbage collection from script classes
  3195. /*
  3196. asCArray<asCObjectType*> typesToValidate;
  3197. for( n = 0; n < classDeclarations.GetLength(); n++ )
  3198. {
  3199. // Existing shared classes won't need evaluating, nor interfaces
  3200. sClassDeclaration *decl = classDeclarations[n];
  3201. if( decl->isExistingShared ) continue;
  3202. asCObjectType *ot = CastToObjectType(decl->typeInfo);
  3203. if( ot->IsInterface() ) continue;
  3204. typesToValidate.PushLast(ot);
  3205. }
  3206. asUINT numReevaluations = 0;
  3207. while( typesToValidate.GetLength() )
  3208. {
  3209. if( numReevaluations > typesToValidate.GetLength() )
  3210. {
  3211. // No types could be completely evaluated in the last iteration so
  3212. // we consider the remaining types in the array as garbage collected
  3213. break;
  3214. }
  3215. asCObjectType *type = typesToValidate[0];
  3216. typesToValidate.RemoveIndex(0);
  3217. // If the type inherits from another type that is yet to be validated, then reinsert it at the end
  3218. if( type->derivedFrom && typesToValidate.Exists(type->derivedFrom) )
  3219. {
  3220. typesToValidate.PushLast(type);
  3221. numReevaluations++;
  3222. continue;
  3223. }
  3224. // If the type inherits from a known garbage collected type, then this type must also be garbage collected
  3225. if( type->derivedFrom && (type->derivedFrom->flags & asOBJ_GC) )
  3226. {
  3227. type->flags |= asOBJ_GC;
  3228. continue;
  3229. }
  3230. // Evaluate template instances (silently) before verifying each of the classes, since it is possible that
  3231. // a class will be marked as non-garbage collected, which in turn will mark the template instance that uses
  3232. // it as non-garbage collected, which in turn means the class that contains the array also do not have to be
  3233. // garbage collected
  3234. EvaluateTemplateInstances(numTempl, true);
  3235. // Is there some path in which this structure is involved in circular references?
  3236. // If the type contains a member of a type that is yet to be validated, then reinsert it at the end
  3237. bool mustReevaluate = false;
  3238. bool gc = false;
  3239. for( asUINT p = 0; p < type->properties.GetLength(); p++ )
  3240. {
  3241. asCDataType dt = type->properties[p]->type;
  3242. if (dt.IsFuncdef())
  3243. {
  3244. // If a class holds a function pointer as member then the class must be garbage collected as the
  3245. // function pointer can form circular references with the class through use of a delegate. Example:
  3246. //
  3247. // class A { B @b; void f(); }
  3248. // class B { F @f; }
  3249. // funcdef void F();
  3250. //
  3251. // A a;
  3252. // @a.b = B(); // instance of A refers to instance of B
  3253. // @a.b.f = F(a.f); // instance of B refers to delegate that refers to instance of A
  3254. //
  3255. gc = true;
  3256. break;
  3257. }
  3258. if( !dt.IsObject() )
  3259. continue;
  3260. if( typesToValidate.Exists(CastToObjectType(dt.GetTypeInfo())) )
  3261. mustReevaluate = true;
  3262. else
  3263. {
  3264. if( dt.IsTemplate() )
  3265. {
  3266. // Check if any of the subtypes are yet to be evaluated
  3267. bool skip = false;
  3268. for( asUINT s = 0; s < dt.GetTypeInfo()->GetSubTypeCount(); s++ )
  3269. {
  3270. asCObjectType *t = reinterpret_cast<asCObjectType*>(dt.GetTypeInfo()->GetSubType(s));
  3271. if( typesToValidate.Exists(t) )
  3272. {
  3273. mustReevaluate = true;
  3274. skip = true;
  3275. break;
  3276. }
  3277. }
  3278. if( skip )
  3279. continue;
  3280. }
  3281. if( dt.IsObjectHandle() )
  3282. {
  3283. // If it is known that the handle can't be involved in a circular reference
  3284. // then this object doesn't need to be marked as garbage collected.
  3285. asCObjectType *prop = CastToObjectType(dt.GetTypeInfo());
  3286. if( prop->flags & asOBJ_SCRIPT_OBJECT )
  3287. {
  3288. // For script objects, treat non-final classes as if they can contain references
  3289. // as it is not known what derived classes might do. For final types, check all
  3290. // properties to determine if any of those can cause a circular reference with this
  3291. // class.
  3292. if( prop->flags & asOBJ_NOINHERIT )
  3293. {
  3294. for( asUINT sp = 0; sp < prop->properties.GetLength(); sp++ )
  3295. {
  3296. asCDataType sdt = prop->properties[sp]->type;
  3297. if( sdt.IsObject() )
  3298. {
  3299. if( sdt.IsObjectHandle() )
  3300. {
  3301. // TODO: runtime optimize: If the handle is again to a final class, then we can recursively check if the circular reference can occur
  3302. if( sdt.GetTypeInfo()->flags & (asOBJ_SCRIPT_OBJECT | asOBJ_GC) )
  3303. {
  3304. gc = true;
  3305. break;
  3306. }
  3307. }
  3308. else if( sdt.GetTypeInfo()->flags & asOBJ_GC )
  3309. {
  3310. // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is.
  3311. // Only if the object is of a type that can reference this type, either directly or indirectly
  3312. gc = true;
  3313. break;
  3314. }
  3315. }
  3316. }
  3317. if( gc )
  3318. break;
  3319. }
  3320. else
  3321. {
  3322. // Assume it is garbage collected as it is not known at compile time what might inherit from this type
  3323. gc = true;
  3324. break;
  3325. }
  3326. }
  3327. else if( prop->flags & asOBJ_GC )
  3328. {
  3329. // If a type is not a script object, adopt its GC flag
  3330. // TODO: runtime optimize: Just because an application registered class is garbage collected, doesn't mean it
  3331. // can form a circular reference with this script class. Perhaps need a flag to tell
  3332. // if the script classes that contains the type should be garbage collected or not.
  3333. gc = true;
  3334. break;
  3335. }
  3336. }
  3337. else if( dt.GetTypeInfo()->flags & asOBJ_GC )
  3338. {
  3339. // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is.
  3340. // Only if the object is of a type that can reference this type, either directly or indirectly
  3341. gc = true;
  3342. break;
  3343. }
  3344. }
  3345. }
  3346. // If the class wasn't found to require garbage collection, but it
  3347. // contains another type that has yet to be evaluated then it must be
  3348. // re-evaluated.
  3349. if( !gc && mustReevaluate )
  3350. {
  3351. typesToValidate.PushLast(type);
  3352. numReevaluations++;
  3353. continue;
  3354. }
  3355. // Update the flag in the object type
  3356. if( gc )
  3357. type->flags |= asOBJ_GC;
  3358. else
  3359. type->flags &= ~asOBJ_GC;
  3360. // Reset the counter
  3361. numReevaluations = 0;
  3362. }
  3363. // Urho3D: end
  3364. */
  3365. }
  3366. void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl)
  3367. {
  3368. asCScriptNode *node = decl->node->firstChild;
  3369. // Skip the class attributes
  3370. while( node->nodeType == snIdentifier &&
  3371. !decl->script->TokenEquals(node->tokenPos, node->tokenLength, decl->name.AddressOf()) )
  3372. node = node->next;
  3373. // Skip the name of the class
  3374. node = node->next;
  3375. // Find the included mixin classes
  3376. while( node && node->nodeType == snIdentifier )
  3377. {
  3378. asSNameSpace *ns;
  3379. asCString name;
  3380. if( GetNamespaceAndNameFromNode(node, decl->script, decl->typeInfo->nameSpace, ns, name) < 0 )
  3381. {
  3382. node = node->next;
  3383. continue;
  3384. }
  3385. sMixinClass *mixin = 0;
  3386. while( ns )
  3387. {
  3388. // Need to make sure the name is not an object type
  3389. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  3390. if( objType == 0 )
  3391. mixin = GetMixinClass(name.AddressOf(), ns);
  3392. if( objType || mixin )
  3393. break;
  3394. ns = engine->GetParentNameSpace(ns);
  3395. }
  3396. if( mixin )
  3397. {
  3398. // Find methods from mixin declaration
  3399. asCScriptNode *n = mixin->node->firstChild;
  3400. // Skip to the member declarations
  3401. // Possible keywords 'final' and 'shared' are removed in RegisterMixinClass so we don't need to worry about those here
  3402. while( n && n->nodeType == snIdentifier )
  3403. n = n->next;
  3404. // Add methods from the mixin that are not already existing in the class
  3405. while( n )
  3406. {
  3407. if( n->nodeType == snFunction )
  3408. {
  3409. // Instead of disconnecting the node, we need to clone it, otherwise other
  3410. // classes that include the same mixin will not see the methods
  3411. asCScriptNode *copy = n->CreateCopy(engine);
  3412. // Register the method, but only if it doesn't already exist in the class
  3413. RegisterScriptFunctionFromNode(copy, mixin->script, CastToObjectType(decl->typeInfo), false, false, mixin->ns, false, true);
  3414. }
  3415. else if( n->nodeType == snVirtualProperty )
  3416. {
  3417. // TODO: mixin: Support virtual properties too
  3418. WriteError("The virtual property syntax is currently not supported for mixin classes", mixin->script, n);
  3419. //RegisterVirtualProperty(node, decl->script, decl->objType, false, false);
  3420. }
  3421. n = n->next;
  3422. }
  3423. }
  3424. node = node->next;
  3425. }
  3426. }
  3427. void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl)
  3428. {
  3429. asCScriptNode *node = decl->node->firstChild;
  3430. // Skip the class attributes
  3431. while( node->nodeType == snIdentifier &&
  3432. !decl->script->TokenEquals(node->tokenPos, node->tokenLength, decl->name.AddressOf()) )
  3433. node = node->next;
  3434. // Skip the name of the class
  3435. node = node->next;
  3436. // Find the included mixin classes
  3437. while( node && node->nodeType == snIdentifier )
  3438. {
  3439. asSNameSpace *ns;
  3440. asCString name;
  3441. if( GetNamespaceAndNameFromNode(node, decl->script, decl->typeInfo->nameSpace, ns, name) < 0 )
  3442. {
  3443. node = node->next;
  3444. continue;
  3445. }
  3446. sMixinClass *mixin = 0;
  3447. while( ns )
  3448. {
  3449. // Need to make sure the name is not an object type
  3450. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  3451. if( objType == 0 )
  3452. mixin = GetMixinClass(name.AddressOf(), ns);
  3453. if( objType || mixin )
  3454. break;
  3455. ns = engine->GetParentNameSpace(ns);
  3456. }
  3457. if( mixin )
  3458. {
  3459. // Find properties from mixin declaration
  3460. asCScriptNode *n = mixin->node->firstChild;
  3461. // Skip to the member declarations
  3462. // Possible keywords 'final' and 'shared' are removed in RegisterMixinClass so we don't need to worry about those here
  3463. while( n && n->nodeType == snIdentifier )
  3464. n = n->next;
  3465. // Add properties from the mixin that are not already existing in the class
  3466. while( n )
  3467. {
  3468. if( n->nodeType == snDeclaration )
  3469. {
  3470. asCScriptNode *n2 = n->firstChild;
  3471. bool isPrivate = false, isProtected = false;
  3472. if( n2 && n2->tokenType == ttPrivate )
  3473. {
  3474. isPrivate = true;
  3475. n2 = n2->next;
  3476. }
  3477. else if( n2 && n2->tokenType == ttProtected )
  3478. {
  3479. isProtected = true;
  3480. n2 = n2->next;
  3481. }
  3482. asCScriptCode *file = mixin->script;
  3483. asCDataType dt = CreateDataTypeFromNode(n2, file, mixin->ns);
  3484. if( decl->typeInfo->IsShared() && dt.GetTypeInfo() && !dt.GetTypeInfo()->IsShared() )
  3485. {
  3486. asCString msg;
  3487. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetTypeInfo()->name.AddressOf());
  3488. WriteError(msg, file, n);
  3489. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  3490. }
  3491. if( dt.IsReadOnly() )
  3492. WriteError(TXT_PROPERTY_CANT_BE_CONST, file, n);
  3493. n2 = n2->next;
  3494. while( n2 )
  3495. {
  3496. name.Assign(&file->code[n2->tokenPos], n2->tokenLength);
  3497. // Add the property only if it doesn't already exist in the class
  3498. bool exists = false;
  3499. asCObjectType *ot = CastToObjectType(decl->typeInfo);
  3500. for( asUINT p = 0; p < ot->properties.GetLength(); p++ )
  3501. if( ot->properties[p]->name == name )
  3502. {
  3503. exists = true;
  3504. break;
  3505. }
  3506. if( !exists )
  3507. {
  3508. if( !decl->isExistingShared )
  3509. {
  3510. // It must not conflict with the name of methods
  3511. int r = CheckNameConflictMember(ot, name.AddressOf(), n2, file, true, false);
  3512. if( r < 0 )
  3513. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  3514. AddPropertyToClass(decl, name, dt, isPrivate, isProtected, false, file, n2);
  3515. }
  3516. else
  3517. {
  3518. // Verify that the property exists in the original declaration
  3519. bool found = false;
  3520. for( asUINT p = 0; p < ot->properties.GetLength(); p++ )
  3521. {
  3522. asCObjectProperty *prop = ot->properties[p];
  3523. if( prop->isPrivate == isPrivate &&
  3524. prop->isProtected == isProtected &&
  3525. prop->name == name &&
  3526. prop->type == dt )
  3527. {
  3528. found = true;
  3529. break;
  3530. }
  3531. }
  3532. if( !found )
  3533. {
  3534. asCString str;
  3535. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  3536. WriteError(str, decl->script, decl->node);
  3537. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  3538. }
  3539. }
  3540. }
  3541. // Skip the initialization expression
  3542. if( n2->next && n2->next->nodeType != snIdentifier )
  3543. n2 = n2->next;
  3544. n2 = n2->next;
  3545. }
  3546. }
  3547. n = n->next;
  3548. }
  3549. }
  3550. node = node->next;
  3551. }
  3552. }
  3553. int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
  3554. {
  3555. asCScriptFunction *vf = asNEW(asCScriptFunction)(engine, module, asFUNC_VIRTUAL);
  3556. if( vf == 0 )
  3557. return asOUT_OF_MEMORY;
  3558. vf->name = func->name;
  3559. vf->nameSpace = func->nameSpace;
  3560. vf->returnType = func->returnType;
  3561. vf->parameterTypes = func->parameterTypes;
  3562. vf->inOutFlags = func->inOutFlags;
  3563. vf->id = engine->GetNextScriptFunctionId();
  3564. vf->objectType = func->objectType;
  3565. vf->objectType->AddRefInternal();
  3566. vf->signatureId = func->signatureId;
  3567. vf->vfTableIdx = idx;
  3568. vf->traits = func->traits;
  3569. // Clear the shared trait since the virtual function should not have that
  3570. vf->SetShared(false);
  3571. // It is not necessary to copy the default args, as they have no meaning in the virtual function
  3572. module->AddScriptFunction(vf);
  3573. // Add a dummy to the builder so that it doesn't mix up function ids
  3574. functions.PushLast(0);
  3575. return vf->id;
  3576. }
  3577. asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const asCString &name, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited, asCScriptCode *file, asCScriptNode *node)
  3578. {
  3579. if( node )
  3580. {
  3581. asASSERT(!isInherited);
  3582. // Check if the property is allowed
  3583. if( !dt.CanBeInstantiated() )
  3584. {
  3585. if( file && node )
  3586. {
  3587. asCString str;
  3588. if( dt.IsAbstractClass() )
  3589. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->typeInfo->nameSpace).AddressOf());
  3590. else if( dt.IsInterface() )
  3591. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->typeInfo->nameSpace).AddressOf());
  3592. else
  3593. // TODO: Improve error message to explain why
  3594. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(decl->typeInfo->nameSpace).AddressOf());
  3595. WriteError(str, file, node);
  3596. }
  3597. return 0;
  3598. }
  3599. // Register the initialization expression (if any) to be compiled later
  3600. asCScriptNode *declNode = node;
  3601. asCScriptNode *initNode = 0;
  3602. if( node->next && node->next->nodeType != snIdentifier )
  3603. {
  3604. asASSERT( node->next->nodeType == snAssignment );
  3605. initNode = node->next;
  3606. }
  3607. sPropertyInitializer p(name, declNode, initNode, file);
  3608. decl->propInits.PushLast(p);
  3609. }
  3610. else
  3611. {
  3612. // If the declaration node is not given, then
  3613. // this property is inherited from a base class
  3614. asASSERT(isInherited);
  3615. }
  3616. // Add the property to the object type
  3617. return CastToObjectType(decl->typeInfo)->AddPropertyToClass(name, dt, isPrivate, isProtected, isInherited);
  3618. }
  3619. bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex)
  3620. {
  3621. asCScriptFunction *method = GetFunctionDescription(methodId);
  3622. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  3623. {
  3624. asCScriptFunction *m = GetFunctionDescription(objType->methods[n]);
  3625. if( m->name != method->name ) continue;
  3626. if( m->returnType != method->returnType ) continue;
  3627. if( m->IsReadOnly() != method->IsReadOnly() ) continue;
  3628. if( m->parameterTypes != method->parameterTypes ) continue;
  3629. if( m->inOutFlags != method->inOutFlags ) continue;
  3630. if( methodIndex )
  3631. *methodIndex = n;
  3632. return true;
  3633. }
  3634. return false;
  3635. }
  3636. void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file)
  3637. {
  3638. int funcId = engine->GetNextScriptFunctionId();
  3639. asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false);
  3640. asCArray<asCDataType> parameterTypes;
  3641. asCArray<asETypeModifiers> inOutFlags;
  3642. asCArray<asCString *> defaultArgs;
  3643. asCArray<asCString> parameterNames;
  3644. // Add the script function
  3645. // TODO: declaredAt should be set to where the class has been declared
  3646. module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, objType, false, asSFunctionTraits(), objType->nameSpace);
  3647. // Set it as default constructor
  3648. if( objType->beh.construct )
  3649. engine->scriptFunctions[objType->beh.construct]->ReleaseInternal();
  3650. objType->beh.construct = funcId;
  3651. objType->beh.constructors[0] = funcId;
  3652. engine->scriptFunctions[funcId]->AddRefInternal();
  3653. // The bytecode for the default constructor will be generated
  3654. // only after the potential inheritance has been established
  3655. sFunctionDescription *func = asNEW(sFunctionDescription);
  3656. if( func == 0 )
  3657. {
  3658. // Out of memory
  3659. return;
  3660. }
  3661. functions.PushLast(func);
  3662. func->script = file;
  3663. func->node = 0;
  3664. func->name = objType->name;
  3665. func->objType = objType;
  3666. func->funcId = funcId;
  3667. func->isExistingShared = false;
  3668. // Add a default factory as well
  3669. funcId = engine->GetNextScriptFunctionId();
  3670. if( objType->beh.factory )
  3671. engine->scriptFunctions[objType->beh.factory]->ReleaseInternal();
  3672. objType->beh.factory = funcId;
  3673. objType->beh.factories[0] = funcId;
  3674. returnType = asCDataType::CreateObjectHandle(objType, false);
  3675. // TODO: should be the same as the constructor
  3676. module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false);
  3677. functions.PushLast(0);
  3678. asCCompiler compiler(engine);
  3679. compiler.CompileFactory(this, file, engine->scriptFunctions[funcId]);
  3680. engine->scriptFunctions[funcId]->AddRefInternal();
  3681. // If the object is shared, then the factory must also be marked as shared
  3682. if( objType->flags & asOBJ_SHARED )
  3683. engine->scriptFunctions[funcId]->SetShared(true);
  3684. }
  3685. int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  3686. {
  3687. // Is it a shared enum?
  3688. bool isShared = false;
  3689. bool isExternal = false;
  3690. asCEnumType *existingSharedType = 0;
  3691. asCScriptNode *tmp = node->firstChild;
  3692. while( tmp->nodeType == snIdentifier )
  3693. {
  3694. if (file->TokenEquals(tmp->tokenPos, tmp->tokenLength, SHARED_TOKEN))
  3695. isShared = true;
  3696. else if (file->TokenEquals(tmp->tokenPos, tmp->tokenLength, EXTERNAL_TOKEN))
  3697. isExternal = true;
  3698. else
  3699. break;
  3700. tmp = tmp->next;
  3701. }
  3702. // Grab the name of the enumeration
  3703. asCString name;
  3704. asASSERT(snDataType == tmp->nodeType);
  3705. asASSERT(snIdentifier == tmp->firstChild->nodeType);
  3706. name.Assign(&file->code[tmp->firstChild->tokenPos], tmp->firstChild->tokenLength);
  3707. if( isShared )
  3708. {
  3709. // Look for a pre-existing shared enum with the same signature
  3710. for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ )
  3711. {
  3712. asCTypeInfo *o = engine->sharedScriptTypes[n];
  3713. if( o &&
  3714. o->IsShared() &&
  3715. (o->flags & asOBJ_ENUM) &&
  3716. o->name == name &&
  3717. o->nameSpace == ns )
  3718. {
  3719. existingSharedType = CastToEnumType(o);
  3720. break;
  3721. }
  3722. }
  3723. }
  3724. // If the enum was declared as external then it must have been compiled in a different module first
  3725. if (isExternal && existingSharedType == 0)
  3726. {
  3727. asCString str;
  3728. str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf());
  3729. WriteError(str, file, tmp);
  3730. }
  3731. // Remember if the type was declared as external so the saved bytecode can be flagged accordingly
  3732. if (isExternal && existingSharedType)
  3733. module->m_externalTypes.PushLast(existingSharedType);
  3734. // Check the name and add the enum
  3735. int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns, true, false, false);
  3736. if( asSUCCESS == r )
  3737. {
  3738. asCEnumType *st;
  3739. if( existingSharedType )
  3740. {
  3741. st = existingSharedType;
  3742. st->AddRefInternal();
  3743. }
  3744. else
  3745. {
  3746. st = asNEW(asCEnumType)(engine);
  3747. if( st == 0 )
  3748. return asOUT_OF_MEMORY;
  3749. st->flags = asOBJ_ENUM;
  3750. if( isShared )
  3751. st->flags |= asOBJ_SHARED;
  3752. st->size = 4;
  3753. st->name = name;
  3754. st->nameSpace = ns;
  3755. st->module = module;
  3756. }
  3757. module->AddEnumType(st);
  3758. if( !existingSharedType && isShared )
  3759. {
  3760. engine->sharedScriptTypes.PushLast(st);
  3761. st->AddRefInternal();
  3762. }
  3763. // Store the location of this declaration for reference in name collisions
  3764. sClassDeclaration *decl = asNEW(sClassDeclaration);
  3765. if( decl == 0 )
  3766. return asOUT_OF_MEMORY;
  3767. decl->name = name;
  3768. decl->script = file;
  3769. decl->typeInfo = st;
  3770. namedTypeDeclarations.PushLast(decl);
  3771. asCDataType type = CreateDataTypeFromNode(tmp, file, ns);
  3772. asASSERT(!type.IsReference());
  3773. // External shared enums must not redeclare the enum values
  3774. if (isExternal && (tmp->next == 0 || tmp->next->tokenType != ttEndStatement) )
  3775. {
  3776. asCString str;
  3777. str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf());
  3778. WriteError(str, file, tmp);
  3779. }
  3780. else if (!isExternal && tmp->next && tmp->next->tokenType == ttEndStatement)
  3781. {
  3782. asCString str;
  3783. str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf());
  3784. WriteError(str, file, tmp);
  3785. }
  3786. // Register the enum values
  3787. tmp = tmp->next;
  3788. while( tmp && tmp->nodeType == snIdentifier )
  3789. {
  3790. name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength);
  3791. if( existingSharedType )
  3792. {
  3793. // If this is a pre-existent shared enum, then just double check
  3794. // that the value is already defined in the original declaration
  3795. bool found = false;
  3796. for( asUINT n = 0; n < st->enumValues.GetLength(); n++ )
  3797. if( st->enumValues[n]->name == name )
  3798. {
  3799. found = true;
  3800. break;
  3801. }
  3802. if( !found )
  3803. {
  3804. asCString str;
  3805. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, st->GetName());
  3806. WriteError(str, file, tmp);
  3807. break;
  3808. }
  3809. tmp = tmp->next;
  3810. if( tmp && tmp->nodeType == snAssignment )
  3811. tmp = tmp->next;
  3812. continue;
  3813. }
  3814. else
  3815. {
  3816. // Check for name conflict errors with other values in the enum
  3817. if( globVariables.GetFirst(ns, name, asCCompGlobVarType(type)) )
  3818. {
  3819. asCString str;
  3820. str.Format(TXT_NAME_CONFLICT_s_ALREADY_USED, name.AddressOf());
  3821. WriteError(str, file, tmp);
  3822. tmp = tmp->next;
  3823. if( tmp && tmp->nodeType == snAssignment )
  3824. tmp = tmp->next;
  3825. continue;
  3826. }
  3827. // Check for assignment
  3828. asCScriptNode *asnNode = tmp->next;
  3829. if( asnNode && snAssignment == asnNode->nodeType )
  3830. asnNode->DisconnectParent();
  3831. else
  3832. asnNode = 0;
  3833. // Create the global variable description so the enum value can be evaluated
  3834. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  3835. if( gvar == 0 )
  3836. return asOUT_OF_MEMORY;
  3837. gvar->script = file;
  3838. gvar->declaredAtNode = tmp;
  3839. tmp = tmp->next;
  3840. gvar->declaredAtNode->DisconnectParent();
  3841. gvar->initializationNode = asnNode;
  3842. gvar->name = name;
  3843. gvar->datatype = type;
  3844. gvar->ns = ns;
  3845. // No need to allocate space on the global memory stack since the values are stored in the asCObjectType
  3846. // Set the index to a negative to allow compiler to diferentiate from ordinary global var when compiling the initialization
  3847. gvar->index = -1;
  3848. gvar->isCompiled = false;
  3849. gvar->isPureConstant = true;
  3850. gvar->isEnumValue = true;
  3851. gvar->constantValue = 0xdeadbeef;
  3852. // Allocate dummy property so we can compile the value.
  3853. // This will be removed later on so we don't add it to the engine.
  3854. gvar->property = asNEW(asCGlobalProperty);
  3855. if( gvar->property == 0 )
  3856. return asOUT_OF_MEMORY;
  3857. gvar->property->name = name;
  3858. gvar->property->nameSpace = ns;
  3859. gvar->property->type = gvar->datatype;
  3860. gvar->property->id = 0;
  3861. globVariables.Put(gvar);
  3862. }
  3863. }
  3864. }
  3865. node->Destroy(engine);
  3866. return r;
  3867. }
  3868. int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  3869. {
  3870. // Get the native data type
  3871. asCScriptNode *tmp = node->firstChild;
  3872. asASSERT(NULL != tmp && snDataType == tmp->nodeType);
  3873. asCDataType dataType;
  3874. dataType.CreatePrimitive(tmp->tokenType, false);
  3875. dataType.SetTokenType(tmp->tokenType);
  3876. tmp = tmp->next;
  3877. // Grab the name of the typedef
  3878. asASSERT(NULL != tmp && NULL == tmp->next);
  3879. asCString name;
  3880. name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength);
  3881. // If the name is not already in use add it
  3882. int r = CheckNameConflict(name.AddressOf(), tmp, file, ns, true, false, false);
  3883. asCTypedefType *st = 0;
  3884. if( asSUCCESS == r )
  3885. {
  3886. // Create the new type
  3887. st = asNEW(asCTypedefType)(engine);
  3888. if( st == 0 )
  3889. r = asOUT_OF_MEMORY;
  3890. }
  3891. if( asSUCCESS == r )
  3892. {
  3893. st->flags = asOBJ_TYPEDEF;
  3894. st->size = dataType.GetSizeInMemoryBytes();
  3895. st->name = name;
  3896. st->nameSpace = ns;
  3897. st->aliasForType = dataType;
  3898. st->module = module;
  3899. module->AddTypeDef(st);
  3900. // Store the location of this declaration for reference in name collisions
  3901. sClassDeclaration *decl = asNEW(sClassDeclaration);
  3902. if( decl == 0 )
  3903. r = asOUT_OF_MEMORY;
  3904. else
  3905. {
  3906. decl->name = name;
  3907. decl->script = file;
  3908. decl->typeInfo = st;
  3909. namedTypeDeclarations.PushLast(decl);
  3910. }
  3911. }
  3912. node->Destroy(engine);
  3913. return r;
  3914. }
  3915. 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, asSFunctionTraits &funcTraits, asSNameSpace *implicitNamespace)
  3916. {
  3917. node = node->firstChild;
  3918. // Is the function shared?
  3919. funcTraits.SetTrait(asTRAIT_SHARED, false);
  3920. funcTraits.SetTrait(asTRAIT_EXTERNAL, false);
  3921. while (node->tokenType == ttIdentifier)
  3922. {
  3923. if (file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN))
  3924. funcTraits.SetTrait(asTRAIT_SHARED, true);
  3925. else if (file->TokenEquals(node->tokenPos, node->tokenLength, EXTERNAL_TOKEN))
  3926. funcTraits.SetTrait(asTRAIT_EXTERNAL, true);
  3927. else
  3928. break;
  3929. node = node->next;
  3930. }
  3931. // Is the function a private or protected class method?
  3932. funcTraits.SetTrait(asTRAIT_PRIVATE, false);
  3933. funcTraits.SetTrait(asTRAIT_PROTECTED, false);
  3934. if( node->tokenType == ttPrivate )
  3935. {
  3936. funcTraits.SetTrait(asTRAIT_PRIVATE, true);
  3937. node = node->next;
  3938. }
  3939. else if( node->tokenType == ttProtected )
  3940. {
  3941. funcTraits.SetTrait(asTRAIT_PROTECTED, true);
  3942. node = node->next;
  3943. }
  3944. // Find the name
  3945. funcTraits.SetTrait(asTRAIT_CONSTRUCTOR, false);
  3946. funcTraits.SetTrait(asTRAIT_DESTRUCTOR, false);
  3947. asCScriptNode *n = 0;
  3948. if( node->nodeType == snDataType )
  3949. n = node->next->next;
  3950. else
  3951. {
  3952. // If the first node is a ~ token, then we know it is a destructor
  3953. if( node->tokenType == ttBitNot )
  3954. {
  3955. n = node->next;
  3956. funcTraits.SetTrait(asTRAIT_DESTRUCTOR, true);
  3957. }
  3958. else
  3959. {
  3960. n = node;
  3961. funcTraits.SetTrait(asTRAIT_CONSTRUCTOR, true);
  3962. }
  3963. }
  3964. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  3965. if( !funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) && !funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
  3966. {
  3967. returnType = CreateDataTypeFromNode(node, file, implicitNamespace, false, objType);
  3968. returnType = ModifyDataTypeFromNode(returnType, node->next, file, 0, 0);
  3969. if( engine->ep.disallowValueAssignForRefType &&
  3970. returnType.GetTypeInfo() &&
  3971. (returnType.GetTypeInfo()->flags & asOBJ_REF) &&
  3972. !(returnType.GetTypeInfo()->flags & asOBJ_SCOPED) &&
  3973. !returnType.IsReference() &&
  3974. !returnType.IsObjectHandle() )
  3975. {
  3976. WriteError(TXT_REF_TYPE_CANT_BE_RETURNED_BY_VAL, file, node);
  3977. }
  3978. }
  3979. else
  3980. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  3981. funcTraits.SetTrait(asTRAIT_CONST, false);
  3982. funcTraits.SetTrait(asTRAIT_FINAL, false);
  3983. funcTraits.SetTrait(asTRAIT_OVERRIDE, false);
  3984. funcTraits.SetTrait(asTRAIT_EXPLICIT, false);
  3985. funcTraits.SetTrait(asTRAIT_PROPERTY, false);
  3986. if( n->next->next )
  3987. {
  3988. asCScriptNode *decorator = n->next->next;
  3989. // Is this a const method?
  3990. if( objType && decorator->tokenType == ttConst )
  3991. {
  3992. funcTraits.SetTrait(asTRAIT_CONST, true);
  3993. decorator = decorator->next;
  3994. }
  3995. while( decorator && decorator->tokenType == ttIdentifier )
  3996. {
  3997. if (objType && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, FINAL_TOKEN))
  3998. funcTraits.SetTrait(asTRAIT_FINAL, true);
  3999. else if (objType && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, OVERRIDE_TOKEN))
  4000. funcTraits.SetTrait(asTRAIT_OVERRIDE, true);
  4001. else if (objType && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, EXPLICIT_TOKEN))
  4002. funcTraits.SetTrait(asTRAIT_EXPLICIT, true);
  4003. else if (file->TokenEquals(decorator->tokenPos, decorator->tokenLength, PROPERTY_TOKEN))
  4004. funcTraits.SetTrait(asTRAIT_PROPERTY, true);
  4005. else
  4006. {
  4007. asCString msg(&file->code[decorator->tokenPos], decorator->tokenLength);
  4008. msg.Format(TXT_UNEXPECTED_TOKEN_s, msg.AddressOf());
  4009. WriteError(msg.AddressOf(), file, decorator);
  4010. }
  4011. decorator = decorator->next;
  4012. }
  4013. }
  4014. // Count the number of parameters
  4015. int count = 0;
  4016. asCScriptNode *c = n->next->firstChild;
  4017. while( c )
  4018. {
  4019. count++;
  4020. c = c->next->next;
  4021. if( c && c->nodeType == snIdentifier )
  4022. c = c->next;
  4023. if( c && c->nodeType == snExpression )
  4024. c = c->next;
  4025. }
  4026. // Get the parameter types
  4027. parameterNames.Allocate(count, false);
  4028. parameterTypes.Allocate(count, false);
  4029. inOutFlags.Allocate(count, false);
  4030. defaultArgs.Allocate(count, false);
  4031. n = n->next->firstChild;
  4032. while( n )
  4033. {
  4034. asETypeModifiers inOutFlag;
  4035. asCDataType type = CreateDataTypeFromNode(n, file, implicitNamespace, false, objType);
  4036. type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);
  4037. if( engine->ep.disallowValueAssignForRefType &&
  4038. type.GetTypeInfo() &&
  4039. (type.GetTypeInfo()->flags & asOBJ_REF) &&
  4040. !(type.GetTypeInfo()->flags & asOBJ_SCOPED) &&
  4041. !type.IsReference() &&
  4042. !type.IsObjectHandle() )
  4043. {
  4044. WriteError(TXT_REF_TYPE_CANT_BE_PASSED_BY_VAL, file, node);
  4045. }
  4046. // Store the parameter type
  4047. parameterTypes.PushLast(type);
  4048. inOutFlags.PushLast(inOutFlag);
  4049. // Move to next parameter
  4050. n = n->next->next;
  4051. if( n && n->nodeType == snIdentifier )
  4052. {
  4053. asCString paramName(&file->code[n->tokenPos], n->tokenLength);
  4054. parameterNames.PushLast(paramName);
  4055. n = n->next;
  4056. }
  4057. else
  4058. {
  4059. // No name was given for the parameter
  4060. parameterNames.PushLast(asCString());
  4061. }
  4062. if( n && n->nodeType == snExpression )
  4063. {
  4064. // Strip out white space and comments to better share the string
  4065. asCString *defaultArgStr = asNEW(asCString);
  4066. if( defaultArgStr )
  4067. *defaultArgStr = GetCleanExpressionString(n, file);
  4068. defaultArgs.PushLast(defaultArgStr);
  4069. n = n->next;
  4070. }
  4071. else
  4072. defaultArgs.PushLast(0);
  4073. }
  4074. }
  4075. #endif
  4076. asCString asCBuilder::GetCleanExpressionString(asCScriptNode *node, asCScriptCode *file)
  4077. {
  4078. asASSERT(node && node->nodeType == snExpression);
  4079. asCString str;
  4080. str.Assign(file->code + node->tokenPos, node->tokenLength);
  4081. asCString cleanStr;
  4082. for( asUINT n = 0; n < str.GetLength(); )
  4083. {
  4084. asUINT len = 0;
  4085. asETokenClass tok = engine->ParseToken(str.AddressOf() + n, str.GetLength() - n, &len);
  4086. if( tok != asTC_COMMENT && tok != asTC_WHITESPACE )
  4087. {
  4088. if( cleanStr.GetLength() ) cleanStr += " ";
  4089. cleanStr.Concatenate(str.AddressOf() + n, len);
  4090. }
  4091. n += len;
  4092. }
  4093. return cleanStr;
  4094. }
  4095. #ifndef AS_NO_COMPILER
  4096. int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin)
  4097. {
  4098. asCString name;
  4099. asCDataType returnType;
  4100. asCArray<asCString> parameterNames;
  4101. asCArray<asCDataType> parameterTypes;
  4102. asCArray<asETypeModifiers> inOutFlags;
  4103. asCArray<asCString *> defaultArgs;
  4104. asSFunctionTraits funcTraits;
  4105. asASSERT( (objType && ns == 0) || isGlobalFunction || isMixin );
  4106. // Set the default namespace
  4107. if( ns == 0 )
  4108. {
  4109. if( objType )
  4110. ns = objType->nameSpace;
  4111. else
  4112. ns = engine->nameSpaces[0];
  4113. }
  4114. GetParsedFunctionDetails(node, file, objType, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns);
  4115. return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits);
  4116. }
  4117. asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns, bool isShared)
  4118. {
  4119. // Get the parameter names from the node
  4120. asCArray<asCString> parameterNames;
  4121. asCArray<asCString*> defaultArgs;
  4122. asCScriptNode *args = node->firstChild;
  4123. while( args && args->nodeType != snStatementBlock )
  4124. {
  4125. if (args->nodeType == snIdentifier)
  4126. {
  4127. asCString argName;
  4128. argName.Assign(&file->code[args->tokenPos], args->tokenLength);
  4129. parameterNames.PushLast(argName);
  4130. defaultArgs.PushLast(0);
  4131. }
  4132. args = args->next;
  4133. }
  4134. // The statement block for the function must be disconnected, as the builder is going to be the owner of it
  4135. args->DisconnectParent();
  4136. // Get the return and parameter types from the funcDef
  4137. asCString funcName = name;
  4138. asSFunctionTraits traits;
  4139. traits.SetTrait(asTRAIT_SHARED, isShared);
  4140. int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, traits);
  4141. if( r < 0 )
  4142. return 0;
  4143. // Return the function that was just created (but that will be compiled later)
  4144. return engine->scriptFunctions[functions[functions.GetLength()-1]->funcId];
  4145. }
  4146. 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, asSFunctionTraits funcTraits)
  4147. {
  4148. // Determine default namespace if not specified
  4149. if( ns == 0 )
  4150. {
  4151. if( objType )
  4152. ns = objType->nameSpace;
  4153. else
  4154. ns = engine->nameSpaces[0];
  4155. }
  4156. if( isExistingShared )
  4157. {
  4158. asASSERT( objType );
  4159. // Should validate that the function really exists in the class/interface
  4160. bool found = false;
  4161. if(funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) || funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
  4162. {
  4163. // TODO: shared: Should check the existance of these too
  4164. found = true;
  4165. }
  4166. else
  4167. {
  4168. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  4169. {
  4170. asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
  4171. if( func->name == name &&
  4172. func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
  4173. {
  4174. // Add the shared function in this module too
  4175. module->AddScriptFunction(func);
  4176. found = true;
  4177. break;
  4178. }
  4179. }
  4180. }
  4181. if( !found )
  4182. {
  4183. asCString str;
  4184. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, objType->GetName());
  4185. WriteError(str, file, node);
  4186. }
  4187. // Free the default args
  4188. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  4189. if( defaultArgs[n] )
  4190. asDELETE(defaultArgs[n], asCString);
  4191. node->Destroy(engine);
  4192. return 0;
  4193. }
  4194. // Check for name conflicts
  4195. if( !funcTraits.GetTrait(asTRAIT_CONSTRUCTOR) && !funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
  4196. {
  4197. if( objType )
  4198. {
  4199. CheckNameConflictMember(objType, name.AddressOf(), node, file, false, false);
  4200. if( name == objType->name )
  4201. WriteError(TXT_METHOD_CANT_HAVE_NAME_OF_CLASS, file, node);
  4202. }
  4203. else
  4204. CheckNameConflict(name.AddressOf(), node, file, ns, false, false, false);
  4205. }
  4206. else
  4207. {
  4208. if( isMixin )
  4209. {
  4210. // Mixins cannot implement constructors/destructors
  4211. WriteError(TXT_MIXIN_CANNOT_HAVE_CONSTRUCTOR, file, node);
  4212. // Free the default args
  4213. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  4214. if( defaultArgs[n] )
  4215. asDELETE(defaultArgs[n], asCString);
  4216. node->Destroy(engine);
  4217. return 0;
  4218. }
  4219. // Verify that the name of the constructor/destructor is the same as the class
  4220. if( name != objType->name )
  4221. {
  4222. asCString str;
  4223. if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR) )
  4224. str.Format(TXT_DESTRUCTOR_s_s_NAME_ERROR, objType->name.AddressOf(), name.AddressOf());
  4225. else
  4226. str.Format(TXT_METHOD_s_s_HAS_NO_RETURN_TYPE, objType->name.AddressOf(), name.AddressOf());
  4227. WriteError(str, file, node);
  4228. }
  4229. if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR))
  4230. name = "~" + name;
  4231. }
  4232. // Validate virtual properties signature
  4233. if( funcTraits.GetTrait(asTRAIT_PROPERTY) )
  4234. {
  4235. asCScriptFunction func(engine, module, asFUNC_SCRIPT);
  4236. func.name = name;
  4237. func.nameSpace = ns;
  4238. func.objectType = objType;
  4239. if( objType )
  4240. objType->AddRefInternal();
  4241. func.traits = funcTraits;
  4242. func.returnType = returnType;
  4243. func.parameterTypes = parameterTypes;
  4244. int r = ValidateVirtualProperty(&func);
  4245. if( r < 0 )
  4246. {
  4247. asCString str;
  4248. if( r == -2 || r == -3 )
  4249. str.Format(TXT_INVALID_SIG_FOR_VIRTPROP);
  4250. else if( r == -4 )
  4251. str.Format(TXT_GET_SET_ACCESSOR_TYPE_MISMATCH_FOR_s, name.SubString(4).AddressOf());
  4252. else if( r == -5 )
  4253. str.Format(TXT_NAME_CONFLICT_s_ALREADY_USED, name.SubString(4).AddressOf());
  4254. WriteError(str, file, node);
  4255. }
  4256. func.funcType = asFUNC_DUMMY;
  4257. }
  4258. isExistingShared = false;
  4259. int funcId = engine->GetNextScriptFunctionId();
  4260. if( !isInterface )
  4261. {
  4262. sFunctionDescription *func = asNEW(sFunctionDescription);
  4263. if( func == 0 )
  4264. {
  4265. // Free the default args
  4266. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  4267. if( defaultArgs[n] )
  4268. asDELETE(defaultArgs[n], asCString);
  4269. return asOUT_OF_MEMORY;
  4270. }
  4271. functions.PushLast(func);
  4272. func->script = file;
  4273. func->node = node;
  4274. func->name = name;
  4275. func->objType = objType;
  4276. func->funcId = funcId;
  4277. func->isExistingShared = false;
  4278. func->paramNames = parameterNames;
  4279. if(funcTraits.GetTrait(asTRAIT_SHARED))
  4280. {
  4281. // Look for a pre-existing shared function with the same signature
  4282. for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
  4283. {
  4284. asCScriptFunction *f = engine->scriptFunctions[n];
  4285. if( f &&
  4286. f->IsShared() &&
  4287. f->name == name &&
  4288. f->nameSpace == ns &&
  4289. f->objectType == objType &&
  4290. f->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, 0, false) )
  4291. {
  4292. funcId = func->funcId = f->id;
  4293. isExistingShared = func->isExistingShared = true;
  4294. break;
  4295. }
  4296. }
  4297. }
  4298. // Remember if the function was declared as external so the saved bytecode can be flagged accordingly
  4299. if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && func->isExistingShared)
  4300. module->m_externalFunctions.PushLast(engine->scriptFunctions[func->funcId]);
  4301. if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !func->isExistingShared)
  4302. {
  4303. // Mark it as existing shared to avoid compiling it
  4304. func->isExistingShared = true;
  4305. asCString str;
  4306. str.Format(TXT_EXTERNAL_SHARED_s_NOT_FOUND, name.AddressOf());
  4307. WriteError(str, file, node);
  4308. }
  4309. // External shared function must not try to redefine the interface
  4310. if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !(node->tokenType == ttEndStatement || node->lastChild->tokenType == ttEndStatement))
  4311. {
  4312. asCString str;
  4313. str.Format(TXT_EXTERNAL_SHARED_s_CANNOT_REDEF, name.AddressOf());
  4314. WriteError(str, file, node);
  4315. }
  4316. else if (!funcTraits.GetTrait(asTRAIT_EXTERNAL) && !(node->nodeType == snStatementBlock || node->lastChild->nodeType == snStatementBlock) )
  4317. {
  4318. asCString str;
  4319. str.Format(TXT_MISSING_DEFINITION_OF_s, name.AddressOf());
  4320. WriteError(str, file, node);
  4321. }
  4322. }
  4323. // Destructors may not have any parameters
  4324. if (funcTraits.GetTrait(asTRAIT_DESTRUCTOR) && parameterTypes.GetLength() > 0)
  4325. WriteError(TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, file, node);
  4326. // If a function, class, or interface is shared then only shared types may be used in the signature
  4327. if( (objType && objType->IsShared()) || funcTraits.GetTrait(asTRAIT_SHARED))
  4328. {
  4329. asCTypeInfo *ti = returnType.GetTypeInfo();
  4330. if( ti && !ti->IsShared() )
  4331. {
  4332. asCString msg;
  4333. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ti->name.AddressOf());
  4334. WriteError(msg, file, node);
  4335. }
  4336. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  4337. {
  4338. ti = parameterTypes[p].GetTypeInfo();
  4339. if( ti && !ti->IsShared() )
  4340. {
  4341. asCString msg;
  4342. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ti->name.AddressOf());
  4343. WriteError(msg, file, node);
  4344. }
  4345. }
  4346. }
  4347. // Check that the same function hasn't been registered already in the namespace
  4348. asCArray<int> funcs;
  4349. if( objType )
  4350. GetObjectMethodDescriptions(name.AddressOf(), objType, funcs, false);
  4351. else
  4352. GetFunctionDescriptions(name.AddressOf(), funcs, ns);
  4353. if( objType && (name == "opConv" || name == "opImplConv" || name == "opCast" || name == "opImplCast") && parameterTypes.GetLength() == 0 )
  4354. {
  4355. // opConv and opCast are special methods used for type casts
  4356. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  4357. {
  4358. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  4359. if( func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
  4360. {
  4361. // TODO: clean up: Reuse the same error handling for both opConv and normal methods
  4362. if( isMixin )
  4363. {
  4364. // Clean up the memory, as the function will not be registered
  4365. if( node )
  4366. node->Destroy(engine);
  4367. sFunctionDescription *funcDesc = functions.PopLast();
  4368. asDELETE(funcDesc, sFunctionDescription);
  4369. // Free the default args
  4370. for( n = 0; n < defaultArgs.GetLength(); n++ )
  4371. if( defaultArgs[n] )
  4372. asDELETE(defaultArgs[n], asCString);
  4373. return 0;
  4374. }
  4375. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  4376. break;
  4377. }
  4378. }
  4379. }
  4380. else
  4381. {
  4382. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  4383. {
  4384. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  4385. if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
  4386. {
  4387. if( isMixin )
  4388. {
  4389. // Clean up the memory, as the function will not be registered
  4390. if( node )
  4391. node->Destroy(engine);
  4392. sFunctionDescription *funcDesc = functions.PopLast();
  4393. asDELETE(funcDesc, sFunctionDescription);
  4394. // Free the default args
  4395. for( n = 0; n < defaultArgs.GetLength(); n++ )
  4396. if( defaultArgs[n] )
  4397. asDELETE(defaultArgs[n], asCString);
  4398. return 0;
  4399. }
  4400. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  4401. break;
  4402. }
  4403. }
  4404. }
  4405. // Register the function
  4406. if( isExistingShared )
  4407. {
  4408. // Delete the default args as they won't be used anymore
  4409. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  4410. if( defaultArgs[n] )
  4411. asDELETE(defaultArgs[n], asCString);
  4412. asCScriptFunction *f = engine->scriptFunctions[funcId];
  4413. module->AddScriptFunction(f);
  4414. // TODO: clean up: This should be done by AddScriptFunction() itself
  4415. module->m_globalFunctions.Put(f);
  4416. }
  4417. else
  4418. {
  4419. int row = 0, col = 0;
  4420. if( node )
  4421. file->ConvertPosToRowCol(node->tokenPos, &row, &col);
  4422. module->AddScriptFunction(file->idx, (row&0xFFFFF)|((col&0xFFF)<<20), funcId, name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, isInterface, objType, isGlobalFunction, funcTraits, ns);
  4423. }
  4424. // Make sure the default args are declared correctly
  4425. ValidateDefaultArgs(file, node, engine->scriptFunctions[funcId]);
  4426. CheckForConflictsDueToDefaultArgs(file, node, engine->scriptFunctions[funcId], objType);
  4427. if( objType )
  4428. {
  4429. asASSERT( !isExistingShared );
  4430. engine->scriptFunctions[funcId]->AddRefInternal();
  4431. if(funcTraits.GetTrait(asTRAIT_CONSTRUCTOR))
  4432. {
  4433. int factoryId = engine->GetNextScriptFunctionId();
  4434. if( parameterTypes.GetLength() == 0 )
  4435. {
  4436. // Overload the default constructor
  4437. engine->scriptFunctions[objType->beh.construct]->ReleaseInternal();
  4438. objType->beh.construct = funcId;
  4439. objType->beh.constructors[0] = funcId;
  4440. // Register the default factory as well
  4441. engine->scriptFunctions[objType->beh.factory]->ReleaseInternal();
  4442. objType->beh.factory = factoryId;
  4443. objType->beh.factories[0] = factoryId;
  4444. }
  4445. else
  4446. {
  4447. // The copy constructor needs to be marked for easy finding
  4448. if( parameterTypes.GetLength() == 1 &&
  4449. parameterTypes[0].GetTypeInfo() == objType &&
  4450. (parameterTypes[0].IsReference() || parameterTypes[0].IsObjectHandle()) )
  4451. {
  4452. // Verify that there are not multiple options matching the copy constructor
  4453. // TODO: Need a better message, since the parameters can be slightly different, e.g. & vs @
  4454. if( objType->beh.copyconstruct )
  4455. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  4456. objType->beh.copyconstruct = funcId;
  4457. objType->beh.copyfactory = factoryId;
  4458. }
  4459. // Register as a normal constructor
  4460. objType->beh.constructors.PushLast(funcId);
  4461. // Register the factory as well
  4462. objType->beh.factories.PushLast(factoryId);
  4463. }
  4464. // We must copy the default arg strings to avoid deleting the same object multiple times
  4465. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  4466. if( defaultArgs[n] )
  4467. defaultArgs[n] = asNEW(asCString)(*defaultArgs[n]);
  4468. asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
  4469. module->AddScriptFunction(file->idx, engine->scriptFunctions[funcId]->scriptData->declaredAt, factoryId, name, dt, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, 0, false, funcTraits);
  4470. // If the object is shared, then the factory must also be marked as shared
  4471. if( objType->flags & asOBJ_SHARED )
  4472. engine->scriptFunctions[factoryId]->SetShared(true);
  4473. // Add a dummy function to the builder so that it doesn't mix up the fund Ids
  4474. functions.PushLast(0);
  4475. // Compile the factory immediately
  4476. asCCompiler compiler(engine);
  4477. compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
  4478. engine->scriptFunctions[factoryId]->AddRefInternal();
  4479. }
  4480. else if(funcTraits.GetTrait(asTRAIT_DESTRUCTOR))
  4481. objType->beh.destruct = funcId;
  4482. else
  4483. {
  4484. // If the method is the assignment operator we need to replace the default implementation
  4485. asCScriptFunction *f = engine->scriptFunctions[funcId];
  4486. if( f->name == "opAssign" && f->parameterTypes.GetLength() == 1 &&
  4487. f->parameterTypes[0].GetTypeInfo() == f->objectType &&
  4488. (f->inOutFlags[0] & asTM_INREF) )
  4489. {
  4490. engine->scriptFunctions[objType->beh.copy]->ReleaseInternal();
  4491. objType->beh.copy = funcId;
  4492. f->AddRefInternal();
  4493. }
  4494. objType->methods.PushLast(funcId);
  4495. }
  4496. }
  4497. // We need to delete the node already if this is an interface method
  4498. if( isInterface && node )
  4499. node->Destroy(engine);
  4500. return 0;
  4501. }
  4502. int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared)
  4503. {
  4504. if( engine->ep.propertyAccessorMode < 2 )
  4505. {
  4506. WriteError(TXT_PROPERTY_ACCESSOR_DISABLED, file, node);
  4507. node->Destroy(engine);
  4508. return 0;
  4509. }
  4510. asASSERT( (objType && ns == 0) || isGlobalFunction );
  4511. if( ns == 0 )
  4512. {
  4513. if( objType )
  4514. ns = objType->nameSpace;
  4515. else
  4516. ns = engine->nameSpaces[0];
  4517. }
  4518. bool isPrivate = false, isProtected = false;
  4519. asCString emulatedName;
  4520. asCDataType emulatedType;
  4521. asCScriptNode *mainNode = node;
  4522. node = node->firstChild;
  4523. if( !isGlobalFunction && node->tokenType == ttPrivate )
  4524. {
  4525. isPrivate = true;
  4526. node = node->next;
  4527. }
  4528. else if( !isGlobalFunction && node->tokenType == ttProtected )
  4529. {
  4530. isProtected = true;
  4531. node = node->next;
  4532. }
  4533. emulatedType = CreateDataTypeFromNode(node, file, ns);
  4534. emulatedType = ModifyDataTypeFromNode(emulatedType, node->next, file, 0, 0);
  4535. node = node->next->next;
  4536. emulatedName.Assign(&file->code[node->tokenPos], node->tokenLength);
  4537. if( node->next == 0 )
  4538. WriteError(TXT_PROPERTY_WITHOUT_ACCESSOR, file, node);
  4539. node = node->next;
  4540. while (node)
  4541. {
  4542. asCScriptNode *next = node->next;
  4543. asCScriptNode *funcNode = 0;
  4544. bool success = false;
  4545. asSFunctionTraits funcTraits;
  4546. asCDataType returnType;
  4547. asCArray<asCString> paramNames;
  4548. asCArray<asCDataType> paramTypes;
  4549. asCArray<asETypeModifiers> paramModifiers;
  4550. asCArray<asCString*> defaultArgs;
  4551. asCString name;
  4552. funcTraits.SetTrait(asTRAIT_PRIVATE, isPrivate);
  4553. funcTraits.SetTrait(asTRAIT_PROTECTED, isProtected);
  4554. funcTraits.SetTrait(asTRAIT_PROPERTY, true);
  4555. if (node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN))
  4556. name = "get_";
  4557. else if (node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN))
  4558. name = "set_";
  4559. else
  4560. WriteError(TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, file, node);
  4561. if (name != "")
  4562. {
  4563. success = true;
  4564. funcNode = node->firstChild->next;
  4565. if (funcNode && funcNode->tokenType == ttConst)
  4566. {
  4567. funcTraits.SetTrait(asTRAIT_CONST, true);
  4568. funcNode = funcNode->next;
  4569. }
  4570. while (funcNode && funcNode->nodeType != snStatementBlock)
  4571. {
  4572. if (funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN))
  4573. funcTraits.SetTrait(asTRAIT_FINAL, true);
  4574. else if (funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN))
  4575. funcTraits.SetTrait(asTRAIT_OVERRIDE, true);
  4576. else
  4577. {
  4578. asCString msg(&file->code[funcNode->tokenPos], funcNode->tokenLength);;
  4579. msg.Format(TXT_UNEXPECTED_TOKEN_s, msg.AddressOf());
  4580. WriteError(msg.AddressOf(), file, node);
  4581. }
  4582. funcNode = funcNode->next;
  4583. }
  4584. if (funcNode)
  4585. funcNode->DisconnectParent();
  4586. if (funcNode == 0 && (objType == 0 || !objType->IsInterface()))
  4587. {
  4588. // TODO: getset: If no implementation is supplied the builder should provide an automatically generated implementation
  4589. // The compiler needs to be able to handle the different types, primitive, value type, and handle
  4590. // The code is also different for global property accessors
  4591. WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node);
  4592. }
  4593. if (name == "get_")
  4594. {
  4595. // Setup the signature for the get accessor method
  4596. returnType = emulatedType;
  4597. name = "get_" + emulatedName;
  4598. }
  4599. else if (name == "set_")
  4600. {
  4601. // Setup the signature for the set accessor method
  4602. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  4603. paramModifiers.PushLast(asTM_NONE);
  4604. paramNames.PushLast("value");
  4605. paramTypes.PushLast(emulatedType);
  4606. defaultArgs.PushLast(0);
  4607. name = "set_" + emulatedName;
  4608. }
  4609. }
  4610. if( success )
  4611. {
  4612. if( !isExistingShared )
  4613. RegisterScriptFunction(funcNode, file, objType, isInterface, isGlobalFunction, ns, false, false, name, returnType, paramNames, paramTypes, paramModifiers, defaultArgs, funcTraits);
  4614. else
  4615. {
  4616. // Free the funcNode as it won't be used
  4617. if( funcNode ) funcNode->Destroy(engine);
  4618. // Should validate that the function really exists in the class/interface
  4619. bool found = false;
  4620. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  4621. {
  4622. asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
  4623. if( func->name == name &&
  4624. func->IsSignatureExceptNameEqual(returnType, paramTypes, paramModifiers, objType, funcTraits.GetTrait(asTRAIT_CONST)) )
  4625. {
  4626. found = true;
  4627. break;
  4628. }
  4629. }
  4630. if( !found )
  4631. {
  4632. asCString str;
  4633. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, objType->GetName());
  4634. WriteError(str, file, node);
  4635. }
  4636. }
  4637. }
  4638. node = next;
  4639. };
  4640. mainNode->Destroy(engine);
  4641. return 0;
  4642. }
  4643. int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  4644. {
  4645. asCString name;
  4646. asCDataType returnType;
  4647. asCArray<asCString> parameterNames;
  4648. asCArray<asCDataType> parameterTypes;
  4649. asCArray<asETypeModifiers> inOutFlags;
  4650. asCArray<asCString *> defaultArgs;
  4651. asSFunctionTraits funcTraits;
  4652. if( ns == 0 )
  4653. ns = engine->nameSpaces[0];
  4654. GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns);
  4655. CheckNameConflict(name.AddressOf(), node, file, ns, false, false, false);
  4656. // Check that the same function hasn't been registered already in the namespace
  4657. asCArray<int> funcs;
  4658. GetFunctionDescriptions(name.AddressOf(), funcs, ns);
  4659. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  4660. {
  4661. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  4662. if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, 0, false) )
  4663. {
  4664. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  4665. break;
  4666. }
  4667. }
  4668. // Read the module name as well
  4669. asCScriptNode *nd = node->lastChild;
  4670. asASSERT( nd->nodeType == snConstant && nd->tokenType == ttStringConstant );
  4671. asCString moduleName;
  4672. moduleName.Assign(&file->code[nd->tokenPos+1], nd->tokenLength-2);
  4673. node->Destroy(engine);
  4674. // Register the function
  4675. module->AddImportedFunction(importID, name, returnType, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns, moduleName);
  4676. return 0;
  4677. }
  4678. asCScriptFunction *asCBuilder::GetFunctionDescription(int id)
  4679. {
  4680. // TODO: import: This should be improved when the imported functions are removed
  4681. // Get the description from the engine
  4682. if( (id & FUNC_IMPORTED) == 0 )
  4683. return engine->scriptFunctions[id];
  4684. else
  4685. return engine->importedFunctions[id & ~FUNC_IMPORTED]->importedFunctionSignature;
  4686. }
  4687. void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs, asSNameSpace *ns)
  4688. {
  4689. asUINT n;
  4690. // Get the script declared global functions
  4691. const asCArray<unsigned int> &idxs = module->m_globalFunctions.GetIndexes(ns, name);
  4692. for( n = 0; n < idxs.GetLength(); n++ )
  4693. {
  4694. const asCScriptFunction *f = module->m_globalFunctions.Get(idxs[n]);
  4695. asASSERT( f->objectType == 0 );
  4696. funcs.PushLast(f->id);
  4697. }
  4698. // Add the imported functions
  4699. // TODO: optimize: Linear search: This is probably not that critial. Also bindInformation will probably be removed in near future
  4700. for( n = 0; n < module->m_bindInformations.GetLength(); n++ )
  4701. {
  4702. if( module->m_bindInformations[n]->importedFunctionSignature->name == name &&
  4703. module->m_bindInformations[n]->importedFunctionSignature->nameSpace == ns )
  4704. funcs.PushLast(module->m_bindInformations[n]->importedFunctionSignature->id);
  4705. }
  4706. // Add the registered global functions
  4707. const asCArray<unsigned int> &idxs2 = engine->registeredGlobalFuncs.GetIndexes(ns, name);
  4708. for( n = 0; n < idxs2.GetLength(); n++ )
  4709. {
  4710. asCScriptFunction *f = engine->registeredGlobalFuncs.Get(idxs2[n]);
  4711. // Verify if the module has access to the function
  4712. if( module->m_accessMask & f->accessMask )
  4713. {
  4714. funcs.PushLast(f->id);
  4715. }
  4716. }
  4717. }
  4718. // scope is only informed when looking for a base class' method
  4719. void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope, asCScriptNode *errNode, asCScriptCode *script)
  4720. {
  4721. asASSERT(objectType);
  4722. if( scope != "" )
  4723. {
  4724. // If searching with a scope informed, then the node and script must also be informed for potential error reporting
  4725. asASSERT( errNode && script );
  4726. // If the scope contains ::identifier, then use the last identifier as the class name and the rest of it as the namespace
  4727. // TODO: child funcdef: A scope can include a template type, e.g. array<ns::type>
  4728. int n = scope.FindLast("::");
  4729. asCString className = n >= 0 ? scope.SubString(n+2) : scope;
  4730. asCString nsName = n >= 0 ? scope.SubString(0, n) : asCString("");
  4731. // If a namespace was specifically defined, then this must be used
  4732. asSNameSpace *ns = 0;
  4733. if (n >= 0)
  4734. {
  4735. if (nsName == "")
  4736. ns = engine->nameSpaces[0];
  4737. else
  4738. ns = GetNameSpaceByString(nsName, objectType->nameSpace, errNode, script, 0, false);
  4739. // If the namespace isn't found return silently and let the calling
  4740. // function report the error if it cannot resolve the symbol
  4741. if (ns == 0)
  4742. return;
  4743. }
  4744. // Find the base class with the specified scope
  4745. while (objectType)
  4746. {
  4747. // If the name and namespace matches it is the correct class. If no
  4748. // specific namespace was given, then don't compare the namespace
  4749. if (objectType->name == className && (ns == 0 || objectType->nameSpace == ns))
  4750. break;
  4751. objectType = objectType->derivedFrom;
  4752. }
  4753. // If the scope is not any of the base classes, then return no methods
  4754. if( objectType == 0 )
  4755. return;
  4756. }
  4757. // Find the methods in the object that match the name
  4758. // TODO: optimize: Improve linear search
  4759. for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
  4760. {
  4761. asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]];
  4762. if( func->name == name &&
  4763. (!objIsConst || func->IsReadOnly()) &&
  4764. (func->accessMask & module->m_accessMask) )
  4765. {
  4766. // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
  4767. if( scope == "" )
  4768. methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
  4769. else
  4770. {
  4771. asCScriptFunction *f = engine->scriptFunctions[objectType->methods[n]];
  4772. if( f && f->funcType == asFUNC_VIRTUAL )
  4773. f = objectType->virtualFunctionTable[f->vfTableIdx];
  4774. methods.PushLast(f->id);
  4775. }
  4776. }
  4777. }
  4778. }
  4779. #endif
  4780. void asCBuilder::WriteInfo(const asCString &scriptname, const asCString &message, int r, int c, bool pre)
  4781. {
  4782. // Need to store the pre message in a structure
  4783. if( pre )
  4784. {
  4785. engine->preMessage.isSet = true;
  4786. engine->preMessage.c = c;
  4787. engine->preMessage.r = r;
  4788. engine->preMessage.message = message;
  4789. engine->preMessage.scriptname = scriptname;
  4790. }
  4791. else
  4792. {
  4793. engine->preMessage.isSet = false;
  4794. if( !silent )
  4795. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_INFORMATION, message.AddressOf());
  4796. }
  4797. }
  4798. void asCBuilder::WriteInfo(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  4799. {
  4800. int r = 0, c = 0;
  4801. if( node )
  4802. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  4803. WriteInfo(file->name, message, r, c, false);
  4804. }
  4805. void asCBuilder::WriteError(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  4806. {
  4807. int r = 0, c = 0;
  4808. if( node && file )
  4809. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  4810. WriteError(file ? file->name : asCString(""), message, r, c);
  4811. }
  4812. void asCBuilder::WriteError(const asCString &scriptname, const asCString &message, int r, int c)
  4813. {
  4814. numErrors++;
  4815. if( !silent )
  4816. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_ERROR, message.AddressOf());
  4817. }
  4818. void asCBuilder::WriteWarning(const asCString &scriptname, const asCString &message, int r, int c)
  4819. {
  4820. if( engine->ep.compilerWarnings )
  4821. {
  4822. numWarnings++;
  4823. if( !silent )
  4824. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_WARNING, message.AddressOf());
  4825. }
  4826. }
  4827. void asCBuilder::WriteWarning(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  4828. {
  4829. int r = 0, c = 0;
  4830. if( node && file )
  4831. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  4832. WriteWarning(file ? file->name : asCString(""), message, r, c);
  4833. }
  4834. // TODO: child funcdef: Should try to eliminate this function. GetNameSpaceFromNode is more complete
  4835. asCString asCBuilder::GetScopeFromNode(asCScriptNode *node, asCScriptCode *script, asCScriptNode **next)
  4836. {
  4837. if (node->nodeType != snScope)
  4838. {
  4839. if (next)
  4840. *next = node;
  4841. return "";
  4842. }
  4843. asCString scope;
  4844. asCScriptNode *sn = node->firstChild;
  4845. if( sn->tokenType == ttScope )
  4846. {
  4847. scope = "::";
  4848. sn = sn->next;
  4849. }
  4850. // TODO: child funcdef: A scope can have a template type as the innermost
  4851. while( sn && sn->next && sn->next->tokenType == ttScope )
  4852. {
  4853. asCString tmp;
  4854. tmp.Assign(&script->code[sn->tokenPos], sn->tokenLength);
  4855. if( scope != "" && scope != "::" )
  4856. scope += "::";
  4857. scope += tmp;
  4858. sn = sn->next->next;
  4859. }
  4860. if( next )
  4861. *next = node->next;
  4862. return scope;
  4863. }
  4864. asSNameSpace *asCBuilder::GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next, asCObjectType **objType)
  4865. {
  4866. if (objType)
  4867. *objType = 0;
  4868. // If no scope has been informed, then return the implicit namespace
  4869. if (node->nodeType != snScope)
  4870. {
  4871. if (next)
  4872. *next = node;
  4873. return implicitNs ? implicitNs : engine->nameSpaces[0];
  4874. }
  4875. if (next)
  4876. *next = node->next;
  4877. asCString scope;
  4878. asCScriptNode *sn = node->firstChild;
  4879. if (sn && sn->tokenType == ttScope)
  4880. {
  4881. scope = "::";
  4882. sn = sn->next;
  4883. }
  4884. while (sn)
  4885. {
  4886. if (sn->next->tokenType == ttScope)
  4887. {
  4888. asCString tmp;
  4889. tmp.Assign(&script->code[sn->tokenPos], sn->tokenLength);
  4890. if (scope != "" && scope != "::")
  4891. scope += "::";
  4892. scope += tmp;
  4893. sn = sn->next->next;
  4894. }
  4895. else
  4896. {
  4897. // This is a template type
  4898. asASSERT(sn->next->nodeType == snDataType);
  4899. asSNameSpace *ns = implicitNs;
  4900. if (scope != "")
  4901. ns = engine->FindNameSpace(scope.AddressOf());
  4902. asCString templateName(&script->code[sn->tokenPos], sn->tokenLength);
  4903. asCObjectType *templateType = GetObjectType(templateName.AddressOf(), ns);
  4904. if (templateType == 0 || (templateType->flags & asOBJ_TEMPLATE) == 0)
  4905. {
  4906. // TODO: child funcdef: Report error
  4907. return ns;
  4908. }
  4909. if (objType)
  4910. *objType = GetTemplateInstanceFromNode(sn, script, templateType, implicitNs, 0);
  4911. // Return no namespace, since this is an object type
  4912. return 0;
  4913. }
  4914. }
  4915. asCTypeInfo *ti = 0;
  4916. asSNameSpace *ns = GetNameSpaceByString(scope, implicitNs ? implicitNs : engine->nameSpaces[0], node, script, &ti);
  4917. if (ti && objType)
  4918. *objType = CastToObjectType(ti);
  4919. return ns;
  4920. }
  4921. asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, asCTypeInfo **scopeType, bool isRequired)
  4922. {
  4923. if( scopeType )
  4924. *scopeType = 0;
  4925. asSNameSpace *ns = implicitNs;
  4926. if( nsName == "::" )
  4927. ns = engine->nameSpaces[0];
  4928. else if( nsName != "" )
  4929. {
  4930. ns = engine->FindNameSpace(nsName.AddressOf());
  4931. if (ns == 0 && scopeType)
  4932. {
  4933. asCString typeName;
  4934. asCString searchNs;
  4935. // Split the scope with at the inner most ::
  4936. int pos = nsName.FindLast("::");
  4937. bool recursive = false;
  4938. if (pos >= 0)
  4939. {
  4940. // Fully qualified namespace
  4941. typeName = nsName.SubString(pos + 2);
  4942. searchNs = nsName.SubString(0, pos);
  4943. }
  4944. else
  4945. {
  4946. // Partially qualified, use the implicit namespace and then search recursively for the type
  4947. typeName = nsName;
  4948. searchNs = implicitNs->name;
  4949. recursive = true;
  4950. }
  4951. asSNameSpace *nsTmp = searchNs == "::" ? engine->nameSpaces[0] : engine->FindNameSpace(searchNs.AddressOf());
  4952. asCTypeInfo *ti = 0;
  4953. while( !ti && nsTmp )
  4954. {
  4955. // Check if the typeName is an existing type in the namespace
  4956. ti = GetType(typeName.AddressOf(), nsTmp, 0);
  4957. if (ti)
  4958. {
  4959. // The informed scope is not a namespace, but it does match a type
  4960. *scopeType = ti;
  4961. return 0;
  4962. }
  4963. nsTmp = recursive ? engine->GetParentNameSpace(nsTmp) : 0;
  4964. }
  4965. }
  4966. if (ns == 0 && isRequired)
  4967. {
  4968. asCString msg;
  4969. msg.Format(TXT_NAMESPACE_s_DOESNT_EXIST, nsName.AddressOf());
  4970. WriteError(msg, script, errNode);
  4971. }
  4972. }
  4973. return ns;
  4974. }
  4975. asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope, asCObjectType *currentType, bool reportError, bool *isValid)
  4976. {
  4977. asASSERT(node->nodeType == snDataType || node->nodeType == snIdentifier || node->nodeType == snScope );
  4978. asCDataType dt;
  4979. asCScriptNode *n = node->firstChild;
  4980. if (isValid)
  4981. *isValid = true;
  4982. // If the informed node is an identifier or scope, then the
  4983. // datatype should be identified directly from that
  4984. if (node->nodeType != snDataType)
  4985. n = node;
  4986. bool isConst = false;
  4987. bool isImplicitHandle = false;
  4988. if( n->tokenType == ttConst )
  4989. {
  4990. isConst = true;
  4991. n = n->next;
  4992. }
  4993. // Determine namespace (or parent type) to search for the data type in
  4994. asCObjectType *parentType = 0;
  4995. asSNameSpace *ns = GetNameSpaceFromNode(n, file, implicitNamespace, &n, &parentType);
  4996. if( ns == 0 && parentType == 0 )
  4997. {
  4998. // The namespace and parent type doesn't exist. Return a dummy type instead.
  4999. dt = asCDataType::CreatePrimitive(ttInt, false);
  5000. if (isValid)
  5001. *isValid = false;
  5002. return dt;
  5003. }
  5004. if( n->tokenType == ttIdentifier )
  5005. {
  5006. bool found = false;
  5007. asCString str;
  5008. str.Assign(&file->code[n->tokenPos], n->tokenLength);
  5009. // Recursively search parent namespaces for matching type
  5010. asSNameSpace *origNs = ns;
  5011. asCObjectType *origParentType = parentType;
  5012. while( (ns || parentType) && !found )
  5013. {
  5014. asCTypeInfo *ti = 0;
  5015. if (currentType)
  5016. {
  5017. // If this is for a template type, then we must first determine if the
  5018. // identifier matches any of the template subtypes
  5019. if (currentType->flags & asOBJ_TEMPLATE)
  5020. {
  5021. for (asUINT subtypeIndex = 0; subtypeIndex < currentType->templateSubTypes.GetLength(); subtypeIndex++)
  5022. {
  5023. asCTypeInfo *type = currentType->templateSubTypes[subtypeIndex].GetTypeInfo();
  5024. if (type && str == type->name)
  5025. {
  5026. ti = type;
  5027. break;
  5028. }
  5029. }
  5030. }
  5031. if (ti == 0)
  5032. {
  5033. // Check if the type is a child type of the current type
  5034. ti = GetFuncDef(str.AddressOf(), 0, currentType);
  5035. if (ti)
  5036. {
  5037. dt = asCDataType::CreateType(ti, false);
  5038. found = true;
  5039. }
  5040. }
  5041. }
  5042. if( ti == 0 )
  5043. ti = GetType(str.AddressOf(), ns, parentType);
  5044. if( ti == 0 && !module && currentType )
  5045. ti = GetTypeFromTypesKnownByObject(str.AddressOf(), currentType);
  5046. if( ti && !found )
  5047. {
  5048. found = true;
  5049. if( ti->flags & asOBJ_IMPLICIT_HANDLE )
  5050. isImplicitHandle = true;
  5051. // Make sure the module has access to the object type
  5052. if( !module || (module->m_accessMask & ti->accessMask) )
  5053. {
  5054. if( asOBJ_TYPEDEF == (ti->flags & asOBJ_TYPEDEF) )
  5055. {
  5056. // TODO: typedef: A typedef should be considered different from the original type (though with implicit conversions between the two)
  5057. // Create primitive data type based on object flags
  5058. dt = CastToTypedefType(ti)->aliasForType;
  5059. dt.MakeReadOnly(isConst);
  5060. }
  5061. else
  5062. {
  5063. if( ti->flags & asOBJ_TEMPLATE )
  5064. {
  5065. ti = GetTemplateInstanceFromNode(n, file, CastToObjectType(ti), implicitNamespace, currentType, &n);
  5066. if (ti == 0)
  5067. {
  5068. if (isValid)
  5069. *isValid = false;
  5070. // Return a dummy
  5071. return asCDataType::CreatePrimitive(ttInt, false);
  5072. }
  5073. }
  5074. else if( n && n->next && n->next->nodeType == snDataType )
  5075. {
  5076. if (reportError)
  5077. {
  5078. asCString msg;
  5079. msg.Format(TXT_TYPE_s_NOT_TEMPLATE, ti->name.AddressOf());
  5080. WriteError(msg, file, n);
  5081. }
  5082. if (isValid)
  5083. *isValid = false;
  5084. }
  5085. // Create object data type
  5086. if( ti )
  5087. dt = asCDataType::CreateType(ti, isConst);
  5088. else
  5089. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  5090. }
  5091. }
  5092. else
  5093. {
  5094. if (reportError)
  5095. {
  5096. asCString msg;
  5097. msg.Format(TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE, (const char *)str.AddressOf());
  5098. WriteError(msg, file, n);
  5099. }
  5100. dt.SetTokenType(ttInt);
  5101. if (isValid)
  5102. *isValid = false;
  5103. }
  5104. }
  5105. if( !found )
  5106. {
  5107. // Try to find it in the parent namespace
  5108. if( ns )
  5109. ns = engine->GetParentNameSpace(ns);
  5110. if (parentType)
  5111. parentType = 0;
  5112. }
  5113. }
  5114. if( !found )
  5115. {
  5116. if (reportError)
  5117. {
  5118. asCString msg;
  5119. if (origNs && origNs->name == "")
  5120. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, str.AddressOf());
  5121. else if (origNs)
  5122. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, str.AddressOf(), origNs->name.AddressOf());
  5123. else
  5124. {
  5125. // TODO: child funcdef: Message should explain that the identifier is not a type of the parent type
  5126. asCDataType pt = asCDataType::CreateType(origParentType, false);
  5127. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, str.AddressOf(), pt.Format(origParentType->nameSpace, false).AddressOf());
  5128. }
  5129. WriteError(msg, file, n);
  5130. }
  5131. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  5132. if (isValid)
  5133. *isValid = false;
  5134. return dt;
  5135. }
  5136. }
  5137. else if( n->tokenType == ttAuto )
  5138. {
  5139. dt = asCDataType::CreateAuto(isConst);
  5140. }
  5141. else
  5142. {
  5143. // Create primitive data type
  5144. dt = asCDataType::CreatePrimitive(n->tokenType, isConst);
  5145. }
  5146. // Determine array dimensions and object handles
  5147. n = n->next;
  5148. while( n && (n->tokenType == ttOpenBracket || n->tokenType == ttHandle) )
  5149. {
  5150. if( n->tokenType == ttOpenBracket )
  5151. {
  5152. if (isImplicitHandle)
  5153. {
  5154. // Make the type a handle
  5155. if (dt.MakeHandle(true, acceptHandleForScope) < 0)
  5156. {
  5157. if (reportError)
  5158. WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
  5159. if (isValid)
  5160. *isValid = false;
  5161. }
  5162. isImplicitHandle = false;
  5163. }
  5164. // Make sure the sub type can be instantiated
  5165. if( !dt.CanBeInstantiated() )
  5166. {
  5167. if (reportError)
  5168. {
  5169. asCString str;
  5170. if (dt.IsAbstractClass())
  5171. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf());
  5172. else if (dt.IsInterface())
  5173. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf());
  5174. else
  5175. // TODO: Improve error message to explain why
  5176. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(ns).AddressOf());
  5177. WriteError(str, file, n);
  5178. }
  5179. if (isValid)
  5180. *isValid = false;
  5181. }
  5182. // Make the type an array (or multidimensional array)
  5183. if( dt.MakeArray(engine, module) < 0 )
  5184. {
  5185. if( reportError )
  5186. WriteError(TXT_NO_DEFAULT_ARRAY_TYPE, file, n);
  5187. if (isValid)
  5188. *isValid = false;
  5189. break;
  5190. }
  5191. }
  5192. else
  5193. {
  5194. // Make the type a handle
  5195. if( dt.IsObjectHandle() )
  5196. {
  5197. if( reportError )
  5198. WriteError(TXT_HANDLE_OF_HANDLE_IS_NOT_ALLOWED, file, n);
  5199. if (isValid)
  5200. *isValid = false;
  5201. break;
  5202. }
  5203. else
  5204. {
  5205. if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
  5206. {
  5207. if( reportError )
  5208. WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
  5209. if (isValid)
  5210. *isValid = false;
  5211. break;
  5212. }
  5213. // Check if the handle should be read-only
  5214. if( n && n->next && n->next->tokenType == ttConst )
  5215. dt.MakeReadOnly(true);
  5216. }
  5217. }
  5218. n = n->next;
  5219. }
  5220. if( isImplicitHandle )
  5221. {
  5222. // Make the type a handle
  5223. if (dt.MakeHandle(true, acceptHandleForScope) < 0)
  5224. {
  5225. if( reportError )
  5226. WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
  5227. if (isValid)
  5228. *isValid = false;
  5229. }
  5230. }
  5231. return dt;
  5232. }
  5233. asCObjectType *asCBuilder::GetTemplateInstanceFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *templateType, asSNameSpace *implicitNamespace, asCObjectType *currentType, asCScriptNode **next)
  5234. {
  5235. // Check if the subtype is a type or the template's subtype
  5236. // if it is the template's subtype then this is the actual template type,
  5237. // orderwise it is a template instance.
  5238. // Only do this for application registered interface, as the
  5239. // scripts cannot implement templates.
  5240. asCArray<asCDataType> subTypes;
  5241. asUINT subtypeIndex;
  5242. asCScriptNode *n = node;
  5243. while (n && n->next && n->next->nodeType == snDataType)
  5244. {
  5245. n = n->next;
  5246. // When parsing function definitions for template registrations (currentType != 0) it is necessary
  5247. // to pass in the current template type to the recursive call since it is this ones sub-template types
  5248. // that should be allowed.
  5249. asCDataType subType = CreateDataTypeFromNode(n, file, implicitNamespace, false, module ? 0 : (currentType ? currentType : templateType));
  5250. subTypes.PushLast(subType);
  5251. if (subType.IsReadOnly())
  5252. {
  5253. asCString msg;
  5254. msg.Format(TXT_TMPL_SUBTYPE_MUST_NOT_BE_READ_ONLY);
  5255. WriteError(msg, file, n);
  5256. // Return a dummy
  5257. return 0;
  5258. }
  5259. }
  5260. if (next)
  5261. *next = n;
  5262. if (subTypes.GetLength() != templateType->templateSubTypes.GetLength())
  5263. {
  5264. asCString msg;
  5265. msg.Format(TXT_TMPL_s_EXPECTS_d_SUBTYPES, templateType->name.AddressOf(), int(templateType->templateSubTypes.GetLength()));
  5266. WriteError(msg, file, node);
  5267. // Return a dummy
  5268. return 0;
  5269. }
  5270. // Check if any of the given subtypes are different from the template's declared subtypes
  5271. bool isDifferent = false;
  5272. for (subtypeIndex = 0; subtypeIndex < subTypes.GetLength(); subtypeIndex++)
  5273. {
  5274. if (subTypes[subtypeIndex].GetTypeInfo() != templateType->templateSubTypes[subtypeIndex].GetTypeInfo())
  5275. {
  5276. isDifferent = true;
  5277. break;
  5278. }
  5279. }
  5280. if (isDifferent)
  5281. {
  5282. // This is a template instance
  5283. // Need to find the correct object type
  5284. asCObjectType *otInstance = engine->GetTemplateInstanceType(templateType, subTypes, module);
  5285. if (otInstance && otInstance->scriptSectionIdx < 0)
  5286. {
  5287. // If this is the first time the template instance is used, store where it was declared from
  5288. otInstance->scriptSectionIdx = engine->GetScriptSectionNameIndex(file->name.AddressOf());
  5289. int row, column;
  5290. file->ConvertPosToRowCol(n->tokenPos, &row, &column);
  5291. otInstance->declaredAt = (row & 0xFFFFF) | (column << 20);
  5292. }
  5293. if (!otInstance)
  5294. {
  5295. asCString sub = subTypes[0].Format(templateType->nameSpace);
  5296. for (asUINT s = 1; s < subTypes.GetLength(); s++)
  5297. {
  5298. sub += ",";
  5299. sub += subTypes[s].Format(templateType->nameSpace);
  5300. }
  5301. asCString msg;
  5302. msg.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, templateType->name.AddressOf(), sub.AddressOf());
  5303. WriteError(msg, file, n);
  5304. }
  5305. return otInstance;
  5306. }
  5307. return templateType;
  5308. }
  5309. asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlags, bool *autoHandle)
  5310. {
  5311. asCDataType dt = type;
  5312. if( inOutFlags ) *inOutFlags = asTM_NONE;
  5313. // Is the argument sent by reference?
  5314. asCScriptNode *n = node->firstChild;
  5315. if( n && n->tokenType == ttAmp )
  5316. {
  5317. if (dt.GetTokenType() == ttVoid)
  5318. {
  5319. asCString msg;
  5320. msg.Format(TXT_TYPE_s_CANNOT_BE_REFERENCE, type.Format(0).AddressOf());
  5321. WriteError(msg, file, node->firstChild);
  5322. return dt;
  5323. }
  5324. dt.MakeReference(true);
  5325. n = n->next;
  5326. if( n )
  5327. {
  5328. if( inOutFlags )
  5329. {
  5330. if( n->tokenType == ttIn )
  5331. *inOutFlags = asTM_INREF;
  5332. else if( n->tokenType == ttOut )
  5333. *inOutFlags = asTM_OUTREF;
  5334. else if( n->tokenType == ttInOut )
  5335. *inOutFlags = asTM_INOUTREF;
  5336. else
  5337. asASSERT(false);
  5338. }
  5339. n = n->next;
  5340. }
  5341. else
  5342. {
  5343. if( inOutFlags )
  5344. *inOutFlags = asTM_INOUTREF; // ttInOut
  5345. }
  5346. if( !engine->ep.allowUnsafeReferences &&
  5347. inOutFlags && *inOutFlags == asTM_INOUTREF &&
  5348. !(dt.GetTypeInfo() && (dt.GetTypeInfo()->flags & asOBJ_TEMPLATE_SUBTYPE)) )
  5349. {
  5350. // Verify that the base type support &inout parameter types
  5351. if( !dt.IsObject() || dt.IsObjectHandle() ||
  5352. !((dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) || (CastToObjectType(dt.GetTypeInfo())->beh.addref && CastToObjectType(dt.GetTypeInfo())->beh.release)) )
  5353. WriteError(TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT, file, node->firstChild);
  5354. }
  5355. }
  5356. if( autoHandle ) *autoHandle = false;
  5357. if( n && n->tokenType == ttPlus )
  5358. {
  5359. // Autohandles are not supported for types with NOCOUNT
  5360. // If the type is not a handle then there was an error with building the type, but
  5361. // this error would already have been reported so no need to report another error here
  5362. if( dt.IsObjectHandle() && (dt.GetTypeInfo()->flags & asOBJ_NOCOUNT) )
  5363. WriteError(TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT, file, node->firstChild);
  5364. if( autoHandle ) *autoHandle = true;
  5365. }
  5366. if (n && n->tokenType == ttIdentifier)
  5367. {
  5368. asCString str;
  5369. str.Assign(&file->code[n->tokenPos], n->tokenLength);
  5370. if (str == IF_HANDLE_TOKEN)
  5371. dt.SetIfHandleThenConst(true);
  5372. else
  5373. {
  5374. // TODO: Should give error if not currently parsing template registration
  5375. asCString msg;
  5376. msg.Format(TXT_UNEXPECTED_TOKEN_s, str.AddressOf());
  5377. WriteError(msg, file, node->firstChild);
  5378. }
  5379. }
  5380. return dt;
  5381. }
  5382. asCTypeInfo *asCBuilder::GetType(const char *type, asSNameSpace *ns, asCObjectType *parentType)
  5383. {
  5384. asASSERT((ns == 0 && parentType) || (ns && parentType == 0));
  5385. if (ns)
  5386. {
  5387. asCTypeInfo *ti = engine->GetRegisteredType(type, ns);
  5388. if (!ti && module)
  5389. ti = module->GetType(type, ns);
  5390. return ti;
  5391. }
  5392. else
  5393. {
  5394. // Recursively check base classes
  5395. asCObjectType *currType = parentType;
  5396. while (currType)
  5397. {
  5398. for (asUINT n = 0; n < currType->childFuncDefs.GetLength(); n++)
  5399. {
  5400. asCFuncdefType *funcDef = currType->childFuncDefs[n];
  5401. if (funcDef && funcDef->name == type)
  5402. return funcDef;
  5403. }
  5404. currType = currType->derivedFrom;
  5405. }
  5406. }
  5407. return 0;
  5408. }
  5409. asCObjectType *asCBuilder::GetObjectType(const char *type, asSNameSpace *ns)
  5410. {
  5411. return CastToObjectType(GetType(type, ns, 0));
  5412. }
  5413. #ifndef AS_NO_COMPILER
  5414. // This function will return true if there are any types in the engine or module
  5415. // with the given name. The namespace is ignored in this verification.
  5416. bool asCBuilder::DoesTypeExist(const asCString &type)
  5417. {
  5418. asUINT n;
  5419. // This function is only used when parsing expressions for building bytecode
  5420. // and this is only done after all types are known. For this reason the types
  5421. // can be safely cached in a map for quick lookup. Once the builder is released
  5422. // the cache will also be destroyed thus avoiding unnecessary memory consumption.
  5423. if( !hasCachedKnownTypes )
  5424. {
  5425. // Only do this once
  5426. hasCachedKnownTypes = true;
  5427. // Add registered types
  5428. asSMapNode<asSNameSpaceNamePair, asCTypeInfo*> *cursor;
  5429. engine->allRegisteredTypes.MoveFirst(&cursor);
  5430. while( cursor )
  5431. {
  5432. if( !knownTypes.MoveTo(0, cursor->key.name) )
  5433. knownTypes.Insert(cursor->key.name, true);
  5434. engine->allRegisteredTypes.MoveNext(&cursor, cursor);
  5435. }
  5436. if (module)
  5437. {
  5438. // Add script classes and interfaces
  5439. for (n = 0; n < module->m_classTypes.GetLength(); n++)
  5440. if (!knownTypes.MoveTo(0, module->m_classTypes[n]->name))
  5441. knownTypes.Insert(module->m_classTypes[n]->name, true);
  5442. // Add script enums
  5443. for (n = 0; n < module->m_enumTypes.GetLength(); n++)
  5444. if (!knownTypes.MoveTo(0, module->m_enumTypes[n]->name))
  5445. knownTypes.Insert(module->m_enumTypes[n]->name, true);
  5446. // Add script typedefs
  5447. for (n = 0; n < module->m_typeDefs.GetLength(); n++)
  5448. if (!knownTypes.MoveTo(0, module->m_typeDefs[n]->name))
  5449. knownTypes.Insert(module->m_typeDefs[n]->name, true);
  5450. // Add script funcdefs
  5451. for (n = 0; n < module->m_funcDefs.GetLength(); n++)
  5452. if (!knownTypes.MoveTo(0, module->m_funcDefs[n]->name))
  5453. knownTypes.Insert(module->m_funcDefs[n]->name, true);
  5454. }
  5455. }
  5456. // Check if the type is known
  5457. return knownTypes.MoveTo(0, type);
  5458. }
  5459. #endif
  5460. asCTypeInfo *asCBuilder::GetTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType)
  5461. {
  5462. if (currentType->name == type)
  5463. return currentType;
  5464. asUINT n;
  5465. asCTypeInfo *found = 0;
  5466. for (n = 0; found == 0 && n < currentType->properties.GetLength(); n++)
  5467. if (currentType->properties[n]->type.GetTypeInfo() &&
  5468. currentType->properties[n]->type.GetTypeInfo()->name == type)
  5469. found = currentType->properties[n]->type.GetTypeInfo();
  5470. for (n = 0; found == 0 && n < currentType->methods.GetLength(); n++)
  5471. {
  5472. asCScriptFunction *func = engine->scriptFunctions[currentType->methods[n]];
  5473. if (func->returnType.GetTypeInfo() &&
  5474. func->returnType.GetTypeInfo()->name == type)
  5475. found = func->returnType.GetTypeInfo();
  5476. for (asUINT f = 0; found == 0 && f < func->parameterTypes.GetLength(); f++)
  5477. if (func->parameterTypes[f].GetTypeInfo() &&
  5478. func->parameterTypes[f].GetTypeInfo()->name == type)
  5479. found = func->parameterTypes[f].GetTypeInfo();
  5480. }
  5481. if (found)
  5482. {
  5483. // In case we find a template instance it mustn't be returned
  5484. // because it is not known if the subtype is really matching
  5485. if (found->flags & asOBJ_TEMPLATE)
  5486. return 0;
  5487. }
  5488. return found;
  5489. }
  5490. asCFuncdefType *asCBuilder::GetFuncDef(const char *type, asSNameSpace *ns, asCObjectType *parentType)
  5491. {
  5492. asASSERT((ns == 0 && parentType) || (ns && parentType == 0));
  5493. if (ns)
  5494. {
  5495. for (asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++)
  5496. {
  5497. asCFuncdefType *funcDef = engine->registeredFuncDefs[n];
  5498. // TODO: access: Only return the definitions that the module has access to
  5499. if (funcDef && funcDef->nameSpace == ns && funcDef->name == type)
  5500. return funcDef;
  5501. }
  5502. if (module)
  5503. {
  5504. for (asUINT n = 0; n < module->m_funcDefs.GetLength(); n++)
  5505. {
  5506. asCFuncdefType *funcDef = module->m_funcDefs[n];
  5507. if (funcDef && funcDef->nameSpace == ns && funcDef->name == type)
  5508. return funcDef;
  5509. }
  5510. }
  5511. }
  5512. else
  5513. {
  5514. // Recursively check base classes
  5515. asCObjectType *currType = parentType;
  5516. while (currType)
  5517. {
  5518. for (asUINT n = 0; n < currType->childFuncDefs.GetLength(); n++)
  5519. {
  5520. asCFuncdefType *funcDef = currType->childFuncDefs[n];
  5521. if (funcDef && funcDef->name == type)
  5522. return funcDef;
  5523. }
  5524. currType = currType->derivedFrom;
  5525. }
  5526. }
  5527. return 0;
  5528. }
  5529. #ifndef AS_NO_COMPILER
  5530. int asCBuilder::GetEnumValueFromType(asCEnumType *type, const char *name, asCDataType &outDt, asDWORD &outValue)
  5531. {
  5532. if( !type || !(type->flags & asOBJ_ENUM) )
  5533. return 0;
  5534. for( asUINT n = 0; n < type->enumValues.GetLength(); ++n )
  5535. {
  5536. if( type->enumValues[n]->name == name )
  5537. {
  5538. outDt = asCDataType::CreateType(type, true);
  5539. outValue = type->enumValues[n]->value;
  5540. return 1;
  5541. }
  5542. }
  5543. return 0;
  5544. }
  5545. int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outValue, asSNameSpace *ns)
  5546. {
  5547. bool found = false;
  5548. // Search all available enum types
  5549. asUINT t;
  5550. for( t = 0; t < engine->registeredEnums.GetLength(); t++ )
  5551. {
  5552. asCEnumType *et = engine->registeredEnums[t];
  5553. if( ns != et->nameSpace ) continue;
  5554. // Don't bother with types the module doesn't have access to
  5555. if( (et->accessMask & module->m_accessMask) == 0 )
  5556. continue;
  5557. if( GetEnumValueFromType(et, name, outDt, outValue) )
  5558. {
  5559. if( !found )
  5560. found = true;
  5561. else
  5562. {
  5563. // Found more than one value in different enum types
  5564. return 2;
  5565. }
  5566. }
  5567. }
  5568. for( t = 0; t < module->m_enumTypes.GetLength(); t++ )
  5569. {
  5570. asCEnumType *et = module->m_enumTypes[t];
  5571. if( ns != et->nameSpace ) continue;
  5572. if( GetEnumValueFromType(et, name, outDt, outValue) )
  5573. {
  5574. if( !found )
  5575. found = true;
  5576. else
  5577. {
  5578. // Found more than one value in different enum types
  5579. return 2;
  5580. }
  5581. }
  5582. }
  5583. if( found )
  5584. return 1;
  5585. // Didn't find any value
  5586. return 0;
  5587. }
  5588. #endif // AS_NO_COMPILER
  5589. END_AS_NAMESPACE