as_scriptengine.cpp 191 KB

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