as_scriptengine.cpp 188 KB

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