as_scriptengine.cpp 190 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2015 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_scriptengine.cpp
  25. //
  26. // The implementation of the script engine interface
  27. //
  28. #include <stdlib.h>
  29. #include "as_config.h"
  30. #include "as_scriptengine.h"
  31. #include "as_builder.h"
  32. #include "as_context.h"
  33. #include "as_string_util.h"
  34. #include "as_tokenizer.h"
  35. #include "as_texts.h"
  36. #include "as_module.h"
  37. #include "as_callfunc.h"
  38. #include "as_generic.h"
  39. #include "as_scriptobject.h"
  40. #include "as_compiler.h"
  41. #include "as_bytecode.h"
  42. #include "as_debug.h"
  43. BEGIN_AS_NAMESPACE
  44. #ifdef AS_PROFILE
  45. // Instantiate the profiler once
  46. CProfiler g_profiler;
  47. #endif
  48. extern "C"
  49. {
  50. AS_API const char * asGetLibraryVersion()
  51. {
  52. #ifdef _DEBUG
  53. return ANGELSCRIPT_VERSION_STRING " DEBUG";
  54. #else
  55. return ANGELSCRIPT_VERSION_STRING;
  56. #endif
  57. }
  58. AS_API const char * asGetLibraryOptions()
  59. {
  60. const char *string = " "
  61. // Options
  62. #ifdef AS_MAX_PORTABILITY
  63. "AS_MAX_PORTABILITY "
  64. #endif
  65. #ifdef AS_DEBUG
  66. "AS_DEBUG "
  67. #endif
  68. #ifdef AS_NO_CLASS_METHODS
  69. "AS_NO_CLASS_METHODS "
  70. #endif
  71. #ifdef AS_USE_DOUBLE_AS_FLOAT
  72. "AS_USE_DOUBLE_AS_FLOAT "
  73. #endif
  74. #ifdef AS_64BIT_PTR
  75. "AS_64BIT_PTR "
  76. #endif
  77. #ifdef AS_NO_THREADS
  78. "AS_NO_THREADS "
  79. #endif
  80. #ifdef AS_NO_ATOMIC
  81. "AS_NO_ATOMIC "
  82. #endif
  83. #ifdef AS_NO_COMPILER
  84. "AS_NO_COMPILER "
  85. #endif
  86. #ifdef AS_NO_MEMBER_INIT
  87. "AS_NO_MEMBER_INIT "
  88. #endif
  89. #ifdef AS_NO_THISCALL_FUNCTOR_METHOD
  90. "AS_NO_THISCALL_FUNCTOR_METHOD "
  91. #endif
  92. #ifdef AS_NO_EXCEPTIONS
  93. "AS_NO_EXCEPTIONS "
  94. #endif
  95. #ifdef WIP_16BYTE_ALIGN
  96. "WIP_16BYTE_ALIGN "
  97. #endif
  98. #ifdef AS_BIG_ENDIAN
  99. "AS_BIG_ENDIAN "
  100. #endif
  101. // Target system
  102. #ifdef AS_WIN
  103. "AS_WIN "
  104. #endif
  105. #ifdef AS_LINUX
  106. "AS_LINUX "
  107. #endif
  108. #ifdef AS_MAC
  109. "AS_MAC "
  110. #endif
  111. #ifdef AS_SUN
  112. "AS_SUN "
  113. #endif
  114. #ifdef AS_BSD
  115. "AS_BSD "
  116. #endif
  117. #ifdef AS_XBOX
  118. "AS_XBOX "
  119. #endif
  120. #ifdef AS_XBOX360
  121. "AS_XBOX360 "
  122. #endif
  123. #ifdef AS_PSP
  124. "AS_PSP "
  125. #endif
  126. #ifdef AS_PS2
  127. "AS_PS2 "
  128. #endif
  129. #ifdef AS_PS3
  130. "AS_PS3 "
  131. #endif
  132. #ifdef AS_PSVITA
  133. "AS_PSVITA "
  134. #endif
  135. #ifdef AS_DC
  136. "AS_DC "
  137. #endif
  138. #ifdef AS_GC
  139. "AS_GC "
  140. #endif
  141. #ifdef AS_WII
  142. "AS_WII "
  143. #endif
  144. #ifdef AS_WIIU
  145. "AS_WIIU "
  146. #endif
  147. #ifdef AS_IPHONE
  148. "AS_IPHONE "
  149. #endif
  150. #ifdef AS_ANDROID
  151. "AS_ANDROID "
  152. #endif
  153. #ifdef AS_HAIKU
  154. "AS_HAIKU "
  155. #endif
  156. #ifdef AS_ILLUMOS
  157. "AS_ILLUMOS "
  158. #endif
  159. #ifdef AS_MARMALADE
  160. "AS_MARMALADE "
  161. #endif
  162. // CPU family
  163. #ifdef AS_PPC
  164. "AS_PPC "
  165. #endif
  166. #ifdef AS_PPC_64
  167. "AS_PPC_64 "
  168. #endif
  169. #ifdef AS_X86
  170. "AS_X86 "
  171. #endif
  172. #ifdef AS_MIPS
  173. "AS_MIPS "
  174. #endif
  175. #ifdef AS_SH4
  176. "AS_SH4 "
  177. #endif
  178. #ifdef AS_XENON
  179. "AS_XENON "
  180. #endif
  181. #ifdef AS_ARM
  182. "AS_ARM "
  183. #endif
  184. #ifdef AS_SOFTFP
  185. "AS_SOFTFP "
  186. #endif
  187. #ifdef AS_X64_GCC
  188. "AS_X64_GCC "
  189. #endif
  190. #ifdef AS_X64_MSVC
  191. "AS_X64_MSVC "
  192. #endif
  193. #ifdef AS_SPARC
  194. "AS_SPARC "
  195. #endif
  196. ;
  197. return string;
  198. }
  199. AS_API asIScriptEngine *asCreateScriptEngine(asDWORD version)
  200. {
  201. // Verify the version that the application expects
  202. if( (version/10000) != (ANGELSCRIPT_VERSION/10000) )
  203. return 0;
  204. if( (version/100)%100 != (ANGELSCRIPT_VERSION/100)%100 )
  205. return 0;
  206. if( (version%100) > (ANGELSCRIPT_VERSION%100) )
  207. return 0;
  208. // Verify the size of the types
  209. asASSERT( sizeof(asBYTE) == 1 );
  210. asASSERT( sizeof(asWORD) == 2 );
  211. asASSERT( sizeof(asDWORD) == 4 );
  212. asASSERT( sizeof(asQWORD) == 8 );
  213. asASSERT( sizeof(asPWORD) == sizeof(void*) );
  214. // Verify the boolean type
  215. asASSERT( sizeof(bool) == AS_SIZEOF_BOOL );
  216. asASSERT( true == VALUE_OF_BOOLEAN_TRUE );
  217. // Verify endianess
  218. #ifdef AS_BIG_ENDIAN
  219. asDWORD dw = 0x00010203;
  220. asQWORD qw = ((asQWORD(0x00010203)<<32)|asQWORD(0x04050607));
  221. #else
  222. asDWORD dw = 0x03020100;
  223. // C++ didn't have a standard way of declaring 64bit literal constants until C++11, so
  224. // I'm forced to do it like this to avoid compilers warnings when compiling with the full
  225. // C++ compliance.
  226. asQWORD qw = ((asQWORD(0x07060504)<<32)|asQWORD(0x03020100));
  227. #endif
  228. asASSERT( memcmp("\x00\x01\x02\x03", &dw, 4) == 0 );
  229. asASSERT( memcmp("\x00\x01\x02\x03\x04\x05\x06\x07", &qw, 8) == 0 );
  230. UNUSED_VAR(dw);
  231. UNUSED_VAR(qw);
  232. return asNEW(asCScriptEngine)();
  233. }
  234. } // extern "C"
  235. // interface
  236. int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
  237. {
  238. switch( property )
  239. {
  240. case asEP_ALLOW_UNSAFE_REFERENCES:
  241. ep.allowUnsafeReferences = value ? true : false;
  242. break;
  243. case asEP_OPTIMIZE_BYTECODE:
  244. ep.optimizeByteCode = value ? true : false;
  245. break;
  246. case asEP_COPY_SCRIPT_SECTIONS:
  247. ep.copyScriptSections = value ? true : false;
  248. break;
  249. case asEP_MAX_STACK_SIZE:
  250. if( value == 0 )
  251. {
  252. // Restore default: no limit and initially size 4KB
  253. ep.maximumContextStackSize = 0;
  254. initialContextStackSize = 1024;
  255. }
  256. else
  257. {
  258. // The size is given in bytes, but we only store dwords
  259. ep.maximumContextStackSize = (asUINT)value/4;
  260. if( initialContextStackSize > ep.maximumContextStackSize )
  261. {
  262. initialContextStackSize = ep.maximumContextStackSize;
  263. if( initialContextStackSize == 0 )
  264. initialContextStackSize = 1;
  265. }
  266. }
  267. break;
  268. case asEP_USE_CHARACTER_LITERALS:
  269. ep.useCharacterLiterals = value ? true : false;
  270. break;
  271. case asEP_ALLOW_MULTILINE_STRINGS:
  272. ep.allowMultilineStrings = value ? true : false;
  273. break;
  274. case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
  275. ep.allowImplicitHandleTypes = value ? true : false;
  276. break;
  277. case asEP_BUILD_WITHOUT_LINE_CUES:
  278. ep.buildWithoutLineCues = value ? true : false;
  279. break;
  280. case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
  281. ep.initGlobalVarsAfterBuild = value ? true : false;
  282. break;
  283. case asEP_REQUIRE_ENUM_SCOPE:
  284. ep.requireEnumScope = value ? true : false;
  285. break;
  286. case asEP_SCRIPT_SCANNER:
  287. if( value <= 1 )
  288. ep.scanner = (int)value;
  289. else
  290. return asINVALID_ARG;
  291. break;
  292. case asEP_INCLUDE_JIT_INSTRUCTIONS:
  293. ep.includeJitInstructions = value ? true : false;
  294. break;
  295. case asEP_STRING_ENCODING:
  296. if( value <= 1 )
  297. ep.stringEncoding = (int)value;
  298. else
  299. return asINVALID_ARG;
  300. break;
  301. case asEP_PROPERTY_ACCESSOR_MODE:
  302. if( value <= 2 )
  303. ep.propertyAccessorMode = (int)value;
  304. else
  305. return asINVALID_ARG;
  306. break;
  307. case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
  308. ep.expandDefaultArrayToTemplate = value ? true : false;
  309. break;
  310. case asEP_AUTO_GARBAGE_COLLECT:
  311. ep.autoGarbageCollect = value ? true : false;
  312. break;
  313. case asEP_DISALLOW_GLOBAL_VARS:
  314. ep.disallowGlobalVars = value ? true : false;
  315. break;
  316. case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
  317. ep.alwaysImplDefaultConstruct = value ? true : false;
  318. break;
  319. case asEP_COMPILER_WARNINGS:
  320. if( value <= 2 )
  321. ep.compilerWarnings = (int)value;
  322. else
  323. return asINVALID_ARG;
  324. break;
  325. case asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE:
  326. ep.disallowValueAssignForRefType = value ? true : false;
  327. break;
  328. case asEP_ALTER_SYNTAX_NAMED_ARGS:
  329. if( value <= 2 )
  330. ep.alterSyntaxNamedArgs = (int)value;
  331. else
  332. return asINVALID_ARG;
  333. break;
  334. case asEP_DISABLE_INTEGER_DIVISION:
  335. ep.disableIntegerDivision = value ? true : false;
  336. break;
  337. case asEP_DISALLOW_EMPTY_LIST_ELEMENTS:
  338. ep.disallowEmptyListElements = value ? true : false;
  339. break;
  340. case asEP_PRIVATE_PROP_AS_PROTECTED:
  341. ep.privatePropAsProtected = value ? true : false;
  342. break;
  343. default:
  344. return asINVALID_ARG;
  345. }
  346. return asSUCCESS;
  347. }
  348. // interface
  349. asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
  350. {
  351. switch( property )
  352. {
  353. case asEP_ALLOW_UNSAFE_REFERENCES:
  354. return ep.allowUnsafeReferences;
  355. case asEP_OPTIMIZE_BYTECODE:
  356. return ep.optimizeByteCode;
  357. case asEP_COPY_SCRIPT_SECTIONS:
  358. return ep.copyScriptSections;
  359. case asEP_MAX_STACK_SIZE:
  360. return ep.maximumContextStackSize*4;
  361. case asEP_USE_CHARACTER_LITERALS:
  362. return ep.useCharacterLiterals;
  363. case asEP_ALLOW_MULTILINE_STRINGS:
  364. return ep.allowMultilineStrings;
  365. case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
  366. return ep.allowImplicitHandleTypes;
  367. case asEP_BUILD_WITHOUT_LINE_CUES:
  368. return ep.buildWithoutLineCues;
  369. case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
  370. return ep.initGlobalVarsAfterBuild;
  371. case asEP_REQUIRE_ENUM_SCOPE:
  372. return ep.requireEnumScope;
  373. case asEP_SCRIPT_SCANNER:
  374. return ep.scanner;
  375. case asEP_INCLUDE_JIT_INSTRUCTIONS:
  376. return ep.includeJitInstructions;
  377. case asEP_STRING_ENCODING:
  378. return ep.stringEncoding;
  379. case asEP_PROPERTY_ACCESSOR_MODE:
  380. return ep.propertyAccessorMode;
  381. case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
  382. return ep.expandDefaultArrayToTemplate;
  383. case asEP_AUTO_GARBAGE_COLLECT:
  384. return ep.autoGarbageCollect;
  385. case asEP_DISALLOW_GLOBAL_VARS:
  386. return ep.disallowGlobalVars;
  387. case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
  388. return ep.alwaysImplDefaultConstruct;
  389. case asEP_COMPILER_WARNINGS:
  390. return ep.compilerWarnings;
  391. case asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE:
  392. return ep.disallowValueAssignForRefType;
  393. case asEP_ALTER_SYNTAX_NAMED_ARGS:
  394. return ep.alterSyntaxNamedArgs;
  395. case asEP_DISABLE_INTEGER_DIVISION:
  396. return ep.disableIntegerDivision;
  397. case asEP_DISALLOW_EMPTY_LIST_ELEMENTS:
  398. return ep.disallowEmptyListElements;
  399. case asEP_PRIVATE_PROP_AS_PROTECTED:
  400. return ep.privatePropAsProtected;
  401. default:
  402. return 0;
  403. }
  404. UNREACHABLE_RETURN;
  405. }
  406. // interface
  407. asIScriptFunction *asCScriptEngine::CreateDelegate(asIScriptFunction *func, void *obj)
  408. {
  409. if( func == 0 || obj == 0 )
  410. return 0;
  411. // The function must be a class method
  412. asIObjectType *type = func->GetObjectType();
  413. if( type == 0 )
  414. return 0;
  415. // The object type must allow handles
  416. if( (type->GetFlags() & asOBJ_REF) == 0 || (type->GetFlags() & (asOBJ_SCOPED | asOBJ_NOHANDLE)) )
  417. return 0;
  418. // Create the delegate the same way it would be created by the scripts
  419. return AS_NAMESPACE_QUALIFIER CreateDelegate(reinterpret_cast<asCScriptFunction*>(func), obj);
  420. }
  421. asCScriptEngine::asCScriptEngine()
  422. {
  423. asCThreadManager::Prepare(0);
  424. shuttingDown = false;
  425. inDestructor = false;
  426. // Engine properties
  427. {
  428. ep.allowUnsafeReferences = false;
  429. ep.optimizeByteCode = true;
  430. ep.copyScriptSections = true;
  431. ep.maximumContextStackSize = 0; // no limit
  432. ep.useCharacterLiterals = false;
  433. ep.allowMultilineStrings = false;
  434. ep.allowImplicitHandleTypes = false;
  435. // TODO: optimize: Maybe this should be turned off by default? If a debugger is not used
  436. // then this is just slowing down the execution.
  437. ep.buildWithoutLineCues = false;
  438. ep.initGlobalVarsAfterBuild = true;
  439. ep.requireEnumScope = false;
  440. ep.scanner = 1; // utf8. 0 = ascii
  441. ep.includeJitInstructions = false;
  442. ep.stringEncoding = 0; // utf8. 1 = utf16
  443. ep.propertyAccessorMode = 2; // 0 = disable, 1 = app registered only, 2 = app and script created
  444. ep.expandDefaultArrayToTemplate = false;
  445. ep.autoGarbageCollect = true;
  446. ep.disallowGlobalVars = false;
  447. ep.alwaysImplDefaultConstruct = false;
  448. ep.compilerWarnings = 1; // 0 = no warnings, 1 = warning, 2 = treat as error
  449. // TODO: 3.0.0: disallowValueAssignForRefType should be true by default
  450. ep.disallowValueAssignForRefType = false;
  451. ep.alterSyntaxNamedArgs = 0; // 0 = no alternate syntax, 1 = accept alternate syntax but warn, 2 = accept without warning
  452. ep.disableIntegerDivision = false;
  453. ep.disallowEmptyListElements = false;
  454. ep.privatePropAsProtected = false;
  455. }
  456. gc.engine = this;
  457. tok.engine = this;
  458. refCount.set(1);
  459. stringFactory = 0;
  460. configFailed = false;
  461. isPrepared = false;
  462. isBuilding = false;
  463. deferValidationOfTemplateTypes = false;
  464. lastModule = 0;
  465. initialContextStackSize = 1024; // 4 KB (1024 * sizeof(asDWORD)
  466. typeIdSeqNbr = 0;
  467. currentGroup = &defaultGroup;
  468. defaultAccessMask = 1;
  469. msgCallback = 0;
  470. jitCompiler = 0;
  471. // Create the global namespace
  472. defaultNamespace = AddNameSpace("");
  473. requestCtxFunc = 0;
  474. returnCtxFunc = 0;
  475. ctxCallbackParam = 0;
  476. // We must set the namespace in the built-in types explicitly as
  477. // this wasn't done by the default constructor. If we do not do
  478. // this we will get null pointer access in other parts of the code
  479. scriptTypeBehaviours.nameSpace = defaultNamespace;
  480. functionBehaviours.nameSpace = defaultNamespace;
  481. // Reserve function id 0 for no function
  482. scriptFunctions.PushLast(0);
  483. // Reserve the first typeIds for the primitive types
  484. typeIdSeqNbr = asTYPEID_DOUBLE + 1;
  485. // Make sure typeId for the built-in primitives are defined according to asETypeIdFlags
  486. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttVoid, false)) == asTYPEID_VOID );
  487. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttBool, false)) == asTYPEID_BOOL );
  488. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt8, false)) == asTYPEID_INT8 );
  489. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt16, false)) == asTYPEID_INT16 );
  490. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt, false)) == asTYPEID_INT32 );
  491. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt64, false)) == asTYPEID_INT64 );
  492. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt8, false)) == asTYPEID_UINT8 );
  493. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt16, false)) == asTYPEID_UINT16 );
  494. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt, false)) == asTYPEID_UINT32 );
  495. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt64, false)) == asTYPEID_UINT64 );
  496. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttFloat, false)) == asTYPEID_FLOAT );
  497. asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttDouble, false)) == asTYPEID_DOUBLE );
  498. defaultArrayObjectType = 0;
  499. RegisterScriptObject(this);
  500. RegisterScriptFunction(this);
  501. }
  502. void asCScriptEngine::DeleteDiscardedModules()
  503. {
  504. // TODO: redesign: Prevent more than one thread from entering this function at the same time.
  505. // If a thread is already doing the work for the clean-up the other thread should
  506. // simply return, as the first thread will continue.
  507. ACQUIRESHARED(engineRWLock);
  508. asUINT maxCount = discardedModules.GetLength();
  509. RELEASESHARED(engineRWLock);
  510. for( asUINT n = 0; n < maxCount; n++ )
  511. {
  512. ACQUIRESHARED(engineRWLock);
  513. asCModule *mod = discardedModules[n];
  514. RELEASESHARED(engineRWLock);
  515. if( !mod->HasExternalReferences(shuttingDown) )
  516. {
  517. asDELETE(mod, asCModule);
  518. n--;
  519. }
  520. ACQUIRESHARED(engineRWLock);
  521. // Determine the max count again, since another module may have been discarded during the processing
  522. maxCount = discardedModules.GetLength();
  523. RELEASESHARED(engineRWLock);
  524. }
  525. // Go over the list of global properties, to see if it is possible to clean
  526. // up some variables that are no longer referred to by any functions
  527. for( asUINT n = 0; n < globalProperties.GetLength(); n++ )
  528. {
  529. asCGlobalProperty *prop = globalProperties[n];
  530. if( prop && prop->refCount.get() == 1 )
  531. RemoveGlobalProperty(prop);
  532. }
  533. }
  534. asCScriptEngine::~asCScriptEngine()
  535. {
  536. // TODO: clean-up: Clean up redundant code
  537. asUINT n = 0;
  538. inDestructor = true;
  539. asASSERT(refCount.get() == 0);
  540. // If ShutDown hasn't been called yet do it now
  541. if( !shuttingDown )
  542. {
  543. AddRef();
  544. ShutDownAndRelease();
  545. }
  546. // Unravel the registered interface
  547. if( defaultArrayObjectType )
  548. {
  549. defaultArrayObjectType->ReleaseInternal();
  550. defaultArrayObjectType = 0;
  551. }
  552. // Delete the functions for generated template types that may references object types
  553. for( n = 0; n < templateInstanceTypes.GetLength(); n++ )
  554. {
  555. asCObjectType *templateType = templateInstanceTypes[n];
  556. if( templateInstanceTypes[n] )
  557. templateType->DestroyInternal();
  558. }
  559. for( n = 0; n < listPatternTypes.GetLength(); n++ )
  560. {
  561. asCObjectType *type = listPatternTypes[n];
  562. if( type )
  563. type->ReleaseInternal();
  564. }
  565. listPatternTypes.SetLength(0);
  566. // No script types must have survived
  567. asASSERT( sharedScriptTypes.GetLength() == 0 );
  568. // It is allowed to create new references to the engine temporarily while destroying objects
  569. // but these references must be release immediately or else something is can go wrong later on
  570. if( refCount.get() > 0 )
  571. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ENGINE_REF_COUNT_ERROR_DURING_SHUTDOWN);
  572. mapTypeIdToObjectType.EraseAll();
  573. mapTypeIdToFunction.EraseAll();
  574. // First remove what is not used, so that other groups can be deleted safely
  575. defaultGroup.RemoveConfiguration(this, true);
  576. while( configGroups.GetLength() )
  577. {
  578. // Delete config groups in the right order
  579. asCConfigGroup *grp = configGroups.PopLast();
  580. if( grp )
  581. {
  582. grp->RemoveConfiguration(this);
  583. asDELETE(grp,asCConfigGroup);
  584. }
  585. }
  586. // Remove what is remaining
  587. defaultGroup.RemoveConfiguration(this);
  588. // Any remaining objects in templateInstanceTypes is from generated template instances
  589. for( n = 0; n < templateInstanceTypes.GetLength(); n++ )
  590. {
  591. asCObjectType *templateType = templateInstanceTypes[n];
  592. if( templateInstanceTypes[n] )
  593. templateType->ReleaseInternal();
  594. }
  595. templateInstanceTypes.SetLength(0);
  596. asCSymbolTable<asCGlobalProperty>::iterator it = registeredGlobalProps.List();
  597. for( ; it; it++ )
  598. {
  599. RemoveGlobalProperty(*it);
  600. (*it)->Release();
  601. }
  602. registeredGlobalProps.Clear();
  603. for( n = 0; n < templateSubTypes.GetLength(); n++ )
  604. {
  605. if( templateSubTypes[n] )
  606. {
  607. templateSubTypes[n]->DestroyInternal();
  608. templateSubTypes[n]->ReleaseInternal();
  609. }
  610. }
  611. templateSubTypes.SetLength(0);
  612. registeredTypeDefs.SetLength(0);
  613. registeredEnums.SetLength(0);
  614. registeredObjTypes.SetLength(0);
  615. asCSymbolTable<asCScriptFunction>::iterator funcIt = registeredGlobalFuncs.List();
  616. for( ; funcIt; funcIt++ )
  617. (*funcIt)->ReleaseInternal();
  618. registeredGlobalFuncs.Clear();
  619. scriptTypeBehaviours.ReleaseAllFunctions();
  620. functionBehaviours.ReleaseAllFunctions();
  621. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  622. if( scriptFunctions[n] )
  623. {
  624. scriptFunctions[n]->DestroyInternal();
  625. // Set the engine pointer to null to signal that the function is no longer part of the engine
  626. scriptFunctions[n]->engine = 0;
  627. }
  628. scriptFunctions.SetLength(0);
  629. // Increase the internal ref count for these builtin object types, so the destructor is not called incorrectly
  630. scriptTypeBehaviours.AddRefInternal();
  631. functionBehaviours.AddRefInternal();
  632. // Destroy the funcdefs
  633. // As funcdefs are shared between modules it shouldn't be a problem to keep the objects until the engine is released
  634. for( n = 0; n < funcDefs.GetLength(); n++ )
  635. if( funcDefs[n] )
  636. {
  637. funcDefs[n]->DestroyInternal();
  638. funcDefs[n]->ReleaseInternal();
  639. }
  640. funcDefs.SetLength(0);
  641. // Free the global properties
  642. for( asUINT n = 0; n < globalProperties.GetLength(); n++ )
  643. {
  644. asCGlobalProperty *prop = globalProperties[n];
  645. if( prop )
  646. {
  647. asASSERT( prop->refCount.get() == 1 );
  648. RemoveGlobalProperty(prop);
  649. }
  650. }
  651. // Free string constants
  652. for( n = 0; n < stringConstants.GetLength(); n++ )
  653. asDELETE(stringConstants[n],asCString);
  654. stringConstants.SetLength(0);
  655. stringToIdMap.EraseAll();
  656. // Free the script section names
  657. for( n = 0; n < scriptSectionNames.GetLength(); n++ )
  658. asDELETE(scriptSectionNames[n],asCString);
  659. scriptSectionNames.SetLength(0);
  660. // Clean the user data
  661. for( n = 0; n < userData.GetLength(); n += 2 )
  662. {
  663. if( userData[n+1] )
  664. {
  665. for( asUINT c = 0; c < cleanEngineFuncs.GetLength(); c++ )
  666. if( cleanEngineFuncs[c].type == userData[n] )
  667. cleanEngineFuncs[c].cleanFunc(this);
  668. }
  669. }
  670. // Free namespaces
  671. for( n = 0; n < nameSpaces.GetLength(); n++ )
  672. asDELETE(nameSpaces[n], asSNameSpace);
  673. nameSpaces.SetLength(0);
  674. asCThreadManager::Unprepare();
  675. }
  676. // interface
  677. int asCScriptEngine::SetContextCallbacks(asREQUESTCONTEXTFUNC_t requestCtx, asRETURNCONTEXTFUNC_t returnCtx, void *param)
  678. {
  679. // Both callbacks or neither must be set
  680. if( (requestCtx == 0 && returnCtx != 0) || (requestCtx != 0 && returnCtx == 0) )
  681. return asINVALID_ARG;
  682. requestCtxFunc = requestCtx;
  683. returnCtxFunc = returnCtx;
  684. ctxCallbackParam = param;
  685. return 0;
  686. }
  687. // interface
  688. asIScriptContext *asCScriptEngine::RequestContext()
  689. {
  690. if( requestCtxFunc )
  691. {
  692. // The return callback must also exist
  693. asASSERT( returnCtxFunc );
  694. asIScriptContext *ctx = requestCtxFunc(this, ctxCallbackParam);
  695. return ctx;
  696. }
  697. // As fallback we create a new context
  698. return CreateContext();
  699. }
  700. // internal
  701. asCModule *asCScriptEngine::FindNewOwnerForSharedType(asCObjectType *type, asCModule *mod)
  702. {
  703. asASSERT( type->IsShared() );
  704. if( type->module != mod )
  705. return type->module;
  706. for( asUINT n = 0; n < scriptModules.GetLength(); n++ )
  707. {
  708. // TODO: optimize: If the modules already stored the shared types separately, this would be quicker
  709. int foundIdx = -1;
  710. asCModule *mod = scriptModules[n];
  711. if( mod == type->module ) continue;
  712. if( type->flags & asOBJ_ENUM )
  713. foundIdx = mod->enumTypes.IndexOf(type);
  714. else if( type->flags & asOBJ_TYPEDEF )
  715. foundIdx = mod->typeDefs.IndexOf(type);
  716. else
  717. foundIdx = mod->classTypes.IndexOf(type);
  718. if( foundIdx >= 0 )
  719. {
  720. type->module = mod;
  721. break;
  722. }
  723. }
  724. return type->module;
  725. }
  726. // internal
  727. asCModule *asCScriptEngine::FindNewOwnerForSharedFunc(asCScriptFunction *func, asCModule *mod)
  728. {
  729. asASSERT( func->IsShared() );
  730. if( func->module != mod )
  731. return func->module;
  732. for( asUINT n = 0; n < scriptModules.GetLength(); n++ )
  733. {
  734. // TODO: optimize: If the modules already stored the shared types separately, this would be quicker
  735. int foundIdx = -1;
  736. asCModule *mod = scriptModules[n];
  737. if( mod == func->module ) continue;
  738. if( func->funcType == asFUNC_FUNCDEF )
  739. foundIdx = mod->funcDefs.IndexOf(func);
  740. else
  741. foundIdx = mod->scriptFunctions.IndexOf(func);
  742. if( foundIdx >= 0 )
  743. {
  744. func->module = mod;
  745. break;
  746. }
  747. }
  748. return func->module;
  749. }
  750. // interface
  751. void asCScriptEngine::ReturnContext(asIScriptContext *ctx)
  752. {
  753. if( returnCtxFunc )
  754. {
  755. returnCtxFunc(this, ctx, ctxCallbackParam);
  756. return;
  757. }
  758. // As fallback we just release the context
  759. if( ctx )
  760. ctx->Release();
  761. }
  762. // interface
  763. int asCScriptEngine::AddRef() const
  764. {
  765. asASSERT( refCount.get() > 0 || inDestructor );
  766. return refCount.atomicInc();
  767. }
  768. // interface
  769. int asCScriptEngine::Release() const
  770. {
  771. int r = refCount.atomicDec();
  772. if( r == 0 )
  773. {
  774. // It is possible that some function will temporarily increment the engine ref count
  775. // during clean-up for example while destroying the objects in the garbage collector.
  776. if( !inDestructor )
  777. asDELETE(const_cast<asCScriptEngine*>(this),asCScriptEngine);
  778. return 0;
  779. }
  780. return r;
  781. }
  782. // interface
  783. int asCScriptEngine::ShutDownAndRelease()
  784. {
  785. // Do a full garbage collection cycle to clean up any object that may still hold on to the engine
  786. GarbageCollect();
  787. // Set the flag that the engine is being shutdown now. This will speed up
  788. // the process, and will also allow the engine to warn about invalid calls
  789. shuttingDown = true;
  790. // Clear the context callbacks. If new context's are needed for the clean-up the engine will take care of this itself.
  791. // Context callbacks are normally used for pooling contexts, and if we allow new contexts to be created without being
  792. // immediately destroyed afterwards it means the engine's refcount will increase. This is turn may cause memory access
  793. // violations later on when the pool releases its contexts.
  794. SetContextCallbacks(0, 0, 0);
  795. // The modules must be deleted first, as they may use
  796. // object types from the config groups
  797. for( asUINT n = (asUINT)scriptModules.GetLength(); n-- > 0; )
  798. if( scriptModules[n] )
  799. scriptModules[n]->Discard();
  800. scriptModules.SetLength(0);
  801. // Do another full garbage collection to destroy the object types/functions
  802. // that may have been placed in the gc when destroying the modules
  803. GarbageCollect();
  804. // Do another sweep to delete discarded modules, that may not have
  805. // been deleted earlier due to still having external references
  806. DeleteDiscardedModules();
  807. // If the application hasn't registered GC behaviours for all types
  808. // that can form circular references with script types, then there
  809. // may still be objects in the GC.
  810. gc.ReportAndReleaseUndestroyedObjects();
  811. // Release the engine reference
  812. return Release();
  813. }
  814. // internal
  815. asSNameSpace *asCScriptEngine::AddNameSpace(const char *name)
  816. {
  817. // First check if it doesn't exist already
  818. asSNameSpace *ns = FindNameSpace(name);
  819. if( ns ) return ns;
  820. ns = asNEW(asSNameSpace);
  821. if( ns == 0 )
  822. {
  823. // Out of memory
  824. return 0;
  825. }
  826. ns->name = name;
  827. nameSpaces.PushLast(ns);
  828. return ns;
  829. }
  830. // internal
  831. asSNameSpace *asCScriptEngine::FindNameSpace(const char *name) const
  832. {
  833. // TODO: optimize: Improve linear search
  834. for( asUINT n = 0; n < nameSpaces.GetLength(); n++ )
  835. if( nameSpaces[n]->name == name )
  836. return nameSpaces[n];
  837. return 0;
  838. }
  839. // interface
  840. const char *asCScriptEngine::GetDefaultNamespace() const
  841. {
  842. return defaultNamespace->name.AddressOf();
  843. }
  844. // interface
  845. int asCScriptEngine::SetDefaultNamespace(const char *nameSpace)
  846. {
  847. if( nameSpace == 0 )
  848. return ConfigError(asINVALID_ARG, "SetDefaultNamespace", nameSpace, 0);
  849. asCString ns = nameSpace;
  850. if( ns != "" )
  851. {
  852. // Make sure the namespace is composed of alternating identifier and ::
  853. size_t pos = 0;
  854. bool expectIdentifier = true;
  855. size_t len;
  856. eTokenType t = ttIdentifier;
  857. for( ; pos < ns.GetLength(); pos += len)
  858. {
  859. t = tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len);
  860. if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) )
  861. return ConfigError(asINVALID_DECLARATION, "SetDefaultNamespace", nameSpace, 0);
  862. expectIdentifier = !expectIdentifier;
  863. }
  864. // If the namespace ends with :: then strip it off
  865. if( t == ttScope )
  866. ns.SetLength(ns.GetLength()-2);
  867. }
  868. defaultNamespace = AddNameSpace(ns.AddressOf());
  869. return 0;
  870. }
  871. // interface
  872. void *asCScriptEngine::SetUserData(void *data, asPWORD type)
  873. {
  874. // As a thread might add a new new user data at the same time as another
  875. // it is necessary to protect both read and write access to the userData member
  876. ACQUIREEXCLUSIVE(engineRWLock);
  877. // It is not intended to store a lot of different types of userdata,
  878. // so a more complex structure like a associative map would just have
  879. // more overhead than a simple array.
  880. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  881. {
  882. if( userData[n] == type )
  883. {
  884. void *oldData = reinterpret_cast<void*>(userData[n+1]);
  885. userData[n+1] = reinterpret_cast<asPWORD>(data);
  886. RELEASEEXCLUSIVE(engineRWLock);
  887. return oldData;
  888. }
  889. }
  890. userData.PushLast(type);
  891. userData.PushLast(reinterpret_cast<asPWORD>(data));
  892. RELEASEEXCLUSIVE(engineRWLock);
  893. return 0;
  894. }
  895. // interface
  896. void *asCScriptEngine::GetUserData(asPWORD type) const
  897. {
  898. // There may be multiple threads reading, but when
  899. // setting the user data nobody must be reading.
  900. ACQUIRESHARED(engineRWLock);
  901. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  902. {
  903. if( userData[n] == type )
  904. {
  905. RELEASESHARED(engineRWLock);
  906. return reinterpret_cast<void*>(userData[n+1]);
  907. }
  908. }
  909. RELEASESHARED(engineRWLock);
  910. return 0;
  911. }
  912. // interface
  913. int asCScriptEngine::SetMessageCallback(const asSFuncPtr &callback, void *obj, asDWORD callConv)
  914. {
  915. msgCallback = true;
  916. msgCallbackObj = obj;
  917. bool isObj = false;
  918. if( (unsigned)callConv == asCALL_GENERIC || (unsigned)callConv == asCALL_THISCALL_OBJFIRST || (unsigned)callConv == asCALL_THISCALL_OBJLAST )
  919. {
  920. msgCallback = false;
  921. return asNOT_SUPPORTED;
  922. }
  923. if( (unsigned)callConv >= asCALL_THISCALL )
  924. {
  925. isObj = true;
  926. if( obj == 0 )
  927. {
  928. msgCallback = false;
  929. return asINVALID_ARG;
  930. }
  931. }
  932. int r = DetectCallingConvention(isObj, callback, callConv, 0, &msgCallbackFunc);
  933. if( r < 0 ) msgCallback = false;
  934. return r;
  935. }
  936. // interface
  937. int asCScriptEngine::ClearMessageCallback()
  938. {
  939. msgCallback = false;
  940. return 0;
  941. }
  942. // interface
  943. int asCScriptEngine::WriteMessage(const char *section, int row, int col, asEMsgType type, const char *message)
  944. {
  945. // Validate input parameters
  946. if( section == 0 ||
  947. message == 0 )
  948. return asINVALID_ARG;
  949. // If there is no callback then there's nothing to do
  950. if( !msgCallback )
  951. return 0;
  952. // If a pre-message has been set, then write that first
  953. if( preMessage.isSet )
  954. {
  955. asSMessageInfo msg;
  956. msg.section = preMessage.scriptname.AddressOf();
  957. msg.row = preMessage.r;
  958. msg.col = preMessage.c;
  959. msg.type = asMSGTYPE_INFORMATION;
  960. msg.message = preMessage.message.AddressOf();
  961. if( msgCallbackFunc.callConv < ICC_THISCALL )
  962. CallGlobalFunction(&msg, msgCallbackObj, &msgCallbackFunc, 0);
  963. else
  964. CallObjectMethod(msgCallbackObj, &msg, &msgCallbackFunc, 0);
  965. preMessage.isSet = false;
  966. }
  967. // Write the message to the callback
  968. asSMessageInfo msg;
  969. msg.section = section;
  970. msg.row = row;
  971. msg.col = col;
  972. msg.type = type;
  973. msg.message = message;
  974. if( msgCallbackFunc.callConv < ICC_THISCALL )
  975. CallGlobalFunction(&msg, msgCallbackObj, &msgCallbackFunc, 0);
  976. else
  977. CallObjectMethod(msgCallbackObj, &msg, &msgCallbackFunc, 0);
  978. return 0;
  979. }
  980. int asCScriptEngine::SetJITCompiler(asIJITCompiler *compiler)
  981. {
  982. jitCompiler = compiler;
  983. return asSUCCESS;
  984. }
  985. asIJITCompiler *asCScriptEngine::GetJITCompiler() const
  986. {
  987. return jitCompiler;
  988. }
  989. // interface
  990. asETokenClass asCScriptEngine::ParseToken(const char *string, size_t stringLength, asUINT *tokenLength) const
  991. {
  992. if( stringLength == 0 )
  993. stringLength = strlen(string);
  994. size_t len;
  995. asETokenClass tc;
  996. tok.GetToken(string, stringLength, &len, &tc);
  997. if( tokenLength )
  998. *tokenLength = (asUINT)len;
  999. return tc;
  1000. }
  1001. // interface
  1002. asIScriptModule *asCScriptEngine::GetModule(const char *module, asEGMFlags flag)
  1003. {
  1004. asCModule *mod = GetModule(module, false);
  1005. if( flag == asGM_ALWAYS_CREATE )
  1006. {
  1007. if( mod != 0 )
  1008. mod->Discard();
  1009. return GetModule(module, true);
  1010. }
  1011. if( mod == 0 && flag == asGM_CREATE_IF_NOT_EXISTS )
  1012. return GetModule(module, true);
  1013. return mod;
  1014. }
  1015. // interface
  1016. int asCScriptEngine::DiscardModule(const char *module)
  1017. {
  1018. asCModule *mod = GetModule(module, false);
  1019. if( mod == 0 ) return asNO_MODULE;
  1020. mod->Discard();
  1021. return 0;
  1022. }
  1023. // interface
  1024. asUINT asCScriptEngine::GetModuleCount() const
  1025. {
  1026. ACQUIRESHARED(engineRWLock);
  1027. asUINT length = asUINT(scriptModules.GetLength());
  1028. RELEASESHARED(engineRWLock);
  1029. return length;
  1030. }
  1031. // interface
  1032. asIScriptModule *asCScriptEngine::GetModuleByIndex(asUINT index) const
  1033. {
  1034. asIScriptModule *mod = 0;
  1035. ACQUIRESHARED(engineRWLock);
  1036. if( index < scriptModules.GetLength() )
  1037. mod = scriptModules[index];
  1038. RELEASESHARED(engineRWLock);
  1039. return mod;
  1040. }
  1041. // Internal
  1042. void asCScriptEngine::RemoveTypeAndRelatedFromList(asCMap<asCObjectType*,char> &types, asCObjectType *ot)
  1043. {
  1044. // Remove the type from the list
  1045. asSMapNode<asCObjectType*,char>* node;
  1046. if( !types.MoveTo(&node, ot) )
  1047. return;
  1048. types.Erase(node);
  1049. // If the type is an template type then remove all sub types as well
  1050. for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ )
  1051. {
  1052. if( ot->templateSubTypes[n].GetObjectType() )
  1053. RemoveTypeAndRelatedFromList(types, ot->templateSubTypes[n].GetObjectType());
  1054. }
  1055. // If the type is a class then remove all properties types as well
  1056. if( ot->properties.GetLength() )
  1057. {
  1058. for( asUINT n = 0; n < ot->properties.GetLength(); n++ )
  1059. RemoveTypeAndRelatedFromList(types, ot->properties[n]->type.GetObjectType());
  1060. }
  1061. }
  1062. // internal
  1063. int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *decl)
  1064. {
  1065. asCModule *mod = 0;
  1066. // Is this a script class?
  1067. if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size > 0 )
  1068. mod = scriptFunctions[ot->beh.factories[0]]->module;
  1069. asCBuilder bld(this, mod);
  1070. // Don't write parser errors to the message callback
  1071. bld.silent = true;
  1072. asCScriptFunction func(this, mod, asFUNC_DUMMY);
  1073. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  1074. if( r < 0 )
  1075. return asINVALID_DECLARATION;
  1076. // Search for matching factory function
  1077. int id = -1;
  1078. for( asUINT n = 0; n < ot->beh.factories.GetLength(); n++ )
  1079. {
  1080. asCScriptFunction *f = scriptFunctions[ot->beh.factories[n]];
  1081. if( f->IsSignatureEqual(&func) )
  1082. {
  1083. id = ot->beh.factories[n];
  1084. break;
  1085. }
  1086. }
  1087. if( id == -1 ) return asNO_FUNCTION;
  1088. return id;
  1089. }
  1090. // internal
  1091. int asCScriptEngine::GetMethodIdByDecl(const asCObjectType *ot, const char *decl, asCModule *mod)
  1092. {
  1093. asCBuilder bld(this, mod);
  1094. // Don't write parser errors to the message callback
  1095. bld.silent = true;
  1096. asCScriptFunction func(this, mod, asFUNC_DUMMY);
  1097. // Set the object type so that the signature can be properly compared
  1098. // This cast is OK, it will only be used for comparison
  1099. func.objectType = const_cast<asCObjectType*>(ot);
  1100. func.objectType->AddRefInternal();
  1101. int r = bld.ParseFunctionDeclaration(func.objectType, decl, &func, false);
  1102. if( r < 0 )
  1103. return asINVALID_DECLARATION;
  1104. // Search script functions for matching interface
  1105. int id = -1;
  1106. for( asUINT n = 0; n < ot->methods.GetLength(); ++n )
  1107. {
  1108. if( func.IsSignatureEqual(scriptFunctions[ot->methods[n]]) )
  1109. {
  1110. if( id == -1 )
  1111. id = ot->methods[n];
  1112. else
  1113. return asMULTIPLE_FUNCTIONS;
  1114. }
  1115. }
  1116. if( id == -1 ) return asNO_FUNCTION;
  1117. return id;
  1118. }
  1119. // internal
  1120. asCString asCScriptEngine::GetFunctionDeclaration(int funcId)
  1121. {
  1122. asCString str;
  1123. asCScriptFunction *func = GetScriptFunction(funcId);
  1124. if( func )
  1125. str = func->GetDeclarationStr();
  1126. return str;
  1127. }
  1128. // internal
  1129. asCScriptFunction *asCScriptEngine::GetScriptFunction(int funcId) const
  1130. {
  1131. if( funcId < 0 || funcId >= (int)scriptFunctions.GetLength() )
  1132. return 0;
  1133. return scriptFunctions[funcId];
  1134. }
  1135. // interface
  1136. asIScriptContext *asCScriptEngine::CreateContext()
  1137. {
  1138. asIScriptContext *ctx = 0;
  1139. CreateContext(&ctx, false);
  1140. return ctx;
  1141. }
  1142. // internal
  1143. int asCScriptEngine::CreateContext(asIScriptContext **context, bool isInternal)
  1144. {
  1145. *context = asNEW(asCContext)(this, !isInternal);
  1146. if( *context == 0 )
  1147. return asOUT_OF_MEMORY;
  1148. // We need to make sure the engine has been
  1149. // prepared before any context is executed
  1150. PrepareEngine();
  1151. return 0;
  1152. }
  1153. // interface
  1154. int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset)
  1155. {
  1156. int r;
  1157. asCDataType dt;
  1158. asCBuilder bld(this, 0);
  1159. r = bld.ParseDataType(obj, &dt, defaultNamespace);
  1160. if( r < 0 )
  1161. return ConfigError(r, "RegisterObjectProperty", obj, declaration);
  1162. // Don't allow modifying generated template instances
  1163. if( dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(dt.GetObjectType()) )
  1164. return ConfigError(asINVALID_TYPE, "RegisterObjectProperty", obj, declaration);
  1165. // Verify that the correct config group is used
  1166. if( currentGroup->FindType(dt.GetObjectType()->name.AddressOf()) == 0 )
  1167. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterObjectProperty", obj, declaration);
  1168. asCDataType type;
  1169. asCString name;
  1170. if( (r = bld.VerifyProperty(&dt, declaration, name, type, 0)) < 0 )
  1171. return ConfigError(r, "RegisterObjectProperty", obj, declaration);
  1172. // Store the property info
  1173. if( dt.GetObjectType() == 0 || dt.IsObjectHandle() )
  1174. return ConfigError(asINVALID_OBJECT, "RegisterObjectProperty", obj, declaration);
  1175. // The VM currently only supports 16bit offsets
  1176. // TODO: The VM needs to have support for 32bit offsets. Probably with a second ADDSi instruction
  1177. // However, when implementing this it is necessary for the bytecode serialization to support
  1178. // the switch between the instructions upon loading bytecode as the offset may not be the
  1179. // same on all platforms
  1180. if( byteOffset > 32767 || byteOffset < -32768 )
  1181. return ConfigError(asINVALID_ARG, "RegisterObjectProperty", obj, declaration);
  1182. asCObjectProperty *prop = asNEW(asCObjectProperty);
  1183. if( prop == 0 )
  1184. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectProperty", obj, declaration);
  1185. prop->name = name;
  1186. prop->type = type;
  1187. prop->byteOffset = byteOffset;
  1188. prop->isPrivate = false;
  1189. prop->isProtected = false;
  1190. prop->accessMask = defaultAccessMask;
  1191. dt.GetObjectType()->properties.PushLast(prop);
  1192. // Add references to types so they are not released too early
  1193. if( type.GetObjectType() )
  1194. {
  1195. type.GetObjectType()->AddRefInternal();
  1196. // Add template instances to the config group
  1197. if( (type.GetObjectType()->flags & asOBJ_TEMPLATE) && !currentGroup->objTypes.Exists(type.GetObjectType()) )
  1198. currentGroup->objTypes.PushLast(type.GetObjectType());
  1199. }
  1200. currentGroup->AddReferencesForType(this, type.GetObjectType());
  1201. return asSUCCESS;
  1202. }
  1203. // interface
  1204. int asCScriptEngine::RegisterInterface(const char *name)
  1205. {
  1206. if( name == 0 ) return ConfigError(asINVALID_NAME, "RegisterInterface", 0, 0);
  1207. // Verify if the name has been registered as a type already
  1208. if( GetRegisteredObjectType(name, defaultNamespace) )
  1209. return asALREADY_REGISTERED;
  1210. // Use builder to parse the datatype
  1211. asCDataType dt;
  1212. asCBuilder bld(this, 0);
  1213. bool oldMsgCallback = msgCallback; msgCallback = false;
  1214. int r = bld.ParseDataType(name, &dt, defaultNamespace);
  1215. msgCallback = oldMsgCallback;
  1216. if( r >= 0 )
  1217. {
  1218. // If it is not in the defaultNamespace then the type was successfully parsed because
  1219. // it is declared in a parent namespace which shouldn't be treated as an error
  1220. if( dt.GetObjectType() && dt.GetObjectType()->nameSpace == defaultNamespace )
  1221. return ConfigError(asERROR, "RegisterInterface", name, 0);
  1222. }
  1223. // Make sure the name is not a reserved keyword
  1224. size_t tokenLen;
  1225. int token = tok.GetToken(name, strlen(name), &tokenLen);
  1226. if( token != ttIdentifier || strlen(name) != tokenLen )
  1227. return ConfigError(asINVALID_NAME, "RegisterInterface", name, 0);
  1228. r = bld.CheckNameConflict(name, 0, 0, defaultNamespace);
  1229. if( r < 0 )
  1230. return ConfigError(asNAME_TAKEN, "RegisterInterface", name, 0);
  1231. // Don't have to check against members of object
  1232. // types as they are allowed to use the names
  1233. // Register the object type for the interface
  1234. asCObjectType *st = asNEW(asCObjectType)(this);
  1235. if( st == 0 )
  1236. return ConfigError(asOUT_OF_MEMORY, "RegisterInterface", name, 0);
  1237. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_SHARED;
  1238. st->size = 0; // Cannot be instantiated
  1239. st->name = name;
  1240. st->nameSpace = defaultNamespace;
  1241. // Use the default script class behaviours
  1242. st->beh.factory = 0;
  1243. st->beh.addref = scriptTypeBehaviours.beh.addref;
  1244. scriptFunctions[st->beh.addref]->AddRefInternal();
  1245. st->beh.release = scriptTypeBehaviours.beh.release;
  1246. scriptFunctions[st->beh.release]->AddRefInternal();
  1247. st->beh.copy = 0;
  1248. allRegisteredTypes.Insert(asSNameSpaceNamePair(st->nameSpace, st->name), st);
  1249. registeredObjTypes.PushLast(st);
  1250. currentGroup->objTypes.PushLast(st);
  1251. return asSUCCESS;
  1252. }
  1253. // interface
  1254. int asCScriptEngine::RegisterInterfaceMethod(const char *intf, const char *declaration)
  1255. {
  1256. // Verify that the correct config group is set.
  1257. if( currentGroup->FindType(intf) == 0 )
  1258. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterInterfaceMethod", intf, declaration);
  1259. asCDataType dt;
  1260. asCBuilder bld(this, 0);
  1261. int r = bld.ParseDataType(intf, &dt, defaultNamespace);
  1262. if( r < 0 )
  1263. return ConfigError(r, "RegisterInterfaceMethod", intf, declaration);
  1264. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_INTERFACE);
  1265. if( func == 0 )
  1266. return ConfigError(asOUT_OF_MEMORY, "RegisterInterfaceMethod", intf, declaration);
  1267. func->objectType = dt.GetObjectType();
  1268. func->objectType->AddRefInternal();
  1269. r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, false);
  1270. if( r < 0 )
  1271. {
  1272. func->funcType = asFUNC_DUMMY;
  1273. asDELETE(func,asCScriptFunction);
  1274. return ConfigError(asINVALID_DECLARATION, "RegisterInterfaceMethod", intf, declaration);
  1275. }
  1276. // Check name conflicts
  1277. r = bld.CheckNameConflictMember(dt.GetObjectType(), func->name.AddressOf(), 0, 0, false);
  1278. if( r < 0 )
  1279. {
  1280. func->funcType = asFUNC_DUMMY;
  1281. asDELETE(func,asCScriptFunction);
  1282. return ConfigError(asNAME_TAKEN, "RegisterInterfaceMethod", intf, declaration);
  1283. }
  1284. func->id = GetNextScriptFunctionId();
  1285. AddScriptFunction(func);
  1286. // The index into the interface's vftable chunk should be
  1287. // its index in the methods array.
  1288. func->vfTableIdx = int(func->objectType->methods.GetLength());
  1289. func->objectType->methods.PushLast(func->id);
  1290. func->ComputeSignatureId();
  1291. currentGroup->AddReferencesForFunc(this, func);
  1292. // Return function id as success
  1293. return func->id;
  1294. }
  1295. int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD flags)
  1296. {
  1297. int r;
  1298. isPrepared = false;
  1299. // Verify flags
  1300. // Must have either asOBJ_REF or asOBJ_VALUE
  1301. if( flags & asOBJ_REF )
  1302. {
  1303. // Can optionally have the asOBJ_GC, asOBJ_NOHANDLE, asOBJ_SCOPED, or asOBJ_TEMPLATE flag set, but nothing else
  1304. if( flags & ~(asOBJ_REF | asOBJ_GC | asOBJ_NOHANDLE | asOBJ_SCOPED | asOBJ_TEMPLATE | asOBJ_NOCOUNT | asOBJ_IMPLICIT_HANDLE) )
  1305. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1306. // flags are exclusive
  1307. if( (flags & asOBJ_GC) && (flags & (asOBJ_NOHANDLE|asOBJ_SCOPED|asOBJ_NOCOUNT)) )
  1308. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1309. if( (flags & asOBJ_NOHANDLE) && (flags & (asOBJ_GC|asOBJ_SCOPED|asOBJ_NOCOUNT|asOBJ_IMPLICIT_HANDLE)) )
  1310. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1311. if( (flags & asOBJ_SCOPED) && (flags & (asOBJ_GC|asOBJ_NOHANDLE|asOBJ_NOCOUNT|asOBJ_IMPLICIT_HANDLE)) )
  1312. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1313. if( (flags & asOBJ_NOCOUNT) && (flags & (asOBJ_GC|asOBJ_NOHANDLE|asOBJ_SCOPED)) )
  1314. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1315. // Implicit handle is only allowed if the engine property for this is turned on
  1316. if( !ep.allowImplicitHandleTypes && (flags & asOBJ_IMPLICIT_HANDLE) )
  1317. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1318. }
  1319. else if( flags & asOBJ_VALUE )
  1320. {
  1321. // Cannot use reference flags
  1322. if( flags & (asOBJ_REF | asOBJ_GC | asOBJ_NOHANDLE | asOBJ_SCOPED | asOBJ_NOCOUNT | asOBJ_IMPLICIT_HANDLE) )
  1323. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1324. // Flags are exclusive
  1325. if( (flags & asOBJ_POD) && (flags & (asOBJ_ASHANDLE | asOBJ_TEMPLATE)) )
  1326. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1327. // If the app type is given, we must validate the flags
  1328. if( flags & asOBJ_APP_CLASS )
  1329. {
  1330. // Must not set the primitive or float flag
  1331. if( flags & (asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT | asOBJ_APP_ARRAY) )
  1332. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1333. }
  1334. else
  1335. {
  1336. // Must not set the class properties, without the class flag
  1337. if( flags & (asOBJ_APP_CLASS_CONSTRUCTOR |
  1338. asOBJ_APP_CLASS_DESTRUCTOR |
  1339. asOBJ_APP_CLASS_ASSIGNMENT |
  1340. asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
  1341. asOBJ_APP_CLASS_ALLINTS |
  1342. asOBJ_APP_CLASS_ALLFLOATS) )
  1343. {
  1344. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1345. }
  1346. }
  1347. if( flags & asOBJ_APP_PRIMITIVE )
  1348. {
  1349. if( flags & (asOBJ_APP_CLASS |
  1350. asOBJ_APP_FLOAT |
  1351. asOBJ_APP_ARRAY) )
  1352. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1353. }
  1354. else if( flags & asOBJ_APP_FLOAT )
  1355. {
  1356. if( flags & (asOBJ_APP_CLASS |
  1357. asOBJ_APP_PRIMITIVE |
  1358. asOBJ_APP_ARRAY) )
  1359. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1360. }
  1361. else if( flags & asOBJ_APP_ARRAY )
  1362. {
  1363. if( flags & (asOBJ_APP_CLASS |
  1364. asOBJ_APP_PRIMITIVE |
  1365. asOBJ_APP_FLOAT) )
  1366. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1367. }
  1368. }
  1369. else
  1370. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1371. // Don't allow anything else than the defined flags
  1372. #ifndef WIP_16BYTE_ALIGN
  1373. if( flags - (flags & asOBJ_MASK_VALID_FLAGS) )
  1374. #else
  1375. if( flags - (flags & (asOBJ_MASK_VALID_FLAGS | asOBJ_APP_ALIGN16)) )
  1376. #endif
  1377. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1378. // Value types must have a defined size
  1379. if( (flags & asOBJ_VALUE) && byteSize == 0 )
  1380. {
  1381. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_VALUE_TYPE_MUST_HAVE_SIZE);
  1382. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1383. }
  1384. // Verify type name
  1385. if( name == 0 )
  1386. return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0);
  1387. asCString typeName;
  1388. asCBuilder bld(this, 0);
  1389. if( flags & asOBJ_TEMPLATE )
  1390. {
  1391. asCArray<asCString> subtypeNames;
  1392. r = bld.ParseTemplateDecl(name, &typeName, subtypeNames);
  1393. if( r < 0 )
  1394. return ConfigError(r, "RegisterObjectType", name, 0);
  1395. // Verify that the template name hasn't been registered as a type already
  1396. if( GetRegisteredObjectType(typeName, defaultNamespace) )
  1397. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1398. return asALREADY_REGISTERED;
  1399. asCObjectType *type = asNEW(asCObjectType)(this);
  1400. if( type == 0 )
  1401. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1402. type->name = typeName;
  1403. type->nameSpace = defaultNamespace;
  1404. type->size = byteSize;
  1405. #ifdef WIP_16BYTE_ALIGN
  1406. // TODO: Types smaller than 4 don't need to be aligned to 4 byte boundaries
  1407. type->alignment = (flags & asOBJ_APP_ALIGN16) ? 16 : 4;
  1408. #endif
  1409. type->flags = flags;
  1410. type->accessMask = defaultAccessMask;
  1411. // Store it in the object types
  1412. allRegisteredTypes.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1413. currentGroup->objTypes.PushLast(type);
  1414. registeredObjTypes.PushLast(type);
  1415. registeredTemplateTypes.PushLast(type);
  1416. // Define the template subtypes
  1417. for( asUINT subTypeIdx = 0; subTypeIdx < subtypeNames.GetLength(); subTypeIdx++ )
  1418. {
  1419. asCObjectType *subtype = 0;
  1420. for( asUINT n = 0; n < templateSubTypes.GetLength(); n++ )
  1421. {
  1422. if( templateSubTypes[n]->name == subtypeNames[subTypeIdx] )
  1423. {
  1424. subtype = templateSubTypes[n];
  1425. break;
  1426. }
  1427. }
  1428. if( subtype == 0 )
  1429. {
  1430. // Create the new subtype if not already existing
  1431. subtype = asNEW(asCObjectType)(this);
  1432. if( subtype == 0 )
  1433. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1434. subtype->name = subtypeNames[subTypeIdx];
  1435. subtype->size = 0;
  1436. #ifdef WIP_16BYTE_ALIGN
  1437. type->alignment = 0; // template subtypes cannot be instantiated and don't need alignment
  1438. #endif
  1439. subtype->flags = asOBJ_TEMPLATE_SUBTYPE;
  1440. templateSubTypes.PushLast(subtype);
  1441. }
  1442. type->templateSubTypes.PushLast(asCDataType::CreateObject(subtype, false));
  1443. subtype->AddRefInternal();
  1444. }
  1445. }
  1446. else
  1447. {
  1448. typeName = name;
  1449. // Verify if the name has been registered as a type already
  1450. if( GetRegisteredObjectType(typeName, defaultNamespace) )
  1451. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1452. return asALREADY_REGISTERED;
  1453. // TODO: clean up: Is it really necessary to check here?
  1454. for( asUINT n = 0; n < templateInstanceTypes.GetLength(); n++ )
  1455. {
  1456. if( templateInstanceTypes[n] &&
  1457. templateInstanceTypes[n]->name == typeName &&
  1458. templateInstanceTypes[n]->nameSpace == defaultNamespace )
  1459. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1460. return asALREADY_REGISTERED;
  1461. }
  1462. // Keep the most recent template generated instance type, so we know what it was before parsing the datatype
  1463. asCObjectType *mostRecentTemplateInstanceType = 0;
  1464. asUINT originalSizeOfGeneratedTemplateTypes = (asUINT)generatedTemplateTypes.GetLength();
  1465. if( originalSizeOfGeneratedTemplateTypes )
  1466. mostRecentTemplateInstanceType = generatedTemplateTypes[originalSizeOfGeneratedTemplateTypes-1];
  1467. // Use builder to parse the datatype
  1468. asCDataType dt;
  1469. bool oldMsgCallback = msgCallback; msgCallback = false;
  1470. r = bld.ParseDataType(name, &dt, defaultNamespace);
  1471. msgCallback = oldMsgCallback;
  1472. // If the builder fails or the namespace is different than the default
  1473. // namespace, then the type name is new and it should be registered
  1474. if( r < 0 || dt.GetObjectType()->nameSpace != defaultNamespace )
  1475. {
  1476. // Make sure the name is not a reserved keyword
  1477. size_t tokenLen;
  1478. int token = tok.GetToken(name, typeName.GetLength(), &tokenLen);
  1479. if( token != ttIdentifier || typeName.GetLength() != tokenLen )
  1480. return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0);
  1481. int r = bld.CheckNameConflict(name, 0, 0, defaultNamespace);
  1482. if( r < 0 )
  1483. return ConfigError(asNAME_TAKEN, "RegisterObjectType", name, 0);
  1484. // Don't have to check against members of object
  1485. // types as they are allowed to use the names
  1486. // Put the data type in the list
  1487. asCObjectType *type = asNEW(asCObjectType)(this);
  1488. if( type == 0 )
  1489. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1490. type->name = typeName;
  1491. type->nameSpace = defaultNamespace;
  1492. type->size = byteSize;
  1493. #ifdef WIP_16BYTE_ALIGN
  1494. // TODO: Types smaller than 4 don't need to be aligned to 4 byte boundaries
  1495. type->alignment = (flags & asOBJ_APP_ALIGN16) ? 16 : 4;
  1496. #endif
  1497. type->flags = flags;
  1498. type->accessMask = defaultAccessMask;
  1499. allRegisteredTypes.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1500. registeredObjTypes.PushLast(type);
  1501. currentGroup->objTypes.PushLast(type);
  1502. }
  1503. else
  1504. {
  1505. // The application is registering a template specialization so we
  1506. // need to replace the template instance type with the new type.
  1507. // TODO: Template: We don't require the lower dimensions to be registered first for registered template types
  1508. // int[][] must not be allowed to be registered
  1509. // if int[] hasn't been registered first
  1510. if( dt.GetSubType().IsTemplate() )
  1511. return ConfigError(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED, "RegisterObjectType", name, 0);
  1512. if( dt.IsReadOnly() ||
  1513. dt.IsReference() )
  1514. return ConfigError(asINVALID_TYPE, "RegisterObjectType", name, 0);
  1515. // Was the template instance type generated before?
  1516. if( generatedTemplateTypes.Exists(dt.GetObjectType()) &&
  1517. generatedTemplateTypes[generatedTemplateTypes.GetLength()-1] == mostRecentTemplateInstanceType )
  1518. {
  1519. asCString str;
  1520. str.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, typeName.AddressOf());
  1521. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1522. return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0);
  1523. }
  1524. // If this is not a generated template instance type, then it means it is an
  1525. // already registered template specialization
  1526. if( !generatedTemplateTypes.Exists(dt.GetObjectType()) )
  1527. return ConfigError(asALREADY_REGISTERED, "RegisterObjectType", name, 0);
  1528. // TODO: Add this again. The type is used by the factory stubs so we need to discount that
  1529. // Is the template instance type already being used?
  1530. // if( dt.GetObjectType()->GetRefCount() > 1 )
  1531. // return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0);
  1532. // Put the data type in the list
  1533. asCObjectType *type = asNEW(asCObjectType)(this);
  1534. if( type == 0 )
  1535. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1536. type->name = dt.GetObjectType()->name;
  1537. // The namespace will be the same as the original template type
  1538. type->nameSpace = dt.GetObjectType()->nameSpace;
  1539. type->templateSubTypes.PushLast(dt.GetSubType());
  1540. for( asUINT s = 0; s < type->templateSubTypes.GetLength(); s++ )
  1541. if( type->templateSubTypes[s].GetObjectType() )
  1542. type->templateSubTypes[s].GetObjectType()->AddRefInternal();
  1543. type->size = byteSize;
  1544. #ifdef WIP_16BYTE_ALIGN
  1545. // TODO: Types smaller than 4 don't need to be aligned to 4 byte boundaries
  1546. type->alignment = (flags & asOBJ_APP_ALIGN16) ? 16 : 4;
  1547. #endif
  1548. type->flags = flags;
  1549. type->accessMask = defaultAccessMask;
  1550. templateInstanceTypes.PushLast(type);
  1551. currentGroup->objTypes.PushLast(type);
  1552. // Remove the template instance type, which will no longer be used.
  1553. // It is possible that multiple template instances are generated if
  1554. // they have any relationship, so all of them must be removed
  1555. while( generatedTemplateTypes.GetLength() > originalSizeOfGeneratedTemplateTypes )
  1556. RemoveTemplateInstanceType(generatedTemplateTypes[generatedTemplateTypes.GetLength()-1]);
  1557. }
  1558. }
  1559. // Return the type id as the success (except for template types)
  1560. if( flags & asOBJ_TEMPLATE )
  1561. return asSUCCESS;
  1562. return GetTypeIdByDecl(name);
  1563. }
  1564. // interface
  1565. int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall)
  1566. {
  1567. if( datatype == 0 ) return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", datatype, decl);
  1568. // Determine the object type
  1569. asCBuilder bld(this, 0);
  1570. asCDataType type;
  1571. int r = bld.ParseDataType(datatype, &type, defaultNamespace);
  1572. if( r < 0 )
  1573. return ConfigError(r, "RegisterObjectBehaviour", datatype, decl);
  1574. if( type.GetObjectType() == 0 || type.IsObjectHandle() )
  1575. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1576. // Don't allow application to modify built-in types
  1577. if( type.GetObjectType() == &functionBehaviours ||
  1578. type.GetObjectType() == &scriptTypeBehaviours )
  1579. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1580. if( type.IsReadOnly() || type.IsReference() )
  1581. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1582. // Don't allow modifying generated template instances
  1583. if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(type.GetObjectType()) )
  1584. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1585. return RegisterBehaviourToObjectType(type.GetObjectType(), behaviour, decl, funcPointer, callConv, objForThiscall);
  1586. }
  1587. // internal
  1588. int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall)
  1589. {
  1590. #ifdef AS_MAX_PORTABILITY
  1591. if( callConv != asCALL_GENERIC )
  1592. return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1593. #endif
  1594. asSSystemFunctionInterface internal;
  1595. bool isMethod = !(behaviour == asBEHAVE_FACTORY ||
  1596. behaviour == asBEHAVE_LIST_FACTORY ||
  1597. behaviour == asBEHAVE_TEMPLATE_CALLBACK);
  1598. int r = DetectCallingConvention(isMethod, funcPointer, callConv, objForThiscall, &internal);
  1599. if( r < 0 )
  1600. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1601. // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType
  1602. // If the object type is a template, make sure there are no generated instances already
  1603. if( objectType->flags & asOBJ_TEMPLATE )
  1604. {
  1605. for( asUINT n = 0; n < generatedTemplateTypes.GetLength(); n++ )
  1606. {
  1607. asCObjectType *tmpl = generatedTemplateTypes[n];
  1608. if( tmpl->name == objectType->name &&
  1609. tmpl->nameSpace == objectType->nameSpace &&
  1610. !(tmpl->templateSubTypes[0].GetObjectType() && (tmpl->templateSubTypes[0].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE)) )
  1611. {
  1612. asCString msg;
  1613. msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateObject(tmpl, false).Format(tmpl->nameSpace).AddressOf());
  1614. WriteMessage("",0,0, asMSGTYPE_ERROR, msg.AddressOf());
  1615. return ConfigError(asERROR, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1616. }
  1617. }
  1618. }
  1619. isPrepared = false;
  1620. asSTypeBehaviour *beh = &objectType->beh;
  1621. // Verify function declaration
  1622. asCScriptFunction func(this, 0, asFUNC_DUMMY);
  1623. bool expectListPattern = behaviour == asBEHAVE_LIST_FACTORY || behaviour == asBEHAVE_LIST_CONSTRUCT;
  1624. asCScriptNode *listPattern = 0;
  1625. asCBuilder bld(this, 0);
  1626. r = bld.ParseFunctionDeclaration(objectType, decl, &func, true, &internal.paramAutoHandles, &internal.returnAutoHandle, 0, expectListPattern ? &listPattern : 0);
  1627. if( r < 0 )
  1628. {
  1629. if( listPattern )
  1630. listPattern->Destroy(this);
  1631. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1632. }
  1633. func.name.Format("$beh%d", behaviour);
  1634. if( behaviour != asBEHAVE_FACTORY && behaviour != asBEHAVE_LIST_FACTORY )
  1635. {
  1636. func.objectType = objectType;
  1637. func.objectType->AddRefInternal();
  1638. }
  1639. // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType
  1640. // Check if the method restricts that use of the template to value types or reference types
  1641. if( objectType->flags & asOBJ_TEMPLATE )
  1642. {
  1643. for( asUINT subTypeIdx = 0; subTypeIdx < objectType->templateSubTypes.GetLength(); subTypeIdx++ )
  1644. {
  1645. if( func.returnType.GetObjectType() == objectType->templateSubTypes[subTypeIdx].GetObjectType() )
  1646. {
  1647. if( func.returnType.IsObjectHandle() )
  1648. objectType->acceptValueSubType = false;
  1649. else if( !func.returnType.IsReference() )
  1650. objectType->acceptRefSubType = false;
  1651. // Can't support template subtypes by value, since each type is treated differently in the ABI
  1652. if( !func.returnType.IsObjectHandle() && !func.returnType.IsReference() )
  1653. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), decl);
  1654. }
  1655. for( asUINT n = 0; n < func.parameterTypes.GetLength(); n++ )
  1656. {
  1657. if( func.parameterTypes[n].GetObjectType() == objectType->templateSubTypes[subTypeIdx].GetObjectType() )
  1658. {
  1659. // TODO: If unsafe references are allowed, then inout references allow value types
  1660. if( func.parameterTypes[n].IsObjectHandle() || (func.parameterTypes[n].IsReference() && func.inOutFlags[n] == asTM_INOUTREF) )
  1661. objectType->acceptValueSubType = false;
  1662. else if( !func.parameterTypes[n].IsReference() )
  1663. objectType->acceptRefSubType = false;
  1664. // Can't support template subtypes by value, since each type is treated differently in the ABI
  1665. if( !func.parameterTypes[n].IsObjectHandle() && !func.parameterTypes[n].IsReference() )
  1666. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), decl);
  1667. }
  1668. }
  1669. }
  1670. }
  1671. if( behaviour == asBEHAVE_CONSTRUCT )
  1672. {
  1673. // Verify that the return type is void
  1674. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1675. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1676. if( objectType->flags & asOBJ_SCRIPT_OBJECT )
  1677. {
  1678. // The script object is a special case
  1679. asASSERT(func.parameterTypes.GetLength() == 1);
  1680. beh->construct = AddBehaviourFunction(func, internal);
  1681. beh->factory = beh->construct;
  1682. scriptFunctions[beh->factory]->AddRefInternal();
  1683. beh->constructors.PushLast(beh->construct);
  1684. beh->factories.PushLast(beh->factory);
  1685. func.id = beh->construct;
  1686. }
  1687. else
  1688. {
  1689. // Verify that it is a value type
  1690. if( !(func.objectType->flags & asOBJ_VALUE) )
  1691. {
  1692. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1693. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1694. }
  1695. // The templates take a hidden parameter with the object type
  1696. if( (objectType->flags & asOBJ_TEMPLATE) &&
  1697. (func.parameterTypes.GetLength() == 0 ||
  1698. !func.parameterTypes[0].IsReference()) )
  1699. {
  1700. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_FIRST_PARAM_MUST_BE_REF_FOR_TEMPLATE_FACTORY);
  1701. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1702. }
  1703. // TODO: Verify that the same constructor hasn't been registered already
  1704. // Store all constructors in a list
  1705. func.id = AddBehaviourFunction(func, internal);
  1706. beh->constructors.PushLast(func.id);
  1707. if( func.parameterTypes.GetLength() == 0 ||
  1708. (func.parameterTypes.GetLength() == 1 && (objectType->flags & asOBJ_TEMPLATE)) )
  1709. {
  1710. beh->construct = func.id;
  1711. }
  1712. else if( func.parameterTypes.GetLength() == 1 )
  1713. {
  1714. // Is this the copy constructor?
  1715. asCDataType paramType = func.parameterTypes[0];
  1716. // If the parameter is object, and const reference for input or inout,
  1717. // and same type as this class, then this is a copy constructor.
  1718. if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() &&
  1719. (func.inOutFlags[0] & asTM_INREF) && paramType.GetObjectType() == objectType )
  1720. beh->copyconstruct = func.id;
  1721. }
  1722. }
  1723. }
  1724. else if( behaviour == asBEHAVE_DESTRUCT )
  1725. {
  1726. // Must be a value type
  1727. if( !(func.objectType->flags & asOBJ_VALUE) )
  1728. {
  1729. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1730. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1731. }
  1732. if( beh->destruct )
  1733. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1734. // Verify that the return type is void
  1735. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1736. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1737. // Verify that there are no parameters
  1738. if( func.parameterTypes.GetLength() > 0 )
  1739. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1740. func.id = beh->destruct = AddBehaviourFunction(func, internal);
  1741. }
  1742. else if( behaviour == asBEHAVE_LIST_CONSTRUCT )
  1743. {
  1744. // Verify that the return type is void
  1745. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1746. {
  1747. if( listPattern )
  1748. listPattern->Destroy(this);
  1749. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1750. }
  1751. // Verify that it is a value type
  1752. if( !(func.objectType->flags & asOBJ_VALUE) )
  1753. {
  1754. if( listPattern )
  1755. listPattern->Destroy(this);
  1756. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1757. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1758. }
  1759. // Verify the parameters
  1760. if( func.parameterTypes.GetLength() != 1 || !func.parameterTypes[0].IsReference() )
  1761. {
  1762. if( listPattern )
  1763. listPattern->Destroy(this);
  1764. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM);
  1765. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1766. }
  1767. // Don't accept duplicates
  1768. if( beh->listFactory )
  1769. {
  1770. if( listPattern )
  1771. listPattern->Destroy(this);
  1772. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1773. }
  1774. // Add the function
  1775. func.id = AddBehaviourFunction(func, internal);
  1776. // Re-use the listFactory member, as it is not possible to have both anyway
  1777. beh->listFactory = func.id;
  1778. // Store the list pattern for this function
  1779. int r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern);
  1780. if( listPattern )
  1781. listPattern->Destroy(this);
  1782. if( r < 0 )
  1783. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1784. }
  1785. else if( behaviour == asBEHAVE_FACTORY || behaviour == asBEHAVE_LIST_FACTORY )
  1786. {
  1787. // Must be a ref type and must not have asOBJ_NOHANDLE
  1788. if( !(objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_NOHANDLE) )
  1789. {
  1790. if( listPattern )
  1791. listPattern->Destroy(this);
  1792. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1793. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1794. }
  1795. // Verify that the return type is a handle to the type
  1796. if( func.returnType != asCDataType::CreateObjectHandle(objectType, false) )
  1797. {
  1798. if( listPattern )
  1799. listPattern->Destroy(this);
  1800. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1801. }
  1802. // The templates take a hidden parameter with the object type
  1803. if( (objectType->flags & asOBJ_TEMPLATE) &&
  1804. (func.parameterTypes.GetLength() == 0 ||
  1805. !func.parameterTypes[0].IsReference()) )
  1806. {
  1807. if( listPattern )
  1808. listPattern->Destroy(this);
  1809. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_FIRST_PARAM_MUST_BE_REF_FOR_TEMPLATE_FACTORY);
  1810. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1811. }
  1812. if( behaviour == asBEHAVE_LIST_FACTORY )
  1813. {
  1814. // Make sure the factory takes a reference as its last parameter
  1815. if( objectType->flags & asOBJ_TEMPLATE )
  1816. {
  1817. if( func.parameterTypes.GetLength() != 2 || !func.parameterTypes[1].IsReference() )
  1818. {
  1819. if( listPattern )
  1820. listPattern->Destroy(this);
  1821. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_TEMPLATE_LIST_FACTORY_EXPECTS_2_REF_PARAMS);
  1822. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1823. }
  1824. }
  1825. else
  1826. {
  1827. if( func.parameterTypes.GetLength() != 1 || !func.parameterTypes[0].IsReference() )
  1828. {
  1829. if( listPattern )
  1830. listPattern->Destroy(this);
  1831. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM);
  1832. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1833. }
  1834. }
  1835. }
  1836. // TODO: Verify that the same factory function hasn't been registered already
  1837. // Don't accept duplicates
  1838. if( behaviour == asBEHAVE_LIST_FACTORY && beh->listFactory )
  1839. {
  1840. if( listPattern )
  1841. listPattern->Destroy(this);
  1842. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1843. }
  1844. // Store all factory functions in a list
  1845. func.id = AddBehaviourFunction(func, internal);
  1846. // The list factory is a special factory and isn't stored together with the rest
  1847. if( behaviour != asBEHAVE_LIST_FACTORY )
  1848. beh->factories.PushLast(func.id);
  1849. if( (func.parameterTypes.GetLength() == 0) ||
  1850. (func.parameterTypes.GetLength() == 1 && (objectType->flags & asOBJ_TEMPLATE)) )
  1851. {
  1852. beh->factory = func.id;
  1853. }
  1854. else if( (func.parameterTypes.GetLength() == 1) ||
  1855. (func.parameterTypes.GetLength() == 2 && (objectType->flags & asOBJ_TEMPLATE)) )
  1856. {
  1857. if( behaviour == asBEHAVE_LIST_FACTORY )
  1858. {
  1859. beh->listFactory = func.id;
  1860. // Store the list pattern for this function
  1861. int r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern);
  1862. if( listPattern )
  1863. listPattern->Destroy(this);
  1864. if( r < 0 )
  1865. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1866. }
  1867. else
  1868. {
  1869. // Is this the copy factory?
  1870. asCDataType paramType = func.parameterTypes[func.parameterTypes.GetLength()-1];
  1871. // If the parameter is object, and const reference for input,
  1872. // and same type as this class, then this is a copy constructor.
  1873. if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[func.parameterTypes.GetLength()-1] == asTM_INREF && paramType.GetObjectType() == objectType )
  1874. beh->copyfactory = func.id;
  1875. }
  1876. }
  1877. }
  1878. else if( behaviour == asBEHAVE_ADDREF )
  1879. {
  1880. // Must be a ref type and must not have asOBJ_NOHANDLE, nor asOBJ_SCOPED
  1881. if( !(func.objectType->flags & asOBJ_REF) ||
  1882. (func.objectType->flags & asOBJ_NOHANDLE) ||
  1883. (func.objectType->flags & asOBJ_SCOPED) ||
  1884. (func.objectType->flags & asOBJ_NOCOUNT) )
  1885. {
  1886. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1887. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1888. }
  1889. if( beh->addref )
  1890. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1891. // Verify that the return type is void
  1892. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1893. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1894. // Verify that there are no parameters
  1895. if( func.parameterTypes.GetLength() > 0 )
  1896. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1897. func.id = beh->addref = AddBehaviourFunction(func, internal);
  1898. }
  1899. else if( behaviour == asBEHAVE_RELEASE )
  1900. {
  1901. // Must be a ref type and must not have asOBJ_NOHANDLE
  1902. if( !(func.objectType->flags & asOBJ_REF) ||
  1903. (func.objectType->flags & asOBJ_NOHANDLE) ||
  1904. (func.objectType->flags & asOBJ_NOCOUNT) )
  1905. {
  1906. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1907. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1908. }
  1909. if( beh->release )
  1910. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1911. // Verify that the return type is void
  1912. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1913. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1914. // Verify that there are no parameters
  1915. if( func.parameterTypes.GetLength() > 0 )
  1916. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1917. func.id = beh->release = AddBehaviourFunction(func, internal);
  1918. }
  1919. else if( behaviour == asBEHAVE_TEMPLATE_CALLBACK )
  1920. {
  1921. // Must be a template type
  1922. if( !(func.objectType->flags & asOBJ_TEMPLATE) )
  1923. {
  1924. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1925. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1926. }
  1927. if( beh->templateCallback )
  1928. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1929. // Verify that the return type is bool
  1930. if( func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
  1931. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1932. // Verify that there are two parameters
  1933. if( func.parameterTypes.GetLength() != 2 )
  1934. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1935. // The first parameter must be an inref (to receive the object type), and
  1936. // the second must be a bool out ref (to return if the type should or shouldn't be garbage collected)
  1937. if( func.inOutFlags[0] != asTM_INREF || func.inOutFlags[1] != asTM_OUTREF || !func.parameterTypes[1].IsEqualExceptRef(asCDataType::CreatePrimitive(ttBool, false)) )
  1938. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1939. func.id = beh->templateCallback = AddBehaviourFunction(func, internal);
  1940. }
  1941. else if( behaviour >= asBEHAVE_FIRST_GC &&
  1942. behaviour <= asBEHAVE_LAST_GC )
  1943. {
  1944. // Only allow GC behaviours for types registered to be garbage collected
  1945. if( !(func.objectType->flags & asOBJ_GC) )
  1946. {
  1947. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1948. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1949. }
  1950. // Verify parameter count
  1951. if( (behaviour == asBEHAVE_GETREFCOUNT ||
  1952. behaviour == asBEHAVE_SETGCFLAG ||
  1953. behaviour == asBEHAVE_GETGCFLAG) &&
  1954. func.parameterTypes.GetLength() != 0 )
  1955. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1956. if( (behaviour == asBEHAVE_ENUMREFS ||
  1957. behaviour == asBEHAVE_RELEASEREFS) &&
  1958. func.parameterTypes.GetLength() != 1 )
  1959. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1960. // Verify return type
  1961. if( behaviour == asBEHAVE_GETREFCOUNT &&
  1962. func.returnType != asCDataType::CreatePrimitive(ttInt, false) )
  1963. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1964. if( behaviour == asBEHAVE_GETGCFLAG &&
  1965. func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
  1966. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1967. if( (behaviour == asBEHAVE_SETGCFLAG ||
  1968. behaviour == asBEHAVE_ENUMREFS ||
  1969. behaviour == asBEHAVE_RELEASEREFS) &&
  1970. func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1971. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1972. if( behaviour == asBEHAVE_GETREFCOUNT )
  1973. func.id = beh->gcGetRefCount = AddBehaviourFunction(func, internal);
  1974. else if( behaviour == asBEHAVE_SETGCFLAG )
  1975. func.id = beh->gcSetFlag = AddBehaviourFunction(func, internal);
  1976. else if( behaviour == asBEHAVE_GETGCFLAG )
  1977. func.id = beh->gcGetFlag = AddBehaviourFunction(func, internal);
  1978. else if( behaviour == asBEHAVE_ENUMREFS )
  1979. func.id = beh->gcEnumReferences = AddBehaviourFunction(func, internal);
  1980. else if( behaviour == asBEHAVE_RELEASEREFS )
  1981. func.id = beh->gcReleaseAllReferences = AddBehaviourFunction(func, internal);
  1982. }
  1983. #ifdef AS_DEPRECATED
  1984. // Deprecated since 2.30.0. 2014-10-24
  1985. else if( behaviour == asBEHAVE_IMPLICIT_VALUE_CAST ||
  1986. behaviour == asBEHAVE_VALUE_CAST )
  1987. {
  1988. // There are two allowed signatures
  1989. // 1. type f()
  1990. // 2. void f(?&out)
  1991. if( !(func.parameterTypes.GetLength() == 1 && func.parameterTypes[0].GetTokenType() == ttQuestion && func.inOutFlags[0] == asTM_OUTREF && func.returnType.GetTokenType() == ttVoid) &&
  1992. !(func.parameterTypes.GetLength() == 0 && func.returnType.GetTokenType() != ttVoid) )
  1993. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1994. // It is not allowed to implement a value cast to bool
  1995. if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, false)) )
  1996. return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1997. asCString decl;
  1998. decl += func.returnType.Format(defaultNamespace);
  1999. decl += behaviour == asBEHAVE_VALUE_CAST ? " opConv(" : " opImplConv(";
  2000. if( func.parameterTypes.GetLength() )
  2001. decl += "?&out";
  2002. decl += ")";
  2003. func.id = RegisterMethodToObjectType(objectType, decl.AddressOf(), funcPointer, callConv, objForThiscall);
  2004. }
  2005. // Deprecated since 2.30.0, 2014-12-30
  2006. else if( behaviour == asBEHAVE_REF_CAST ||
  2007. behaviour == asBEHAVE_IMPLICIT_REF_CAST )
  2008. {
  2009. // There are two allowed signatures
  2010. // 1. obj @f()
  2011. // 2. void f(?&out)
  2012. if( !(func.parameterTypes.GetLength() == 0 && func.returnType.IsObjectHandle()) &&
  2013. !(func.parameterTypes.GetLength() == 1 && func.parameterTypes[0].GetTokenType() == ttQuestion && func.inOutFlags[0] == asTM_OUTREF && func.returnType.GetTokenType() == ttVoid) )
  2014. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2015. // Currently it is not supported to register const overloads for the ref cast behaviour
  2016. if( func.IsReadOnly() )
  2017. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2018. asCString decl;
  2019. decl += func.returnType.Format(defaultNamespace);
  2020. if( internal.returnAutoHandle )
  2021. decl += "+";
  2022. decl += behaviour == asBEHAVE_REF_CAST ? " opCast(" : " opImplCast(";
  2023. if( func.parameterTypes.GetLength() )
  2024. decl += "?&out";
  2025. decl += ")";
  2026. func.id = RegisterMethodToObjectType(objectType, decl.AddressOf(), funcPointer, callConv, objForThiscall);
  2027. }
  2028. #endif
  2029. else if ( behaviour == asBEHAVE_GET_WEAKREF_FLAG )
  2030. {
  2031. // This behaviour is only allowed for reference types
  2032. if( !(func.objectType->flags & asOBJ_REF) )
  2033. {
  2034. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  2035. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2036. }
  2037. // Don't allow it if the type is registered with nohandle or scoped
  2038. if( func.objectType->flags & (asOBJ_NOHANDLE|asOBJ_SCOPED) )
  2039. {
  2040. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  2041. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2042. }
  2043. // Verify that the return type is a reference since it needs to return a pointer to an asISharedBool
  2044. if( !func.returnType.IsReference() )
  2045. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2046. // Verify that there are no parameters
  2047. if( func.parameterTypes.GetLength() != 0 )
  2048. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2049. if( beh->getWeakRefFlag )
  2050. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2051. func.id = beh->getWeakRefFlag = AddBehaviourFunction(func, internal);
  2052. }
  2053. else
  2054. {
  2055. asASSERT(false);
  2056. return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2057. }
  2058. if( func.id < 0 )
  2059. return ConfigError(func.id, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  2060. // Return function id as success
  2061. return func.id;
  2062. }
  2063. int asCScriptEngine::VerifyVarTypeNotInFunction(asCScriptFunction *func)
  2064. {
  2065. // Don't allow var type in this function
  2066. if( func->returnType.GetTokenType() == ttQuestion )
  2067. return asINVALID_DECLARATION;
  2068. for( unsigned int n = 0; n < func->parameterTypes.GetLength(); n++ )
  2069. if( func->parameterTypes[n].GetTokenType() == ttQuestion )
  2070. return asINVALID_DECLARATION;
  2071. return 0;
  2072. }
  2073. int asCScriptEngine::AddBehaviourFunction(asCScriptFunction &func, asSSystemFunctionInterface &internal)
  2074. {
  2075. asUINT n;
  2076. int id = GetNextScriptFunctionId();
  2077. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2078. if( newInterface == 0 )
  2079. return asOUT_OF_MEMORY;
  2080. asCScriptFunction *f = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2081. if( f == 0 )
  2082. {
  2083. asDELETE(newInterface, asSSystemFunctionInterface);
  2084. return asOUT_OF_MEMORY;
  2085. }
  2086. asASSERT(func.name != "" && func.name != "f");
  2087. f->name = func.name;
  2088. f->sysFuncIntf = newInterface;
  2089. f->returnType = func.returnType;
  2090. f->objectType = func.objectType;
  2091. if( f->objectType )
  2092. f->objectType->AddRefInternal();
  2093. f->id = id;
  2094. f->isReadOnly = func.isReadOnly;
  2095. f->accessMask = defaultAccessMask;
  2096. f->parameterTypes = func.parameterTypes;
  2097. f->inOutFlags = func.inOutFlags;
  2098. for( n = 0; n < func.defaultArgs.GetLength(); n++ )
  2099. if( func.defaultArgs[n] )
  2100. f->defaultArgs.PushLast(asNEW(asCString)(*func.defaultArgs[n]));
  2101. else
  2102. f->defaultArgs.PushLast(0);
  2103. AddScriptFunction(f);
  2104. // If parameter type from other groups are used, add references
  2105. currentGroup->AddReferencesForFunc(this, f);
  2106. return id;
  2107. }
  2108. // interface
  2109. int asCScriptEngine::RegisterGlobalProperty(const char *declaration, void *pointer)
  2110. {
  2111. // Don't accept a null pointer
  2112. if( pointer == 0 )
  2113. return ConfigError(asINVALID_ARG, "RegisterGlobalProperty", declaration, 0);
  2114. asCDataType type;
  2115. asCString name;
  2116. int r;
  2117. asCBuilder bld(this, 0);
  2118. if( (r = bld.VerifyProperty(0, declaration, name, type, defaultNamespace)) < 0 )
  2119. return ConfigError(r, "RegisterGlobalProperty", declaration, 0);
  2120. // Don't allow registering references as global properties
  2121. if( type.IsReference() )
  2122. return ConfigError(asINVALID_TYPE, "RegisterGlobalProperty", declaration, 0);
  2123. // Store the property info
  2124. asCGlobalProperty *prop = AllocateGlobalProperty();
  2125. prop->name = name;
  2126. prop->nameSpace = defaultNamespace;
  2127. prop->type = type;
  2128. prop->accessMask = defaultAccessMask;
  2129. prop->SetRegisteredAddress(pointer);
  2130. varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  2131. registeredGlobalProps.Put(prop);
  2132. prop->AddRef();
  2133. currentGroup->globalProps.PushLast(prop);
  2134. currentGroup->AddReferencesForType(this, type.GetObjectType());
  2135. return asSUCCESS;
  2136. }
  2137. // internal
  2138. asCGlobalProperty *asCScriptEngine::AllocateGlobalProperty()
  2139. {
  2140. asCGlobalProperty *prop = asNEW(asCGlobalProperty);
  2141. if( prop == 0 )
  2142. {
  2143. // Out of memory
  2144. return 0;
  2145. }
  2146. // First check the availability of a free slot
  2147. if( freeGlobalPropertyIds.GetLength() )
  2148. {
  2149. prop->id = freeGlobalPropertyIds.PopLast();
  2150. globalProperties[prop->id] = prop;
  2151. return prop;
  2152. }
  2153. prop->id = (asUINT)globalProperties.GetLength();
  2154. globalProperties.PushLast(prop);
  2155. return prop;
  2156. }
  2157. // internal
  2158. void asCScriptEngine::RemoveGlobalProperty(asCGlobalProperty *prop)
  2159. {
  2160. int index = globalProperties.IndexOf(prop);
  2161. if( index >= 0 )
  2162. {
  2163. freeGlobalPropertyIds.PushLast(index);
  2164. globalProperties[index] = 0;
  2165. asSMapNode<void*, asCGlobalProperty*> *node;
  2166. varAddressMap.MoveTo(&node, prop->GetAddressOfValue());
  2167. asASSERT(node);
  2168. if( node )
  2169. varAddressMap.Erase(node);
  2170. prop->Release();
  2171. }
  2172. }
  2173. // interface
  2174. asUINT asCScriptEngine::GetGlobalPropertyCount() const
  2175. {
  2176. return asUINT(registeredGlobalProps.GetSize());
  2177. }
  2178. // interface
  2179. // TODO: If the typeId ever encodes the const flag, then the isConst parameter should be removed
  2180. int asCScriptEngine::GetGlobalPropertyByIndex(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst, const char **configGroup, void **pointer, asDWORD *accessMask) const
  2181. {
  2182. const asCGlobalProperty *prop = registeredGlobalProps.Get(index);
  2183. if( !prop )
  2184. return asINVALID_ARG;
  2185. if( name ) *name = prop->name.AddressOf();
  2186. if( nameSpace ) *nameSpace = prop->nameSpace->name.AddressOf();
  2187. if( typeId ) *typeId = GetTypeIdFromDataType(prop->type);
  2188. if( isConst ) *isConst = prop->type.IsReadOnly();
  2189. if( pointer ) *pointer = prop->GetRegisteredAddress();
  2190. if( accessMask ) *accessMask = prop->accessMask;
  2191. if( configGroup )
  2192. {
  2193. asCConfigGroup *group = FindConfigGroupForGlobalVar(index);
  2194. if( group )
  2195. *configGroup = group->groupName.AddressOf();
  2196. else
  2197. *configGroup = 0;
  2198. }
  2199. return asSUCCESS;
  2200. }
  2201. // interface
  2202. int asCScriptEngine::GetGlobalPropertyIndexByName(const char *name) const
  2203. {
  2204. asSNameSpace *ns = defaultNamespace;
  2205. // Find the global var id
  2206. while( ns )
  2207. {
  2208. int id = registeredGlobalProps.GetFirstIndex(ns, name);
  2209. if( id >= 0 )
  2210. return id;
  2211. // Recursively search parent namespace
  2212. ns = GetParentNameSpace(ns);
  2213. }
  2214. return asNO_GLOBAL_VAR;
  2215. }
  2216. // interface
  2217. int asCScriptEngine::GetGlobalPropertyIndexByDecl(const char *decl) const
  2218. {
  2219. // This const cast is OK. The builder won't modify the engine
  2220. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  2221. // Don't write parser errors to the message callback
  2222. bld.silent = true;
  2223. asCString name;
  2224. asSNameSpace *ns;
  2225. asCDataType dt;
  2226. int r = bld.ParseVariableDeclaration(decl, defaultNamespace, name, ns, dt);
  2227. if( r < 0 )
  2228. return r;
  2229. // Search for a match
  2230. while( ns )
  2231. {
  2232. int id = registeredGlobalProps.GetFirstIndex(ns, name, asCCompGlobPropType(dt));
  2233. if( id >= 0 )
  2234. return id;
  2235. ns = GetParentNameSpace(ns);
  2236. }
  2237. return asNO_GLOBAL_VAR;
  2238. }
  2239. // interface
  2240. int asCScriptEngine::RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall)
  2241. {
  2242. if( obj == 0 )
  2243. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  2244. // Determine the object type
  2245. asCDataType dt;
  2246. asCBuilder bld(this, 0);
  2247. int r = bld.ParseDataType(obj, &dt, defaultNamespace);
  2248. if( r < 0 )
  2249. return ConfigError(r, "RegisterObjectMethod", obj, declaration);
  2250. if( dt.GetObjectType() == 0 || dt.IsObjectHandle() )
  2251. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  2252. // Don't allow application to modify built-in types
  2253. if( dt.GetObjectType() == &functionBehaviours ||
  2254. dt.GetObjectType() == &scriptTypeBehaviours )
  2255. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  2256. // Don't allow modifying generated template instances
  2257. if( dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_TEMPLATE) && generatedTemplateTypes.Exists(dt.GetObjectType()) )
  2258. return ConfigError(asINVALID_TYPE, "RegisterObjectMethod", obj, declaration);
  2259. return RegisterMethodToObjectType(dt.GetObjectType(), declaration, funcPointer, callConv, objForThiscall);
  2260. }
  2261. // internal
  2262. int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall)
  2263. {
  2264. #ifdef AS_MAX_PORTABILITY
  2265. if( callConv != asCALL_GENERIC )
  2266. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2267. #endif
  2268. asSSystemFunctionInterface internal;
  2269. int r = DetectCallingConvention(true, funcPointer, callConv, objForThiscall, &internal);
  2270. if( r < 0 )
  2271. return ConfigError(r, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2272. // TODO: cleanup: This is identical to what is in RegisterMethodToObjectType
  2273. // If the object type is a template, make sure there are no generated instances already
  2274. if( objectType->flags & asOBJ_TEMPLATE )
  2275. {
  2276. for( asUINT n = 0; n < generatedTemplateTypes.GetLength(); n++ )
  2277. {
  2278. asCObjectType *tmpl = generatedTemplateTypes[n];
  2279. if( tmpl->name == objectType->name &&
  2280. tmpl->nameSpace == objectType->nameSpace &&
  2281. !(tmpl->templateSubTypes[0].GetObjectType() && (tmpl->templateSubTypes[0].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE)) )
  2282. {
  2283. asCString msg;
  2284. msg.Format(TXT_TEMPLATE_s_ALREADY_GENERATED_CANT_REGISTER, asCDataType::CreateObject(tmpl, false).Format(tmpl->nameSpace).AddressOf());
  2285. WriteMessage("",0,0, asMSGTYPE_ERROR, msg.AddressOf());
  2286. return ConfigError(asERROR, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2287. }
  2288. }
  2289. }
  2290. isPrepared = false;
  2291. // Put the system function in the list of system functions
  2292. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2293. if( newInterface == 0 )
  2294. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2295. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2296. if( func == 0 )
  2297. {
  2298. asDELETE(newInterface, asSSystemFunctionInterface);
  2299. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2300. }
  2301. func->sysFuncIntf = newInterface;
  2302. func->objectType = objectType;
  2303. func->objectType->AddRefInternal();
  2304. asCBuilder bld(this, 0);
  2305. r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle);
  2306. if( r < 0 )
  2307. {
  2308. // Set as dummy function before deleting
  2309. func->funcType = asFUNC_DUMMY;
  2310. asDELETE(func,asCScriptFunction);
  2311. return ConfigError(asINVALID_DECLARATION, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2312. }
  2313. // Check name conflicts
  2314. r = bld.CheckNameConflictMember(objectType, func->name.AddressOf(), 0, 0, false);
  2315. if( r < 0 )
  2316. {
  2317. func->funcType = asFUNC_DUMMY;
  2318. asDELETE(func,asCScriptFunction);
  2319. return ConfigError(asNAME_TAKEN, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2320. }
  2321. // Check against duplicate methods
  2322. asUINT n;
  2323. if( func->name == "opConv" || func->name == "opImplConv" || func->name == "opCast" || func->name == "opImplCast" )
  2324. {
  2325. // opConv and opCast are special methods that the compiler differentiates between by the return type
  2326. for( n = 0; n < func->objectType->methods.GetLength(); n++ )
  2327. {
  2328. asCScriptFunction *f = scriptFunctions[func->objectType->methods[n]];
  2329. if( f->name == func->name &&
  2330. f->IsSignatureExceptNameEqual(func) )
  2331. {
  2332. func->funcType = asFUNC_DUMMY;
  2333. asDELETE(func,asCScriptFunction);
  2334. return ConfigError(asALREADY_REGISTERED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2335. }
  2336. }
  2337. }
  2338. else
  2339. {
  2340. for( n = 0; n < func->objectType->methods.GetLength(); n++ )
  2341. {
  2342. asCScriptFunction *f = scriptFunctions[func->objectType->methods[n]];
  2343. if( f->name == func->name &&
  2344. f->IsSignatureExceptNameAndReturnTypeEqual(func) )
  2345. {
  2346. func->funcType = asFUNC_DUMMY;
  2347. asDELETE(func,asCScriptFunction);
  2348. return ConfigError(asALREADY_REGISTERED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2349. }
  2350. }
  2351. }
  2352. func->id = GetNextScriptFunctionId();
  2353. func->objectType->methods.PushLast(func->id);
  2354. func->accessMask = defaultAccessMask;
  2355. AddScriptFunction(func);
  2356. // If parameter type from other groups are used, add references
  2357. currentGroup->AddReferencesForFunc(this, func);
  2358. // Check if the method restricts that use of the template to value types or reference types
  2359. if( func->objectType->flags & asOBJ_TEMPLATE )
  2360. {
  2361. for( asUINT subTypeIdx = 0; subTypeIdx < func->objectType->templateSubTypes.GetLength(); subTypeIdx++ )
  2362. {
  2363. if( func->returnType.GetObjectType() == func->objectType->templateSubTypes[subTypeIdx].GetObjectType() )
  2364. {
  2365. if( func->returnType.IsObjectHandle() )
  2366. func->objectType->acceptValueSubType = false;
  2367. else if( !func->returnType.IsReference() )
  2368. func->objectType->acceptRefSubType = false;
  2369. // Can't support template subtypes by value, since each type is treated differently in the ABI
  2370. if( !func->returnType.IsObjectHandle() && !func->returnType.IsReference() )
  2371. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2372. }
  2373. for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
  2374. {
  2375. if( func->parameterTypes[n].GetObjectType() == func->objectType->templateSubTypes[subTypeIdx].GetObjectType() )
  2376. {
  2377. // TODO: If unsafe references are allowed, then inout references allow value types
  2378. if( func->parameterTypes[n].IsObjectHandle() || (func->parameterTypes[n].IsReference() && func->inOutFlags[n] == asTM_INOUTREF) )
  2379. func->objectType->acceptValueSubType = false;
  2380. else if( !func->parameterTypes[n].IsReference() )
  2381. func->objectType->acceptRefSubType = false;
  2382. // Can't support template subtypes by value, since each type is treated differently in the ABI
  2383. if( !func->parameterTypes[n].IsObjectHandle() && !func->parameterTypes[n].IsReference() )
  2384. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2385. }
  2386. }
  2387. }
  2388. }
  2389. // TODO: beh.copy member will be removed, so this is not necessary
  2390. // Is this the default copy behaviour?
  2391. if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 && func->isReadOnly == false &&
  2392. ((objectType->flags & asOBJ_SCRIPT_OBJECT) || func->parameterTypes[0].IsEqualExceptRefAndConst(asCDataType::CreateObject(func->objectType, false))) )
  2393. {
  2394. if( func->objectType->beh.copy != 0 )
  2395. return ConfigError(asALREADY_REGISTERED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  2396. func->objectType->beh.copy = func->id;
  2397. func->AddRefInternal();
  2398. }
  2399. // Return the function id as success
  2400. return func->id;
  2401. }
  2402. // interface
  2403. int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall)
  2404. {
  2405. #ifdef AS_MAX_PORTABILITY
  2406. if( callConv != asCALL_GENERIC )
  2407. return ConfigError(asNOT_SUPPORTED, "RegisterGlobalFunction", declaration, 0);
  2408. #endif
  2409. asSSystemFunctionInterface internal;
  2410. int r = DetectCallingConvention(false, funcPointer, callConv, objForThiscall, &internal);
  2411. if( r < 0 )
  2412. return ConfigError(r, "RegisterGlobalFunction", declaration, 0);
  2413. isPrepared = false;
  2414. // Put the system function in the list of system functions
  2415. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2416. if( newInterface == 0 )
  2417. return ConfigError(asOUT_OF_MEMORY, "RegisterGlobalFunction", declaration, 0);
  2418. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2419. if( func == 0 )
  2420. {
  2421. asDELETE(newInterface, asSSystemFunctionInterface);
  2422. return ConfigError(asOUT_OF_MEMORY, "RegisterGlobalFunction", declaration, 0);
  2423. }
  2424. func->sysFuncIntf = newInterface;
  2425. asCBuilder bld(this, 0);
  2426. r = bld.ParseFunctionDeclaration(0, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle, defaultNamespace);
  2427. if( r < 0 )
  2428. {
  2429. // Set as dummy function before deleting
  2430. func->funcType = asFUNC_DUMMY;
  2431. asDELETE(func,asCScriptFunction);
  2432. return ConfigError(asINVALID_DECLARATION, "RegisterGlobalFunction", declaration, 0);
  2433. }
  2434. // TODO: namespace: What if the declaration defined an explicit namespace?
  2435. func->nameSpace = defaultNamespace;
  2436. // Check name conflicts
  2437. r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace);
  2438. if( r < 0 )
  2439. {
  2440. // Set as dummy function before deleting
  2441. func->funcType = asFUNC_DUMMY;
  2442. asDELETE(func,asCScriptFunction);
  2443. return ConfigError(asNAME_TAKEN, "RegisterGlobalFunction", declaration, 0);
  2444. }
  2445. // Make sure the function is not identical to a previously registered function
  2446. asUINT n;
  2447. const asCArray<unsigned int> &idxs = registeredGlobalFuncs.GetIndexes(func->nameSpace, func->name);
  2448. for( n = 0; n < idxs.GetLength(); n++ )
  2449. {
  2450. asCScriptFunction *f = registeredGlobalFuncs.Get(idxs[n]);
  2451. if( f->IsSignatureExceptNameAndReturnTypeEqual(func) )
  2452. {
  2453. func->funcType = asFUNC_DUMMY;
  2454. asDELETE(func,asCScriptFunction);
  2455. return ConfigError(asALREADY_REGISTERED, "RegisterGlobalFunction", declaration, 0);
  2456. }
  2457. }
  2458. func->id = GetNextScriptFunctionId();
  2459. AddScriptFunction(func);
  2460. currentGroup->scriptFunctions.PushLast(func);
  2461. func->accessMask = defaultAccessMask;
  2462. registeredGlobalFuncs.Put(func);
  2463. // If parameter type from other groups are used, add references
  2464. currentGroup->AddReferencesForFunc(this, func);
  2465. // Return the function id as success
  2466. return func->id;
  2467. }
  2468. // interface
  2469. asUINT asCScriptEngine::GetGlobalFunctionCount() const
  2470. {
  2471. // Don't count the builtin delegate factory
  2472. return asUINT(registeredGlobalFuncs.GetSize()-1);
  2473. }
  2474. // interface
  2475. asIScriptFunction *asCScriptEngine::GetGlobalFunctionByIndex(asUINT index) const
  2476. {
  2477. // Don't count the builtin delegate factory
  2478. index++;
  2479. if( index >= registeredGlobalFuncs.GetSize() )
  2480. return 0;
  2481. return static_cast<asIScriptFunction*>(const_cast<asCScriptFunction*>(registeredGlobalFuncs.Get(index)));
  2482. }
  2483. // interface
  2484. asIScriptFunction *asCScriptEngine::GetGlobalFunctionByDecl(const char *decl) const
  2485. {
  2486. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  2487. // Don't write parser errors to the message callback
  2488. bld.silent = true;
  2489. asCScriptFunction func(const_cast<asCScriptEngine*>(this), 0, asFUNC_DUMMY);
  2490. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  2491. if( r < 0 )
  2492. return 0;
  2493. asSNameSpace *ns = defaultNamespace;
  2494. // Search script functions for matching interface
  2495. while( ns )
  2496. {
  2497. asIScriptFunction *f = 0;
  2498. const asCArray<unsigned int> &idxs = registeredGlobalFuncs.GetIndexes(ns, func.name);
  2499. for( unsigned int n = 0; n < idxs.GetLength(); n++ )
  2500. {
  2501. const asCScriptFunction *funcPtr = registeredGlobalFuncs.Get(idxs[n]);
  2502. if( funcPtr->objectType == 0 &&
  2503. func.returnType == funcPtr->returnType &&
  2504. func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
  2505. )
  2506. {
  2507. bool match = true;
  2508. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  2509. {
  2510. if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
  2511. {
  2512. match = false;
  2513. break;
  2514. }
  2515. }
  2516. if( match )
  2517. {
  2518. if( f == 0 )
  2519. f = const_cast<asCScriptFunction*>(funcPtr);
  2520. else
  2521. // Multiple functions
  2522. return 0;
  2523. }
  2524. }
  2525. }
  2526. if( f )
  2527. return f;
  2528. // Recursively search parent namespaces
  2529. ns = GetParentNameSpace(ns);
  2530. }
  2531. return 0;
  2532. }
  2533. asCObjectType *asCScriptEngine::GetRegisteredObjectType(const asCString &type, asSNameSpace *ns) const
  2534. {
  2535. asSMapNode<asSNameSpaceNamePair, asCObjectType *> *cursor;
  2536. if( allRegisteredTypes.MoveTo(&cursor, asSNameSpaceNamePair(ns, type)) )
  2537. return cursor->value;
  2538. return 0;
  2539. }
  2540. void asCScriptEngine::PrepareEngine()
  2541. {
  2542. if( isPrepared ) return;
  2543. if( configFailed ) return;
  2544. asUINT n;
  2545. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  2546. {
  2547. // Determine the host application interface
  2548. if( scriptFunctions[n] && scriptFunctions[n]->funcType == asFUNC_SYSTEM )
  2549. {
  2550. if( scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_FUNC ||
  2551. scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_METHOD )
  2552. PrepareSystemFunctionGeneric(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
  2553. else
  2554. PrepareSystemFunction(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
  2555. }
  2556. }
  2557. // Validate object type registrations
  2558. for( n = 0; n < registeredObjTypes.GetLength(); n++ )
  2559. {
  2560. asCObjectType *type = registeredObjTypes[n];
  2561. if( type && !(type->flags & asOBJ_SCRIPT_OBJECT) )
  2562. {
  2563. bool missingBehaviour = false;
  2564. const char *infoMsg = 0;
  2565. // Verify that GC types have all behaviours
  2566. if( type->flags & asOBJ_GC )
  2567. {
  2568. if( type->beh.addref == 0 ||
  2569. type->beh.release == 0 ||
  2570. type->beh.gcGetRefCount == 0 ||
  2571. type->beh.gcSetFlag == 0 ||
  2572. type->beh.gcGetFlag == 0 ||
  2573. type->beh.gcEnumReferences == 0 ||
  2574. type->beh.gcReleaseAllReferences == 0 )
  2575. {
  2576. infoMsg = TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR;
  2577. missingBehaviour = true;
  2578. }
  2579. }
  2580. // Verify that scoped ref types have the release behaviour
  2581. else if( type->flags & asOBJ_SCOPED )
  2582. {
  2583. if( type->beh.release == 0 )
  2584. {
  2585. infoMsg = TXT_SCOPE_REQUIRE_REL_BEHAVIOUR;
  2586. missingBehaviour = true;
  2587. }
  2588. }
  2589. // Verify that ref types have add ref and release behaviours
  2590. else if( (type->flags & asOBJ_REF) &&
  2591. !(type->flags & asOBJ_NOHANDLE) &&
  2592. !(type->flags & asOBJ_NOCOUNT) )
  2593. {
  2594. if( type->beh.addref == 0 ||
  2595. type->beh.release == 0 )
  2596. {
  2597. infoMsg = TXT_REF_REQUIRE_ADD_REL_BEHAVIOUR;
  2598. missingBehaviour = true;
  2599. }
  2600. }
  2601. // Verify that non-pod value types have the constructor and destructor registered
  2602. else if( (type->flags & asOBJ_VALUE) &&
  2603. !(type->flags & asOBJ_POD) )
  2604. {
  2605. if( type->beh.construct == 0 ||
  2606. type->beh.destruct == 0 )
  2607. {
  2608. infoMsg = TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR;
  2609. missingBehaviour = true;
  2610. }
  2611. }
  2612. if( missingBehaviour )
  2613. {
  2614. asCString str;
  2615. str.Format(TXT_TYPE_s_IS_MISSING_BEHAVIOURS, type->name.AddressOf());
  2616. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  2617. WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, infoMsg);
  2618. ConfigError(asINVALID_CONFIGURATION, 0, 0, 0);
  2619. }
  2620. }
  2621. }
  2622. isPrepared = true;
  2623. }
  2624. int asCScriptEngine::ConfigError(int err, const char *funcName, const char *arg1, const char *arg2)
  2625. {
  2626. configFailed = true;
  2627. if( funcName )
  2628. {
  2629. asCString str;
  2630. if( arg1 )
  2631. {
  2632. if( arg2 )
  2633. str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_AND_s_d, funcName, arg1, arg2, err);
  2634. else
  2635. str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_d, funcName, arg1, err);
  2636. }
  2637. else
  2638. str.Format(TXT_FAILED_IN_FUNC_s_d, funcName, err);
  2639. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  2640. }
  2641. return err;
  2642. }
  2643. // interface
  2644. int asCScriptEngine::RegisterDefaultArrayType(const char *type)
  2645. {
  2646. asCBuilder bld(this, 0);
  2647. asCDataType dt;
  2648. int r = bld.ParseDataType(type, &dt, defaultNamespace);
  2649. if( r < 0 ) return r;
  2650. if( dt.GetObjectType() == 0 ||
  2651. !(dt.GetObjectType()->GetFlags() & asOBJ_TEMPLATE) )
  2652. return asINVALID_TYPE;
  2653. defaultArrayObjectType = dt.GetObjectType();
  2654. defaultArrayObjectType->AddRefInternal();
  2655. return 0;
  2656. }
  2657. // interface
  2658. int asCScriptEngine::GetDefaultArrayTypeId() const
  2659. {
  2660. if( defaultArrayObjectType )
  2661. return GetTypeIdFromDataType(asCDataType::CreateObject(defaultArrayObjectType, false));
  2662. return asINVALID_TYPE;
  2663. }
  2664. // interface
  2665. int asCScriptEngine::RegisterStringFactory(const char *datatype, const asSFuncPtr &funcPointer, asDWORD callConv, void *objForThiscall)
  2666. {
  2667. asSSystemFunctionInterface internal;
  2668. int r = DetectCallingConvention(false, funcPointer, callConv, objForThiscall, &internal);
  2669. if( r < 0 )
  2670. return ConfigError(r, "RegisterStringFactory", datatype, 0);
  2671. #ifdef AS_MAX_PORTABILITY
  2672. if( callConv != asCALL_GENERIC )
  2673. return ConfigError(asNOT_SUPPORTED, "RegisterStringFactory", datatype, 0);
  2674. #else
  2675. if( callConv != asCALL_CDECL &&
  2676. callConv != asCALL_STDCALL &&
  2677. callConv != asCALL_THISCALL_ASGLOBAL &&
  2678. callConv != asCALL_GENERIC )
  2679. return ConfigError(asNOT_SUPPORTED, "RegisterStringFactory", datatype, 0);
  2680. #endif
  2681. // Put the system function in the list of system functions
  2682. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2683. if( newInterface == 0 )
  2684. return ConfigError(asOUT_OF_MEMORY, "RegisterStringFactory", datatype, 0);
  2685. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2686. if( func == 0 )
  2687. {
  2688. asDELETE(newInterface, asSSystemFunctionInterface);
  2689. return ConfigError(asOUT_OF_MEMORY, "RegisterStringFactory", datatype, 0);
  2690. }
  2691. func->name = "$str";
  2692. func->sysFuncIntf = newInterface;
  2693. asCBuilder bld(this, 0);
  2694. asCDataType dt;
  2695. r = bld.ParseDataType(datatype, &dt, defaultNamespace, true);
  2696. if( r < 0 )
  2697. {
  2698. // Set as dummy before deleting
  2699. func->funcType = asFUNC_DUMMY;
  2700. asDELETE(func,asCScriptFunction);
  2701. return ConfigError(asINVALID_TYPE, "RegisterStringFactory", datatype, 0);
  2702. }
  2703. func->returnType = dt;
  2704. func->parameterTypes.PushLast(asCDataType::CreatePrimitive(ttInt, true));
  2705. func->inOutFlags.PushLast(asTM_NONE);
  2706. asCDataType parm1 = asCDataType::CreatePrimitive(ttUInt8, true);
  2707. parm1.MakeReference(true);
  2708. func->parameterTypes.PushLast(parm1);
  2709. func->inOutFlags.PushLast(asTM_INREF);
  2710. func->id = GetNextScriptFunctionId();
  2711. AddScriptFunction(func);
  2712. stringFactory = func;
  2713. if( func->returnType.GetObjectType() )
  2714. {
  2715. asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
  2716. if( group == 0 ) group = &defaultGroup;
  2717. group->scriptFunctions.PushLast(func);
  2718. }
  2719. // Register function id as success
  2720. return func->id;
  2721. }
  2722. // interface
  2723. int asCScriptEngine::GetStringFactoryReturnTypeId(asDWORD *flags) const
  2724. {
  2725. if( stringFactory == 0 )
  2726. return asNO_FUNCTION;
  2727. return stringFactory->GetReturnTypeId(flags);
  2728. }
  2729. // internal
  2730. asCModule *asCScriptEngine::GetModule(const char *name, bool create)
  2731. {
  2732. // Accept null as well as zero-length string
  2733. if( name == 0 ) name = "";
  2734. asCModule *retModule = 0;
  2735. ACQUIRESHARED(engineRWLock);
  2736. if( lastModule && lastModule->name == name )
  2737. retModule = lastModule;
  2738. else
  2739. {
  2740. // TODO: optimize: Improve linear search
  2741. for( asUINT n = 0; n < scriptModules.GetLength(); ++n )
  2742. if( scriptModules[n] && scriptModules[n]->name == name )
  2743. {
  2744. retModule = scriptModules[n];
  2745. break;
  2746. }
  2747. }
  2748. RELEASESHARED(engineRWLock);
  2749. if( retModule )
  2750. {
  2751. ACQUIREEXCLUSIVE(engineRWLock);
  2752. lastModule = retModule;
  2753. RELEASEEXCLUSIVE(engineRWLock);
  2754. return retModule;
  2755. }
  2756. if( create )
  2757. {
  2758. retModule = asNEW(asCModule)(name, this);
  2759. if( retModule == 0 )
  2760. {
  2761. // Out of memory
  2762. return 0;
  2763. }
  2764. ACQUIREEXCLUSIVE(engineRWLock);
  2765. scriptModules.PushLast(retModule);
  2766. lastModule = retModule;
  2767. RELEASEEXCLUSIVE(engineRWLock);
  2768. }
  2769. return retModule;
  2770. }
  2771. asCModule *asCScriptEngine::GetModuleFromFuncId(int id)
  2772. {
  2773. if( id < 0 ) return 0;
  2774. if( id >= (int)scriptFunctions.GetLength() ) return 0;
  2775. asCScriptFunction *func = scriptFunctions[id];
  2776. if( func == 0 ) return 0;
  2777. return func->module;
  2778. }
  2779. // internal
  2780. int asCScriptEngine::RequestBuild()
  2781. {
  2782. ACQUIREEXCLUSIVE(engineRWLock);
  2783. if( isBuilding )
  2784. {
  2785. RELEASEEXCLUSIVE(engineRWLock);
  2786. return asBUILD_IN_PROGRESS;
  2787. }
  2788. isBuilding = true;
  2789. RELEASEEXCLUSIVE(engineRWLock);
  2790. return 0;
  2791. }
  2792. // internal
  2793. void asCScriptEngine::BuildCompleted()
  2794. {
  2795. // Always free up pooled memory after a completed build
  2796. memoryMgr.FreeUnusedMemory();
  2797. isBuilding = false;
  2798. }
  2799. void asCScriptEngine::RemoveTemplateInstanceType(asCObjectType *t)
  2800. {
  2801. // If there is a module that still owns the generated type, then don't remove it
  2802. if( t->module )
  2803. return;
  2804. // Don't remove it if there are external refernces
  2805. if( t->externalRefCount.get() )
  2806. return;
  2807. // Only remove the template instance type if no config group is using it
  2808. if( defaultGroup.generatedTemplateInstances.Exists(t) )
  2809. return;
  2810. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  2811. if( configGroups[n]->generatedTemplateInstances.Exists(t) )
  2812. return;
  2813. t->DestroyInternal();
  2814. templateInstanceTypes.RemoveValue(t);
  2815. generatedTemplateTypes.RemoveValue(t);
  2816. t->ReleaseInternal();
  2817. }
  2818. // internal
  2819. asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateType, asCArray<asCDataType> &subTypes, asCModule *requestingModule)
  2820. {
  2821. asUINT n;
  2822. // Is there any template instance type or template specialization already with this subtype?
  2823. for( n = 0; n < templateInstanceTypes.GetLength(); n++ )
  2824. {
  2825. asCObjectType *type = templateInstanceTypes[n];
  2826. if( type &&
  2827. type->name == templateType->name &&
  2828. type->templateSubTypes == subTypes )
  2829. {
  2830. // If the template instance is generated, then the module should hold a reference
  2831. // to it so the config group can determine see that the template type is in use.
  2832. // Template specializations will be treated as normal types
  2833. if( requestingModule && generatedTemplateTypes.Exists(type) )
  2834. {
  2835. if( type->module == 0 )
  2836. {
  2837. // Set the ownership of this template type
  2838. // It may be without ownership if it was previously created from application with for example GetObjectTypeByDecl
  2839. type->module = requestingModule;
  2840. }
  2841. if( !requestingModule->templateInstances.Exists(type) )
  2842. {
  2843. requestingModule->templateInstances.PushLast(type);
  2844. type->AddRefInternal();
  2845. }
  2846. }
  2847. return templateInstanceTypes[n];
  2848. }
  2849. }
  2850. // No previous template instance exists
  2851. // Make sure this template supports the subtype
  2852. for( n = 0; n < subTypes.GetLength(); n++ )
  2853. {
  2854. if( !templateType->acceptValueSubType && (subTypes[n].IsPrimitive() || (subTypes[n].GetObjectType()->flags & asOBJ_VALUE)) )
  2855. return 0;
  2856. if( !templateType->acceptRefSubType && (subTypes[n].IsObject() && (subTypes[n].GetObjectType()->flags & asOBJ_REF)) )
  2857. return 0;
  2858. }
  2859. // Create a new template instance type based on the templateType
  2860. asCObjectType *ot = asNEW(asCObjectType)(this);
  2861. if( ot == 0 )
  2862. {
  2863. // Out of memory
  2864. return 0;
  2865. }
  2866. ot->templateSubTypes = subTypes;
  2867. ot->flags = templateType->flags;
  2868. ot->size = templateType->size;
  2869. ot->name = templateType->name;
  2870. ot->nameSpace = templateType->nameSpace;
  2871. // If the template is being requested from a module, then the module should hold a reference to the type
  2872. if( requestingModule )
  2873. {
  2874. // Set the ownership of this template type
  2875. ot->module = requestingModule;
  2876. requestingModule->templateInstances.PushLast(ot);
  2877. ot->AddRefInternal();
  2878. }
  2879. else
  2880. {
  2881. // If the template type is not requested directly from a module, then set the ownership
  2882. // of it to the same module as one of the subtypes. If none of the subtypes are owned by]
  2883. // any module, the template instance will be without ownership and can be removed from the
  2884. // engine at any time (unless the application holds an external reference).
  2885. for( n = 0; n < subTypes.GetLength(); n++ )
  2886. {
  2887. if( subTypes[n].GetObjectType() )
  2888. {
  2889. ot->module = subTypes[n].GetObjectType()->module;
  2890. if( ot->module )
  2891. {
  2892. ot->module->templateInstances.PushLast(ot);
  2893. ot->AddRefInternal();
  2894. break;
  2895. }
  2896. }
  2897. }
  2898. }
  2899. // Before filling in the methods, call the template instance callback behaviour to validate the type
  2900. if( templateType->beh.templateCallback )
  2901. {
  2902. // If the validation is deferred then the validation will be done later,
  2903. // so it is necessary to continue the preparation of the template instance type
  2904. if( !deferValidationOfTemplateTypes )
  2905. {
  2906. asCScriptFunction *callback = scriptFunctions[templateType->beh.templateCallback];
  2907. bool dontGarbageCollect = false;
  2908. if( !CallGlobalFunctionRetBool(ot, &dontGarbageCollect, callback->sysFuncIntf, callback) )
  2909. {
  2910. // The type cannot be instantiated
  2911. ot->templateSubTypes.SetLength(0);
  2912. if( ot->module )
  2913. {
  2914. ot->module->templateInstances.RemoveValue(ot);
  2915. ot->ReleaseInternal();
  2916. }
  2917. ot->ReleaseInternal();
  2918. return 0;
  2919. }
  2920. // If the callback said this template instance won't be garbage collected then remove the flag
  2921. if( dontGarbageCollect )
  2922. ot->flags &= ~asOBJ_GC;
  2923. }
  2924. ot->beh.templateCallback = templateType->beh.templateCallback;
  2925. scriptFunctions[ot->beh.templateCallback]->AddRefInternal();
  2926. }
  2927. ot->methods = templateType->methods;
  2928. for( n = 0; n < ot->methods.GetLength(); n++ )
  2929. scriptFunctions[ot->methods[n]]->AddRefInternal();
  2930. if( templateType->flags & asOBJ_REF )
  2931. {
  2932. // Store the real factory in the constructor. This is used by the CreateScriptObject function.
  2933. // Otherwise it wouldn't be necessary to store the real factory ids.
  2934. ot->beh.construct = templateType->beh.factory;
  2935. ot->beh.constructors = templateType->beh.factories;
  2936. }
  2937. else
  2938. {
  2939. ot->beh.construct = templateType->beh.construct;
  2940. ot->beh.constructors = templateType->beh.constructors;
  2941. }
  2942. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2943. scriptFunctions[ot->beh.constructors[n]]->AddRefInternal();
  2944. // Before proceeding with the generation of the template functions for the template instance it is necessary
  2945. // to include the new template instance type in the list of known types, otherwise it is possible that we get
  2946. // a infinite recursive loop as the template instance type is requested again during the generation of the
  2947. // template functions.
  2948. templateInstanceTypes.PushLast(ot);
  2949. // Store the template instance types that have been created automatically by the engine from a template type
  2950. // The object types in templateInstanceTypes that are not also in generatedTemplateTypes are registered template specializations
  2951. generatedTemplateTypes.PushLast(ot);
  2952. // As the new template type is instantiated the engine should
  2953. // generate new functions to substitute the ones with the template subtype.
  2954. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2955. {
  2956. int funcId = ot->beh.constructors[n];
  2957. asCScriptFunction *func = scriptFunctions[funcId];
  2958. if( GenerateNewTemplateFunction(templateType, ot, func, &func) )
  2959. {
  2960. // Release the old function, the new one already has its ref count set to 1
  2961. scriptFunctions[funcId]->ReleaseInternal();
  2962. ot->beh.constructors[n] = func->id;
  2963. if( ot->beh.construct == funcId )
  2964. ot->beh.construct = func->id;
  2965. }
  2966. }
  2967. ot->beh.factory = 0;
  2968. if( templateType->flags & asOBJ_REF )
  2969. {
  2970. // Generate factory stubs for each of the factories
  2971. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2972. {
  2973. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, ot->beh.constructors[n]);
  2974. ot->beh.factories.PushLast(func->id);
  2975. // Set the default factory as well
  2976. if( ot->beh.constructors[n] == ot->beh.construct )
  2977. ot->beh.factory = func->id;
  2978. }
  2979. }
  2980. else
  2981. {
  2982. // Generate factory stubs for each of the constructors
  2983. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2984. {
  2985. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, ot->beh.constructors[n]);
  2986. if( ot->beh.constructors[n] == ot->beh.construct )
  2987. ot->beh.construct = func->id;
  2988. // Release previous constructor
  2989. scriptFunctions[ot->beh.constructors[n]]->ReleaseInternal();
  2990. ot->beh.constructors[n] = func->id;
  2991. }
  2992. }
  2993. // Generate stub for the list factory as well
  2994. if( templateType->beh.listFactory )
  2995. {
  2996. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.listFactory);
  2997. // Rename the function to easily identify it in LoadByteCode
  2998. func->name = "$list";
  2999. ot->beh.listFactory = func->id;
  3000. }
  3001. ot->beh.addref = templateType->beh.addref;
  3002. if( scriptFunctions[ot->beh.addref] ) scriptFunctions[ot->beh.addref]->AddRefInternal();
  3003. ot->beh.release = templateType->beh.release;
  3004. if( scriptFunctions[ot->beh.release] ) scriptFunctions[ot->beh.release]->AddRefInternal();
  3005. ot->beh.destruct = templateType->beh.destruct;
  3006. if( scriptFunctions[ot->beh.destruct] ) scriptFunctions[ot->beh.destruct]->AddRefInternal();
  3007. ot->beh.copy = templateType->beh.copy;
  3008. if( scriptFunctions[ot->beh.copy] ) scriptFunctions[ot->beh.copy]->AddRefInternal();
  3009. ot->beh.gcGetRefCount = templateType->beh.gcGetRefCount;
  3010. if( scriptFunctions[ot->beh.gcGetRefCount] ) scriptFunctions[ot->beh.gcGetRefCount]->AddRefInternal();
  3011. ot->beh.gcSetFlag = templateType->beh.gcSetFlag;
  3012. if( scriptFunctions[ot->beh.gcSetFlag] ) scriptFunctions[ot->beh.gcSetFlag]->AddRefInternal();
  3013. ot->beh.gcGetFlag = templateType->beh.gcGetFlag;
  3014. if( scriptFunctions[ot->beh.gcGetFlag] ) scriptFunctions[ot->beh.gcGetFlag]->AddRefInternal();
  3015. ot->beh.gcEnumReferences = templateType->beh.gcEnumReferences;
  3016. if( scriptFunctions[ot->beh.gcEnumReferences] ) scriptFunctions[ot->beh.gcEnumReferences]->AddRefInternal();
  3017. ot->beh.gcReleaseAllReferences = templateType->beh.gcReleaseAllReferences;
  3018. if( scriptFunctions[ot->beh.gcReleaseAllReferences] ) scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRefInternal();
  3019. ot->beh.getWeakRefFlag = templateType->beh.getWeakRefFlag;
  3020. if( scriptFunctions[ot->beh.getWeakRefFlag] ) scriptFunctions[ot->beh.getWeakRefFlag]->AddRefInternal();
  3021. // As the new template type is instantiated, the engine should
  3022. // generate new functions to substitute the ones with the template subtype.
  3023. for( n = 0; n < ot->methods.GetLength(); n++ )
  3024. {
  3025. int funcId = ot->methods[n];
  3026. asCScriptFunction *func = scriptFunctions[funcId];
  3027. if( GenerateNewTemplateFunction(templateType, ot, func, &func) )
  3028. {
  3029. // Release the old function, the new one already has its ref count set to 1
  3030. scriptFunctions[funcId]->ReleaseInternal();
  3031. ot->methods[n] = func->id;
  3032. }
  3033. }
  3034. // Increase ref counter for sub type if it is an object type
  3035. for( n = 0; n < ot->templateSubTypes.GetLength(); n++ )
  3036. if( ot->templateSubTypes[n].GetObjectType() )
  3037. ot->templateSubTypes[n].GetObjectType()->AddRefInternal();
  3038. // Copy the properties to the template instance
  3039. for( n = 0; n < templateType->properties.GetLength(); n++ )
  3040. {
  3041. asCObjectProperty *prop = templateType->properties[n];
  3042. ot->properties.PushLast(asNEW(asCObjectProperty)(*prop));
  3043. if( prop->type.GetObjectType() )
  3044. prop->type.GetObjectType()->AddRefInternal();
  3045. }
  3046. return ot;
  3047. }
  3048. // interface
  3049. asILockableSharedBool *asCScriptEngine::GetWeakRefFlagOfScriptObject(void *obj, const asIObjectType *type) const
  3050. {
  3051. // Make sure it is not a null pointer
  3052. if( obj == 0 || type == 0 ) return 0;
  3053. const asCObjectType *objType = static_cast<const asCObjectType *>(type);
  3054. asILockableSharedBool *dest = 0;
  3055. if( objType->beh.getWeakRefFlag )
  3056. {
  3057. // Call the getweakrefflag behaviour
  3058. dest = reinterpret_cast<asILockableSharedBool*>(CallObjectMethodRetPtr(obj, objType->beh.getWeakRefFlag));
  3059. }
  3060. return dest;
  3061. }
  3062. // internal
  3063. asCDataType asCScriptEngine::DetermineTypeForTemplate(const asCDataType &orig, asCObjectType *tmpl, asCObjectType *ot)
  3064. {
  3065. asCDataType dt;
  3066. if( orig.GetObjectType() && (orig.GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE) )
  3067. {
  3068. bool found = false;
  3069. for( asUINT n = 0; n < tmpl->templateSubTypes.GetLength(); n++ )
  3070. {
  3071. if( orig.GetObjectType() == tmpl->templateSubTypes[n].GetObjectType() )
  3072. {
  3073. found = true;
  3074. dt = ot->templateSubTypes[n];
  3075. if( orig.IsObjectHandle() && !ot->templateSubTypes[n].IsObjectHandle() )
  3076. {
  3077. dt.MakeHandle(true, true);
  3078. if( orig.IsHandleToConst() )
  3079. dt.MakeHandleToConst(true);
  3080. dt.MakeReference(orig.IsReference());
  3081. dt.MakeReadOnly(orig.IsReadOnly());
  3082. }
  3083. else
  3084. {
  3085. dt.MakeReference(orig.IsReference());
  3086. dt.MakeReadOnly(ot->templateSubTypes[n].IsReadOnly() || orig.IsReadOnly());
  3087. }
  3088. break;
  3089. }
  3090. }
  3091. asASSERT( found );
  3092. UNUSED_VAR( found );
  3093. }
  3094. else if( orig.GetObjectType() == tmpl )
  3095. {
  3096. if( orig.IsObjectHandle() )
  3097. dt = asCDataType::CreateObjectHandle(ot, false);
  3098. else
  3099. dt = asCDataType::CreateObject(ot, false);
  3100. dt.MakeReference(orig.IsReference());
  3101. dt.MakeReadOnly(orig.IsReadOnly());
  3102. }
  3103. else if( orig.GetObjectType() && (orig.GetObjectType()->flags & asOBJ_TEMPLATE) )
  3104. {
  3105. // The type is itself a template, so it is necessary to find the correct template instance type
  3106. asCArray<asCDataType> tmplSubTypes;
  3107. asCObjectType *origType = orig.GetObjectType();
  3108. bool needInstance = true;
  3109. // Find the matching replacements for the subtypes
  3110. for( asUINT n = 0; n < origType->templateSubTypes.GetLength(); n++ )
  3111. {
  3112. if( origType->templateSubTypes[n].GetObjectType() == 0 ||
  3113. !(origType->templateSubTypes[n].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE) )
  3114. {
  3115. // The template is already an instance so we shouldn't attempt to create another instance
  3116. needInstance = false;
  3117. break;
  3118. }
  3119. for( asUINT m = 0; m < tmpl->templateSubTypes.GetLength(); m++ )
  3120. if( origType->templateSubTypes[n].GetObjectType() == tmpl->templateSubTypes[m].GetObjectType() )
  3121. tmplSubTypes.PushLast(ot->templateSubTypes[m]);
  3122. if( tmplSubTypes.GetLength() != n+1 )
  3123. {
  3124. asASSERT( false );
  3125. return orig;
  3126. }
  3127. }
  3128. asCObjectType *ntype = origType;
  3129. if( needInstance )
  3130. {
  3131. // Always find the original template type when creating a new template instance otherwise the
  3132. // generation will fail since it will attempt to create factory stubs when they already exists, etc
  3133. for( asUINT n = 0; n < registeredTemplateTypes.GetLength(); n++ )
  3134. if( registeredTemplateTypes[n]->name == origType->name )
  3135. {
  3136. origType = registeredTemplateTypes[n];
  3137. break;
  3138. }
  3139. ntype = GetTemplateInstanceType(origType, tmplSubTypes, ot->module);
  3140. if( ntype == 0 )
  3141. {
  3142. // It not possible to instantiate the subtype
  3143. asASSERT( false );
  3144. ntype = tmpl;
  3145. }
  3146. }
  3147. if( orig.IsObjectHandle() )
  3148. dt = asCDataType::CreateObjectHandle(ntype, false);
  3149. else
  3150. dt = asCDataType::CreateObject(ntype, false);
  3151. dt.MakeReference(orig.IsReference());
  3152. dt.MakeReadOnly(orig.IsReadOnly());
  3153. }
  3154. else
  3155. dt = orig;
  3156. return dt;
  3157. }
  3158. // internal
  3159. asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *templateType, asCObjectType *ot, int factoryId)
  3160. {
  3161. asCScriptFunction *factory = scriptFunctions[factoryId];
  3162. // By first instantiating the function as a dummy and then changing it to be a script function
  3163. // I avoid having it added to the garbage collector. As it is known that this object will stay
  3164. // alive until the template instance is no longer used there is no need to have the GC check
  3165. // this function all the time.
  3166. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_DUMMY);
  3167. if( func == 0 )
  3168. {
  3169. // Out of memory
  3170. return 0;
  3171. }
  3172. func->funcType = asFUNC_SCRIPT;
  3173. func->AllocateScriptFunctionData();
  3174. func->name = "$fact";
  3175. func->id = GetNextScriptFunctionId();
  3176. AddScriptFunction(func);
  3177. func->isShared = true;
  3178. if( templateType->flags & asOBJ_REF )
  3179. {
  3180. func->returnType = asCDataType::CreateObjectHandle(ot, false);
  3181. }
  3182. else
  3183. {
  3184. func->returnType = factory->returnType; // constructors return nothing
  3185. func->objectType = ot;
  3186. func->objectType->AddRefInternal();
  3187. }
  3188. // Skip the first parameter as this is the object type pointer that the stub will add
  3189. func->parameterTypes.SetLength(factory->parameterTypes.GetLength()-1);
  3190. func->inOutFlags.SetLength(factory->inOutFlags.GetLength()-1);
  3191. for( asUINT p = 1; p < factory->parameterTypes.GetLength(); p++ )
  3192. {
  3193. func->parameterTypes[p-1] = factory->parameterTypes[p];
  3194. func->inOutFlags[p-1] = factory->inOutFlags[p];
  3195. }
  3196. func->scriptData->objVariablesOnHeap = 0;
  3197. // Generate the bytecode for the factory stub
  3198. asUINT bcLength = asBCTypeSize[asBCInfo[asBC_OBJTYPE].type] +
  3199. asBCTypeSize[asBCInfo[asBC_CALLSYS].type] +
  3200. asBCTypeSize[asBCInfo[asBC_RET].type];
  3201. if( ep.includeJitInstructions )
  3202. bcLength += asBCTypeSize[asBCInfo[asBC_JitEntry].type];
  3203. if( templateType->flags & asOBJ_VALUE )
  3204. bcLength += asBCTypeSize[asBCInfo[asBC_SwapPtr].type];
  3205. func->scriptData->byteCode.SetLength(bcLength);
  3206. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  3207. if( ep.includeJitInstructions )
  3208. {
  3209. *(asBYTE*)bc = asBC_JitEntry;
  3210. *(asPWORD*)(bc+1) = 0;
  3211. bc += asBCTypeSize[asBCInfo[asBC_JitEntry].type];
  3212. }
  3213. *(asBYTE*)bc = asBC_OBJTYPE;
  3214. *(asPWORD*)(bc+1) = (asPWORD)ot;
  3215. bc += asBCTypeSize[asBCInfo[asBC_OBJTYPE].type];
  3216. if( templateType->flags & asOBJ_VALUE )
  3217. {
  3218. // Swap the object pointer with the object type
  3219. *(asBYTE*)bc = asBC_SwapPtr;
  3220. bc += asBCTypeSize[asBCInfo[asBC_SwapPtr].type];
  3221. }
  3222. *(asBYTE*)bc = asBC_CALLSYS;
  3223. *(asDWORD*)(bc+1) = factoryId;
  3224. bc += asBCTypeSize[asBCInfo[asBC_CALLSYS].type];
  3225. *(asBYTE*)bc = asBC_RET;
  3226. *(((asWORD*)bc)+1) = (asWORD)func->GetSpaceNeededForArguments() + (func->objectType ? AS_PTR_SIZE : 0);
  3227. func->AddReferences();
  3228. func->scriptData->stackNeeded = AS_PTR_SIZE;
  3229. // Tell the virtual machine not to clean up the object on exception
  3230. func->dontCleanUpOnException = true;
  3231. func->JITCompile();
  3232. // Need to translate the list pattern too so the VM and compiler will know the correct type of the members
  3233. if( factory->listPattern )
  3234. {
  3235. asSListPatternNode *n = factory->listPattern;
  3236. asSListPatternNode *last = 0;
  3237. while( n )
  3238. {
  3239. asSListPatternNode *newNode = n->Duplicate();
  3240. if( newNode->type == asLPT_TYPE )
  3241. {
  3242. asSListPatternDataTypeNode *typeNode = reinterpret_cast<asSListPatternDataTypeNode*>(newNode);
  3243. typeNode->dataType = DetermineTypeForTemplate(typeNode->dataType, templateType, ot);
  3244. }
  3245. if( last )
  3246. last->next = newNode;
  3247. else
  3248. func->listPattern = newNode;
  3249. last = newNode;
  3250. n = n->next;
  3251. }
  3252. }
  3253. return func;
  3254. }
  3255. bool asCScriptEngine::RequireTypeReplacement(asCDataType &type, asCObjectType *templateType)
  3256. {
  3257. if( type.GetObjectType() == templateType ) return true;
  3258. if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE) ) return true;
  3259. if( type.GetObjectType() && (type.GetObjectType()->flags & asOBJ_TEMPLATE) )
  3260. {
  3261. for( asUINT n = 0; n < type.GetObjectType()->templateSubTypes.GetLength(); n++ )
  3262. if( type.GetObjectType()->templateSubTypes[n].GetObjectType() &&
  3263. type.GetObjectType()->templateSubTypes[n].GetObjectType()->flags & asOBJ_TEMPLATE_SUBTYPE )
  3264. return true;
  3265. }
  3266. return false;
  3267. }
  3268. bool asCScriptEngine::GenerateNewTemplateFunction(asCObjectType *templateType, asCObjectType *ot, asCScriptFunction *func, asCScriptFunction **newFunc)
  3269. {
  3270. bool needNewFunc = false;
  3271. if( RequireTypeReplacement(func->returnType, templateType) )
  3272. needNewFunc = true;
  3273. else
  3274. {
  3275. for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
  3276. {
  3277. if( RequireTypeReplacement(func->parameterTypes[p], templateType) )
  3278. {
  3279. needNewFunc = true;
  3280. break;
  3281. }
  3282. }
  3283. }
  3284. if( !needNewFunc )
  3285. return false;
  3286. asCScriptFunction *func2 = asNEW(asCScriptFunction)(this, 0, func->funcType);
  3287. if( func2 == 0 )
  3288. {
  3289. // Out of memory
  3290. return false;
  3291. }
  3292. func2->name = func->name;
  3293. func2->returnType = DetermineTypeForTemplate(func->returnType, templateType, ot);
  3294. func2->parameterTypes.SetLength(func->parameterTypes.GetLength());
  3295. for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
  3296. func2->parameterTypes[p] = DetermineTypeForTemplate(func->parameterTypes[p], templateType, ot);
  3297. // TODO: template: Must be careful when instantiating templates for garbage collected types
  3298. // If the template hasn't been registered with the behaviours, it shouldn't
  3299. // permit instantiation of garbage collected types that in turn may refer to
  3300. // this instance.
  3301. func2->inOutFlags = func->inOutFlags;
  3302. func2->isReadOnly = func->isReadOnly;
  3303. func2->objectType = ot;
  3304. func2->objectType->AddRefInternal();
  3305. func2->sysFuncIntf = asNEW(asSSystemFunctionInterface)(*func->sysFuncIntf);
  3306. // Adjust the clean up instructions
  3307. if( func2->sysFuncIntf->callConv == ICC_GENERIC_FUNC ||
  3308. func2->sysFuncIntf->callConv == ICC_GENERIC_METHOD )
  3309. PrepareSystemFunctionGeneric(func2, func2->sysFuncIntf, this);
  3310. else
  3311. PrepareSystemFunction(func2, func2->sysFuncIntf, this);
  3312. func2->id = GetNextScriptFunctionId();
  3313. AddScriptFunction(func2);
  3314. // Return the new function
  3315. *newFunc = func2;
  3316. return true;
  3317. }
  3318. void asCScriptEngine::CallObjectMethod(void *obj, int func) const
  3319. {
  3320. asCScriptFunction *s = scriptFunctions[func];
  3321. asASSERT( s != 0 );
  3322. CallObjectMethod(obj, s->sysFuncIntf, s);
  3323. }
  3324. void asCScriptEngine::CallObjectMethod(void *obj, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3325. {
  3326. #if defined(__GNUC__) || defined(AS_PSVITA)
  3327. if( i->callConv == ICC_GENERIC_METHOD )
  3328. {
  3329. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3330. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3331. f(&gen);
  3332. }
  3333. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3334. {
  3335. // For virtual thiscalls we must call the method as a true class method
  3336. // so that the compiler will lookup the function address in the vftable
  3337. union
  3338. {
  3339. asSIMPLEMETHOD_t mthd;
  3340. struct
  3341. {
  3342. asFUNCTION_t func;
  3343. asPWORD baseOffset; // Same size as the pointer
  3344. } f;
  3345. } p;
  3346. p.f.func = (asFUNCTION_t)(i->func);
  3347. p.f.baseOffset = asPWORD(i->baseOffset);
  3348. void (asCSimpleDummy::*f)() = p.mthd;
  3349. (((asCSimpleDummy*)obj)->*f)();
  3350. }
  3351. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3352. {
  3353. void (*f)(void *) = (void (*)(void *))(i->func);
  3354. f(obj);
  3355. }
  3356. #else
  3357. #ifndef AS_NO_CLASS_METHODS
  3358. if( i->callConv == ICC_THISCALL )
  3359. {
  3360. union
  3361. {
  3362. asSIMPLEMETHOD_t mthd;
  3363. asFUNCTION_t func;
  3364. } p;
  3365. p.func = (asFUNCTION_t)(i->func);
  3366. void (asCSimpleDummy::*f)() = p.mthd;
  3367. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3368. (((asCSimpleDummy*)obj)->*f)();
  3369. }
  3370. else
  3371. #endif
  3372. if( i->callConv == ICC_GENERIC_METHOD )
  3373. {
  3374. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3375. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3376. f(&gen);
  3377. }
  3378. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3379. {
  3380. void (*f)(void *) = (void (*)(void *))(i->func);
  3381. f(obj);
  3382. }
  3383. #endif
  3384. }
  3385. bool asCScriptEngine::CallObjectMethodRetBool(void *obj, int func) const
  3386. {
  3387. asCScriptFunction *s = scriptFunctions[func];
  3388. asASSERT( s != 0 );
  3389. asSSystemFunctionInterface *i = s->sysFuncIntf;
  3390. #if defined(__GNUC__) || defined(AS_PSVITA)
  3391. if( i->callConv == ICC_GENERIC_METHOD )
  3392. {
  3393. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3394. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3395. f(&gen);
  3396. return *(bool*)gen.GetReturnPointer();
  3397. }
  3398. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3399. {
  3400. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3401. union
  3402. {
  3403. asSIMPLEMETHOD_t mthd;
  3404. struct
  3405. {
  3406. asFUNCTION_t func;
  3407. asPWORD baseOffset;
  3408. } f;
  3409. } p;
  3410. p.f.func = (asFUNCTION_t)(i->func);
  3411. p.f.baseOffset = asPWORD(i->baseOffset);
  3412. bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())(p.mthd);
  3413. return (((asCSimpleDummy*)obj)->*f)();
  3414. }
  3415. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3416. {
  3417. bool (*f)(void *) = (bool (*)(void *))(i->func);
  3418. return f(obj);
  3419. }
  3420. #else
  3421. #ifndef AS_NO_CLASS_METHODS
  3422. if( i->callConv == ICC_THISCALL )
  3423. {
  3424. union
  3425. {
  3426. asSIMPLEMETHOD_t mthd;
  3427. asFUNCTION_t func;
  3428. } p;
  3429. p.func = (asFUNCTION_t)(i->func);
  3430. bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())p.mthd;
  3431. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3432. return (((asCSimpleDummy*)obj)->*f)();
  3433. }
  3434. else
  3435. #endif
  3436. if( i->callConv == ICC_GENERIC_METHOD )
  3437. {
  3438. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3439. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3440. f(&gen);
  3441. return *(bool*)gen.GetReturnPointer();
  3442. }
  3443. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3444. {
  3445. bool (*f)(void *) = (bool (*)(void *))(i->func);
  3446. return f(obj);
  3447. }
  3448. #endif
  3449. }
  3450. int asCScriptEngine::CallObjectMethodRetInt(void *obj, int func) const
  3451. {
  3452. asCScriptFunction *s = scriptFunctions[func];
  3453. asASSERT( s != 0 );
  3454. asSSystemFunctionInterface *i = s->sysFuncIntf;
  3455. #if defined(__GNUC__) || defined(AS_PSVITA)
  3456. if( i->callConv == ICC_GENERIC_METHOD )
  3457. {
  3458. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3459. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3460. f(&gen);
  3461. return *(int*)gen.GetReturnPointer();
  3462. }
  3463. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3464. {
  3465. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3466. union
  3467. {
  3468. asSIMPLEMETHOD_t mthd;
  3469. struct
  3470. {
  3471. asFUNCTION_t func;
  3472. asPWORD baseOffset;
  3473. } f;
  3474. } p;
  3475. p.f.func = (asFUNCTION_t)(i->func);
  3476. p.f.baseOffset = asPWORD(i->baseOffset);
  3477. int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())(p.mthd);
  3478. return (((asCSimpleDummy*)obj)->*f)();
  3479. }
  3480. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3481. {
  3482. int (*f)(void *) = (int (*)(void *))(i->func);
  3483. return f(obj);
  3484. }
  3485. #else
  3486. #ifndef AS_NO_CLASS_METHODS
  3487. if( i->callConv == ICC_THISCALL )
  3488. {
  3489. union
  3490. {
  3491. asSIMPLEMETHOD_t mthd;
  3492. asFUNCTION_t func;
  3493. } p;
  3494. p.func = (asFUNCTION_t)(i->func);
  3495. int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())p.mthd;
  3496. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3497. return (((asCSimpleDummy*)obj)->*f)();
  3498. }
  3499. else
  3500. #endif
  3501. if( i->callConv == ICC_GENERIC_METHOD )
  3502. {
  3503. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3504. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3505. f(&gen);
  3506. return *(int*)gen.GetReturnPointer();
  3507. }
  3508. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3509. {
  3510. int (*f)(void *) = (int (*)(void *))(i->func);
  3511. return f(obj);
  3512. }
  3513. #endif
  3514. }
  3515. void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int func) const
  3516. {
  3517. asCScriptFunction *s = scriptFunctions[func];
  3518. asASSERT( s != 0 );
  3519. asSSystemFunctionInterface *i = s->sysFuncIntf;
  3520. #if defined(__GNUC__) || defined(AS_PSVITA)
  3521. if( i->callConv == ICC_GENERIC_METHOD )
  3522. {
  3523. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3524. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3525. f(&gen);
  3526. return *(void**)gen.GetReturnPointer();
  3527. }
  3528. else if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3529. {
  3530. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3531. union
  3532. {
  3533. asSIMPLEMETHOD_t mthd;
  3534. struct
  3535. {
  3536. asFUNCTION_t func;
  3537. asPWORD baseOffset;
  3538. } f;
  3539. } p;
  3540. p.f.func = (asFUNCTION_t)(i->func);
  3541. p.f.baseOffset = asPWORD(i->baseOffset);
  3542. void *(asCSimpleDummy::*f)() = (void *(asCSimpleDummy::*)())(p.mthd);
  3543. return (((asCSimpleDummy*)obj)->*f)();
  3544. }
  3545. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3546. {
  3547. void *(*f)(void *) = (void *(*)(void *))(i->func);
  3548. return f(obj);
  3549. }
  3550. #else
  3551. #ifndef AS_NO_CLASS_METHODS
  3552. if( i->callConv == ICC_THISCALL )
  3553. {
  3554. union
  3555. {
  3556. asSIMPLEMETHOD_t mthd;
  3557. asFUNCTION_t func;
  3558. } p;
  3559. p.func = (asFUNCTION_t)(i->func);
  3560. void *(asCSimpleDummy::*f)() = (void *(asCSimpleDummy::*)())p.mthd;
  3561. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3562. return (((asCSimpleDummy*)obj)->*f)();
  3563. }
  3564. else
  3565. #endif
  3566. if( i->callConv == ICC_GENERIC_METHOD )
  3567. {
  3568. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, 0);
  3569. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3570. f(&gen);
  3571. return *(void **)gen.GetReturnPointer();
  3572. }
  3573. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  3574. {
  3575. void *(*f)(void *) = (void *(*)(void *))(i->func);
  3576. return f(obj);
  3577. }
  3578. #endif
  3579. }
  3580. void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int param1, asCScriptFunction *func) const
  3581. {
  3582. asASSERT( func != 0 );
  3583. asSSystemFunctionInterface *i = func->sysFuncIntf;
  3584. #ifndef AS_NO_CLASS_METHODS
  3585. if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
  3586. {
  3587. #if defined(__GNUC__) || defined(AS_PSVITA)
  3588. // For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
  3589. union
  3590. {
  3591. asSIMPLEMETHOD_t mthd;
  3592. struct
  3593. {
  3594. asFUNCTION_t func;
  3595. asPWORD baseOffset;
  3596. } f;
  3597. } p;
  3598. p.f.func = (asFUNCTION_t)(i->func);
  3599. p.f.baseOffset = asPWORD(i->baseOffset);
  3600. void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))(p.mthd);
  3601. return (((asCSimpleDummy*)obj)->*f)(param1);
  3602. #else
  3603. union
  3604. {
  3605. asSIMPLEMETHOD_t mthd;
  3606. asFUNCTION_t func;
  3607. } p;
  3608. p.func = (asFUNCTION_t)(i->func);
  3609. void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))p.mthd;
  3610. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3611. return (((asCSimpleDummy*)obj)->*f)(param1);
  3612. #endif
  3613. }
  3614. else
  3615. #endif
  3616. if( i->callConv == ICC_GENERIC_METHOD )
  3617. {
  3618. asCGeneric gen(const_cast<asCScriptEngine*>(this), func, obj, reinterpret_cast<asDWORD*>(&param1));
  3619. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3620. f(&gen);
  3621. return *(void **)gen.GetReturnPointer();
  3622. }
  3623. else if( i->callConv == ICC_CDECL_OBJLAST )
  3624. {
  3625. void *(*f)(int, void *) = (void *(*)(int, void *))(i->func);
  3626. return f(param1, obj);
  3627. }
  3628. else /*if( i->callConv == ICC_CDECL_OBJFIRST )*/
  3629. {
  3630. void *(*f)(void *, int) = (void *(*)(void *, int))(i->func);
  3631. return f(obj, param1);
  3632. }
  3633. }
  3634. void *asCScriptEngine::CallGlobalFunctionRetPtr(int func) const
  3635. {
  3636. asCScriptFunction *s = scriptFunctions[func];
  3637. asASSERT( s != 0 );
  3638. return CallGlobalFunctionRetPtr(s->sysFuncIntf, s);
  3639. }
  3640. void *asCScriptEngine::CallGlobalFunctionRetPtr(int func, void *param1) const
  3641. {
  3642. asCScriptFunction *s = scriptFunctions[func];
  3643. asASSERT( s != 0 );
  3644. return CallGlobalFunctionRetPtr(s->sysFuncIntf, s, param1);
  3645. }
  3646. void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3647. {
  3648. if( i->callConv == ICC_CDECL )
  3649. {
  3650. void *(*f)() = (void *(*)())(i->func);
  3651. return f();
  3652. }
  3653. else if( i->callConv == ICC_STDCALL )
  3654. {
  3655. typedef void *(STDCALL *func_t)();
  3656. func_t f = (func_t)(i->func);
  3657. return f();
  3658. }
  3659. else
  3660. {
  3661. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, 0);
  3662. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3663. f(&gen);
  3664. return *(void**)gen.GetReturnPointer();
  3665. }
  3666. }
  3667. void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s, void *param1) const
  3668. {
  3669. if( i->callConv == ICC_CDECL )
  3670. {
  3671. void *(*f)(void *) = (void *(*)(void *))(i->func);
  3672. return f(param1);
  3673. }
  3674. else if( i->callConv == ICC_STDCALL )
  3675. {
  3676. typedef void *(STDCALL *func_t)(void *);
  3677. func_t f = (func_t)(i->func);
  3678. return f(param1);
  3679. }
  3680. else
  3681. {
  3682. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, (asDWORD*)&param1);
  3683. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3684. f(&gen);
  3685. return *(void**)gen.GetReturnPointer();
  3686. }
  3687. }
  3688. void asCScriptEngine::CallObjectMethod(void *obj, void *param, int func) const
  3689. {
  3690. asCScriptFunction *s = scriptFunctions[func];
  3691. asASSERT( s != 0 );
  3692. CallObjectMethod(obj, param, s->sysFuncIntf, s);
  3693. }
  3694. void asCScriptEngine::CallObjectMethod(void *obj, void *param, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3695. {
  3696. #if defined(__GNUC__) || defined(AS_PSVITA)
  3697. if( i->callConv == ICC_CDECL_OBJLAST )
  3698. {
  3699. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3700. f(param, obj);
  3701. }
  3702. else if( i->callConv == ICC_GENERIC_METHOD )
  3703. {
  3704. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, (asDWORD*)&param);
  3705. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3706. f(&gen);
  3707. }
  3708. else if( i->callConv == ICC_VIRTUAL_THISCALL || i->callConv == ICC_THISCALL )
  3709. {
  3710. // For virtual thiscalls we must call the method as a true class method
  3711. // so that the compiler will lookup the function address in the vftable
  3712. union
  3713. {
  3714. asSIMPLEMETHOD_t mthd;
  3715. struct
  3716. {
  3717. asFUNCTION_t func;
  3718. asPWORD baseOffset; // Same size as the pointer
  3719. } f;
  3720. } p;
  3721. p.f.func = (asFUNCTION_t)(i->func);
  3722. p.f.baseOffset = asPWORD(i->baseOffset);
  3723. void (asCSimpleDummy::*f)(void*) = (void (asCSimpleDummy::*)(void*))(p.mthd);
  3724. (((asCSimpleDummy*)obj)->*f)(param);
  3725. }
  3726. else /*if( i->callConv == ICC_CDECL_OBJFIRST */
  3727. {
  3728. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3729. f(obj, param);
  3730. }
  3731. #else
  3732. #ifndef AS_NO_CLASS_METHODS
  3733. if( i->callConv == ICC_THISCALL )
  3734. {
  3735. union
  3736. {
  3737. asSIMPLEMETHOD_t mthd;
  3738. asFUNCTION_t func;
  3739. } p;
  3740. p.func = (asFUNCTION_t)(i->func);
  3741. void (asCSimpleDummy::*f)(void *) = (void (asCSimpleDummy::*)(void *))(p.mthd);
  3742. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3743. (((asCSimpleDummy*)obj)->*f)(param);
  3744. }
  3745. else
  3746. #endif
  3747. if( i->callConv == ICC_CDECL_OBJLAST )
  3748. {
  3749. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3750. f(param, obj);
  3751. }
  3752. else if( i->callConv == ICC_GENERIC_METHOD )
  3753. {
  3754. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, obj, (asDWORD*)&param);
  3755. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3756. f(&gen);
  3757. }
  3758. else /*if( i->callConv == ICC_CDECL_OBJFIRST )*/
  3759. {
  3760. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3761. f(obj, param);
  3762. }
  3763. #endif
  3764. }
  3765. void asCScriptEngine::CallGlobalFunction(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3766. {
  3767. if( i->callConv == ICC_CDECL )
  3768. {
  3769. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3770. f(param1, param2);
  3771. }
  3772. else if( i->callConv == ICC_STDCALL )
  3773. {
  3774. typedef void (STDCALL *func_t)(void *, void *);
  3775. func_t f = (func_t)(i->func);
  3776. f(param1, param2);
  3777. }
  3778. else
  3779. {
  3780. // We must guarantee the order of the arguments which is why we copy them to this
  3781. // array. Otherwise the compiler may put them anywhere it likes, or even keep them
  3782. // in the registers which causes problem.
  3783. void *params[2] = {param1, param2};
  3784. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, (asDWORD*)&params);
  3785. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3786. f(&gen);
  3787. }
  3788. }
  3789. bool asCScriptEngine::CallGlobalFunctionRetBool(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s) const
  3790. {
  3791. if( i->callConv == ICC_CDECL )
  3792. {
  3793. bool (*f)(void *, void *) = (bool (*)(void *, void *))(i->func);
  3794. return f(param1, param2);
  3795. }
  3796. else if( i->callConv == ICC_STDCALL )
  3797. {
  3798. typedef bool (STDCALL *func_t)(void *, void *);
  3799. func_t f = (func_t)(i->func);
  3800. return f(param1, param2);
  3801. }
  3802. else
  3803. {
  3804. // TODO: When simulating a 64bit environment by defining AS_64BIT_PTR on a 32bit platform this code
  3805. // fails, because the stack given to asCGeneric is not prepared with two 64bit arguments.
  3806. // We must guarantee the order of the arguments which is why we copy them to this
  3807. // array. Otherwise the compiler may put them anywhere it likes, or even keep them
  3808. // in the registers which causes problem.
  3809. void *params[2] = {param1, param2};
  3810. asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, (asDWORD*)params);
  3811. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3812. f(&gen);
  3813. return *(bool*)gen.GetReturnPointer();
  3814. }
  3815. }
  3816. void *asCScriptEngine::CallAlloc(const asCObjectType *type) const
  3817. {
  3818. // Allocate 4 bytes as the smallest size. Otherwise CallSystemFunction may try to
  3819. // copy a DWORD onto a smaller memory block, in case the object type is return in registers.
  3820. // Pad to the next even 4 bytes to avoid asBC_CPY writing outside of allocated buffer for registered POD types
  3821. asUINT size = type->size;
  3822. if( size & 0x3 )
  3823. size += 4 - (size & 0x3);
  3824. #ifndef WIP_16BYTE_ALIGN
  3825. #if defined(AS_DEBUG)
  3826. return ((asALLOCFUNCDEBUG_t)userAlloc)(size, __FILE__, __LINE__);
  3827. #else
  3828. return userAlloc(size);
  3829. #endif
  3830. #else
  3831. #if defined(AS_DEBUG)
  3832. return ((asALLOCALIGNEDFUNCDEBUG_t)userAllocAligned)(size, type->alignment, __FILE__, __LINE__);
  3833. #else
  3834. return userAllocAligned(size, type->alignment);
  3835. #endif
  3836. #endif
  3837. }
  3838. void asCScriptEngine::CallFree(void *obj) const
  3839. {
  3840. #ifndef WIP_16BYTE_ALIGN
  3841. userFree(obj);
  3842. #else
  3843. userFreeAligned(obj);
  3844. #endif
  3845. }
  3846. // interface
  3847. int asCScriptEngine::NotifyGarbageCollectorOfNewObject(void *obj, asIObjectType *type)
  3848. {
  3849. return gc.AddScriptObjectToGC(obj, static_cast<asCObjectType*>(type));
  3850. }
  3851. // interface
  3852. int asCScriptEngine::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, asIObjectType **type)
  3853. {
  3854. return gc.GetObjectInGC(idx, seqNbr, obj, type);
  3855. }
  3856. // interface
  3857. int asCScriptEngine::GarbageCollect(asDWORD flags, asUINT iterations)
  3858. {
  3859. int r = gc.GarbageCollect(flags, iterations);
  3860. if( r == 0 )
  3861. {
  3862. // Delete any modules that have been discarded previously but not
  3863. // removed due to being referred to by objects in the garbage collector
  3864. DeleteDiscardedModules();
  3865. }
  3866. return r;
  3867. }
  3868. // interface
  3869. void asCScriptEngine::GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const
  3870. {
  3871. gc.GetStatistics(currentSize, totalDestroyed, totalDetected, newObjects, totalNewDestroyed);
  3872. }
  3873. // interface
  3874. void asCScriptEngine::GCEnumCallback(void *reference)
  3875. {
  3876. gc.GCEnumCallback(reference);
  3877. }
  3878. int asCScriptEngine::GetTypeIdFromDataType(const asCDataType &dtIn) const
  3879. {
  3880. if( dtIn.IsNullHandle() ) return asTYPEID_VOID;
  3881. if( dtIn.GetObjectType() == 0 )
  3882. {
  3883. // Primitives have pre-fixed typeIds
  3884. switch( dtIn.GetTokenType() )
  3885. {
  3886. case ttVoid: return asTYPEID_VOID;
  3887. case ttBool: return asTYPEID_BOOL;
  3888. case ttInt8: return asTYPEID_INT8;
  3889. case ttInt16: return asTYPEID_INT16;
  3890. case ttInt: return asTYPEID_INT32;
  3891. case ttInt64: return asTYPEID_INT64;
  3892. case ttUInt8: return asTYPEID_UINT8;
  3893. case ttUInt16: return asTYPEID_UINT16;
  3894. case ttUInt: return asTYPEID_UINT32;
  3895. case ttUInt64: return asTYPEID_UINT64;
  3896. case ttFloat: return asTYPEID_FLOAT;
  3897. case ttDouble: return asTYPEID_DOUBLE;
  3898. default:
  3899. // All types should be covered by the above. The variable type is not really a type
  3900. asASSERT(dtIn.GetTokenType() == ttQuestion);
  3901. return -1;
  3902. }
  3903. }
  3904. int typeId = -1;
  3905. asCObjectType *ot = dtIn.GetObjectType();
  3906. if( ot != &functionBehaviours )
  3907. {
  3908. // Object's hold the typeId themselves
  3909. typeId = ot->typeId;
  3910. if( typeId == -1 )
  3911. {
  3912. ACQUIREEXCLUSIVE(engineRWLock);
  3913. // Make sure another thread didn't determine the typeId while we were waiting for the lock
  3914. if( ot->typeId == -1 )
  3915. {
  3916. typeId = typeIdSeqNbr++;
  3917. if( ot->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT;
  3918. else if( ot->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE;
  3919. else if( ot->flags & asOBJ_ENUM ) {} // TODO: Should we have a specific bit for this?
  3920. else typeId |= asTYPEID_APPOBJECT;
  3921. ot->typeId = typeId;
  3922. mapTypeIdToObjectType.Insert(typeId, ot);
  3923. }
  3924. RELEASEEXCLUSIVE(engineRWLock);
  3925. }
  3926. }
  3927. else
  3928. {
  3929. // This a funcdef, so we'll need to look in the map for the funcdef
  3930. // TODO: optimize: It shouldn't be necessary to exclusive lock when the typeId already exists
  3931. ACQUIREEXCLUSIVE(engineRWLock);
  3932. // Find the existing type id
  3933. asCScriptFunction *func = dtIn.GetFuncDef();
  3934. asASSERT(func);
  3935. asSMapNode<int,asCScriptFunction*> *cursor = 0;
  3936. mapTypeIdToFunction.MoveFirst(&cursor);
  3937. while( cursor )
  3938. {
  3939. if( mapTypeIdToFunction.GetValue(cursor) == func )
  3940. {
  3941. typeId = mapTypeIdToFunction.GetKey(cursor);
  3942. break;
  3943. }
  3944. mapTypeIdToFunction.MoveNext(&cursor, cursor);
  3945. }
  3946. // The type id doesn't exist, create it
  3947. if( typeId == -1 )
  3948. {
  3949. // Setup the type id for the funcdef
  3950. typeId = typeIdSeqNbr++;
  3951. typeId |= asTYPEID_APPOBJECT;
  3952. mapTypeIdToFunction.Insert(typeId, func);
  3953. }
  3954. RELEASEEXCLUSIVE(engineRWLock);
  3955. }
  3956. // Add flags according to the requested type
  3957. if( dtIn.GetObjectType() && !(dtIn.GetObjectType()->flags & asOBJ_ASHANDLE) )
  3958. {
  3959. // The ASHANDLE types behave like handles, but are really
  3960. // value types so the typeId is never returned as a handle
  3961. if( dtIn.IsObjectHandle() )
  3962. typeId |= asTYPEID_OBJHANDLE;
  3963. if( dtIn.IsHandleToConst() )
  3964. typeId |= asTYPEID_HANDLETOCONST;
  3965. }
  3966. return typeId;
  3967. }
  3968. asCDataType asCScriptEngine::GetDataTypeFromTypeId(int typeId) const
  3969. {
  3970. int baseId = typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR);
  3971. if( typeId <= asTYPEID_DOUBLE )
  3972. {
  3973. eTokenType type[] = {ttVoid, ttBool, ttInt8, ttInt16, ttInt, ttInt64, ttUInt8, ttUInt16, ttUInt, ttUInt64, ttFloat, ttDouble};
  3974. return asCDataType::CreatePrimitive(type[typeId], false);
  3975. }
  3976. // First check if the typeId is an object type
  3977. asCObjectType *ot = 0;
  3978. ACQUIRESHARED(engineRWLock);
  3979. asSMapNode<int,asCObjectType*> *cursor = 0;
  3980. if( mapTypeIdToObjectType.MoveTo(&cursor, baseId) )
  3981. ot = mapTypeIdToObjectType.GetValue(cursor);
  3982. RELEASESHARED(engineRWLock);
  3983. if( ot )
  3984. {
  3985. asCDataType dt = asCDataType::CreateObject(ot, false);
  3986. if( typeId & asTYPEID_OBJHANDLE )
  3987. dt.MakeHandle(true, true);
  3988. if( typeId & asTYPEID_HANDLETOCONST )
  3989. dt.MakeHandleToConst(true);
  3990. return dt;
  3991. }
  3992. // Then check if it is a funcdef
  3993. asCScriptFunction *func = 0;
  3994. ACQUIRESHARED(engineRWLock);
  3995. asSMapNode<int,asCScriptFunction*> *cursor2 = 0;
  3996. if( mapTypeIdToFunction.MoveTo(&cursor2, baseId) )
  3997. func = mapTypeIdToFunction.GetValue(cursor2);
  3998. RELEASESHARED(engineRWLock);
  3999. if( func )
  4000. {
  4001. asCDataType dt = asCDataType::CreateFuncDef(func);
  4002. if( typeId & asTYPEID_OBJHANDLE )
  4003. dt.MakeHandle(true, true);
  4004. if( typeId & asTYPEID_HANDLETOCONST )
  4005. dt.MakeHandleToConst(true);
  4006. return dt;
  4007. }
  4008. return asCDataType();
  4009. }
  4010. asCObjectType *asCScriptEngine::GetObjectTypeFromTypeId(int typeId) const
  4011. {
  4012. asCDataType dt = GetDataTypeFromTypeId(typeId);
  4013. return dt.GetObjectType();
  4014. }
  4015. void asCScriptEngine::RemoveFromTypeIdMap(asCObjectType *type)
  4016. {
  4017. ACQUIREEXCLUSIVE(engineRWLock);
  4018. asSMapNode<int,asCObjectType*> *cursor = 0;
  4019. mapTypeIdToObjectType.MoveFirst(&cursor);
  4020. while( cursor )
  4021. {
  4022. if( mapTypeIdToObjectType.GetValue(cursor) == type )
  4023. {
  4024. mapTypeIdToObjectType.Erase(cursor);
  4025. break;
  4026. }
  4027. mapTypeIdToObjectType.MoveNext(&cursor, cursor);
  4028. }
  4029. RELEASEEXCLUSIVE(engineRWLock);
  4030. }
  4031. // interface
  4032. asIObjectType *asCScriptEngine::GetObjectTypeByDecl(const char *decl) const
  4033. {
  4034. asCDataType dt;
  4035. // This cast is ok, because we are not changing anything in the engine
  4036. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  4037. // Don't write parser errors to the message callback
  4038. bld.silent = true;
  4039. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  4040. if( r < 0 )
  4041. return 0;
  4042. return dt.GetObjectType();
  4043. }
  4044. // interface
  4045. int asCScriptEngine::GetTypeIdByDecl(const char *decl) const
  4046. {
  4047. asCDataType dt;
  4048. // This cast is ok, because we are not changing anything in the engine
  4049. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  4050. // Don't write parser errors to the message callback
  4051. bld.silent = true;
  4052. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  4053. if( r < 0 )
  4054. return asINVALID_TYPE;
  4055. return GetTypeIdFromDataType(dt);
  4056. }
  4057. // interface
  4058. const char *asCScriptEngine::GetTypeDeclaration(int typeId, bool includeNamespace) const
  4059. {
  4060. asCDataType dt = GetDataTypeFromTypeId(typeId);
  4061. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  4062. *tempString = dt.Format(defaultNamespace, includeNamespace);
  4063. return tempString->AddressOf();
  4064. }
  4065. // interface
  4066. int asCScriptEngine::GetSizeOfPrimitiveType(int typeId) const
  4067. {
  4068. asCDataType dt = GetDataTypeFromTypeId(typeId);
  4069. if( !dt.IsPrimitive() ) return 0;
  4070. return dt.GetSizeInMemoryBytes();
  4071. }
  4072. // interface
  4073. int asCScriptEngine::RefCastObject(void *obj, asIObjectType *fromType, asIObjectType *toType, void **newPtr, bool useOnlyImplicitCast)
  4074. {
  4075. if( newPtr == 0 ) return asINVALID_ARG;
  4076. *newPtr = 0;
  4077. if( fromType == 0 || toType == 0 ) return asINVALID_ARG;
  4078. // A null-pointer can always be cast to another type, so it will always be successful
  4079. if( obj == 0 )
  4080. return asSUCCESS;
  4081. // This method doesn't support casting function pointers, since they cannot be described with just an object type
  4082. if( fromType->GetFlags() & asOBJ_SCRIPT_FUNCTION )
  4083. return asNOT_SUPPORTED;
  4084. if( fromType == toType )
  4085. {
  4086. *newPtr = obj;
  4087. AddRefScriptObject(*newPtr, toType);
  4088. return asSUCCESS;
  4089. }
  4090. // Look for ref cast behaviours
  4091. asCScriptFunction *universalCastFunc = 0;
  4092. asCObjectType *from = reinterpret_cast<asCObjectType*>(fromType);
  4093. for( asUINT n = 0; n < from->methods.GetLength(); n++ )
  4094. {
  4095. asCScriptFunction *func = scriptFunctions[from->methods[n]];
  4096. if( func->name == "opImplCast" ||
  4097. (!useOnlyImplicitCast && func->name == "opCast") )
  4098. {
  4099. if( func->returnType.GetObjectType() == toType )
  4100. {
  4101. *newPtr = CallObjectMethodRetPtr(obj, func->id);
  4102. // The ref cast behaviour returns a handle with incremented
  4103. // ref counter, so there is no need to call AddRef explicitly
  4104. // unless the function is registered with autohandle
  4105. if( func->sysFuncIntf->returnAutoHandle )
  4106. AddRefScriptObject(*newPtr, toType);
  4107. return asSUCCESS;
  4108. }
  4109. else
  4110. {
  4111. asASSERT( func->returnType.GetTokenType() == ttVoid &&
  4112. func->parameterTypes.GetLength() == 1 &&
  4113. func->parameterTypes[0].GetTokenType() == ttQuestion );
  4114. universalCastFunc = func;
  4115. }
  4116. }
  4117. }
  4118. // One last chance if the object has a void opCast(?&out) behaviour
  4119. if( universalCastFunc )
  4120. {
  4121. // TODO: Add proper error handling
  4122. asIScriptContext *ctx = RequestContext();
  4123. ctx->Prepare(universalCastFunc);
  4124. ctx->SetObject(obj);
  4125. ctx->SetArgVarType(0, newPtr, toType->GetTypeId() | asTYPEID_OBJHANDLE);
  4126. ctx->Execute();
  4127. ReturnContext(ctx);
  4128. // The opCast(?&out) method already incremented the
  4129. // refCount so there is no need to do it manually
  4130. return asSUCCESS;
  4131. }
  4132. // For script classes and interfaces there is a quick route
  4133. if( (fromType->GetFlags() & asOBJ_SCRIPT_OBJECT) && (toType->GetFlags() & asOBJ_SCRIPT_OBJECT) )
  4134. {
  4135. if( fromType == toType )
  4136. {
  4137. *newPtr = obj;
  4138. reinterpret_cast<asCScriptObject*>(*newPtr)->AddRef();
  4139. return asSUCCESS;
  4140. }
  4141. // Up casts to base class or interface can be done implicitly
  4142. if( fromType->DerivesFrom(toType) ||
  4143. fromType->Implements(toType) )
  4144. {
  4145. *newPtr = obj;
  4146. reinterpret_cast<asCScriptObject*>(*newPtr)->AddRef();
  4147. return asSUCCESS;
  4148. }
  4149. // Down casts to derived class or from interface can only be done explicitly
  4150. if( !useOnlyImplicitCast )
  4151. {
  4152. if( toType->Implements(fromType) ||
  4153. toType->DerivesFrom(fromType) )
  4154. {
  4155. *newPtr = obj;
  4156. reinterpret_cast<asCScriptObject*>(*newPtr)->AddRef();
  4157. return asSUCCESS;
  4158. }
  4159. // Get the true type of the object so the explicit cast can evaluate all possibilities
  4160. asIObjectType *from = reinterpret_cast<asCScriptObject*>(obj)->GetObjectType();
  4161. if( from->DerivesFrom(toType) ||
  4162. from->Implements(toType) )
  4163. {
  4164. *newPtr = obj;
  4165. reinterpret_cast<asCScriptObject*>(*newPtr)->AddRef();
  4166. return asSUCCESS;
  4167. }
  4168. }
  4169. }
  4170. // The cast is not available, but it is still a success
  4171. return asSUCCESS;
  4172. }
  4173. // interface
  4174. void *asCScriptEngine::CreateScriptObject(const asIObjectType *type)
  4175. {
  4176. if( type == 0 ) return 0;
  4177. asCObjectType *objType = const_cast<asCObjectType*>(reinterpret_cast<const asCObjectType *>(type));
  4178. void *ptr = 0;
  4179. // Check that there is a default factory for ref types
  4180. if( objType->beh.factory == 0 && (objType->flags & asOBJ_REF) )
  4181. {
  4182. asCString str;
  4183. str.Format(TXT_FAILED_IN_FUNC_s_d, "CreateScriptObject", asNO_FUNCTION);
  4184. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  4185. return 0;
  4186. }
  4187. // Construct the object
  4188. if( objType->flags & asOBJ_SCRIPT_OBJECT )
  4189. {
  4190. // Call the script class' default factory with a context
  4191. ptr = ScriptObjectFactory(objType, this);
  4192. }
  4193. else if( objType->flags & asOBJ_TEMPLATE )
  4194. {
  4195. // The registered factory that takes the object type is moved
  4196. // to the construct behaviour when the type is instantiated
  4197. #ifdef AS_NO_EXCEPTIONS
  4198. ptr = CallGlobalFunctionRetPtr(objType->beh.construct, objType);
  4199. #else
  4200. try
  4201. {
  4202. ptr = CallGlobalFunctionRetPtr(objType->beh.construct, objType);
  4203. }
  4204. catch(...)
  4205. {
  4206. asIScriptContext *ctx = asGetActiveContext();
  4207. if( ctx )
  4208. ctx->SetException(TXT_EXCEPTION_CAUGHT);
  4209. }
  4210. #endif
  4211. }
  4212. else if( objType->flags & asOBJ_REF )
  4213. {
  4214. // Call the default factory directly
  4215. #ifdef AS_NO_EXCEPTIONS
  4216. ptr = CallGlobalFunctionRetPtr(objType->beh.factory);
  4217. #else
  4218. try
  4219. {
  4220. ptr = CallGlobalFunctionRetPtr(objType->beh.factory);
  4221. }
  4222. catch(...)
  4223. {
  4224. asIScriptContext *ctx = asGetActiveContext();
  4225. if( ctx )
  4226. ctx->SetException(TXT_EXCEPTION_CAUGHT);
  4227. }
  4228. #endif
  4229. }
  4230. else
  4231. {
  4232. // Make sure there is a default constructor or that it is a POD type
  4233. if( objType->beh.construct == 0 && !(objType->flags & asOBJ_POD) )
  4234. {
  4235. asCString str;
  4236. str.Format(TXT_FAILED_IN_FUNC_s_d, "CreateScriptObject", asNO_FUNCTION);
  4237. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  4238. return 0;
  4239. }
  4240. // Manually allocate the memory, then call the default constructor
  4241. ptr = CallAlloc(objType);
  4242. int funcIndex = objType->beh.construct;
  4243. if( funcIndex )
  4244. {
  4245. #ifdef AS_NO_EXCEPTIONS
  4246. CallObjectMethod(ptr, funcIndex);
  4247. #else
  4248. try
  4249. {
  4250. CallObjectMethod(ptr, funcIndex);
  4251. }
  4252. catch(...)
  4253. {
  4254. asIScriptContext *ctx = asGetActiveContext();
  4255. if( ctx )
  4256. ctx->SetException(TXT_EXCEPTION_CAUGHT);
  4257. // Free the memory
  4258. CallFree(ptr);
  4259. ptr = 0;
  4260. }
  4261. #endif
  4262. }
  4263. }
  4264. return ptr;
  4265. }
  4266. // interface
  4267. void *asCScriptEngine::CreateUninitializedScriptObject(const asIObjectType *type)
  4268. {
  4269. // This function only works for script classes. Registered types cannot be created this way.
  4270. if( type == 0 || !(type->GetFlags() & asOBJ_SCRIPT_OBJECT) )
  4271. return 0;
  4272. asCObjectType *objType = const_cast<asCObjectType*>(reinterpret_cast<const asCObjectType*>(type));
  4273. // Construct the object, but do not call the actual constructor that initializes the members
  4274. // The initialization will be done by the application afterwards, e.g. through serialization.
  4275. asCScriptObject *obj = reinterpret_cast<asCScriptObject*>(CallAlloc(objType));
  4276. // Pre-initialize the memory so there are no invalid pointers
  4277. ScriptObject_ConstructUnitialized(objType, obj);
  4278. return obj;
  4279. }
  4280. // interface
  4281. void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, const asIObjectType *type)
  4282. {
  4283. if( origObj == 0 || type == 0 ) return 0;
  4284. void *newObj = 0;
  4285. const asCObjectType *ot = reinterpret_cast<const asCObjectType*>(type);
  4286. // TODO: runtime optimize: Should call copy factory for ref types too
  4287. if( ot->beh.copyconstruct )
  4288. {
  4289. // Manually allocate the memory, then call the copy constructor
  4290. newObj = CallAlloc(ot);
  4291. #ifdef AS_NO_EXCEPTIONS
  4292. CallObjectMethod(newObj, origObj, ot->beh.copyconstruct);
  4293. #else
  4294. try
  4295. {
  4296. CallObjectMethod(newObj, origObj, ot->beh.copyconstruct);
  4297. }
  4298. catch(...)
  4299. {
  4300. asIScriptContext *ctx = asGetActiveContext();
  4301. if( ctx )
  4302. ctx->SetException(TXT_EXCEPTION_CAUGHT);
  4303. // Free the memory
  4304. CallFree(newObj);
  4305. newObj = 0;
  4306. }
  4307. #endif
  4308. }
  4309. else
  4310. {
  4311. // Allocate the object and then do a value assign
  4312. newObj = CreateScriptObject(type);
  4313. if( newObj == 0 ) return 0;
  4314. AssignScriptObject(newObj, origObj, type);
  4315. }
  4316. return newObj;
  4317. }
  4318. // internal
  4319. void asCScriptEngine::ConstructScriptObjectCopy(void *mem, void *obj, asCObjectType *type)
  4320. {
  4321. if( type == 0 || mem == 0 || obj == 0 ) return;
  4322. // This function is only meant to be used for value types
  4323. asASSERT( type->flags & asOBJ_VALUE );
  4324. // Call the copy constructor if available, else call the default constructor followed by the opAssign
  4325. int funcIndex = type->beh.copyconstruct;
  4326. if( funcIndex )
  4327. {
  4328. CallObjectMethod(mem, obj, funcIndex);
  4329. }
  4330. else
  4331. {
  4332. funcIndex = type->beh.construct;
  4333. if( funcIndex )
  4334. CallObjectMethod(mem, funcIndex);
  4335. AssignScriptObject(mem, obj, type);
  4336. }
  4337. }
  4338. // interface
  4339. int asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, const asIObjectType *type)
  4340. {
  4341. // TODO: Warn about invalid call in message stream
  4342. // TODO: Should a script exception be set in case a context is active?
  4343. if( type == 0 || dstObj == 0 || srcObj == 0 ) return asINVALID_ARG;
  4344. const asCObjectType *objType = reinterpret_cast<const asCObjectType*>(type);
  4345. // If value assign for ref types has been disabled, then don't do anything if the type is a ref type
  4346. if( ep.disallowValueAssignForRefType && (objType->flags & asOBJ_REF) && !(objType->flags & asOBJ_SCOPED) )
  4347. return asNOT_SUPPORTED;
  4348. // Must not copy if the opAssign is not available and the object is not a POD object
  4349. if( objType->beh.copy )
  4350. {
  4351. asCScriptFunction *func = scriptFunctions[objType->beh.copy];
  4352. if( func->funcType == asFUNC_SYSTEM )
  4353. CallObjectMethod(dstObj, srcObj, objType->beh.copy);
  4354. else
  4355. {
  4356. // Call the script class' opAssign method
  4357. asASSERT( objType->flags & asOBJ_SCRIPT_OBJECT );
  4358. reinterpret_cast<asCScriptObject*>(dstObj)->CopyFrom(reinterpret_cast<asCScriptObject*>(srcObj));
  4359. }
  4360. }
  4361. else if( objType->size && (objType->flags & asOBJ_POD) )
  4362. {
  4363. memcpy(dstObj, srcObj, objType->size);
  4364. }
  4365. return asSUCCESS;
  4366. }
  4367. // interface
  4368. void asCScriptEngine::AddRefScriptObject(void *obj, const asIObjectType *type)
  4369. {
  4370. // Make sure it is not a null pointer
  4371. if( obj == 0 || type == 0 ) return;
  4372. const asCObjectType *objType = static_cast<const asCObjectType *>(type);
  4373. if( objType->beh.addref )
  4374. {
  4375. // Call the addref behaviour
  4376. CallObjectMethod(obj, objType->beh.addref);
  4377. }
  4378. }
  4379. // interface
  4380. void asCScriptEngine::ReleaseScriptObject(void *obj, const asIObjectType *type)
  4381. {
  4382. // Make sure it is not a null pointer
  4383. if( obj == 0 || type == 0 ) return;
  4384. const asCObjectType *objType = static_cast<const asCObjectType *>(type);
  4385. if( objType->flags & asOBJ_REF )
  4386. {
  4387. asASSERT( (objType->flags & asOBJ_NOCOUNT) || objType->beh.release );
  4388. if( objType->beh.release )
  4389. {
  4390. // Call the release behaviour
  4391. CallObjectMethod(obj, objType->beh.release);
  4392. }
  4393. }
  4394. else
  4395. {
  4396. // Call the destructor
  4397. if( objType->beh.destruct )
  4398. CallObjectMethod(obj, objType->beh.destruct);
  4399. else if( objType->flags & asOBJ_LIST_PATTERN )
  4400. DestroyList((asBYTE*)obj, objType);
  4401. // We'll have to trust that the memory for the object was allocated with CallAlloc.
  4402. // This is true if the object was created in the context, or with CreateScriptObject.
  4403. // Then free the memory
  4404. CallFree(obj);
  4405. }
  4406. }
  4407. #ifdef AS_DEPRECATED
  4408. // Deprecated since 2.30.0, 2014-11-04
  4409. // interface
  4410. bool asCScriptEngine::IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const
  4411. {
  4412. // if equal, then it is obvious they are compatible
  4413. if( objTypeId == handleTypeId )
  4414. return true;
  4415. // Get the actual data types from the type ids
  4416. asCDataType objDt = GetDataTypeFromTypeId(objTypeId);
  4417. asCDataType hdlDt = GetDataTypeFromTypeId(handleTypeId);
  4418. // A handle to const cannot be passed to a handle that is not referencing a const object
  4419. if( objDt.IsHandleToConst() && !hdlDt.IsHandleToConst() )
  4420. return false;
  4421. if( objDt.GetObjectType() == hdlDt.GetObjectType() )
  4422. {
  4423. // The object type is equal
  4424. return true;
  4425. }
  4426. else if( objDt.IsScriptObject() && obj )
  4427. {
  4428. // Get the true type from the object instance
  4429. asCObjectType *objType = ((asCScriptObject*)obj)->objType;
  4430. // Check if the object implements the interface, or derives from the base class
  4431. // This will also return true, if the requested handle type is an exact match for the object type
  4432. if( objType->Implements(hdlDt.GetObjectType()) ||
  4433. objType->DerivesFrom(hdlDt.GetObjectType()) )
  4434. return true;
  4435. }
  4436. return false;
  4437. }
  4438. #endif
  4439. // interface
  4440. int asCScriptEngine::BeginConfigGroup(const char *groupName)
  4441. {
  4442. // Make sure the group name doesn't already exist
  4443. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4444. {
  4445. if( configGroups[n]->groupName == groupName )
  4446. return asNAME_TAKEN;
  4447. }
  4448. if( currentGroup != &defaultGroup )
  4449. return asNOT_SUPPORTED;
  4450. asCConfigGroup *group = asNEW(asCConfigGroup)();
  4451. if( group == 0 )
  4452. return asOUT_OF_MEMORY;
  4453. group->groupName = groupName;
  4454. configGroups.PushLast(group);
  4455. currentGroup = group;
  4456. return 0;
  4457. }
  4458. // interface
  4459. int asCScriptEngine::EndConfigGroup()
  4460. {
  4461. // Raise error if trying to end the default config
  4462. if( currentGroup == &defaultGroup )
  4463. return asERROR;
  4464. currentGroup = &defaultGroup;
  4465. return 0;
  4466. }
  4467. // interface
  4468. int asCScriptEngine::RemoveConfigGroup(const char *groupName)
  4469. {
  4470. // It is not allowed to remove a group that is still in use.
  4471. // It would be possible to change the code in such a way that
  4472. // the group could be removed even though it was still in use,
  4473. // but that would cause severe negative impact on runtime
  4474. // performance, since the VM would then have to be able handle
  4475. // situations where the types, functions, and global variables
  4476. // can be removed at any time.
  4477. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4478. {
  4479. if( configGroups[n]->groupName == groupName )
  4480. {
  4481. asCConfigGroup *group = configGroups[n];
  4482. // Remove any unused generated template instances
  4483. // before verifying if the config group is still in use.
  4484. // RemoveTemplateInstanceType() checks if the instance is in use
  4485. for( asUINT g = generatedTemplateTypes.GetLength(); g-- > 0; )
  4486. RemoveTemplateInstanceType(generatedTemplateTypes[g]);
  4487. // Make sure the group isn't referenced by anyone
  4488. if( group->refCount > 0 )
  4489. return asCONFIG_GROUP_IS_IN_USE;
  4490. // Verify if any objects registered in this group is still alive
  4491. if( group->HasLiveObjects() )
  4492. return asCONFIG_GROUP_IS_IN_USE;
  4493. // Remove the group from the list
  4494. if( n == configGroups.GetLength() - 1 )
  4495. configGroups.PopLast();
  4496. else
  4497. configGroups[n] = configGroups.PopLast();
  4498. // Remove the configurations registered with this group
  4499. group->RemoveConfiguration(this);
  4500. asDELETE(group,asCConfigGroup);
  4501. }
  4502. }
  4503. return 0;
  4504. }
  4505. asCConfigGroup *asCScriptEngine::FindConfigGroupForFunction(int funcId) const
  4506. {
  4507. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4508. {
  4509. // Check global functions
  4510. asUINT m;
  4511. for( m = 0; m < configGroups[n]->scriptFunctions.GetLength(); m++ )
  4512. {
  4513. if( configGroups[n]->scriptFunctions[m]->id == funcId )
  4514. return configGroups[n];
  4515. }
  4516. }
  4517. return 0;
  4518. }
  4519. asCConfigGroup *asCScriptEngine::FindConfigGroupForGlobalVar(int gvarId) const
  4520. {
  4521. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4522. {
  4523. for( asUINT m = 0; m < configGroups[n]->globalProps.GetLength(); m++ )
  4524. {
  4525. if( int(configGroups[n]->globalProps[m]->id) == gvarId )
  4526. return configGroups[n];
  4527. }
  4528. }
  4529. return 0;
  4530. }
  4531. asCConfigGroup *asCScriptEngine::FindConfigGroupForObjectType(const asCObjectType *objType) const
  4532. {
  4533. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4534. {
  4535. for( asUINT m = 0; m < configGroups[n]->objTypes.GetLength(); m++ )
  4536. {
  4537. if( configGroups[n]->objTypes[m] == objType )
  4538. return configGroups[n];
  4539. }
  4540. }
  4541. return 0;
  4542. }
  4543. asCConfigGroup *asCScriptEngine::FindConfigGroupForFuncDef(const asCScriptFunction *funcDef) const
  4544. {
  4545. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  4546. {
  4547. asCScriptFunction *f = const_cast<asCScriptFunction*>(funcDef);
  4548. if( configGroups[n]->funcDefs.Exists(f) )
  4549. return configGroups[n];
  4550. }
  4551. return 0;
  4552. }
  4553. // interface
  4554. asDWORD asCScriptEngine::SetDefaultAccessMask(asDWORD defaultMask)
  4555. {
  4556. asDWORD old = defaultAccessMask;
  4557. defaultAccessMask = defaultMask;
  4558. return old;
  4559. }
  4560. int asCScriptEngine::GetNextScriptFunctionId()
  4561. {
  4562. // This function only returns the next function id that
  4563. // should be used. It doesn't update the internal arrays.
  4564. if( freeScriptFunctionIds.GetLength() )
  4565. return freeScriptFunctionIds[freeScriptFunctionIds.GetLength()-1];
  4566. return (int)scriptFunctions.GetLength();
  4567. }
  4568. void asCScriptEngine::AddScriptFunction(asCScriptFunction *func)
  4569. {
  4570. // Update the internal arrays with the function id that is now used
  4571. if( freeScriptFunctionIds.GetLength() && freeScriptFunctionIds[freeScriptFunctionIds.GetLength()-1] == func->id )
  4572. freeScriptFunctionIds.PopLast();
  4573. if( asUINT(func->id) == scriptFunctions.GetLength() )
  4574. scriptFunctions.PushLast(func);
  4575. else
  4576. {
  4577. // The slot should be empty or already set with the function, which happens if an existing shared function is reused
  4578. asASSERT( scriptFunctions[func->id] == 0 || scriptFunctions[func->id] == func );
  4579. scriptFunctions[func->id] = func;
  4580. }
  4581. }
  4582. void asCScriptEngine::RemoveScriptFunction(asCScriptFunction *func)
  4583. {
  4584. if( func == 0 || func->id < 0 ) return;
  4585. int id = func->id & ~FUNC_IMPORTED;
  4586. if( func->funcType == asFUNC_IMPORTED )
  4587. {
  4588. if( id >= (int)importedFunctions.GetLength() ) return;
  4589. if( importedFunctions[id] )
  4590. {
  4591. // Remove the function from the list of script functions
  4592. if( id == (int)importedFunctions.GetLength() - 1 )
  4593. {
  4594. importedFunctions.PopLast();
  4595. }
  4596. else
  4597. {
  4598. importedFunctions[id] = 0;
  4599. freeImportedFunctionIdxs.PushLast(id);
  4600. }
  4601. }
  4602. }
  4603. else
  4604. {
  4605. if( id >= (int)scriptFunctions.GetLength() ) return;
  4606. asASSERT( func == scriptFunctions[id] );
  4607. if( scriptFunctions[id] )
  4608. {
  4609. // Remove the function from the list of script functions
  4610. if( id == (int)scriptFunctions.GetLength() - 1 )
  4611. {
  4612. scriptFunctions.PopLast();
  4613. }
  4614. else
  4615. {
  4616. scriptFunctions[id] = 0;
  4617. freeScriptFunctionIds.PushLast(id);
  4618. }
  4619. // Is the function used as signature id?
  4620. if( func->signatureId == id )
  4621. {
  4622. // Remove the signature id
  4623. signatureIds.RemoveValue(func);
  4624. // Update all functions using the signature id
  4625. int newSigId = 0;
  4626. for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
  4627. {
  4628. if( scriptFunctions[n] && scriptFunctions[n]->signatureId == id )
  4629. {
  4630. if( newSigId == 0 )
  4631. {
  4632. newSigId = scriptFunctions[n]->id;
  4633. signatureIds.PushLast(scriptFunctions[n]);
  4634. }
  4635. scriptFunctions[n]->signatureId = newSigId;
  4636. }
  4637. }
  4638. }
  4639. }
  4640. }
  4641. }
  4642. // internal
  4643. void asCScriptEngine::RemoveFuncdef(asCScriptFunction *funcdef)
  4644. {
  4645. funcDefs.RemoveValue(funcdef);
  4646. }
  4647. // interface
  4648. int asCScriptEngine::RegisterFuncdef(const char *decl)
  4649. {
  4650. if( decl == 0 ) return ConfigError(asINVALID_ARG, "RegisterFuncdef", decl, 0);
  4651. // Parse the function declaration
  4652. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_FUNCDEF);
  4653. if( func == 0 )
  4654. return ConfigError(asOUT_OF_MEMORY, "RegisterFuncdef", decl, 0);
  4655. asCBuilder bld(this, 0);
  4656. int r = bld.ParseFunctionDeclaration(0, decl, func, false, 0, 0, defaultNamespace);
  4657. if( r < 0 )
  4658. {
  4659. // Set as dummy function before deleting
  4660. func->funcType = asFUNC_DUMMY;
  4661. asDELETE(func,asCScriptFunction);
  4662. return ConfigError(asINVALID_DECLARATION, "RegisterFuncdef", decl, 0);
  4663. }
  4664. // Check name conflicts
  4665. r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace);
  4666. if( r < 0 )
  4667. {
  4668. asDELETE(func,asCScriptFunction);
  4669. return ConfigError(asNAME_TAKEN, "RegisterFuncdef", decl, 0);
  4670. }
  4671. func->id = GetNextScriptFunctionId();
  4672. AddScriptFunction(func);
  4673. funcDefs.PushLast(func);
  4674. func->AddRefInternal();
  4675. registeredFuncDefs.PushLast(func);
  4676. currentGroup->funcDefs.PushLast(func);
  4677. // If parameter type from other groups are used, add references
  4678. currentGroup->AddReferencesForFunc(this, func);
  4679. // Return the function id as success
  4680. return func->id;
  4681. }
  4682. // interface
  4683. asUINT asCScriptEngine::GetFuncdefCount() const
  4684. {
  4685. return asUINT(registeredFuncDefs.GetLength());
  4686. }
  4687. // interface
  4688. asIScriptFunction *asCScriptEngine::GetFuncdefByIndex(asUINT index) const
  4689. {
  4690. if( index >= registeredFuncDefs.GetLength() )
  4691. return 0;
  4692. return registeredFuncDefs[index];
  4693. }
  4694. // interface
  4695. // TODO: typedef: Accept complex types for the typedefs
  4696. int asCScriptEngine::RegisterTypedef(const char *type, const char *decl)
  4697. {
  4698. if( type == 0 ) return ConfigError(asINVALID_NAME, "RegisterTypedef", type, decl);
  4699. // Verify if the name has been registered as a type already
  4700. // TODO: Must check against registered funcdefs too
  4701. if( GetRegisteredObjectType(type, defaultNamespace) )
  4702. // Let the application recover from this error, for example if the same typedef is registered twice
  4703. return asALREADY_REGISTERED;
  4704. // Grab the data type
  4705. size_t tokenLen;
  4706. eTokenType token;
  4707. asCDataType dataType;
  4708. // Create the data type
  4709. token = tok.GetToken(decl, strlen(decl), &tokenLen);
  4710. switch(token)
  4711. {
  4712. case ttBool:
  4713. case ttInt:
  4714. case ttInt8:
  4715. case ttInt16:
  4716. case ttInt64:
  4717. case ttUInt:
  4718. case ttUInt8:
  4719. case ttUInt16:
  4720. case ttUInt64:
  4721. case ttFloat:
  4722. case ttDouble:
  4723. if( strlen(decl) != tokenLen )
  4724. {
  4725. return ConfigError(asINVALID_TYPE, "RegisterTypedef", type, decl);
  4726. }
  4727. break;
  4728. default:
  4729. return ConfigError(asINVALID_TYPE, "RegisterTypedef", type, decl);
  4730. }
  4731. dataType = asCDataType::CreatePrimitive(token, false);
  4732. // Make sure the name is not a reserved keyword
  4733. token = tok.GetToken(type, strlen(type), &tokenLen);
  4734. if( token != ttIdentifier || strlen(type) != tokenLen )
  4735. return ConfigError(asINVALID_NAME, "RegisterTypedef", type, decl);
  4736. asCBuilder bld(this, 0);
  4737. int r = bld.CheckNameConflict(type, 0, 0, defaultNamespace);
  4738. if( r < 0 )
  4739. return ConfigError(asNAME_TAKEN, "RegisterTypedef", type, decl);
  4740. // Don't have to check against members of object
  4741. // types as they are allowed to use the names
  4742. // Put the data type in the list
  4743. asCObjectType *object = asNEW(asCObjectType)(this);
  4744. if( object == 0 )
  4745. return ConfigError(asOUT_OF_MEMORY, "RegisterTypedef", type, decl);
  4746. object->flags = asOBJ_TYPEDEF;
  4747. object->size = dataType.GetSizeInMemoryBytes();
  4748. object->name = type;
  4749. object->nameSpace = defaultNamespace;
  4750. object->templateSubTypes.PushLast(dataType);
  4751. allRegisteredTypes.Insert(asSNameSpaceNamePair(object->nameSpace, object->name), object);
  4752. registeredTypeDefs.PushLast(object);
  4753. currentGroup->objTypes.PushLast(object);
  4754. return asSUCCESS;
  4755. }
  4756. // interface
  4757. asUINT asCScriptEngine::GetTypedefCount() const
  4758. {
  4759. return asUINT(registeredTypeDefs.GetLength());
  4760. }
  4761. // interface
  4762. const char *asCScriptEngine::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace, const char **configGroup, asDWORD *accessMask) const
  4763. {
  4764. if( index >= registeredTypeDefs.GetLength() )
  4765. return 0;
  4766. if( typeId )
  4767. *typeId = GetTypeIdFromDataType(registeredTypeDefs[index]->templateSubTypes[0]);
  4768. if( configGroup )
  4769. {
  4770. asCConfigGroup *group = FindConfigGroupForObjectType(registeredTypeDefs[index]);
  4771. if( group )
  4772. *configGroup = group->groupName.AddressOf();
  4773. else
  4774. *configGroup = 0;
  4775. }
  4776. if( accessMask )
  4777. *accessMask = registeredTypeDefs[index]->accessMask;
  4778. if( nameSpace )
  4779. *nameSpace = registeredTypeDefs[index]->nameSpace->name.AddressOf();
  4780. return registeredTypeDefs[index]->name.AddressOf();
  4781. }
  4782. // interface
  4783. int asCScriptEngine::RegisterEnum(const char *name)
  4784. {
  4785. // Check the name
  4786. if( NULL == name )
  4787. return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0);
  4788. // Verify if the name has been registered as a type already
  4789. if( GetRegisteredObjectType(name, defaultNamespace) )
  4790. return asALREADY_REGISTERED;
  4791. // Use builder to parse the datatype
  4792. asCDataType dt;
  4793. asCBuilder bld(this, 0);
  4794. bool oldMsgCallback = msgCallback; msgCallback = false;
  4795. int r = bld.ParseDataType(name, &dt, defaultNamespace);
  4796. msgCallback = oldMsgCallback;
  4797. if( r >= 0 )
  4798. {
  4799. // If it is not in the defaultNamespace then the type was successfully parsed because
  4800. // it is declared in a parent namespace which shouldn't be treated as an error
  4801. if( dt.GetObjectType() && dt.GetObjectType()->nameSpace == defaultNamespace )
  4802. return ConfigError(asERROR, "RegisterEnum", name, 0);
  4803. }
  4804. // Make sure the name is not a reserved keyword
  4805. size_t tokenLen;
  4806. int token = tok.GetToken(name, strlen(name), &tokenLen);
  4807. if( token != ttIdentifier || strlen(name) != tokenLen )
  4808. return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0);
  4809. r = bld.CheckNameConflict(name, 0, 0, defaultNamespace);
  4810. if( r < 0 )
  4811. return ConfigError(asNAME_TAKEN, "RegisterEnum", name, 0);
  4812. asCObjectType *st = asNEW(asCObjectType)(this);
  4813. if( st == 0 )
  4814. return ConfigError(asOUT_OF_MEMORY, "RegisterEnum", name, 0);
  4815. asCDataType dataType;
  4816. dataType.CreatePrimitive(ttInt, false);
  4817. st->flags = asOBJ_ENUM | asOBJ_SHARED;
  4818. st->size = 4;
  4819. st->name = name;
  4820. st->nameSpace = defaultNamespace;
  4821. allRegisteredTypes.Insert(asSNameSpaceNamePair(st->nameSpace, st->name), st);
  4822. registeredEnums.PushLast(st);
  4823. currentGroup->objTypes.PushLast(st);
  4824. return asSUCCESS;
  4825. }
  4826. // interface
  4827. int asCScriptEngine::RegisterEnumValue(const char *typeName, const char *valueName, int value)
  4828. {
  4829. // Verify that the correct config group is used
  4830. if( currentGroup->FindType(typeName) == 0 )
  4831. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterEnumValue", typeName, valueName);
  4832. asCDataType dt;
  4833. int r;
  4834. asCBuilder bld(this, 0);
  4835. r = bld.ParseDataType(typeName, &dt, defaultNamespace);
  4836. if( r < 0 )
  4837. return ConfigError(r, "RegisterEnumValue", typeName, valueName);
  4838. // Store the enum value
  4839. asCObjectType *ot = dt.GetObjectType();
  4840. if( ot == 0 || !(ot->flags & asOBJ_ENUM) )
  4841. return ConfigError(asINVALID_TYPE, "RegisterEnumValue", typeName, valueName);
  4842. if( NULL == valueName )
  4843. return ConfigError(asINVALID_NAME, "RegisterEnumValue", typeName, valueName);
  4844. asUINT tokenLen = 0;
  4845. asETokenClass tokenClass = ParseToken(valueName, 0, &tokenLen);
  4846. if( tokenClass != asTC_IDENTIFIER || tokenLen != strlen(valueName) )
  4847. return ConfigError(asINVALID_NAME, "RegisterEnumValue", typeName, valueName);
  4848. for( unsigned int n = 0; n < ot->enumValues.GetLength(); n++ )
  4849. {
  4850. if( ot->enumValues[n]->name == valueName )
  4851. return ConfigError(asALREADY_REGISTERED, "RegisterEnumValue", typeName, valueName);
  4852. }
  4853. asSEnumValue *e = asNEW(asSEnumValue);
  4854. if( e == 0 )
  4855. return ConfigError(asOUT_OF_MEMORY, "RegisterEnumValue", typeName, valueName);
  4856. e->name = valueName;
  4857. e->value = value;
  4858. ot->enumValues.PushLast(e);
  4859. return asSUCCESS;
  4860. }
  4861. // interface
  4862. asUINT asCScriptEngine::GetEnumCount() const
  4863. {
  4864. return asUINT(registeredEnums.GetLength());
  4865. }
  4866. // interface
  4867. const char *asCScriptEngine::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace, const char **configGroup, asDWORD *accessMask) const
  4868. {
  4869. if( index >= registeredEnums.GetLength() )
  4870. return 0;
  4871. if( configGroup )
  4872. {
  4873. asCConfigGroup *group = FindConfigGroupForObjectType(registeredEnums[index]);
  4874. if( group )
  4875. *configGroup = group->groupName.AddressOf();
  4876. else
  4877. *configGroup = 0;
  4878. }
  4879. if( accessMask )
  4880. *accessMask = registeredEnums[index]->accessMask;
  4881. if( enumTypeId )
  4882. *enumTypeId = GetTypeIdFromDataType(asCDataType::CreateObject(registeredEnums[index], false));
  4883. if( nameSpace )
  4884. *nameSpace = registeredEnums[index]->nameSpace->name.AddressOf();
  4885. return registeredEnums[index]->name.AddressOf();
  4886. }
  4887. // interface
  4888. int asCScriptEngine::GetEnumValueCount(int enumTypeId) const
  4889. {
  4890. asCDataType dt = GetDataTypeFromTypeId(enumTypeId);
  4891. asCObjectType *t = dt.GetObjectType();
  4892. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  4893. return asINVALID_TYPE;
  4894. return (int)t->enumValues.GetLength();
  4895. }
  4896. // interface
  4897. const char *asCScriptEngine::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
  4898. {
  4899. // TODO: This same function is implemented in as_module.cpp as well. Perhaps it should be moved to asCObjectType?
  4900. asCDataType dt = GetDataTypeFromTypeId(enumTypeId);
  4901. asCObjectType *t = dt.GetObjectType();
  4902. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  4903. return 0;
  4904. if( index >= t->enumValues.GetLength() )
  4905. return 0;
  4906. if( outValue )
  4907. *outValue = t->enumValues[index]->value;
  4908. return t->enumValues[index]->name.AddressOf();
  4909. }
  4910. // interface
  4911. asUINT asCScriptEngine::GetObjectTypeCount() const
  4912. {
  4913. return asUINT(registeredObjTypes.GetLength());
  4914. }
  4915. // interface
  4916. asIObjectType *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const
  4917. {
  4918. if( index >= registeredObjTypes.GetLength() )
  4919. return 0;
  4920. return registeredObjTypes[index];
  4921. }
  4922. // interface
  4923. asIObjectType *asCScriptEngine::GetObjectTypeByName(const char *name) const
  4924. {
  4925. asSNameSpace *ns = defaultNamespace;
  4926. while( ns )
  4927. {
  4928. // Check the object types
  4929. for( asUINT n = 0; n < registeredObjTypes.GetLength(); n++ )
  4930. {
  4931. if( registeredObjTypes[n]->name == name &&
  4932. registeredObjTypes[n]->nameSpace == ns )
  4933. return registeredObjTypes[n];
  4934. }
  4935. // Perhaps it is a template type? In this case
  4936. // the returned type will be the generic type
  4937. for( asUINT n = 0; n < registeredTemplateTypes.GetLength(); n++ )
  4938. {
  4939. if( registeredTemplateTypes[n]->name == name &&
  4940. registeredTemplateTypes[n]->nameSpace == ns )
  4941. return registeredTemplateTypes[n];
  4942. }
  4943. // Recursively search parent namespace
  4944. ns = GetParentNameSpace(ns);
  4945. }
  4946. return 0;
  4947. }
  4948. // interface
  4949. asIObjectType *asCScriptEngine::GetObjectTypeById(int typeId) const
  4950. {
  4951. asCDataType dt = GetDataTypeFromTypeId(typeId);
  4952. // Is the type id valid?
  4953. if( !dt.IsValid() ) return 0;
  4954. // Enum types are not objects, so we shouldn't return an object type for them
  4955. if( dt.GetObjectType() && dt.GetObjectType()->GetFlags() & asOBJ_ENUM )
  4956. return 0;
  4957. return dt.GetObjectType();
  4958. }
  4959. // interface
  4960. asIScriptFunction *asCScriptEngine::GetFunctionById(int funcId) const
  4961. {
  4962. return GetScriptFunction(funcId);
  4963. }
  4964. // interface
  4965. asIScriptFunction *asCScriptEngine::GetFuncDefFromTypeId(int typeId) const
  4966. {
  4967. return GetDataTypeFromTypeId(typeId).GetFuncDef();
  4968. }
  4969. // internal
  4970. bool asCScriptEngine::IsTemplateType(const char *name) const
  4971. {
  4972. // Only look in the list of template types (not instance types)
  4973. for( unsigned int n = 0; n < registeredTemplateTypes.GetLength(); n++ )
  4974. {
  4975. asCObjectType *type = registeredTemplateTypes[n];
  4976. if( type && type->name == name )
  4977. return true;
  4978. }
  4979. return false;
  4980. }
  4981. // internal
  4982. int asCScriptEngine::AddConstantString(const char *str, size_t len)
  4983. {
  4984. // This is only called when build a script module, so it is
  4985. // known that only one thread can enter the function at a time.
  4986. asASSERT( isBuilding );
  4987. // The str may contain null chars, so we cannot use strlen, or strcmp, or strcpy
  4988. // Has the string been registered before?
  4989. asSMapNode<asCStringPointer, int> *cursor = 0;
  4990. if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str, len)))
  4991. return cursor->value;
  4992. // No match was found, add the string
  4993. asCString *cstr = asNEW(asCString)(str, len);
  4994. if( cstr )
  4995. {
  4996. stringConstants.PushLast(cstr);
  4997. int index = (int)stringConstants.GetLength() - 1;
  4998. stringToIdMap.Insert(asCStringPointer(cstr), index);
  4999. // The VM currently doesn't handle string ids larger than 65535
  5000. asASSERT(stringConstants.GetLength() <= 65536);
  5001. return index;
  5002. }
  5003. return 0;
  5004. }
  5005. // internal
  5006. const asCString &asCScriptEngine::GetConstantString(int id)
  5007. {
  5008. return *stringConstants[id];
  5009. }
  5010. // internal
  5011. int asCScriptEngine::GetScriptSectionNameIndex(const char *name)
  5012. {
  5013. ACQUIREEXCLUSIVE(engineRWLock);
  5014. // TODO: These names are only released when the engine is freed. The assumption is that
  5015. // the same script section names will be reused instead of there always being new
  5016. // names. Is this assumption valid? Do we need to add reference counting?
  5017. // Store the script section names for future reference
  5018. for( asUINT n = 0; n < scriptSectionNames.GetLength(); n++ )
  5019. {
  5020. if( scriptSectionNames[n]->Compare(name) == 0 )
  5021. {
  5022. RELEASEEXCLUSIVE(engineRWLock);
  5023. return n;
  5024. }
  5025. }
  5026. asCString *str = asNEW(asCString)(name);
  5027. if( str )
  5028. scriptSectionNames.PushLast(str);
  5029. int r = int(scriptSectionNames.GetLength()-1);
  5030. RELEASEEXCLUSIVE(engineRWLock);
  5031. return r;
  5032. }
  5033. // interface
  5034. void asCScriptEngine::SetEngineUserDataCleanupCallback(asCLEANENGINEFUNC_t callback, asPWORD type)
  5035. {
  5036. ACQUIREEXCLUSIVE(engineRWLock);
  5037. for( asUINT n = 0; n < cleanEngineFuncs.GetLength(); n++ )
  5038. {
  5039. if( cleanEngineFuncs[n].type == type )
  5040. {
  5041. cleanEngineFuncs[n].cleanFunc = callback;
  5042. RELEASEEXCLUSIVE(engineRWLock);
  5043. return;
  5044. }
  5045. }
  5046. SEngineClean otc = {type, callback};
  5047. cleanEngineFuncs.PushLast(otc);
  5048. RELEASEEXCLUSIVE(engineRWLock);
  5049. }
  5050. // interface
  5051. void asCScriptEngine::SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback, asPWORD type)
  5052. {
  5053. ACQUIREEXCLUSIVE(engineRWLock);
  5054. for( asUINT n = 0; n < cleanModuleFuncs.GetLength(); n++ )
  5055. {
  5056. if( cleanModuleFuncs[n].type == type )
  5057. {
  5058. cleanModuleFuncs[n].cleanFunc = callback;
  5059. RELEASEEXCLUSIVE(engineRWLock);
  5060. return;
  5061. }
  5062. }
  5063. SModuleClean otc = {type, callback};
  5064. cleanModuleFuncs.PushLast(otc);
  5065. RELEASEEXCLUSIVE(engineRWLock);
  5066. }
  5067. // interface
  5068. void asCScriptEngine::SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback, asPWORD type)
  5069. {
  5070. ACQUIREEXCLUSIVE(engineRWLock);
  5071. for( asUINT n = 0; n < cleanContextFuncs.GetLength(); n++ )
  5072. {
  5073. if( cleanContextFuncs[n].type == type )
  5074. {
  5075. cleanContextFuncs[n].cleanFunc = callback;
  5076. RELEASEEXCLUSIVE(engineRWLock);
  5077. return;
  5078. }
  5079. }
  5080. SContextClean otc = {type, callback};
  5081. cleanContextFuncs.PushLast(otc);
  5082. RELEASEEXCLUSIVE(engineRWLock);
  5083. }
  5084. // interface
  5085. void asCScriptEngine::SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback, asPWORD type)
  5086. {
  5087. ACQUIREEXCLUSIVE(engineRWLock);
  5088. for( asUINT n = 0; n < cleanFunctionFuncs.GetLength(); n++ )
  5089. {
  5090. if( cleanFunctionFuncs[n].type == type )
  5091. {
  5092. cleanFunctionFuncs[n].cleanFunc = callback;
  5093. RELEASEEXCLUSIVE(engineRWLock);
  5094. return;
  5095. }
  5096. }
  5097. SFunctionClean otc = {type, callback};
  5098. cleanFunctionFuncs.PushLast(otc);
  5099. RELEASEEXCLUSIVE(engineRWLock);
  5100. }
  5101. // interface
  5102. void asCScriptEngine::SetObjectTypeUserDataCleanupCallback(asCLEANOBJECTTYPEFUNC_t callback, asPWORD type)
  5103. {
  5104. ACQUIREEXCLUSIVE(engineRWLock);
  5105. for( asUINT n = 0; n < cleanObjectTypeFuncs.GetLength(); n++ )
  5106. {
  5107. if( cleanObjectTypeFuncs[n].type == type )
  5108. {
  5109. cleanObjectTypeFuncs[n].cleanFunc = callback;
  5110. RELEASEEXCLUSIVE(engineRWLock);
  5111. return;
  5112. }
  5113. }
  5114. SObjTypeClean otc = {type, callback};
  5115. cleanObjectTypeFuncs.PushLast(otc);
  5116. RELEASEEXCLUSIVE(engineRWLock);
  5117. }
  5118. // interface
  5119. void asCScriptEngine::SetScriptObjectUserDataCleanupCallback(asCLEANSCRIPTOBJECTFUNC_t callback, asPWORD type)
  5120. {
  5121. ACQUIREEXCLUSIVE(engineRWLock);
  5122. for( asUINT n = 0; n < cleanScriptObjectFuncs.GetLength(); n++ )
  5123. {
  5124. if( cleanScriptObjectFuncs[n].type == type )
  5125. {
  5126. cleanScriptObjectFuncs[n].cleanFunc = callback;
  5127. RELEASEEXCLUSIVE(engineRWLock);
  5128. return;
  5129. }
  5130. }
  5131. SScriptObjClean soc = {type, callback};
  5132. cleanScriptObjectFuncs.PushLast(soc);
  5133. RELEASEEXCLUSIVE(engineRWLock);
  5134. }
  5135. // internal
  5136. asCObjectType *asCScriptEngine::GetListPatternType(int listPatternFuncId)
  5137. {
  5138. // Get the object type either from the constructor's object for value types
  5139. // or from the factory's return type for reference types
  5140. asCObjectType *ot = scriptFunctions[listPatternFuncId]->objectType;
  5141. if( ot == 0 )
  5142. ot = scriptFunctions[listPatternFuncId]->returnType.GetObjectType();
  5143. asASSERT( ot );
  5144. // Check if this object type already has a list pattern type
  5145. for( asUINT n = 0; n < listPatternTypes.GetLength(); n++ )
  5146. {
  5147. if( listPatternTypes[n]->templateSubTypes[0].GetObjectType() == ot )
  5148. return listPatternTypes[n];
  5149. }
  5150. // Create a new list pattern type for the given object type
  5151. asCObjectType *lpt = asNEW(asCObjectType)(this);
  5152. lpt->templateSubTypes.PushLast(asCDataType::CreateObject(ot, false));
  5153. lpt->flags = asOBJ_LIST_PATTERN;
  5154. listPatternTypes.PushLast(lpt);
  5155. return lpt;
  5156. }
  5157. // internal
  5158. void asCScriptEngine::DestroyList(asBYTE *buffer, const asCObjectType *listPatternType)
  5159. {
  5160. asASSERT( listPatternType && (listPatternType->flags & asOBJ_LIST_PATTERN) );
  5161. // Get the list pattern from the listFactory function
  5162. // TODO: runtime optimize: Store the used list factory in the listPatternType itself
  5163. // TODO: runtime optimize: Keep a flag to indicate if there is really a need to free anything
  5164. asCObjectType *ot = listPatternType->templateSubTypes[0].GetObjectType();
  5165. asCScriptFunction *listFactory = scriptFunctions[ot->beh.listFactory];
  5166. asASSERT( listFactory );
  5167. asSListPatternNode *node = listFactory->listPattern;
  5168. DestroySubList(buffer, node);
  5169. asASSERT( node->type == asLPT_END );
  5170. }
  5171. // internal
  5172. void asCScriptEngine::DestroySubList(asBYTE *&buffer, asSListPatternNode *&node)
  5173. {
  5174. asASSERT( node->type == asLPT_START );
  5175. int count = 0;
  5176. node = node->next;
  5177. while( node )
  5178. {
  5179. if( node->type == asLPT_REPEAT || node->type == asLPT_REPEAT_SAME )
  5180. {
  5181. // Align the offset to 4 bytes boundary
  5182. if( (asPWORD(buffer) & 0x3) )
  5183. buffer += 4 - (asPWORD(buffer) & 0x3);
  5184. // Determine how many times the pattern repeat
  5185. count = *(asUINT*)buffer;
  5186. buffer += 4;
  5187. if( count == 0 )
  5188. {
  5189. // Skip the sub pattern that was expected to be repeated, otherwise
  5190. // we'll try to delete things that don't exist in the buffer
  5191. node = node->next;
  5192. if( node->type == asLPT_START )
  5193. {
  5194. int subCount = 1;
  5195. do
  5196. {
  5197. node = node->next;
  5198. if( node->type == asLPT_START )
  5199. subCount++;
  5200. else if( node->type == asLPT_END )
  5201. subCount--;
  5202. } while( subCount > 0 );
  5203. return;
  5204. }
  5205. }
  5206. }
  5207. else if( node->type == asLPT_TYPE )
  5208. {
  5209. // If we're not in a repeat iteration, then only 1 value should be destroyed
  5210. if( count <= 0 )
  5211. count = 1;
  5212. asCDataType dt = reinterpret_cast<asSListPatternDataTypeNode*>(node)->dataType;
  5213. bool isVarType = dt.GetTokenType() == ttQuestion;
  5214. while( count-- )
  5215. {
  5216. if( isVarType )
  5217. {
  5218. // Align the offset to 4 bytes boundary
  5219. if( (asPWORD(buffer) & 0x3) )
  5220. buffer += 4 - (asPWORD(buffer) & 0x3);
  5221. int typeId = *(int*)buffer;
  5222. buffer += 4;
  5223. dt = GetDataTypeFromTypeId(typeId);
  5224. }
  5225. asCObjectType *ot = dt.GetObjectType();
  5226. if( ot && (ot->flags & asOBJ_ENUM) == 0 )
  5227. {
  5228. // Free all instances of this type
  5229. if( ot->flags & asOBJ_VALUE )
  5230. {
  5231. asUINT size = ot->GetSize();
  5232. // Align the offset to 4 bytes boundary
  5233. if( size >= 4 && (asPWORD(buffer) & 0x3) )
  5234. buffer += 4 - (asPWORD(buffer) & 0x3);
  5235. if( ot->beh.destruct )
  5236. {
  5237. // Only call the destructor if the object has been created
  5238. // We'll assume the object has been created if any byte in
  5239. // the memory is different from 0.
  5240. // TODO: This is not really correct, as bytes may have been
  5241. // modified by the constructor, but then an exception
  5242. // thrown aborting the initialization. The engine
  5243. // really should be keeping track of which objects has
  5244. // been successfully initialized.
  5245. for( asUINT n = 0; n < size; n++ )
  5246. {
  5247. if( buffer[n] != 0 )
  5248. {
  5249. void *ptr = (void*)buffer;
  5250. CallObjectMethod(ptr, ot->beh.destruct);
  5251. break;
  5252. }
  5253. }
  5254. }
  5255. // Advance the pointer in the buffer
  5256. buffer += size;
  5257. }
  5258. else
  5259. {
  5260. // Align the offset to 4 bytes boundary
  5261. if( asPWORD(buffer) & 0x3 )
  5262. buffer += 4 - (asPWORD(buffer) & 0x3);
  5263. // Call the release behaviour
  5264. void *ptr = *(void**)buffer;
  5265. if( ptr )
  5266. ReleaseScriptObject(ptr, ot);
  5267. buffer += AS_PTR_SIZE*4;
  5268. }
  5269. }
  5270. else
  5271. {
  5272. asUINT size = dt.GetSizeInMemoryBytes();
  5273. // Align the offset to 4 bytes boundary
  5274. if( size >= 4 && (asPWORD(buffer) & 0x3) )
  5275. buffer += 4 - (asPWORD(buffer) & 0x3);
  5276. // Advance the buffer
  5277. buffer += size;
  5278. }
  5279. }
  5280. }
  5281. else if( node->type == asLPT_START )
  5282. {
  5283. // If we're not in a repeat iteration, then only 1 value should be destroyed
  5284. if( count <= 0 )
  5285. count = 1;
  5286. while( count-- )
  5287. {
  5288. asSListPatternNode *subList = node;
  5289. DestroySubList(buffer, subList);
  5290. asASSERT( subList->type == asLPT_END );
  5291. if( count == 0 )
  5292. node = subList;
  5293. }
  5294. }
  5295. else if( node->type == asLPT_END )
  5296. {
  5297. return;
  5298. }
  5299. else
  5300. {
  5301. asASSERT( false );
  5302. }
  5303. node = node->next;
  5304. }
  5305. }
  5306. // internal
  5307. asSNameSpace *asCScriptEngine::GetParentNameSpace(asSNameSpace *ns) const
  5308. {
  5309. if( ns == 0 ) return 0;
  5310. if( ns == nameSpaces[0] ) return 0;
  5311. asCString scope = ns->name;
  5312. int pos = scope.FindLast("::");
  5313. if( pos >= 0 )
  5314. {
  5315. scope = scope.SubString(0, pos);
  5316. return FindNameSpace(scope.AddressOf());
  5317. }
  5318. return nameSpaces[0];
  5319. }
  5320. END_AS_NAMESPACE