as_scriptengine.cpp 147 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2012 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. // Modified by Lasse Oorni for Urho3D
  24. //
  25. // as_scriptengine.cpp
  26. //
  27. // The implementation of the script engine interface
  28. //
  29. #include <stdlib.h>
  30. #include "as_config.h"
  31. #include "as_scriptengine.h"
  32. #include "as_builder.h"
  33. #include "as_context.h"
  34. #include "as_string_util.h"
  35. #include "as_tokenizer.h"
  36. #include "as_texts.h"
  37. #include "as_module.h"
  38. #include "as_callfunc.h"
  39. #include "as_generic.h"
  40. #include "as_scriptobject.h"
  41. #include "as_compiler.h"
  42. #include "as_bytecode.h"
  43. BEGIN_AS_NAMESPACE
  44. extern "C"
  45. {
  46. AS_API const char * asGetLibraryVersion()
  47. {
  48. #ifdef _DEBUG
  49. return ANGELSCRIPT_VERSION_STRING " DEBUG";
  50. #else
  51. return ANGELSCRIPT_VERSION_STRING;
  52. #endif
  53. }
  54. AS_API const char * asGetLibraryOptions()
  55. {
  56. const char *string = " "
  57. // Options
  58. #ifdef AS_MAX_PORTABILITY
  59. "AS_MAX_PORTABILITY "
  60. #endif
  61. #ifdef AS_DEBUG
  62. "AS_DEBUG "
  63. #endif
  64. #ifdef AS_NO_CLASS_METHODS
  65. "AS_NO_CLASS_METHODS "
  66. #endif
  67. #ifdef AS_USE_DOUBLE_AS_FLOAT
  68. "AS_USE_DOUBLE_AS_FLOAT "
  69. #endif
  70. #ifdef AS_64BIT_PTR
  71. "AS_64BIT_PTR "
  72. #endif
  73. #ifdef AS_NO_THREADS
  74. "AS_NO_THREADS "
  75. #endif
  76. #ifdef AS_NO_ATOMIC
  77. "AS_NO_ATOMIC "
  78. #endif
  79. #ifdef AS_NO_COMPILER
  80. "AS_NO_COMPILER "
  81. #endif
  82. // Target system
  83. #ifdef AS_WIN
  84. "AS_WIN "
  85. #endif
  86. #ifdef AS_LINUX
  87. "AS_LINUX "
  88. #endif
  89. #ifdef AS_MAC
  90. "AS_MAC "
  91. #endif
  92. #ifdef AS_BSD
  93. "AS_BSD "
  94. #endif
  95. #ifdef AS_XBOX
  96. "AS_XBOX "
  97. #endif
  98. #ifdef AS_XBOX360
  99. "AS_XBOX360 "
  100. #endif
  101. #ifdef AS_PSP
  102. "AS_PSP "
  103. #endif
  104. #ifdef AS_PS2
  105. "AS_PS2 "
  106. #endif
  107. #ifdef AS_PS3
  108. "AS_PS3 "
  109. #endif
  110. #ifdef AS_DC
  111. "AS_DC "
  112. #endif
  113. #ifdef AS_GC
  114. "AS_GC "
  115. #endif
  116. #ifdef AS_WII
  117. "AS_WII "
  118. #endif
  119. #ifdef AS_IPHONE
  120. "AS_IPHONE "
  121. #endif
  122. #ifdef AS_ANDROID
  123. "AS_ANDROID "
  124. #endif
  125. #ifdef AS_HAIKU
  126. "AS_HAIKU "
  127. #endif
  128. #ifdef AS_ILLUMOS
  129. "AS_ILLUMOS "
  130. #endif
  131. // CPU family
  132. #ifdef AS_PPC
  133. "AS_PPC "
  134. #endif
  135. #ifdef AS_PPC_64
  136. "AS_PPC_64 "
  137. #endif
  138. #ifdef AS_X86
  139. "AS_X86 "
  140. #endif
  141. #ifdef AS_MIPS
  142. "AS_MIPS "
  143. #endif
  144. #ifdef AS_SH4
  145. "AS_SH4 "
  146. #endif
  147. #ifdef AS_XENON
  148. "AS_XENON "
  149. #endif
  150. #ifdef AS_ARM
  151. "AS_ARM "
  152. #endif
  153. #ifdef AS_X64_GCC
  154. "AS_X64_GCC "
  155. #endif
  156. #ifdef AS_X64_MSVC
  157. "AS_X64_MSVC "
  158. #endif
  159. ;
  160. return string;
  161. }
  162. AS_API asIScriptEngine *asCreateScriptEngine(asDWORD version)
  163. {
  164. // Verify the version that the application expects
  165. if( (version/10000) != (ANGELSCRIPT_VERSION/10000) )
  166. return 0;
  167. if( (version/100)%100 != (ANGELSCRIPT_VERSION/100)%100 )
  168. return 0;
  169. if( (version%100) > (ANGELSCRIPT_VERSION%100) )
  170. return 0;
  171. // Verify the size of the types
  172. asASSERT( sizeof(asBYTE) == 1 );
  173. asASSERT( sizeof(asWORD) == 2 );
  174. asASSERT( sizeof(asDWORD) == 4 );
  175. asASSERT( sizeof(asQWORD) == 8 );
  176. asASSERT( sizeof(asPWORD) == sizeof(void*) );
  177. // Verify the boolean type
  178. asASSERT( sizeof(bool) == AS_SIZEOF_BOOL );
  179. asASSERT( true == VALUE_OF_BOOLEAN_TRUE );
  180. // Verify endianess
  181. #ifdef AS_BIG_ENDIAN
  182. asASSERT( *(asDWORD*)"\x00\x01\x02\x03" == 0x00010203 );
  183. asASSERT( *(asQWORD*)"\x00\x01\x02\x03\x04\x05\x06\x07" == ((asQWORD(0x00010203)<<32)|asQWORD(0x04050607)) );
  184. #else
  185. asASSERT( *(asDWORD*)"\x00\x01\x02\x03" == 0x03020100 );
  186. // C++ didn't have a standard way of declaring 64bit literal constants until C++11, so
  187. // I'm forced to do it like this to avoid compilers warnings when compiling with the full
  188. // C++ compliance.
  189. asASSERT( *(asQWORD*)"\x00\x01\x02\x03\x04\x05\x06\x07" == ((asQWORD(0x07060504)<<32)|asQWORD(0x03020100)) );
  190. #endif
  191. return asNEW(asCScriptEngine)();
  192. }
  193. int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
  194. {
  195. switch( property )
  196. {
  197. case asEP_ALLOW_UNSAFE_REFERENCES:
  198. ep.allowUnsafeReferences = value ? true : false;
  199. break;
  200. case asEP_OPTIMIZE_BYTECODE:
  201. ep.optimizeByteCode = value ? true : false;
  202. break;
  203. case asEP_COPY_SCRIPT_SECTIONS:
  204. ep.copyScriptSections = value ? true : false;
  205. break;
  206. case asEP_MAX_STACK_SIZE:
  207. if( value == 0 )
  208. {
  209. // Restore default: no limit and initially size 4KB
  210. ep.maximumContextStackSize = 0;
  211. initialContextStackSize = 1024;
  212. }
  213. else
  214. {
  215. // The size is given in bytes, but we only store dwords
  216. ep.maximumContextStackSize = (asUINT)value/4;
  217. if( initialContextStackSize > ep.maximumContextStackSize )
  218. {
  219. initialContextStackSize = ep.maximumContextStackSize;
  220. if( initialContextStackSize == 0 )
  221. initialContextStackSize = 1;
  222. }
  223. }
  224. break;
  225. case asEP_USE_CHARACTER_LITERALS:
  226. ep.useCharacterLiterals = value ? true : false;
  227. break;
  228. case asEP_ALLOW_MULTILINE_STRINGS:
  229. ep.allowMultilineStrings = value ? true : false;
  230. break;
  231. case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
  232. ep.allowImplicitHandleTypes = value ? true : false;
  233. break;
  234. case asEP_BUILD_WITHOUT_LINE_CUES:
  235. ep.buildWithoutLineCues = value ? true : false;
  236. break;
  237. case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
  238. ep.initGlobalVarsAfterBuild = value ? true : false;
  239. break;
  240. case asEP_REQUIRE_ENUM_SCOPE:
  241. ep.requireEnumScope = value ? true : false;
  242. break;
  243. case asEP_SCRIPT_SCANNER:
  244. if( value <= 1 )
  245. ep.scanner = (int)value;
  246. else
  247. return asINVALID_ARG;
  248. break;
  249. case asEP_INCLUDE_JIT_INSTRUCTIONS:
  250. ep.includeJitInstructions = value ? true : false;
  251. break;
  252. case asEP_STRING_ENCODING:
  253. if( value <= 1 )
  254. ep.stringEncoding = (int)value;
  255. else
  256. return asINVALID_ARG;
  257. break;
  258. case asEP_PROPERTY_ACCESSOR_MODE:
  259. if( value <= 2 )
  260. ep.propertyAccessorMode = (int)value;
  261. else
  262. return asINVALID_ARG;
  263. break;
  264. case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
  265. ep.expandDefaultArrayToTemplate = value ? true : false;
  266. break;
  267. case asEP_AUTO_GARBAGE_COLLECT:
  268. ep.autoGarbageCollect = value ? true : false;
  269. break;
  270. case asEP_DISALLOW_GLOBAL_VARS:
  271. ep.disallowGlobalVars = value ? true : false;
  272. break;
  273. case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
  274. ep.alwaysImplDefaultConstruct = value ? true : false;
  275. break;
  276. default:
  277. return asINVALID_ARG;
  278. }
  279. return asSUCCESS;
  280. }
  281. asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
  282. {
  283. switch( property )
  284. {
  285. case asEP_ALLOW_UNSAFE_REFERENCES:
  286. return ep.allowUnsafeReferences;
  287. case asEP_OPTIMIZE_BYTECODE:
  288. return ep.optimizeByteCode;
  289. case asEP_COPY_SCRIPT_SECTIONS:
  290. return ep.copyScriptSections;
  291. case asEP_MAX_STACK_SIZE:
  292. return ep.maximumContextStackSize*4;
  293. case asEP_USE_CHARACTER_LITERALS:
  294. return ep.useCharacterLiterals;
  295. case asEP_ALLOW_MULTILINE_STRINGS:
  296. return ep.allowMultilineStrings;
  297. case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
  298. return ep.allowImplicitHandleTypes;
  299. case asEP_BUILD_WITHOUT_LINE_CUES:
  300. return ep.buildWithoutLineCues;
  301. case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
  302. return ep.initGlobalVarsAfterBuild;
  303. case asEP_REQUIRE_ENUM_SCOPE:
  304. return ep.requireEnumScope;
  305. case asEP_SCRIPT_SCANNER:
  306. return ep.scanner;
  307. case asEP_INCLUDE_JIT_INSTRUCTIONS:
  308. return ep.includeJitInstructions;
  309. case asEP_STRING_ENCODING:
  310. return ep.stringEncoding;
  311. case asEP_PROPERTY_ACCESSOR_MODE:
  312. return ep.propertyAccessorMode;
  313. case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
  314. return ep.expandDefaultArrayToTemplate;
  315. case asEP_AUTO_GARBAGE_COLLECT:
  316. return ep.autoGarbageCollect;
  317. case asEP_DISALLOW_GLOBAL_VARS:
  318. return ep.disallowGlobalVars;
  319. case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
  320. return ep.alwaysImplDefaultConstruct;
  321. }
  322. return 0;
  323. }
  324. } // extern "C"
  325. asCScriptEngine::asCScriptEngine()
  326. {
  327. asCThreadManager::Prepare();
  328. // Engine properties
  329. {
  330. ep.allowUnsafeReferences = false;
  331. ep.optimizeByteCode = true;
  332. ep.copyScriptSections = true;
  333. ep.maximumContextStackSize = 0; // no limit
  334. ep.useCharacterLiterals = false;
  335. ep.allowMultilineStrings = false;
  336. ep.allowImplicitHandleTypes = false;
  337. // TODO: optimize: Maybe this should be turned off by default? If a debugger is not used
  338. // then this is just slowing down the execution. The exception handler
  339. // should still be able to determine the line number from the bytecode
  340. // position.
  341. ep.buildWithoutLineCues = false;
  342. ep.initGlobalVarsAfterBuild = true;
  343. ep.requireEnumScope = false;
  344. ep.scanner = 1; // utf8. 0 = ascii
  345. ep.includeJitInstructions = false;
  346. ep.stringEncoding = 0; // utf8. 1 = utf16
  347. ep.propertyAccessorMode = 2; // 0 = disable, 1 = app registered only, 2 = app and script created
  348. ep.expandDefaultArrayToTemplate = false;
  349. ep.autoGarbageCollect = true;
  350. ep.disallowGlobalVars = false;
  351. ep.alwaysImplDefaultConstruct = false;
  352. }
  353. gc.engine = this;
  354. tok.engine = this;
  355. refCount.set(1);
  356. stringFactory = 0;
  357. configFailed = false;
  358. isPrepared = false;
  359. isBuilding = false;
  360. deferValidationOfTemplateTypes = false;
  361. lastModule = 0;
  362. // User data
  363. cleanModuleFunc = 0;
  364. cleanContextFunc = 0;
  365. cleanFunctionFunc = 0;
  366. initialContextStackSize = 1024; // 4 KB (1024 * sizeof(asDWORD)
  367. typeIdSeqNbr = 0;
  368. currentGroup = &defaultGroup;
  369. defaultAccessMask = 1;
  370. msgCallback = 0;
  371. jitCompiler = 0;
  372. // Create the global namespace
  373. defaultNamespace = AddNameSpace("");
  374. // We must set the namespace in the built-in types explicitly as
  375. // this wasn't done by the default constructor. If we do not do
  376. // this we will get null pointer access in other parts of the code
  377. scriptTypeBehaviours.nameSpace = defaultNamespace;
  378. functionBehaviours.nameSpace = defaultNamespace;
  379. objectTypeBehaviours.nameSpace = defaultNamespace;
  380. globalPropertyBehaviours.nameSpace = defaultNamespace;
  381. // Reserve function id 0 for no function
  382. scriptFunctions.PushLast(0);
  383. // Make sure typeId for the built-in primitives are defined according to asETypeIdFlags
  384. int id = 0;
  385. UNUSED_VAR(id); // It is only used in debug mode
  386. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttVoid, false)); asASSERT( id == asTYPEID_VOID );
  387. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttBool, false)); asASSERT( id == asTYPEID_BOOL );
  388. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt8, false)); asASSERT( id == asTYPEID_INT8 );
  389. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt16, false)); asASSERT( id == asTYPEID_INT16 );
  390. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt, false)); asASSERT( id == asTYPEID_INT32 );
  391. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt64, false)); asASSERT( id == asTYPEID_INT64 );
  392. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt8, false)); asASSERT( id == asTYPEID_UINT8 );
  393. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt16, false)); asASSERT( id == asTYPEID_UINT16 );
  394. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt, false)); asASSERT( id == asTYPEID_UINT32 );
  395. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt64, false)); asASSERT( id == asTYPEID_UINT64 );
  396. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttFloat, false)); asASSERT( id == asTYPEID_FLOAT );
  397. id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttDouble, false)); asASSERT( id == asTYPEID_DOUBLE );
  398. defaultArrayObjectType = 0;
  399. RegisterScriptObject(this);
  400. RegisterScriptFunction(this);
  401. RegisterObjectTypeGCBehaviours(this);
  402. asCGlobalProperty::RegisterGCBehaviours(this);
  403. }
  404. asCScriptEngine::~asCScriptEngine()
  405. {
  406. asASSERT(refCount.get() == 0);
  407. asUINT n;
  408. // The modules must be deleted first, as they may use
  409. // object types from the config groups
  410. for( n = (asUINT)scriptModules.GetLength(); n-- > 0; )
  411. if( scriptModules[n] )
  412. asDELETE(scriptModules[n],asCModule);
  413. scriptModules.SetLength(0);
  414. GarbageCollect(asGC_FULL_CYCLE);
  415. // Delete the functions for template types that may references object types
  416. for( n = 0; n < templateTypes.GetLength(); n++ )
  417. {
  418. if( templateTypes[n] )
  419. {
  420. asUINT f;
  421. // Delete the factory stubs first
  422. for( f = 0; f < templateTypes[n]->beh.factories.GetLength(); f++ )
  423. scriptFunctions[templateTypes[n]->beh.factories[f]]->Release();
  424. templateTypes[n]->beh.factories.Allocate(0, false);
  425. // The list factory is not stored in the list with the rest of the factories
  426. if( templateTypes[n]->beh.listFactory )
  427. {
  428. scriptFunctions[templateTypes[n]->beh.listFactory]->Release();
  429. templateTypes[n]->beh.listFactory = 0;
  430. }
  431. // Delete the specialized functions
  432. for( f = 1; f < templateTypes[n]->beh.operators.GetLength(); f += 2 )
  433. {
  434. if( scriptFunctions[templateTypes[n]->beh.operators[f]]->objectType == templateTypes[n] )
  435. {
  436. scriptFunctions[templateTypes[n]->beh.operators[f]]->Release();
  437. templateTypes[n]->beh.operators[f] = 0;
  438. }
  439. }
  440. for( f = 0; f < templateTypes[n]->methods.GetLength(); f++ )
  441. {
  442. if( scriptFunctions[templateTypes[n]->methods[f]]->objectType == templateTypes[n] )
  443. {
  444. scriptFunctions[templateTypes[n]->methods[f]]->Release();
  445. templateTypes[n]->methods[f] = 0;
  446. }
  447. }
  448. }
  449. }
  450. // Do one more garbage collect to free gc objects that were global variables
  451. GarbageCollect(asGC_FULL_CYCLE);
  452. FreeUnusedGlobalProperties();
  453. ClearUnusedTypes();
  454. // Break all relationship between remaining class types and functions
  455. for( n = 0; n < classTypes.GetLength(); n++ )
  456. {
  457. if( classTypes[n] )
  458. classTypes[n]->ReleaseAllFunctions();
  459. if( classTypes[n]->derivedFrom )
  460. {
  461. classTypes[n]->derivedFrom->Release();
  462. classTypes[n]->derivedFrom = 0;
  463. }
  464. }
  465. GarbageCollect(asGC_FULL_CYCLE);
  466. FreeUnusedGlobalProperties();
  467. ClearUnusedTypes();
  468. // Destroy internals of script functions that may still be kept alive outside of engine
  469. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  470. if( scriptFunctions[n] && scriptFunctions[n]->funcType == asFUNC_SCRIPT )
  471. scriptFunctions[n]->DestroyInternal();
  472. // There may be instances where one more gc cycle must be run
  473. GarbageCollect(asGC_FULL_CYCLE);
  474. ClearUnusedTypes();
  475. // If the application hasn't registered GC behaviours for all types
  476. // that can form circular references with script types, then there
  477. // may still be objects in the GC.
  478. if( gc.ReportAndReleaseUndestroyedObjects() > 0 )
  479. {
  480. // Some items cannot be destroyed because the application is still holding on to them
  481. // Make sure the script functions won't attempt to access the engine if they are destroyed later on
  482. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  483. if( scriptFunctions[n] && scriptFunctions[n]->funcType == asFUNC_SCRIPT )
  484. scriptFunctions[n]->engine = 0;
  485. }
  486. asSMapNode<int,asCDataType*> *cursor = 0;
  487. while( mapTypeIdToDataType.MoveFirst(&cursor) )
  488. {
  489. asDELETE(mapTypeIdToDataType.GetValue(cursor),asCDataType);
  490. mapTypeIdToDataType.Erase(cursor);
  491. }
  492. // First remove what is not used, so that other groups can be deleted safely
  493. defaultGroup.RemoveConfiguration(this, true);
  494. while( configGroups.GetLength() )
  495. {
  496. // Delete config groups in the right order
  497. asCConfigGroup *grp = configGroups.PopLast();
  498. if( grp )
  499. {
  500. grp->RemoveConfiguration(this);
  501. asDELETE(grp,asCConfigGroup);
  502. }
  503. }
  504. // Remove what is remaining
  505. defaultGroup.RemoveConfiguration(this);
  506. asCSymbolTable<asCGlobalProperty>::iterator it = registeredGlobalProps.List();
  507. for( ; it; it++ )
  508. (*it)->Release();
  509. registeredGlobalProps.Clear();
  510. FreeUnusedGlobalProperties();
  511. for( n = 0; n < templateTypes.GetLength(); n++ )
  512. {
  513. if( templateTypes[n] )
  514. {
  515. // Clear the sub type before deleting the template type so that the sub type isn't freed to soon
  516. templateTypes[n]->templateSubType = asCDataType::CreateNullHandle();
  517. asDELETE(templateTypes[n],asCObjectType);
  518. }
  519. }
  520. templateTypes.SetLength(0);
  521. for( n = 0; n < objectTypes.GetLength(); n++ )
  522. {
  523. if( objectTypes[n] )
  524. {
  525. // Clear the sub type before deleting the template type so that the sub type isn't freed to soon
  526. objectTypes[n]->templateSubType = asCDataType::CreateNullHandle();
  527. asDELETE(objectTypes[n],asCObjectType);
  528. }
  529. }
  530. objectTypes.SetLength(0);
  531. for( n = 0; n < templateSubTypes.GetLength(); n++ )
  532. {
  533. if( templateSubTypes[n] )
  534. asDELETE(templateSubTypes[n], asCObjectType);
  535. }
  536. templateSubTypes.SetLength(0);
  537. registeredTypeDefs.SetLength(0);
  538. registeredEnums.SetLength(0);
  539. registeredObjTypes.SetLength(0);
  540. for( n = 0; n < registeredGlobalFuncs.GetLength(); n++ )
  541. {
  542. if( registeredGlobalFuncs[n] )
  543. registeredGlobalFuncs[n]->Release();
  544. }
  545. registeredGlobalFuncs.SetLength(0);
  546. scriptTypeBehaviours.ReleaseAllFunctions();
  547. functionBehaviours.ReleaseAllFunctions();
  548. objectTypeBehaviours.ReleaseAllFunctions();
  549. globalPropertyBehaviours.ReleaseAllFunctions();
  550. // Free string constants
  551. for( n = 0; n < stringConstants.GetLength(); n++ )
  552. asDELETE(stringConstants[n],asCString);
  553. stringConstants.SetLength(0);
  554. stringToIdMap.EraseAll();
  555. // Free the script section names
  556. for( n = 0; n < scriptSectionNames.GetLength(); n++ )
  557. asDELETE(scriptSectionNames[n],asCString);
  558. scriptSectionNames.SetLength(0);
  559. // Clean the user data
  560. for( n = 0; n < userData.GetLength(); n += 2 )
  561. {
  562. if( userData[n+1] )
  563. {
  564. for( asUINT c = 0; c < cleanEngineFuncs.GetLength(); c++ )
  565. if( cleanEngineFuncs[c].type == userData[n] )
  566. cleanEngineFuncs[c].cleanFunc(this);
  567. }
  568. }
  569. // Free namespaces
  570. for( n = 0; n < nameSpaces.GetLength(); n++ )
  571. asDELETE(nameSpaces[n], asSNameSpace);
  572. nameSpaces.SetLength(0);
  573. asCThreadManager::Unprepare();
  574. }
  575. // interface
  576. int asCScriptEngine::AddRef() const
  577. {
  578. return refCount.atomicInc();
  579. }
  580. // interface
  581. int asCScriptEngine::Release() const
  582. {
  583. int r = refCount.atomicDec();
  584. if( r == 0 )
  585. {
  586. asDELETE(const_cast<asCScriptEngine*>(this),asCScriptEngine);
  587. return 0;
  588. }
  589. return r;
  590. }
  591. // internal
  592. asSNameSpace *asCScriptEngine::AddNameSpace(const char *name)
  593. {
  594. // First check if it doesn't exist already
  595. asSNameSpace *ns = FindNameSpace(name);
  596. if( ns ) return ns;
  597. ns = asNEW(asSNameSpace);
  598. if( ns == 0 )
  599. {
  600. // Out of memory
  601. return 0;
  602. }
  603. ns->name = name;
  604. nameSpaces.PushLast(ns);
  605. return ns;
  606. }
  607. // internal
  608. asSNameSpace *asCScriptEngine::FindNameSpace(const char *name)
  609. {
  610. // TODO: optimize: Improve linear search
  611. for( asUINT n = 0; n < nameSpaces.GetLength(); n++ )
  612. if( nameSpaces[n]->name == name )
  613. return nameSpaces[n];
  614. return 0;
  615. }
  616. // interface
  617. int asCScriptEngine::SetDefaultNamespace(const char *nameSpace)
  618. {
  619. if( nameSpace == 0 )
  620. return ConfigError(asINVALID_ARG, "SetDefaultNamespace", nameSpace, 0);
  621. asCString ns = nameSpace;
  622. if( ns != "" )
  623. {
  624. // Make sure the namespace is composed of alternating identifier and ::
  625. size_t pos = 0;
  626. bool expectIdentifier = true;
  627. size_t len;
  628. eTokenType t = ttIdentifier;
  629. for( ; pos < ns.GetLength(); pos += len)
  630. {
  631. t = tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len);
  632. if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) )
  633. return ConfigError(asINVALID_DECLARATION, "SetDefaultNamespace", nameSpace, 0);
  634. expectIdentifier = !expectIdentifier;
  635. }
  636. // If the namespace ends with :: then strip it off
  637. if( t == ttScope )
  638. ns.SetLength(ns.GetLength()-2);
  639. }
  640. defaultNamespace = AddNameSpace(ns.AddressOf());
  641. return 0;
  642. }
  643. // interface
  644. void *asCScriptEngine::SetUserData(void *data, asPWORD type)
  645. {
  646. // As a thread might add a new new user data at the same time as another
  647. // it is necessary to protect both read and write access to the userData member
  648. ACQUIREEXCLUSIVE(engineRWLock);
  649. // It is not intended to store a lot of different types of userdata,
  650. // so a more complex structure like a associative map would just have
  651. // more overhead than a simple array.
  652. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  653. {
  654. if( userData[n] == type )
  655. {
  656. void *oldData = reinterpret_cast<void*>(userData[n+1]);
  657. userData[n+1] = reinterpret_cast<asPWORD>(data);
  658. RELEASEEXCLUSIVE(engineRWLock);
  659. return oldData;
  660. }
  661. }
  662. userData.PushLast(type);
  663. userData.PushLast(reinterpret_cast<asPWORD>(data));
  664. RELEASEEXCLUSIVE(engineRWLock);
  665. return 0;
  666. }
  667. // interface
  668. void *asCScriptEngine::GetUserData(asPWORD type) const
  669. {
  670. // There may be multiple threads reading, but when
  671. // setting the user data nobody must be reading.
  672. ACQUIRESHARED(engineRWLock);
  673. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  674. {
  675. if( userData[n] == type )
  676. {
  677. RELEASESHARED(engineRWLock);
  678. return reinterpret_cast<void*>(userData[n+1]);
  679. }
  680. }
  681. RELEASESHARED(engineRWLock);
  682. return 0;
  683. }
  684. // interface
  685. int asCScriptEngine::SetMessageCallback(const asSFuncPtr &callback, void *obj, asDWORD callConv)
  686. {
  687. msgCallback = true;
  688. msgCallbackObj = obj;
  689. bool isObj = false;
  690. if( (unsigned)callConv == asCALL_GENERIC )
  691. {
  692. msgCallback = false;
  693. return asNOT_SUPPORTED;
  694. }
  695. if( (unsigned)callConv >= asCALL_THISCALL )
  696. {
  697. isObj = true;
  698. if( obj == 0 )
  699. {
  700. msgCallback = false;
  701. return asINVALID_ARG;
  702. }
  703. }
  704. int r = DetectCallingConvention(isObj, callback, callConv, &msgCallbackFunc);
  705. if( r < 0 ) msgCallback = false;
  706. return r;
  707. }
  708. // interface
  709. int asCScriptEngine::ClearMessageCallback()
  710. {
  711. msgCallback = false;
  712. return 0;
  713. }
  714. // interface
  715. int asCScriptEngine::WriteMessage(const char *section, int row, int col, asEMsgType type, const char *message)
  716. {
  717. // Validate input parameters
  718. if( section == 0 ||
  719. message == 0 )
  720. return asINVALID_ARG;
  721. // If there is no callback then there's nothing to do
  722. if( !msgCallback )
  723. return 0;
  724. asSMessageInfo msg;
  725. msg.section = section;
  726. msg.row = row;
  727. msg.col = col;
  728. msg.type = type;
  729. msg.message = message;
  730. if( msgCallbackFunc.callConv < ICC_THISCALL )
  731. CallGlobalFunction(&msg, msgCallbackObj, &msgCallbackFunc, 0);
  732. else
  733. CallObjectMethod(msgCallbackObj, &msg, &msgCallbackFunc, 0);
  734. return 0;
  735. }
  736. int asCScriptEngine::SetJITCompiler(asIJITCompiler *compiler)
  737. {
  738. jitCompiler = compiler;
  739. return asSUCCESS;
  740. }
  741. asIJITCompiler *asCScriptEngine::GetJITCompiler() const
  742. {
  743. return jitCompiler;
  744. }
  745. // interface
  746. asETokenClass asCScriptEngine::ParseToken(const char *string, size_t stringLength, int *tokenLength) const
  747. {
  748. if( stringLength == 0 )
  749. stringLength = strlen(string);
  750. size_t len;
  751. asETokenClass tc;
  752. tok.GetToken(string, stringLength, &len, &tc);
  753. if( tokenLength )
  754. *tokenLength = (int)len;
  755. return tc;
  756. }
  757. // interface
  758. asIScriptModule *asCScriptEngine::GetModule(const char *module, asEGMFlags flag)
  759. {
  760. asCModule *mod = GetModule(module, false);
  761. if( flag == asGM_ALWAYS_CREATE )
  762. {
  763. if( mod != 0 )
  764. {
  765. asDELETE(mod, asCModule);
  766. }
  767. return GetModule(module, true);
  768. }
  769. if( mod == 0 && flag == asGM_CREATE_IF_NOT_EXISTS )
  770. {
  771. return GetModule(module, true);
  772. }
  773. return mod;
  774. }
  775. // interface
  776. int asCScriptEngine::DiscardModule(const char *module)
  777. {
  778. asCModule *mod = GetModule(module, false);
  779. if( mod == 0 ) return asNO_MODULE;
  780. asDELETE(mod, asCModule);
  781. FreeUnusedGlobalProperties();
  782. ClearUnusedTypes();
  783. if( ep.autoGarbageCollect )
  784. GarbageCollect();
  785. return 0;
  786. }
  787. // internal
  788. void asCScriptEngine::ClearUnusedTypes()
  789. {
  790. // Build a list of all types to check for
  791. asCArray<asCObjectType*> types;
  792. types = classTypes;
  793. types.Concatenate(templateInstanceTypes);
  794. // Go through all modules
  795. asUINT n;
  796. for( n = 0; n < scriptModules.GetLength() && types.GetLength(); n++ )
  797. {
  798. asCModule *mod = scriptModules[n];
  799. if( mod )
  800. {
  801. // Functions/Methods/Globals are handled after this
  802. // Go through all type declarations
  803. asUINT m;
  804. for( m = 0; m < mod->classTypes.GetLength() && types.GetLength(); m++ )
  805. RemoveTypeAndRelatedFromList(types, mod->classTypes[m]);
  806. for( m = 0; m < mod->enumTypes.GetLength() && types.GetLength(); m++ )
  807. RemoveTypeAndRelatedFromList(types, mod->enumTypes[m]);
  808. for( m = 0; m < mod->typeDefs.GetLength() && types.GetLength(); m++ )
  809. RemoveTypeAndRelatedFromList(types, mod->typeDefs[m]);
  810. }
  811. }
  812. // Go through all function parameters and remove used types
  813. for( n = 0; n < scriptFunctions.GetLength() && types.GetLength(); n++ )
  814. {
  815. asCScriptFunction *func = scriptFunctions[n];
  816. if( func )
  817. {
  818. // Ignore factory stubs
  819. if( func->name == "factstub" )
  820. continue;
  821. asCObjectType *ot = func->returnType.GetObjectType();
  822. if( ot != 0 && ot != func->objectType )
  823. if( func->name != ot->name )
  824. RemoveTypeAndRelatedFromList(types, ot);
  825. for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
  826. {
  827. ot = func->parameterTypes[p].GetObjectType();
  828. if( ot != 0 && ot != func->objectType )
  829. if( func->name != ot->name )
  830. RemoveTypeAndRelatedFromList(types, ot);
  831. }
  832. }
  833. }
  834. // Go through all global properties
  835. for( n = 0; n < globalProperties.GetLength() && types.GetLength(); n++ )
  836. {
  837. if( globalProperties[n] && globalProperties[n]->type.GetObjectType() )
  838. RemoveTypeAndRelatedFromList(types, globalProperties[n]->type.GetObjectType());
  839. }
  840. // All that remains in the list after this can be discarded, since they are no longer used
  841. for(;;)
  842. {
  843. bool didClearTemplateInstanceType = false;
  844. for( n = 0; n < types.GetLength(); n++ )
  845. {
  846. // Template types and script classes will have two references for each factory stub
  847. int refCount = 0;
  848. if( (types[n]->flags & asOBJ_TEMPLATE) || (types[n]->flags & asOBJ_SCRIPT_OBJECT) )
  849. {
  850. refCount = 2*(int)types[n]->beh.factories.GetLength();
  851. if( types[n]->beh.listFactory )
  852. refCount += 2;
  853. }
  854. if( types[n]->GetRefCount() == refCount )
  855. {
  856. if( types[n]->flags & asOBJ_TEMPLATE )
  857. {
  858. didClearTemplateInstanceType = true;
  859. RemoveTemplateInstanceType(types[n]);
  860. }
  861. else
  862. {
  863. RemoveFromTypeIdMap(types[n]);
  864. asDELETE(types[n],asCObjectType);
  865. int i = classTypes.IndexOf(types[n]);
  866. if( i == (signed)classTypes.GetLength() - 1 )
  867. classTypes.PopLast();
  868. else
  869. classTypes[i] = classTypes.PopLast();
  870. }
  871. // Remove the type from the array
  872. if( n < types.GetLength() - 1 )
  873. types[n] = types.PopLast();
  874. else
  875. types.PopLast();
  876. n--;
  877. }
  878. }
  879. if( didClearTemplateInstanceType == false )
  880. break;
  881. }
  882. }
  883. // internal
  884. void asCScriptEngine::RemoveTypeAndRelatedFromList(asCArray<asCObjectType*> &types, asCObjectType *ot)
  885. {
  886. // Remove the type from the list
  887. int i = types.IndexOf(ot);
  888. if( i == -1 ) return;
  889. if( i == (signed)types.GetLength() - 1 )
  890. types.PopLast();
  891. else
  892. types[i] = types.PopLast();
  893. // If the type is an template type, then remove all sub types as well
  894. if( ot->templateSubType.GetObjectType() )
  895. {
  896. while( ot->templateSubType.GetObjectType() )
  897. {
  898. ot = ot->templateSubType.GetObjectType();
  899. RemoveTypeAndRelatedFromList(types, ot);
  900. }
  901. return;
  902. }
  903. // If the type is a class, then remove all properties types as well
  904. if( ot->properties.GetLength() )
  905. {
  906. for( asUINT n = 0; n < ot->properties.GetLength(); n++ )
  907. RemoveTypeAndRelatedFromList(types, ot->properties[n]->type.GetObjectType());
  908. }
  909. }
  910. // internal
  911. int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *decl)
  912. {
  913. asCModule *mod = 0;
  914. // Is this a script class?
  915. if( ot->flags & asOBJ_SCRIPT_OBJECT && ot->size > 0 )
  916. mod = scriptFunctions[ot->beh.factories[0]]->module;
  917. asCBuilder bld(this, mod);
  918. asCScriptFunction func(this, mod, asFUNC_DUMMY);
  919. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  920. if( r < 0 )
  921. return asINVALID_DECLARATION;
  922. // Search for matching factory function
  923. int id = -1;
  924. for( size_t n = 0; n < ot->beh.factories.GetLength(); n++ )
  925. {
  926. asCScriptFunction *f = scriptFunctions[ot->beh.factories[n]];
  927. if( f->IsSignatureEqual(&func) )
  928. {
  929. id = ot->beh.factories[n];
  930. break;
  931. }
  932. }
  933. if( id == -1 ) return asNO_FUNCTION;
  934. return id;
  935. }
  936. // internal
  937. int asCScriptEngine::GetMethodIdByDecl(const asCObjectType *ot, const char *decl, asCModule *mod)
  938. {
  939. asCBuilder bld(this, mod);
  940. asCScriptFunction func(this, mod, asFUNC_DUMMY);
  941. // Set the object type so that the signature can be properly compared
  942. // This cast is OK, it will only be used for comparison
  943. func.objectType = const_cast<asCObjectType*>(ot);
  944. int r = bld.ParseFunctionDeclaration(func.objectType, decl, &func, false);
  945. if( r < 0 )
  946. return asINVALID_DECLARATION;
  947. // Search script functions for matching interface
  948. int id = -1;
  949. for( size_t n = 0; n < ot->methods.GetLength(); ++n )
  950. {
  951. if( func.IsSignatureEqual(scriptFunctions[ot->methods[n]]) )
  952. {
  953. if( id == -1 )
  954. id = ot->methods[n];
  955. else
  956. return asMULTIPLE_FUNCTIONS;
  957. }
  958. }
  959. if( id == -1 ) return asNO_FUNCTION;
  960. return id;
  961. }
  962. // internal
  963. asCString asCScriptEngine::GetFunctionDeclaration(int funcId)
  964. {
  965. asCString str;
  966. asCScriptFunction *func = GetScriptFunction(funcId);
  967. if( func )
  968. str = func->GetDeclarationStr();
  969. return str;
  970. }
  971. // internal
  972. asCScriptFunction *asCScriptEngine::GetScriptFunction(int funcId) const
  973. {
  974. if( funcId < 0 || funcId >= (int)scriptFunctions.GetLength() )
  975. return 0;
  976. return scriptFunctions[funcId];
  977. }
  978. // interface
  979. asIScriptContext *asCScriptEngine::CreateContext()
  980. {
  981. asIScriptContext *ctx = 0;
  982. CreateContext(&ctx, false);
  983. return ctx;
  984. }
  985. // internal
  986. int asCScriptEngine::CreateContext(asIScriptContext **context, bool isInternal)
  987. {
  988. *context = asNEW(asCContext)(this, !isInternal);
  989. if( *context == 0 )
  990. return asOUT_OF_MEMORY;
  991. // We need to make sure the engine has been
  992. // prepared before any context is executed
  993. PrepareEngine();
  994. return 0;
  995. }
  996. // interface
  997. int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset)
  998. {
  999. int r;
  1000. asCDataType dt;
  1001. asCBuilder bld(this, 0);
  1002. r = bld.ParseDataType(obj, &dt, defaultNamespace);
  1003. if( r < 0 )
  1004. return ConfigError(r, "RegisterObjectProperty", obj, declaration);
  1005. // Verify that the correct config group is used
  1006. if( currentGroup->FindType(dt.GetObjectType()->name.AddressOf()) == 0 )
  1007. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterObjectProperty", obj, declaration);
  1008. asCDataType type;
  1009. asCString name;
  1010. if( (r = bld.VerifyProperty(&dt, declaration, name, type, 0)) < 0 )
  1011. return ConfigError(r, "RegisterObjectProperty", obj, declaration);
  1012. // Store the property info
  1013. if( dt.GetObjectType() == 0 )
  1014. return ConfigError(asINVALID_OBJECT, "RegisterObjectProperty", obj, declaration);
  1015. asCObjectProperty *prop = asNEW(asCObjectProperty);
  1016. if( prop == 0 )
  1017. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectProperty", obj, declaration);
  1018. prop->name = name;
  1019. prop->type = type;
  1020. prop->byteOffset = byteOffset;
  1021. prop->isPrivate = false;
  1022. prop->accessMask = defaultAccessMask;
  1023. dt.GetObjectType()->properties.PushLast(prop);
  1024. currentGroup->RefConfigGroup(FindConfigGroupForObjectType(type.GetObjectType()));
  1025. return asSUCCESS;
  1026. }
  1027. // interface
  1028. int asCScriptEngine::RegisterInterface(const char *name)
  1029. {
  1030. if( name == 0 ) return ConfigError(asINVALID_NAME, "RegisterInterface", 0, 0);
  1031. // Verify if the name has been registered as a type already
  1032. asUINT n;
  1033. for( n = 0; n < objectTypes.GetLength(); n++ )
  1034. {
  1035. if( objectTypes[n] && objectTypes[n]->name == name && objectTypes[n]->nameSpace == defaultNamespace )
  1036. return asALREADY_REGISTERED;
  1037. }
  1038. // Use builder to parse the datatype
  1039. asCDataType dt;
  1040. asCBuilder bld(this, 0);
  1041. bool oldMsgCallback = msgCallback; msgCallback = false;
  1042. int r = bld.ParseDataType(name, &dt, defaultNamespace);
  1043. msgCallback = oldMsgCallback;
  1044. if( r >= 0 ) return ConfigError(asERROR, "RegisterInterface", name, 0);
  1045. // Make sure the name is not a reserved keyword
  1046. size_t tokenLen;
  1047. int token = tok.GetToken(name, strlen(name), &tokenLen);
  1048. if( token != ttIdentifier || strlen(name) != tokenLen )
  1049. return ConfigError(asINVALID_NAME, "RegisterInterface", name, 0);
  1050. r = bld.CheckNameConflict(name, 0, 0, defaultNamespace);
  1051. if( r < 0 )
  1052. return ConfigError(asNAME_TAKEN, "RegisterInterface", name, 0);
  1053. // Don't have to check against members of object
  1054. // types as they are allowed to use the names
  1055. // Register the object type for the interface
  1056. asCObjectType *st = asNEW(asCObjectType)(this);
  1057. if( st == 0 )
  1058. return ConfigError(asOUT_OF_MEMORY, "RegisterInterface", name, 0);
  1059. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_SHARED;
  1060. st->size = 0; // Cannot be instanciated
  1061. st->name = name;
  1062. st->nameSpace = defaultNamespace;
  1063. // Use the default script class behaviours
  1064. st->beh.factory = 0;
  1065. st->beh.addref = scriptTypeBehaviours.beh.addref;
  1066. scriptFunctions[st->beh.addref]->AddRef();
  1067. st->beh.release = scriptTypeBehaviours.beh.release;
  1068. scriptFunctions[st->beh.release]->AddRef();
  1069. st->beh.copy = 0;
  1070. objectTypes.PushLast(st);
  1071. registeredObjTypes.PushLast(st);
  1072. currentGroup->objTypes.PushLast(st);
  1073. return asSUCCESS;
  1074. }
  1075. // interface
  1076. int asCScriptEngine::RegisterInterfaceMethod(const char *intf, const char *declaration)
  1077. {
  1078. // Verify that the correct config group is set.
  1079. if( currentGroup->FindType(intf) == 0 )
  1080. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterInterfaceMethod", intf, declaration);
  1081. asCDataType dt;
  1082. asCBuilder bld(this, 0);
  1083. int r = bld.ParseDataType(intf, &dt, defaultNamespace);
  1084. if( r < 0 )
  1085. return ConfigError(r, "RegisterInterfaceMethod", intf, declaration);
  1086. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_INTERFACE);
  1087. if( func == 0 )
  1088. return ConfigError(asOUT_OF_MEMORY, "RegisterInterfaceMethod", intf, declaration);
  1089. func->objectType = dt.GetObjectType();
  1090. r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, false);
  1091. if( r < 0 )
  1092. {
  1093. asDELETE(func,asCScriptFunction);
  1094. return ConfigError(asINVALID_DECLARATION, "RegisterInterfaceMethod", intf, declaration);
  1095. }
  1096. // Check name conflicts
  1097. r = bld.CheckNameConflictMember(dt.GetObjectType(), func->name.AddressOf(), 0, 0, false);
  1098. if( r < 0 )
  1099. {
  1100. asDELETE(func,asCScriptFunction);
  1101. return ConfigError(asNAME_TAKEN, "RegisterInterfaceMethod", intf, declaration);
  1102. }
  1103. func->id = GetNextScriptFunctionId();
  1104. SetScriptFunction(func);
  1105. func->objectType->methods.PushLast(func->id);
  1106. // The refCount was already set to 1
  1107. func->ComputeSignatureId();
  1108. // If parameter type from other groups are used, add references
  1109. // TODO: The code for adding references to config groups is repeated in a lot of places
  1110. if( func->returnType.GetObjectType() )
  1111. {
  1112. asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
  1113. currentGroup->RefConfigGroup(group);
  1114. }
  1115. for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
  1116. {
  1117. if( func->parameterTypes[n].GetObjectType() )
  1118. {
  1119. asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
  1120. currentGroup->RefConfigGroup(group);
  1121. }
  1122. }
  1123. // Return function id as success
  1124. return func->id;
  1125. }
  1126. int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD flags)
  1127. {
  1128. int r;
  1129. isPrepared = false;
  1130. // Verify flags
  1131. // Must have either asOBJ_REF or asOBJ_VALUE
  1132. if( flags & asOBJ_REF )
  1133. {
  1134. // Can optionally have the asOBJ_GC, asOBJ_NOHANDLE, asOBJ_SCOPED, or asOBJ_TEMPLATE flag set, but nothing else
  1135. if( flags & ~(asOBJ_REF | asOBJ_GC | asOBJ_NOHANDLE | asOBJ_SCOPED | asOBJ_TEMPLATE | asOBJ_NOCOUNT) )
  1136. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1137. // flags are exclusive
  1138. if( (flags & asOBJ_GC) && (flags & (asOBJ_NOHANDLE|asOBJ_SCOPED|asOBJ_NOCOUNT)) )
  1139. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1140. if( (flags & asOBJ_NOHANDLE) && (flags & (asOBJ_GC|asOBJ_SCOPED|asOBJ_NOCOUNT)) )
  1141. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1142. if( (flags & asOBJ_SCOPED) && (flags & (asOBJ_GC|asOBJ_NOHANDLE|asOBJ_NOCOUNT)) )
  1143. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1144. if( (flags & asOBJ_NOCOUNT) && (flags & (asOBJ_GC|asOBJ_NOHANDLE|asOBJ_SCOPED)) )
  1145. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1146. }
  1147. else if( flags & asOBJ_VALUE )
  1148. {
  1149. // Cannot use reference flags
  1150. // TODO: template: Should be possible to register a value type as template type
  1151. if( flags & (asOBJ_REF | asOBJ_GC | asOBJ_SCOPED | asOBJ_TEMPLATE | asOBJ_NOCOUNT) )
  1152. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1153. // flags are exclusive
  1154. if( (flags & asOBJ_POD) && (flags & asOBJ_ASHANDLE) )
  1155. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1156. // If the app type is given, we must validate the flags
  1157. if( flags & asOBJ_APP_CLASS )
  1158. {
  1159. // Must not set the primitive or float flag
  1160. if( flags & (asOBJ_APP_PRIMITIVE | asOBJ_APP_FLOAT) )
  1161. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1162. }
  1163. else if( flags & asOBJ_APP_PRIMITIVE )
  1164. {
  1165. // Must not set the class flags nor the float flag
  1166. if( flags & (asOBJ_APP_CLASS |
  1167. asOBJ_APP_CLASS_CONSTRUCTOR |
  1168. asOBJ_APP_CLASS_DESTRUCTOR |
  1169. asOBJ_APP_CLASS_ASSIGNMENT |
  1170. asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
  1171. asOBJ_APP_FLOAT |
  1172. asOBJ_APP_CLASS_ALLINTS |
  1173. asOBJ_APP_CLASS_ALLFLOATS) )
  1174. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1175. }
  1176. else if( flags & asOBJ_APP_FLOAT )
  1177. {
  1178. // Must not set the class flags nor the primitive flag
  1179. if( flags & (asOBJ_APP_CLASS |
  1180. asOBJ_APP_CLASS_CONSTRUCTOR |
  1181. asOBJ_APP_CLASS_DESTRUCTOR |
  1182. asOBJ_APP_CLASS_ASSIGNMENT |
  1183. asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
  1184. asOBJ_APP_PRIMITIVE |
  1185. asOBJ_APP_CLASS_ALLINTS |
  1186. asOBJ_APP_CLASS_ALLFLOATS) )
  1187. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1188. }
  1189. else if( flags & (asOBJ_APP_CLASS_CONSTRUCTOR |
  1190. asOBJ_APP_CLASS_DESTRUCTOR |
  1191. asOBJ_APP_CLASS_ASSIGNMENT |
  1192. asOBJ_APP_CLASS_COPY_CONSTRUCTOR |
  1193. asOBJ_APP_CLASS_ALLINTS |
  1194. asOBJ_APP_CLASS_ALLFLOATS) )
  1195. {
  1196. // Must not set the class properties, without the class flag
  1197. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1198. }
  1199. }
  1200. else
  1201. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1202. // Don't allow anything else than the defined flags
  1203. if( flags - (flags & asOBJ_MASK_VALID_FLAGS) )
  1204. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1205. // Value types must have a defined size
  1206. if( (flags & asOBJ_VALUE) && byteSize == 0 )
  1207. {
  1208. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_VALUE_TYPE_MUST_HAVE_SIZE);
  1209. return ConfigError(asINVALID_ARG, "RegisterObjectType", name, 0);
  1210. }
  1211. // Verify type name
  1212. if( name == 0 )
  1213. return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0);
  1214. asCString typeName;
  1215. asCBuilder bld(this, 0);
  1216. if( flags & asOBJ_TEMPLATE )
  1217. {
  1218. asCString subtypeName;
  1219. r = bld.ParseTemplateDecl(name, &typeName, &subtypeName);
  1220. if( r < 0 )
  1221. return ConfigError(r, "RegisterObjectType", name, 0);
  1222. // Verify that the template name hasn't been registered as a type already
  1223. asUINT n;
  1224. for( n = 0; n < objectTypes.GetLength(); n++ )
  1225. {
  1226. if( objectTypes[n] && objectTypes[n]->name == typeName && objectTypes[n]->nameSpace == defaultNamespace )
  1227. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1228. return asALREADY_REGISTERED;
  1229. }
  1230. asCObjectType *type = asNEW(asCObjectType)(this);
  1231. if( type == 0 )
  1232. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1233. type->name = typeName;
  1234. type->nameSpace = defaultNamespace;
  1235. type->size = byteSize;
  1236. type->flags = flags;
  1237. type->accessMask = defaultAccessMask;
  1238. // Store it in the object types
  1239. objectTypes.PushLast(type);
  1240. // Define a template subtype
  1241. asCObjectType *subtype = 0;
  1242. for( n = 0; n < templateSubTypes.GetLength(); n++ )
  1243. {
  1244. if( templateSubTypes[n]->name == subtypeName )
  1245. {
  1246. subtype = templateSubTypes[n];
  1247. break;
  1248. }
  1249. }
  1250. if( subtype == 0 )
  1251. {
  1252. // Create the new subtype if not already existing
  1253. subtype = asNEW(asCObjectType)(this);
  1254. if( subtype == 0 )
  1255. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1256. subtype->name = subtypeName;
  1257. subtype->size = 0;
  1258. subtype->flags = asOBJ_TEMPLATE_SUBTYPE;
  1259. templateSubTypes.PushLast(subtype);
  1260. subtype->AddRef();
  1261. }
  1262. type->templateSubType = asCDataType::CreateObject(subtype, false);
  1263. subtype->AddRef();
  1264. currentGroup->objTypes.PushLast(type);
  1265. registeredObjTypes.PushLast(type);
  1266. }
  1267. else
  1268. {
  1269. typeName = name;
  1270. // Verify if the name has been registered as a type already
  1271. asUINT n;
  1272. for( n = 0; n < objectTypes.GetLength(); n++ )
  1273. {
  1274. if( objectTypes[n] &&
  1275. objectTypes[n]->name == typeName &&
  1276. objectTypes[n]->nameSpace == defaultNamespace )
  1277. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1278. return asALREADY_REGISTERED;
  1279. }
  1280. for( n = 0; n < templateTypes.GetLength(); n++ )
  1281. {
  1282. if( templateTypes[n] &&
  1283. templateTypes[n]->name == typeName &&
  1284. templateTypes[n]->nameSpace == defaultNamespace )
  1285. // This is not an irrepairable error, as it may just be that the same type is registered twice
  1286. return asALREADY_REGISTERED;
  1287. }
  1288. // Verify the most recently created template instance type
  1289. asCObjectType *mostRecentTemplateInstanceType = 0;
  1290. if( templateInstanceTypes.GetLength() )
  1291. mostRecentTemplateInstanceType = templateInstanceTypes[templateInstanceTypes.GetLength()-1];
  1292. // Use builder to parse the datatype
  1293. asCDataType dt;
  1294. bool oldMsgCallback = msgCallback; msgCallback = false;
  1295. r = bld.ParseDataType(name, &dt, defaultNamespace);
  1296. msgCallback = oldMsgCallback;
  1297. // If the builder fails, then the type name
  1298. // is new and it should be registered
  1299. if( r < 0 )
  1300. {
  1301. // Make sure the name is not a reserved keyword
  1302. size_t tokenLen;
  1303. int token = tok.GetToken(name, typeName.GetLength(), &tokenLen);
  1304. if( token != ttIdentifier || typeName.GetLength() != tokenLen )
  1305. return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0);
  1306. int r = bld.CheckNameConflict(name, 0, 0, defaultNamespace);
  1307. if( r < 0 )
  1308. return ConfigError(asNAME_TAKEN, "RegisterObjectType", name, 0);
  1309. // Don't have to check against members of object
  1310. // types as they are allowed to use the names
  1311. // Put the data type in the list
  1312. asCObjectType *type = asNEW(asCObjectType)(this);
  1313. if( type == 0 )
  1314. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1315. type->name = typeName;
  1316. type->nameSpace = defaultNamespace;
  1317. type->size = byteSize;
  1318. type->flags = flags;
  1319. type->accessMask = defaultAccessMask;
  1320. objectTypes.PushLast(type);
  1321. registeredObjTypes.PushLast(type);
  1322. currentGroup->objTypes.PushLast(type);
  1323. }
  1324. else
  1325. {
  1326. // The application is registering a template specialization so we
  1327. // need to replace the template instance type with the new type.
  1328. // TODO: Template: We don't require the lower dimensions to be registered first for registered template types
  1329. // int[][] must not be allowed to be registered
  1330. // if int[] hasn't been registered first
  1331. if( dt.GetSubType().IsTemplate() )
  1332. return ConfigError(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED, "RegisterObjectType", name, 0);
  1333. if( dt.IsReadOnly() ||
  1334. dt.IsReference() )
  1335. return ConfigError(asINVALID_TYPE, "RegisterObjectType", name, 0);
  1336. // Was the template instance type created before?
  1337. if( templateInstanceTypes[templateInstanceTypes.GetLength()-1] == mostRecentTemplateInstanceType ||
  1338. mostRecentTemplateInstanceType == dt.GetObjectType() )
  1339. // TODO: Should have a better error message
  1340. return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0);
  1341. // TODO: Add this again. The type is used by the factory stubs so we need to discount that
  1342. // Is the template instance type already being used?
  1343. // if( dt.GetObjectType()->GetRefCount() > 1 )
  1344. // return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0);
  1345. // Put the data type in the list
  1346. asCObjectType *type = asNEW(asCObjectType)(this);
  1347. if( type == 0 )
  1348. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectType", name, 0);
  1349. type->name = dt.GetObjectType()->name;
  1350. // The namespace will be the same as the original template type
  1351. type->nameSpace = dt.GetObjectType()->nameSpace;
  1352. type->templateSubType = dt.GetSubType();
  1353. if( type->templateSubType.GetObjectType() ) type->templateSubType.GetObjectType()->AddRef();
  1354. type->size = byteSize;
  1355. type->flags = flags;
  1356. type->accessMask = defaultAccessMask;
  1357. templateTypes.PushLast(type);
  1358. currentGroup->objTypes.PushLast(type);
  1359. // Remove the template instance type, which will no longer be used.
  1360. RemoveTemplateInstanceType(dt.GetObjectType());
  1361. }
  1362. }
  1363. // Return the type id as the success (except for template types)
  1364. if( flags & asOBJ_TEMPLATE )
  1365. return asSUCCESS;
  1366. return GetTypeIdByDecl(name);
  1367. }
  1368. // interface
  1369. int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv)
  1370. {
  1371. if( datatype == 0 ) return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", datatype, decl);
  1372. // Determine the object type
  1373. asCBuilder bld(this, 0);
  1374. asCDataType type;
  1375. int r = bld.ParseDataType(datatype, &type, defaultNamespace);
  1376. if( r < 0 )
  1377. return ConfigError(r, "RegisterObjectBehaviour", datatype, decl);
  1378. if( type.GetObjectType() == 0 )
  1379. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1380. if( type.IsReadOnly() || type.IsReference() )
  1381. return ConfigError(asINVALID_TYPE, "RegisterObjectBehaviour", datatype, decl);
  1382. return RegisterBehaviourToObjectType(type.GetObjectType(), behaviour, decl, funcPointer, callConv);
  1383. }
  1384. // internal
  1385. int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv)
  1386. {
  1387. asSSystemFunctionInterface internal;
  1388. if( behaviour == asBEHAVE_FACTORY ||
  1389. behaviour == asBEHAVE_LIST_FACTORY ||
  1390. behaviour == asBEHAVE_TEMPLATE_CALLBACK )
  1391. {
  1392. #ifdef AS_MAX_PORTABILITY
  1393. if( callConv != asCALL_GENERIC )
  1394. return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1395. #endif
  1396. int r = DetectCallingConvention(false, funcPointer, callConv, &internal);
  1397. if( r < 0 )
  1398. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1399. }
  1400. else
  1401. {
  1402. #ifdef AS_MAX_PORTABILITY
  1403. if( callConv != asCALL_GENERIC )
  1404. return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1405. #else
  1406. if( callConv != asCALL_THISCALL &&
  1407. callConv != asCALL_CDECL_OBJLAST &&
  1408. callConv != asCALL_CDECL_OBJFIRST &&
  1409. callConv != asCALL_GENERIC )
  1410. return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1411. #endif
  1412. int r = DetectCallingConvention(true, funcPointer, callConv, &internal);
  1413. if( r < 0 )
  1414. return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1415. }
  1416. isPrepared = false;
  1417. asSTypeBehaviour *beh = &objectType->beh;
  1418. // Verify function declaration
  1419. asCScriptFunction func(this, 0, asFUNC_DUMMY);
  1420. asCBuilder bld(this, 0);
  1421. int r = bld.ParseFunctionDeclaration(objectType, decl, &func, true, &internal.paramAutoHandles, &internal.returnAutoHandle);
  1422. if( r < 0 )
  1423. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1424. func.name.Format("_beh_%d_", behaviour);
  1425. if( behaviour != asBEHAVE_FACTORY && behaviour != asBEHAVE_LIST_FACTORY )
  1426. func.objectType = objectType;
  1427. // Check if the method restricts that use of the template to value types or reference types
  1428. if( objectType->flags & asOBJ_TEMPLATE )
  1429. {
  1430. if( func.returnType.GetObjectType() == objectType->templateSubType.GetObjectType() )
  1431. {
  1432. if( func.returnType.IsObjectHandle() )
  1433. objectType->acceptValueSubType = false;
  1434. else if( !func.returnType.IsReference() )
  1435. objectType->acceptRefSubType = false;
  1436. }
  1437. for( asUINT n = 0; n < func.parameterTypes.GetLength(); n++ )
  1438. {
  1439. if( func.parameterTypes[n].GetObjectType() == objectType->templateSubType.GetObjectType() )
  1440. {
  1441. // TODO: If unsafe references are allowed, then inout references allow value types
  1442. if( func.parameterTypes[n].IsObjectHandle() || (func.parameterTypes[n].IsReference() && func.inOutFlags[n] == asTM_INOUTREF) )
  1443. objectType->acceptValueSubType = false;
  1444. else if( !func.parameterTypes[n].IsReference() )
  1445. objectType->acceptRefSubType = false;
  1446. }
  1447. }
  1448. }
  1449. if( behaviour == asBEHAVE_CONSTRUCT )
  1450. {
  1451. // TODO: Add asBEHAVE_IMPLICIT_CONSTRUCT
  1452. // Verify that the return type is void
  1453. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1454. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1455. if( objectType->flags & asOBJ_SCRIPT_OBJECT )
  1456. {
  1457. // The script object is a special case
  1458. asASSERT(func.parameterTypes.GetLength() == 1);
  1459. beh->construct = AddBehaviourFunction(func, internal);
  1460. beh->factory = beh->construct;
  1461. scriptFunctions[beh->factory]->AddRef();
  1462. beh->constructors.PushLast(beh->construct);
  1463. beh->factories.PushLast(beh->factory);
  1464. func.id = beh->construct;
  1465. }
  1466. else
  1467. {
  1468. // Verify that it is a value type
  1469. if( !(func.objectType->flags & asOBJ_VALUE) )
  1470. {
  1471. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1472. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1473. }
  1474. // TODO: Add support for implicit constructors
  1475. // TODO: Verify that the same constructor hasn't been registered already
  1476. // Store all constructors in a list
  1477. func.id = AddBehaviourFunction(func, internal);
  1478. beh->constructors.PushLast(func.id);
  1479. if( func.parameterTypes.GetLength() == 0 )
  1480. {
  1481. beh->construct = func.id;
  1482. }
  1483. else if( func.parameterTypes.GetLength() == 1 )
  1484. {
  1485. // Is this the copy constructor?
  1486. asCDataType paramType = func.parameterTypes[0];
  1487. // If the parameter is object, and const reference for input,
  1488. // and same type as this class, then this is a copy constructor.
  1489. if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[0] == asTM_INREF && paramType.GetObjectType() == objectType )
  1490. beh->copyconstruct = func.id;
  1491. }
  1492. }
  1493. }
  1494. else if( behaviour == asBEHAVE_DESTRUCT )
  1495. {
  1496. // Must be a value type
  1497. if( !(func.objectType->flags & asOBJ_VALUE) )
  1498. {
  1499. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1500. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1501. }
  1502. if( beh->destruct )
  1503. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1504. // Verify that the return type is void
  1505. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1506. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1507. // Verify that there are no parameters
  1508. if( func.parameterTypes.GetLength() > 0 )
  1509. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1510. func.id = beh->destruct = AddBehaviourFunction(func, internal);
  1511. }
  1512. else if( behaviour == asBEHAVE_FACTORY || behaviour == asBEHAVE_LIST_FACTORY )
  1513. {
  1514. // Must be a ref type and must not have asOBJ_NOHANDLE
  1515. if( !(objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_NOHANDLE) )
  1516. {
  1517. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1518. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1519. }
  1520. // Verify that the return type is a handle to the type
  1521. if( func.returnType != asCDataType::CreateObjectHandle(objectType, false) )
  1522. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1523. // TODO: Add support for implicit factories
  1524. // TODO: Verify that the same factory function hasn't been registered already
  1525. // The templates take a hidden parameter with the object type
  1526. if( (objectType->flags & asOBJ_TEMPLATE) &&
  1527. (func.parameterTypes.GetLength() == 0 ||
  1528. !func.parameterTypes[0].IsReference()) )
  1529. {
  1530. // TODO: Give proper error message that explain that the first parameter is expected to be a reference
  1531. // The library should try to avoid having to read the manual as much as possible.
  1532. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1533. }
  1534. // Store all factory functions in a list
  1535. func.id = AddBehaviourFunction(func, internal);
  1536. // The list factory is a special factory and isn't stored together with the rest
  1537. if( behaviour != asBEHAVE_LIST_FACTORY )
  1538. beh->factories.PushLast(func.id);
  1539. if( (func.parameterTypes.GetLength() == 0) ||
  1540. (func.parameterTypes.GetLength() == 1 && (objectType->flags & asOBJ_TEMPLATE)) )
  1541. {
  1542. beh->factory = func.id;
  1543. }
  1544. else if( (func.parameterTypes.GetLength() == 1) ||
  1545. (func.parameterTypes.GetLength() == 2 && (objectType->flags & asOBJ_TEMPLATE)) )
  1546. {
  1547. if( behaviour == asBEHAVE_LIST_FACTORY )
  1548. beh->listFactory = func.id;
  1549. else
  1550. {
  1551. // Is this the copy factory?
  1552. asCDataType paramType = func.parameterTypes[func.parameterTypes.GetLength()-1];
  1553. // If the parameter is object, and const reference for input,
  1554. // and same type as this class, then this is a copy constructor.
  1555. if( paramType.IsObject() && paramType.IsReference() && paramType.IsReadOnly() && func.inOutFlags[func.parameterTypes.GetLength()-1] == asTM_INREF && paramType.GetObjectType() == objectType )
  1556. beh->copyfactory = func.id;
  1557. }
  1558. }
  1559. }
  1560. else if( behaviour == asBEHAVE_ADDREF )
  1561. {
  1562. // Must be a ref type and must not have asOBJ_NOHANDLE, nor asOBJ_SCOPED
  1563. if( !(func.objectType->flags & asOBJ_REF) ||
  1564. (func.objectType->flags & asOBJ_NOHANDLE) ||
  1565. (func.objectType->flags & asOBJ_SCOPED) ||
  1566. (func.objectType->flags & asOBJ_NOCOUNT) )
  1567. {
  1568. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1569. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1570. }
  1571. if( beh->addref )
  1572. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1573. // Verify that the return type is void
  1574. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1575. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1576. // Verify that there are no parameters
  1577. if( func.parameterTypes.GetLength() > 0 )
  1578. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1579. func.id = beh->addref = AddBehaviourFunction(func, internal);
  1580. }
  1581. else if( behaviour == asBEHAVE_RELEASE )
  1582. {
  1583. // Must be a ref type and must not have asOBJ_NOHANDLE
  1584. if( !(func.objectType->flags & asOBJ_REF) ||
  1585. (func.objectType->flags & asOBJ_NOHANDLE) ||
  1586. (func.objectType->flags & asOBJ_NOCOUNT) )
  1587. {
  1588. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1589. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1590. }
  1591. if( beh->release )
  1592. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1593. // Verify that the return type is void
  1594. if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1595. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1596. // Verify that there are no parameters
  1597. if( func.parameterTypes.GetLength() > 0 )
  1598. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1599. func.id = beh->release = AddBehaviourFunction(func, internal);
  1600. }
  1601. else if( behaviour == asBEHAVE_TEMPLATE_CALLBACK )
  1602. {
  1603. // Must be a template type
  1604. if( !(func.objectType->flags & asOBJ_TEMPLATE) )
  1605. {
  1606. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1607. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1608. }
  1609. if( beh->templateCallback )
  1610. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1611. // Verify that the return type is bool
  1612. if( func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
  1613. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1614. // Verify that there are two parameters
  1615. if( func.parameterTypes.GetLength() != 2 )
  1616. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1617. // The first parameter must be an inref (to receive the object type), and
  1618. // the second must be a bool out ref (to return if the type should or shouldn't be garbage collected)
  1619. if( func.inOutFlags[0] != asTM_INREF || func.inOutFlags[1] != asTM_OUTREF || !func.parameterTypes[1].IsEqualExceptRef(asCDataType::CreatePrimitive(ttBool, false)) )
  1620. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1621. func.id = beh->templateCallback = AddBehaviourFunction(func, internal);
  1622. }
  1623. else if( behaviour >= asBEHAVE_FIRST_GC &&
  1624. behaviour <= asBEHAVE_LAST_GC )
  1625. {
  1626. // Only allow GC behaviours for types registered to be garbage collected
  1627. if( !(func.objectType->flags & asOBJ_GC) )
  1628. {
  1629. WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
  1630. return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1631. }
  1632. // Verify parameter count
  1633. if( (behaviour == asBEHAVE_GETREFCOUNT ||
  1634. behaviour == asBEHAVE_SETGCFLAG ||
  1635. behaviour == asBEHAVE_GETGCFLAG) &&
  1636. func.parameterTypes.GetLength() != 0 )
  1637. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1638. if( (behaviour == asBEHAVE_ENUMREFS ||
  1639. behaviour == asBEHAVE_RELEASEREFS) &&
  1640. func.parameterTypes.GetLength() != 1 )
  1641. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1642. // Verify return type
  1643. if( behaviour == asBEHAVE_GETREFCOUNT &&
  1644. func.returnType != asCDataType::CreatePrimitive(ttInt, false) )
  1645. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1646. if( behaviour == asBEHAVE_GETGCFLAG &&
  1647. func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
  1648. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1649. if( (behaviour == asBEHAVE_SETGCFLAG ||
  1650. behaviour == asBEHAVE_ENUMREFS ||
  1651. behaviour == asBEHAVE_RELEASEREFS) &&
  1652. func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
  1653. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1654. if( behaviour == asBEHAVE_GETREFCOUNT )
  1655. func.id = beh->gcGetRefCount = AddBehaviourFunction(func, internal);
  1656. else if( behaviour == asBEHAVE_SETGCFLAG )
  1657. func.id = beh->gcSetFlag = AddBehaviourFunction(func, internal);
  1658. else if( behaviour == asBEHAVE_GETGCFLAG )
  1659. func.id = beh->gcGetFlag = AddBehaviourFunction(func, internal);
  1660. else if( behaviour == asBEHAVE_ENUMREFS )
  1661. func.id = beh->gcEnumReferences = AddBehaviourFunction(func, internal);
  1662. else if( behaviour == asBEHAVE_RELEASEREFS )
  1663. func.id = beh->gcReleaseAllReferences = AddBehaviourFunction(func, internal);
  1664. }
  1665. else if( behaviour == asBEHAVE_IMPLICIT_VALUE_CAST ||
  1666. behaviour == asBEHAVE_VALUE_CAST )
  1667. {
  1668. // Verify parameter count
  1669. if( func.parameterTypes.GetLength() != 0 )
  1670. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1671. // Verify return type
  1672. if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, false)) )
  1673. return ConfigError(asNOT_SUPPORTED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1674. if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttVoid, false)) )
  1675. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1676. // TODO: verify that the same cast is not registered already (const or non-const is treated the same for the return type)
  1677. beh->operators.PushLast(behaviour);
  1678. func.id = AddBehaviourFunction(func, internal);
  1679. beh->operators.PushLast(func.id);
  1680. }
  1681. else if( behaviour == asBEHAVE_REF_CAST ||
  1682. behaviour == asBEHAVE_IMPLICIT_REF_CAST )
  1683. {
  1684. // There are two allowed signatures
  1685. // 1. obj @f()
  1686. // 2. void f(?&out)
  1687. if( !(func.parameterTypes.GetLength() == 0 && func.returnType.IsObjectHandle()) &&
  1688. !(func.parameterTypes.GetLength() == 1 && func.parameterTypes[0].GetTokenType() == ttQuestion && func.inOutFlags[0] == asTM_OUTREF && func.returnType.GetTokenType() == ttVoid) )
  1689. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1690. // Currently it is not supported to register const overloads for the ref cast behaviour
  1691. if( func.IsReadOnly() )
  1692. return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1693. // Verify that the same cast is not registered already
  1694. // (const or non-const is treated the same for the return type)
  1695. if( func.parameterTypes.GetLength() == 1 )
  1696. {
  1697. // Check for existing behaviour with ?&out
  1698. for( asUINT n = 0; n < beh->operators.GetLength(); n+= 2 )
  1699. {
  1700. if( beh->operators[n] == asBEHAVE_REF_CAST ||
  1701. beh->operators[n] == asBEHAVE_IMPLICIT_REF_CAST )
  1702. {
  1703. asCScriptFunction *f = scriptFunctions[beh->operators[n+1]];
  1704. if( f->parameterTypes.GetLength() == 1 )
  1705. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1706. }
  1707. }
  1708. }
  1709. else
  1710. {
  1711. // Check for existing behaviour with same return type
  1712. for( asUINT n = 0; n < beh->operators.GetLength(); n+= 2 )
  1713. {
  1714. if( beh->operators[n] == asBEHAVE_REF_CAST ||
  1715. beh->operators[n] == asBEHAVE_IMPLICIT_REF_CAST )
  1716. {
  1717. asCScriptFunction *f = scriptFunctions[beh->operators[n+1]];
  1718. if( f->returnType.GetObjectType() == func.returnType.GetObjectType() )
  1719. return ConfigError(asALREADY_REGISTERED, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1720. }
  1721. }
  1722. }
  1723. beh->operators.PushLast(behaviour);
  1724. func.id = AddBehaviourFunction(func, internal);
  1725. beh->operators.PushLast(func.id);
  1726. }
  1727. else
  1728. {
  1729. asASSERT(false);
  1730. return ConfigError(asINVALID_ARG, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1731. }
  1732. if( func.id < 0 )
  1733. return ConfigError(func.id, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
  1734. // Return function id as success
  1735. return func.id;
  1736. }
  1737. int asCScriptEngine::VerifyVarTypeNotInFunction(asCScriptFunction *func)
  1738. {
  1739. // Don't allow var type in this function
  1740. if( func->returnType.GetTokenType() == ttQuestion )
  1741. return asINVALID_DECLARATION;
  1742. for( unsigned int n = 0; n < func->parameterTypes.GetLength(); n++ )
  1743. if( func->parameterTypes[n].GetTokenType() == ttQuestion )
  1744. return asINVALID_DECLARATION;
  1745. return 0;
  1746. }
  1747. int asCScriptEngine::AddBehaviourFunction(asCScriptFunction &func, asSSystemFunctionInterface &internal)
  1748. {
  1749. asUINT n;
  1750. int id = GetNextScriptFunctionId();
  1751. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface);
  1752. if( newInterface == 0 )
  1753. return asOUT_OF_MEMORY;
  1754. newInterface->func = internal.func;
  1755. newInterface->baseOffset = internal.baseOffset;
  1756. newInterface->callConv = internal.callConv;
  1757. newInterface->scriptReturnSize = internal.scriptReturnSize;
  1758. newInterface->hostReturnInMemory = internal.hostReturnInMemory;
  1759. newInterface->hostReturnFloat = internal.hostReturnFloat;
  1760. newInterface->hostReturnSize = internal.hostReturnSize;
  1761. newInterface->paramSize = internal.paramSize;
  1762. newInterface->takesObjByVal = internal.takesObjByVal;
  1763. newInterface->paramAutoHandles = internal.paramAutoHandles;
  1764. newInterface->returnAutoHandle = internal.returnAutoHandle;
  1765. newInterface->hasAutoHandles = internal.hasAutoHandles;
  1766. asCScriptFunction *f = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  1767. if( f == 0 )
  1768. {
  1769. asDELETE(newInterface, asSSystemFunctionInterface);
  1770. return asOUT_OF_MEMORY;
  1771. }
  1772. asASSERT(func.name != "" && func.name != "f");
  1773. f->name = func.name;
  1774. f->sysFuncIntf = newInterface;
  1775. f->returnType = func.returnType;
  1776. f->objectType = func.objectType;
  1777. f->id = id;
  1778. f->isReadOnly = func.isReadOnly;
  1779. f->accessMask = defaultAccessMask;
  1780. f->parameterTypes = func.parameterTypes;
  1781. f->inOutFlags = func.inOutFlags;
  1782. for( n = 0; n < func.defaultArgs.GetLength(); n++ )
  1783. if( func.defaultArgs[n] )
  1784. f->defaultArgs.PushLast(asNEW(asCString)(*func.defaultArgs[n]));
  1785. else
  1786. f->defaultArgs.PushLast(0);
  1787. SetScriptFunction(f);
  1788. // If parameter type from other groups are used, add references
  1789. if( f->returnType.GetObjectType() )
  1790. {
  1791. asCConfigGroup *group = FindConfigGroupForObjectType(f->returnType.GetObjectType());
  1792. currentGroup->RefConfigGroup(group);
  1793. }
  1794. for( n = 0; n < f->parameterTypes.GetLength(); n++ )
  1795. {
  1796. if( f->parameterTypes[n].GetObjectType() )
  1797. {
  1798. asCConfigGroup *group = FindConfigGroupForObjectType(f->parameterTypes[n].GetObjectType());
  1799. currentGroup->RefConfigGroup(group);
  1800. }
  1801. }
  1802. return id;
  1803. }
  1804. // interface
  1805. int asCScriptEngine::RegisterGlobalProperty(const char *declaration, void *pointer)
  1806. {
  1807. // Don't accept a null pointer
  1808. if( pointer == 0 )
  1809. return ConfigError(asINVALID_ARG, "RegisterGlobalProperty", declaration, 0);
  1810. asCDataType type;
  1811. asCString name;
  1812. int r;
  1813. asCBuilder bld(this, 0);
  1814. if( (r = bld.VerifyProperty(0, declaration, name, type, defaultNamespace)) < 0 )
  1815. return ConfigError(r, "RegisterGlobalProperty", declaration, 0);
  1816. // Don't allow registering references as global properties
  1817. if( type.IsReference() )
  1818. return ConfigError(asINVALID_TYPE, "RegisterGlobalProperty", declaration, 0);
  1819. // Store the property info
  1820. asCGlobalProperty *prop = AllocateGlobalProperty();
  1821. prop->name = name;
  1822. prop->nameSpace = defaultNamespace;
  1823. prop->type = type;
  1824. prop->accessMask = defaultAccessMask;
  1825. prop->SetRegisteredAddress(pointer);
  1826. varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  1827. registeredGlobalProps.Put(prop);
  1828. currentGroup->globalProps.PushLast(prop);
  1829. // If from another group add reference
  1830. if( type.GetObjectType() )
  1831. {
  1832. asCConfigGroup *group = FindConfigGroupForObjectType(type.GetObjectType());
  1833. currentGroup->RefConfigGroup(group);
  1834. }
  1835. return asSUCCESS;
  1836. }
  1837. // internal
  1838. asCGlobalProperty *asCScriptEngine::AllocateGlobalProperty()
  1839. {
  1840. asCGlobalProperty *prop = asNEW(asCGlobalProperty);
  1841. if( prop == 0 )
  1842. {
  1843. // Out of memory
  1844. return 0;
  1845. }
  1846. // First check the availability of a free slot
  1847. if( freeGlobalPropertyIds.GetLength() )
  1848. {
  1849. prop->id = freeGlobalPropertyIds.PopLast();
  1850. globalProperties[prop->id] = prop;
  1851. return prop;
  1852. }
  1853. prop->id = (asUINT)globalProperties.GetLength();
  1854. globalProperties.PushLast(prop);
  1855. return prop;
  1856. }
  1857. // internal
  1858. void asCScriptEngine::FreeUnusedGlobalProperties()
  1859. {
  1860. for( asUINT n = 0; n < globalProperties.GetLength(); n++ )
  1861. {
  1862. if( globalProperties[n] && globalProperties[n]->GetRefCount() == 0 )
  1863. {
  1864. freeGlobalPropertyIds.PushLast(n);
  1865. asSMapNode<void*, asCGlobalProperty*> *node;
  1866. varAddressMap.MoveTo(&node, globalProperties[n]->GetAddressOfValue());
  1867. asASSERT(node);
  1868. if( node )
  1869. varAddressMap.Erase(node);
  1870. asDELETE(globalProperties[n], asCGlobalProperty);
  1871. globalProperties[n] = 0;
  1872. }
  1873. }
  1874. }
  1875. // interface
  1876. asUINT asCScriptEngine::GetGlobalPropertyCount() const
  1877. {
  1878. return asUINT(registeredGlobalProps.GetSize());
  1879. }
  1880. // interface
  1881. // TODO: If the typeId ever encodes the const flag, then the isConst parameter should be removed
  1882. int asCScriptEngine::GetGlobalPropertyByIndex(asUINT index, const char **name, const char **nameSpace, int *typeId, bool *isConst, const char **configGroup, void **pointer, asDWORD *accessMask) const
  1883. {
  1884. const asCGlobalProperty *prop = registeredGlobalProps.Get(index);
  1885. if( !prop )
  1886. return asINVALID_ARG;
  1887. if( name ) *name = prop->name.AddressOf();
  1888. if( nameSpace ) *nameSpace = prop->nameSpace->name.AddressOf();
  1889. if( typeId ) *typeId = GetTypeIdFromDataType(prop->type);
  1890. if( isConst ) *isConst = prop->type.IsReadOnly();
  1891. if( pointer ) *pointer = prop->GetRegisteredAddress();
  1892. if( accessMask ) *accessMask = prop->accessMask;
  1893. if( configGroup )
  1894. {
  1895. asCConfigGroup *group = FindConfigGroupForGlobalVar(index);
  1896. if( group )
  1897. *configGroup = group->groupName.AddressOf();
  1898. else
  1899. *configGroup = 0;
  1900. }
  1901. return asSUCCESS;
  1902. }
  1903. // interface
  1904. int asCScriptEngine::GetGlobalPropertyIndexByName(const char *name) const
  1905. {
  1906. // Find the global var id
  1907. int id = registeredGlobalProps.GetFirstIndex(defaultNamespace, name);
  1908. if( id == -1 ) return asNO_GLOBAL_VAR;
  1909. return id;
  1910. }
  1911. // interface
  1912. int asCScriptEngine::GetGlobalPropertyIndexByDecl(const char *decl) const
  1913. {
  1914. // This const cast is OK. The builder won't modify the engine
  1915. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  1916. asCString name;
  1917. asSNameSpace *ns;
  1918. asCDataType dt;
  1919. bld.ParseVariableDeclaration(decl, defaultNamespace, name, ns, dt);
  1920. // Search for a match
  1921. int id = registeredGlobalProps.GetFirstIndex(ns, name, asCCompGlobPropType(dt));
  1922. if (id < 0)
  1923. return asNO_GLOBAL_VAR;
  1924. return id;
  1925. }
  1926. // interface
  1927. int asCScriptEngine::RegisterObjectMethod(const char *obj, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv)
  1928. {
  1929. if( obj == 0 )
  1930. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  1931. // Determine the object type
  1932. asCDataType dt;
  1933. asCBuilder bld(this, 0);
  1934. int r = bld.ParseDataType(obj, &dt, defaultNamespace);
  1935. if( r < 0 )
  1936. return ConfigError(r, "RegisterObjectMethod", obj, declaration);
  1937. if( dt.GetObjectType() == 0 )
  1938. return ConfigError(asINVALID_ARG, "RegisterObjectMethod", obj, declaration);
  1939. return RegisterMethodToObjectType(dt.GetObjectType(), declaration, funcPointer, callConv);
  1940. }
  1941. // internal
  1942. int asCScriptEngine::RegisterMethodToObjectType(asCObjectType *objectType, const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv)
  1943. {
  1944. asSSystemFunctionInterface internal;
  1945. int r = DetectCallingConvention(true, funcPointer, callConv, &internal);
  1946. if( r < 0 )
  1947. return ConfigError(r, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  1948. // We only support these calling conventions for object methods
  1949. #ifdef AS_MAX_PORTABILITY
  1950. if( callConv != asCALL_GENERIC )
  1951. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  1952. #else
  1953. if( callConv != asCALL_THISCALL &&
  1954. callConv != asCALL_CDECL_OBJLAST &&
  1955. callConv != asCALL_CDECL_OBJFIRST &&
  1956. callConv != asCALL_GENERIC )
  1957. return ConfigError(asNOT_SUPPORTED, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  1958. #endif
  1959. isPrepared = false;
  1960. // Put the system function in the list of system functions
  1961. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  1962. if( newInterface == 0 )
  1963. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  1964. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  1965. if( func == 0 )
  1966. {
  1967. asDELETE(newInterface, asSSystemFunctionInterface);
  1968. return ConfigError(asOUT_OF_MEMORY, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  1969. }
  1970. func->sysFuncIntf = newInterface;
  1971. func->objectType = objectType;
  1972. asCBuilder bld(this, 0);
  1973. r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle);
  1974. if( r < 0 )
  1975. {
  1976. // Set as dummy function before deleting
  1977. func->funcType = asFUNC_DUMMY;
  1978. asDELETE(func,asCScriptFunction);
  1979. return ConfigError(asINVALID_DECLARATION, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  1980. }
  1981. // Check name conflicts
  1982. r = bld.CheckNameConflictMember(objectType, func->name.AddressOf(), 0, 0, false);
  1983. if( r < 0 )
  1984. {
  1985. asDELETE(func,asCScriptFunction);
  1986. return ConfigError(asNAME_TAKEN, "RegisterObjectMethod", objectType->name.AddressOf(), declaration);
  1987. }
  1988. func->id = GetNextScriptFunctionId();
  1989. func->objectType->methods.PushLast(func->id);
  1990. func->accessMask = defaultAccessMask;
  1991. SetScriptFunction(func);
  1992. // TODO: This code is repeated in many places
  1993. // If parameter type from other groups are used, add references
  1994. if( func->returnType.GetObjectType() )
  1995. {
  1996. asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
  1997. currentGroup->RefConfigGroup(group);
  1998. }
  1999. for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
  2000. {
  2001. if( func->parameterTypes[n].GetObjectType() )
  2002. {
  2003. asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
  2004. currentGroup->RefConfigGroup(group);
  2005. }
  2006. }
  2007. // Check if the method restricts that use of the template to value types or reference types
  2008. if( func->objectType->flags & asOBJ_TEMPLATE )
  2009. {
  2010. if( func->returnType.GetObjectType() == func->objectType->templateSubType.GetObjectType() )
  2011. {
  2012. if( func->returnType.IsObjectHandle() )
  2013. func->objectType->acceptValueSubType = false;
  2014. else if( !func->returnType.IsReference() )
  2015. func->objectType->acceptRefSubType = false;
  2016. }
  2017. for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
  2018. {
  2019. if( func->parameterTypes[n].GetObjectType() == func->objectType->templateSubType.GetObjectType() )
  2020. {
  2021. // TODO: If unsafe references are allowed, then inout references allow value types
  2022. if( func->parameterTypes[n].IsObjectHandle() || (func->parameterTypes[n].IsReference() && func->inOutFlags[n] == asTM_INOUTREF) )
  2023. func->objectType->acceptValueSubType = false;
  2024. else if( !func->parameterTypes[n].IsReference() )
  2025. func->objectType->acceptRefSubType = false;
  2026. }
  2027. }
  2028. }
  2029. // TODO: beh.copy member will be removed, so this is not necessary
  2030. // Is this the default copy behaviour?
  2031. if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 && func->isReadOnly == false &&
  2032. (objectType->flags & asOBJ_SCRIPT_OBJECT || func->parameterTypes[0].IsEqualExceptRefAndConst(asCDataType::CreateObject(func->objectType, false))) )
  2033. {
  2034. func->objectType->beh.copy = func->id;
  2035. func->AddRef();
  2036. }
  2037. // Return the function id as success
  2038. return func->id;
  2039. }
  2040. // interface
  2041. int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFuncPtr &funcPointer, asDWORD callConv)
  2042. {
  2043. asSSystemFunctionInterface internal;
  2044. int r = DetectCallingConvention(false, funcPointer, callConv, &internal);
  2045. if( r < 0 )
  2046. return ConfigError(r, "RegisterGlobalFunction", declaration, 0);
  2047. #ifdef AS_MAX_PORTABILITY
  2048. if( callConv != asCALL_GENERIC )
  2049. return ConfigError(asNOT_SUPPORTED, "RegisterGlobalFunction", declaration, 0);
  2050. #else
  2051. if( callConv != asCALL_CDECL &&
  2052. callConv != asCALL_STDCALL &&
  2053. callConv != asCALL_GENERIC )
  2054. return ConfigError(asNOT_SUPPORTED, "RegisterGlobalFunction", declaration, 0);
  2055. #endif
  2056. isPrepared = false;
  2057. // Put the system function in the list of system functions
  2058. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2059. if( newInterface == 0 )
  2060. return ConfigError(asOUT_OF_MEMORY, "RegisterGlobalFunction", declaration, 0);
  2061. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2062. if( func == 0 )
  2063. {
  2064. asDELETE(newInterface, asSSystemFunctionInterface);
  2065. return ConfigError(asOUT_OF_MEMORY, "RegisterGlobalFunction", declaration, 0);
  2066. }
  2067. func->sysFuncIntf = newInterface;
  2068. asCBuilder bld(this, 0);
  2069. r = bld.ParseFunctionDeclaration(0, declaration, func, true, &newInterface->paramAutoHandles, &newInterface->returnAutoHandle, defaultNamespace);
  2070. if( r < 0 )
  2071. {
  2072. // Set as dummy function before deleting
  2073. func->funcType = asFUNC_DUMMY;
  2074. asDELETE(func,asCScriptFunction);
  2075. return ConfigError(asINVALID_DECLARATION, "RegisterGlobalFunction", declaration, 0);
  2076. }
  2077. // TODO: namespace: What if the declaration defined an explicit namespace?
  2078. func->nameSpace = defaultNamespace;
  2079. // Check name conflicts
  2080. r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace);
  2081. if( r < 0 )
  2082. {
  2083. // Set as dummy function before deleting
  2084. func->funcType = asFUNC_DUMMY;
  2085. asDELETE(func,asCScriptFunction);
  2086. return ConfigError(asNAME_TAKEN, "RegisterGlobalFunction", declaration, 0);
  2087. }
  2088. func->id = GetNextScriptFunctionId();
  2089. SetScriptFunction(func);
  2090. currentGroup->scriptFunctions.PushLast(func);
  2091. func->accessMask = defaultAccessMask;
  2092. registeredGlobalFuncs.PushLast(func);
  2093. // If parameter type from other groups are used, add references
  2094. if( func->returnType.GetObjectType() )
  2095. {
  2096. asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
  2097. currentGroup->RefConfigGroup(group);
  2098. }
  2099. for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
  2100. {
  2101. if( func->parameterTypes[n].GetObjectType() )
  2102. {
  2103. asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
  2104. currentGroup->RefConfigGroup(group);
  2105. }
  2106. }
  2107. // Return the function id as success
  2108. return func->id;
  2109. }
  2110. // interface
  2111. asUINT asCScriptEngine::GetGlobalFunctionCount() const
  2112. {
  2113. return asUINT(registeredGlobalFuncs.GetLength());
  2114. }
  2115. #ifdef AS_DEPRECATED
  2116. // Deprecated since 2.24.0 - 2012-05-20
  2117. // interface
  2118. int asCScriptEngine::GetGlobalFunctionIdByIndex(asUINT index) const
  2119. {
  2120. if( index >= registeredGlobalFuncs.GetLength() )
  2121. return asINVALID_ARG;
  2122. return registeredGlobalFuncs[index]->id;
  2123. }
  2124. #endif
  2125. // interface
  2126. asIScriptFunction *asCScriptEngine::GetGlobalFunctionByIndex(asUINT index) const
  2127. {
  2128. if( index >= registeredGlobalFuncs.GetLength() )
  2129. return 0;
  2130. return registeredGlobalFuncs[index];
  2131. }
  2132. // interface
  2133. asIScriptFunction *asCScriptEngine::GetGlobalFunctionByDecl(const char *decl) const
  2134. {
  2135. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  2136. asCScriptFunction func(const_cast<asCScriptEngine*>(this), 0, asFUNC_DUMMY);
  2137. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace);
  2138. if( r < 0 )
  2139. return 0;
  2140. // TODO: optimize: Improve linear search
  2141. // Search registered functions for matching interface
  2142. int id = -1;
  2143. for( size_t n = 0; n < registeredGlobalFuncs.GetLength(); ++n )
  2144. {
  2145. if( registeredGlobalFuncs[n]->objectType == 0 &&
  2146. func.name == registeredGlobalFuncs[n]->name &&
  2147. func.returnType == registeredGlobalFuncs[n]->returnType &&
  2148. func.parameterTypes.GetLength() == registeredGlobalFuncs[n]->parameterTypes.GetLength() )
  2149. {
  2150. bool match = true;
  2151. for( size_t p = 0; p < func.parameterTypes.GetLength(); ++p )
  2152. {
  2153. if( func.parameterTypes[p] != registeredGlobalFuncs[n]->parameterTypes[p] )
  2154. {
  2155. match = false;
  2156. break;
  2157. }
  2158. }
  2159. if( match )
  2160. {
  2161. if( id == -1 )
  2162. id = registeredGlobalFuncs[n]->id;
  2163. else
  2164. return 0; // Multiple matches
  2165. }
  2166. }
  2167. }
  2168. if( id < 0 ) return 0; // No matches
  2169. return scriptFunctions[id];
  2170. }
  2171. asCObjectType *asCScriptEngine::GetObjectType(const char *type, asSNameSpace *ns)
  2172. {
  2173. // TODO: optimize: Improve linear search
  2174. for( asUINT n = 0; n < objectTypes.GetLength(); n++ )
  2175. if( objectTypes[n] &&
  2176. objectTypes[n]->name == type &&
  2177. objectTypes[n]->nameSpace == ns ) // TODO: template: Should we check the subtype in case of template instances?
  2178. return objectTypes[n];
  2179. return 0;
  2180. }
  2181. void asCScriptEngine::PrepareEngine()
  2182. {
  2183. if( isPrepared ) return;
  2184. if( configFailed ) return;
  2185. asUINT n;
  2186. for( n = 0; n < scriptFunctions.GetLength(); n++ )
  2187. {
  2188. // Determine the host application interface
  2189. if( scriptFunctions[n] && scriptFunctions[n]->funcType == asFUNC_SYSTEM )
  2190. {
  2191. if( scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_FUNC ||
  2192. scriptFunctions[n]->sysFuncIntf->callConv == ICC_GENERIC_METHOD )
  2193. PrepareSystemFunctionGeneric(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
  2194. else
  2195. PrepareSystemFunction(scriptFunctions[n], scriptFunctions[n]->sysFuncIntf, this);
  2196. }
  2197. }
  2198. // Validate object type registrations
  2199. for( n = 0; n < objectTypes.GetLength(); n++ )
  2200. {
  2201. if( objectTypes[n] && !(objectTypes[n]->flags & asOBJ_SCRIPT_OBJECT) )
  2202. {
  2203. bool missingBehaviour = false;
  2204. const char *infoMsg = 0;
  2205. // Verify that GC types have all behaviours
  2206. if( objectTypes[n]->flags & asOBJ_GC )
  2207. {
  2208. if( objectTypes[n]->beh.addref == 0 ||
  2209. objectTypes[n]->beh.release == 0 ||
  2210. objectTypes[n]->beh.gcGetRefCount == 0 ||
  2211. objectTypes[n]->beh.gcSetFlag == 0 ||
  2212. objectTypes[n]->beh.gcGetFlag == 0 ||
  2213. objectTypes[n]->beh.gcEnumReferences == 0 ||
  2214. objectTypes[n]->beh.gcReleaseAllReferences == 0 )
  2215. {
  2216. infoMsg = TXT_GC_REQUIRE_ADD_REL_GC_BEHAVIOUR;
  2217. missingBehaviour = true;
  2218. }
  2219. }
  2220. // Verify that scoped ref types have the release behaviour
  2221. else if( objectTypes[n]->flags & asOBJ_SCOPED )
  2222. {
  2223. if( objectTypes[n]->beh.release == 0 )
  2224. {
  2225. infoMsg = TXT_SCOPE_REQUIRE_REL_BEHAVIOUR;
  2226. missingBehaviour = true;
  2227. }
  2228. }
  2229. // Verify that ref types have add ref and release behaviours
  2230. else if( (objectTypes[n]->flags & asOBJ_REF) &&
  2231. !(objectTypes[n]->flags & asOBJ_NOHANDLE) &&
  2232. !(objectTypes[n]->flags & asOBJ_NOCOUNT) )
  2233. {
  2234. if( objectTypes[n]->beh.addref == 0 ||
  2235. objectTypes[n]->beh.release == 0 )
  2236. {
  2237. infoMsg = TXT_REF_REQUIRE_ADD_REL_BEHAVIOUR;
  2238. missingBehaviour = true;
  2239. }
  2240. }
  2241. // Verify that non-pod value types have the constructor and destructor registered
  2242. else if( (objectTypes[n]->flags & asOBJ_VALUE) &&
  2243. !(objectTypes[n]->flags & asOBJ_POD) )
  2244. {
  2245. if( objectTypes[n]->beh.construct == 0 ||
  2246. objectTypes[n]->beh.destruct == 0 )
  2247. {
  2248. infoMsg = TXT_NON_POD_REQUIRE_CONSTR_DESTR_BEHAVIOUR;
  2249. missingBehaviour = true;
  2250. }
  2251. }
  2252. if( missingBehaviour )
  2253. {
  2254. asCString str;
  2255. str.Format(TXT_TYPE_s_IS_MISSING_BEHAVIOURS, objectTypes[n]->name.AddressOf());
  2256. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  2257. WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, infoMsg);
  2258. ConfigError(asINVALID_CONFIGURATION, 0, 0, 0);
  2259. }
  2260. }
  2261. }
  2262. isPrepared = true;
  2263. }
  2264. int asCScriptEngine::ConfigError(int err, const char *funcName, const char *arg1, const char *arg2)
  2265. {
  2266. configFailed = true;
  2267. if( funcName )
  2268. {
  2269. asCString str;
  2270. if( arg1 )
  2271. {
  2272. if( arg2 )
  2273. str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_AND_s_d, funcName, arg1, arg2, err);
  2274. else
  2275. str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_d, funcName, arg1, err);
  2276. }
  2277. else
  2278. str.Format(TXT_FAILED_IN_FUNC_s_d, funcName, err);
  2279. WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  2280. }
  2281. return err;
  2282. }
  2283. // interface
  2284. int asCScriptEngine::RegisterDefaultArrayType(const char *type)
  2285. {
  2286. asCBuilder bld(this, 0);
  2287. asCDataType dt;
  2288. int r = bld.ParseDataType(type, &dt, defaultNamespace);
  2289. if( r < 0 ) return r;
  2290. if( dt.GetObjectType() == 0 ||
  2291. !(dt.GetObjectType()->GetFlags() & asOBJ_TEMPLATE) )
  2292. return asINVALID_TYPE;
  2293. defaultArrayObjectType = dt.GetObjectType();
  2294. defaultArrayObjectType->AddRef();
  2295. return 0;
  2296. }
  2297. // interface
  2298. int asCScriptEngine::GetDefaultArrayTypeId() const
  2299. {
  2300. if( defaultArrayObjectType )
  2301. return GetTypeIdFromDataType(asCDataType::CreateObject(defaultArrayObjectType, false));
  2302. return asINVALID_TYPE;
  2303. }
  2304. // interface
  2305. int asCScriptEngine::RegisterStringFactory(const char *datatype, const asSFuncPtr &funcPointer, asDWORD callConv)
  2306. {
  2307. asSSystemFunctionInterface internal;
  2308. int r = DetectCallingConvention(false, funcPointer, callConv, &internal);
  2309. if( r < 0 )
  2310. return ConfigError(r, "RegisterStringFactory", datatype, 0);
  2311. #ifdef AS_MAX_PORTABILITY
  2312. if( callConv != asCALL_GENERIC )
  2313. return ConfigError(asNOT_SUPPORTED, "RegisterStringFactory", datatype, 0);
  2314. #else
  2315. if( callConv != asCALL_CDECL &&
  2316. callConv != asCALL_STDCALL &&
  2317. callConv != asCALL_GENERIC )
  2318. return ConfigError(asNOT_SUPPORTED, "RegisterStringFactory", datatype, 0);
  2319. #endif
  2320. // Put the system function in the list of system functions
  2321. asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface)(internal);
  2322. if( newInterface == 0 )
  2323. return ConfigError(asOUT_OF_MEMORY, "RegisterStringFactory", datatype, 0);
  2324. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
  2325. if( func == 0 )
  2326. {
  2327. asDELETE(newInterface, asSSystemFunctionInterface);
  2328. return ConfigError(asOUT_OF_MEMORY, "RegisterStringFactory", datatype, 0);
  2329. }
  2330. func->name = "_string_factory_";
  2331. func->sysFuncIntf = newInterface;
  2332. asCBuilder bld(this, 0);
  2333. asCDataType dt;
  2334. r = bld.ParseDataType(datatype, &dt, defaultNamespace, true);
  2335. if( r < 0 )
  2336. {
  2337. // Set as dummy before deleting
  2338. func->funcType = asFUNC_DUMMY;
  2339. asDELETE(func,asCScriptFunction);
  2340. return ConfigError(asINVALID_TYPE, "RegisterStringFactory", datatype, 0);
  2341. }
  2342. func->returnType = dt;
  2343. func->parameterTypes.PushLast(asCDataType::CreatePrimitive(ttInt, true));
  2344. asCDataType parm1 = asCDataType::CreatePrimitive(ttUInt8, true);
  2345. parm1.MakeReference(true);
  2346. func->parameterTypes.PushLast(parm1);
  2347. func->id = GetNextScriptFunctionId();
  2348. SetScriptFunction(func);
  2349. stringFactory = func;
  2350. if( func->returnType.GetObjectType() )
  2351. {
  2352. asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
  2353. if( group == 0 ) group = &defaultGroup;
  2354. group->scriptFunctions.PushLast(func);
  2355. }
  2356. // Register function id as success
  2357. return func->id;
  2358. }
  2359. // interface
  2360. int asCScriptEngine::GetStringFactoryReturnTypeId() const
  2361. {
  2362. if( stringFactory == 0 )
  2363. return asNO_FUNCTION;
  2364. return GetTypeIdFromDataType(stringFactory->returnType);
  2365. }
  2366. // interface
  2367. asCModule *asCScriptEngine::GetModule(const char *_name, bool create)
  2368. {
  2369. // Accept null as well as zero-length string
  2370. const char *name = "";
  2371. if( _name != 0 ) name = _name;
  2372. if( lastModule && lastModule->name == name )
  2373. return lastModule;
  2374. // TODO: optimize: Improve linear search
  2375. for( asUINT n = 0; n < scriptModules.GetLength(); ++n )
  2376. if( scriptModules[n] && scriptModules[n]->name == name )
  2377. {
  2378. lastModule = scriptModules[n];
  2379. return lastModule;
  2380. }
  2381. if( create )
  2382. {
  2383. asCModule *module = asNEW(asCModule)(name, this);
  2384. if( module == 0 )
  2385. {
  2386. // Out of memory
  2387. return 0;
  2388. }
  2389. scriptModules.PushLast(module);
  2390. lastModule = module;
  2391. return lastModule;
  2392. }
  2393. return 0;
  2394. }
  2395. asCModule *asCScriptEngine::GetModuleFromFuncId(int id)
  2396. {
  2397. if( id < 0 ) return 0;
  2398. if( id >= (int)scriptFunctions.GetLength() ) return 0;
  2399. asCScriptFunction *func = scriptFunctions[id];
  2400. if( func == 0 ) return 0;
  2401. return func->module;
  2402. }
  2403. // internal
  2404. int asCScriptEngine::RequestBuild()
  2405. {
  2406. ACQUIREEXCLUSIVE(engineRWLock);
  2407. if( isBuilding )
  2408. {
  2409. RELEASEEXCLUSIVE(engineRWLock);
  2410. return asBUILD_IN_PROGRESS;
  2411. }
  2412. isBuilding = true;
  2413. RELEASEEXCLUSIVE(engineRWLock);
  2414. return 0;
  2415. }
  2416. // internal
  2417. void asCScriptEngine::BuildCompleted()
  2418. {
  2419. // Always free up pooled memory after a completed build
  2420. memoryMgr.FreeUnusedMemory();
  2421. isBuilding = false;
  2422. }
  2423. void asCScriptEngine::RemoveTemplateInstanceType(asCObjectType *t)
  2424. {
  2425. int n;
  2426. // Destroy the factory stubs
  2427. for( n = 0; n < (int)t->beh.factories.GetLength(); n++ )
  2428. {
  2429. // Make sure the factory stub isn't referencing this object anymore
  2430. scriptFunctions[t->beh.factories[n]]->ReleaseAllHandles(this);
  2431. scriptFunctions[t->beh.factories[n]]->Release();
  2432. }
  2433. t->beh.factories.SetLength(0);
  2434. // Destroy the stub for the list factory too
  2435. if( t->beh.listFactory )
  2436. {
  2437. scriptFunctions[t->beh.listFactory]->ReleaseAllHandles(this);
  2438. scriptFunctions[t->beh.listFactory]->Release();
  2439. t->beh.listFactory = 0;
  2440. }
  2441. // Destroy the specialized functions
  2442. for( n = 1; n < (int)t->beh.operators.GetLength(); n += 2 )
  2443. {
  2444. if( t->beh.operators[n] && scriptFunctions[t->beh.operators[n]]->objectType == t )
  2445. {
  2446. scriptFunctions[t->beh.operators[n]]->Release();
  2447. }
  2448. }
  2449. t->beh.operators.SetLength(0);
  2450. // Start searching from the end of the list, as most of
  2451. // the time it will be the last two types
  2452. for( n = (int)templateTypes.GetLength()-1; n >= 0; n-- )
  2453. {
  2454. if( templateTypes[n] == t )
  2455. {
  2456. if( n == (signed)templateTypes.GetLength()-1 )
  2457. templateTypes.PopLast();
  2458. else
  2459. templateTypes[n] = templateTypes.PopLast();
  2460. }
  2461. }
  2462. for( n = (int)templateInstanceTypes.GetLength()-1; n >= 0; n-- )
  2463. {
  2464. if( templateInstanceTypes[n] == t )
  2465. {
  2466. if( n == (signed)templateInstanceTypes.GetLength()-1 )
  2467. templateInstanceTypes.PopLast();
  2468. else
  2469. templateInstanceTypes[n] = templateInstanceTypes.PopLast();
  2470. }
  2471. }
  2472. asDELETE(t,asCObjectType);
  2473. }
  2474. // internal
  2475. asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateType, asCDataType &subType)
  2476. {
  2477. asUINT n;
  2478. // Is there any template instance type or template specialization already with this subtype?
  2479. for( n = 0; n < templateTypes.GetLength(); n++ )
  2480. {
  2481. if( templateTypes[n] &&
  2482. templateTypes[n]->name == templateType->name &&
  2483. templateTypes[n]->templateSubType == subType )
  2484. return templateTypes[n];
  2485. }
  2486. // No previous template instance exists
  2487. // Make sure the template has factories as it doesn't have a default factory
  2488. if( templateType->beh.factories.GetLength() == 0 )
  2489. return 0;
  2490. // Make sure this template supports the subtype
  2491. if( !templateType->acceptValueSubType && (subType.IsPrimitive() || (subType.GetObjectType()->flags & asOBJ_VALUE)) )
  2492. return 0;
  2493. if( !templateType->acceptRefSubType && (subType.IsObject() && (subType.GetObjectType()->flags & asOBJ_REF)) )
  2494. return 0;
  2495. // Create a new template instance type based on the templateType
  2496. asCObjectType *ot = asNEW(asCObjectType)(this);
  2497. if( ot == 0 )
  2498. {
  2499. // Out of memory
  2500. return 0;
  2501. }
  2502. ot->templateSubType = subType;
  2503. ot->flags = templateType->flags;
  2504. ot->size = templateType->size;
  2505. ot->name = templateType->name;
  2506. // Before filling in the methods, call the template instance callback behaviour to validate the type
  2507. if( templateType->beh.templateCallback )
  2508. {
  2509. bool dontGarbageCollect = false;
  2510. asCScriptFunction *callback = scriptFunctions[templateType->beh.templateCallback];
  2511. if( !CallGlobalFunctionRetBool(ot, &dontGarbageCollect, callback->sysFuncIntf, callback) )
  2512. {
  2513. // If the validation is deferred then the validation will be done later,
  2514. // so it is necessary to continue the preparation of the template instance type
  2515. if( !deferValidationOfTemplateTypes )
  2516. {
  2517. // The type cannot be instanciated
  2518. ot->templateSubType = asCDataType();
  2519. asDELETE(ot, asCObjectType);
  2520. return 0;
  2521. }
  2522. }
  2523. // If the callback said this template instance won't be garbage collected then remove the flag
  2524. if( dontGarbageCollect )
  2525. ot->flags &= ~asOBJ_GC;
  2526. ot->beh.templateCallback = templateType->beh.templateCallback;
  2527. scriptFunctions[ot->beh.templateCallback]->AddRef();
  2528. }
  2529. ot->methods = templateType->methods;
  2530. for( n = 0; n < ot->methods.GetLength(); n++ )
  2531. scriptFunctions[ot->methods[n]]->AddRef();
  2532. // Store the real factory in the constructor. This is used by the CreateScriptObject function.
  2533. // Otherwise it wouldn't be necessary to store the real factory ids.
  2534. ot->beh.construct = templateType->beh.factory;
  2535. ot->beh.constructors = templateType->beh.factories;
  2536. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  2537. scriptFunctions[ot->beh.constructors[n]]->AddRef();
  2538. // Generate factory stubs for each of the factories
  2539. for( n = 0; n < templateType->beh.factories.GetLength(); n++ )
  2540. {
  2541. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.factories[n]);
  2542. // The function's refCount was already initialized to 1
  2543. ot->beh.factories.PushLast(func->id);
  2544. }
  2545. // If the template has a default factory, then set keep the id
  2546. if( ot->beh.factories.GetLength() && scriptFunctions[ot->beh.factories[0]]->parameterTypes.GetLength() == 0 )
  2547. ot->beh.factory = ot->beh.factories[0];
  2548. else
  2549. ot->beh.factory = 0;
  2550. // Generate stub for the list factory as well
  2551. if( templateType->beh.listFactory )
  2552. {
  2553. asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.listFactory);
  2554. // The function's refCount was already initialized to 1
  2555. ot->beh.listFactory = func->id;
  2556. }
  2557. ot->beh.addref = templateType->beh.addref;
  2558. if( scriptFunctions[ot->beh.addref] ) scriptFunctions[ot->beh.addref]->AddRef();
  2559. ot->beh.release = templateType->beh.release;
  2560. if( scriptFunctions[ot->beh.release] ) scriptFunctions[ot->beh.release]->AddRef();
  2561. ot->beh.copy = templateType->beh.copy;
  2562. if( scriptFunctions[ot->beh.copy] ) scriptFunctions[ot->beh.copy]->AddRef();
  2563. ot->beh.operators = templateType->beh.operators;
  2564. for( n = 1; n < ot->beh.operators.GetLength(); n += 2 )
  2565. {
  2566. scriptFunctions[ot->beh.operators[n]]->AddRef();
  2567. }
  2568. ot->beh.gcGetRefCount = templateType->beh.gcGetRefCount;
  2569. if( scriptFunctions[ot->beh.gcGetRefCount] ) scriptFunctions[ot->beh.gcGetRefCount]->AddRef();
  2570. ot->beh.gcSetFlag = templateType->beh.gcSetFlag;
  2571. if( scriptFunctions[ot->beh.gcSetFlag] ) scriptFunctions[ot->beh.gcSetFlag]->AddRef();
  2572. ot->beh.gcGetFlag = templateType->beh.gcGetFlag;
  2573. if( scriptFunctions[ot->beh.gcGetFlag] ) scriptFunctions[ot->beh.gcGetFlag]->AddRef();
  2574. ot->beh.gcEnumReferences = templateType->beh.gcEnumReferences;
  2575. if( scriptFunctions[ot->beh.gcEnumReferences] ) scriptFunctions[ot->beh.gcEnumReferences]->AddRef();
  2576. ot->beh.gcReleaseAllReferences = templateType->beh.gcReleaseAllReferences;
  2577. if( scriptFunctions[ot->beh.gcReleaseAllReferences] ) scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRef();
  2578. // As the new template type is instanciated, the engine should
  2579. // generate new functions to substitute the ones with the template subtype.
  2580. for( n = 1; n < ot->beh.operators.GetLength(); n += 2 )
  2581. {
  2582. int funcId = ot->beh.operators[n];
  2583. asCScriptFunction *func = scriptFunctions[funcId];
  2584. if( GenerateNewTemplateFunction(templateType, ot, subType, func, &func) )
  2585. {
  2586. // Release the old function, the new one already has its ref count set to 1
  2587. scriptFunctions[ot->beh.operators[n]]->Release();
  2588. ot->beh.operators[n] = func->id;
  2589. }
  2590. }
  2591. // As the new template type is instanciated, the engine should
  2592. // generate new functions to substitute the ones with the template subtype.
  2593. for( n = 0; n < ot->methods.GetLength(); n++ )
  2594. {
  2595. int funcId = ot->methods[n];
  2596. asCScriptFunction *func = scriptFunctions[funcId];
  2597. if( GenerateNewTemplateFunction(templateType, ot, subType, func, &func) )
  2598. {
  2599. // Release the old function, the new one already has its ref count set to 1
  2600. scriptFunctions[ot->methods[n]]->Release();
  2601. ot->methods[n] = func->id;
  2602. }
  2603. }
  2604. // Increase ref counter for sub type if it is an object type
  2605. if( ot->templateSubType.GetObjectType() ) ot->templateSubType.GetObjectType()->AddRef();
  2606. templateTypes.PushLast(ot);
  2607. // We need to store the object type somewhere for clean-up later
  2608. // TODO: Why do we need both templateTypes and templateInstanceTypes? It is possible to differ between template instance and template specialization by checking for the asOBJ_TEMPLATE flag
  2609. templateInstanceTypes.PushLast(ot);
  2610. return ot;
  2611. }
  2612. // internal
  2613. asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *templateType, asCObjectType *ot, int factoryId)
  2614. {
  2615. asCScriptFunction *factory = scriptFunctions[factoryId];
  2616. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_SCRIPT);
  2617. if( func == 0 )
  2618. {
  2619. // Out of memory
  2620. return 0;
  2621. }
  2622. func->name = "factstub";
  2623. func->id = GetNextScriptFunctionId();
  2624. func->returnType = asCDataType::CreateObjectHandle(ot, false);
  2625. func->isShared = true;
  2626. // Skip the first parameter as this is the object type pointer that the stub will add
  2627. func->parameterTypes.SetLength(factory->parameterTypes.GetLength()-1);
  2628. func->inOutFlags.SetLength(factory->inOutFlags.GetLength()-1);
  2629. for( asUINT p = 1; p < factory->parameterTypes.GetLength(); p++ )
  2630. {
  2631. if( factory->parameterTypes[p].GetObjectType() == templateType->templateSubType.GetObjectType() )
  2632. {
  2633. func->parameterTypes[p-1] = ot->templateSubType;
  2634. if( factory->parameterTypes[p].IsObjectHandle() )
  2635. func->parameterTypes[p-1].MakeHandle(true);
  2636. func->parameterTypes[p-1].MakeReference(factory->parameterTypes[p].IsReference());
  2637. func->parameterTypes[p-1].MakeReadOnly(factory->parameterTypes[p].IsReference());
  2638. }
  2639. else if( factory->parameterTypes[p].GetObjectType() == templateType )
  2640. {
  2641. if( factory->parameterTypes[p].IsObjectHandle() )
  2642. func->parameterTypes[p-1] = asCDataType::CreateObjectHandle(ot, false);
  2643. else
  2644. func->parameterTypes[p-1] = asCDataType::CreateObject(ot, false);
  2645. func->parameterTypes[p-1].MakeReference(factory->parameterTypes[p].IsReference());
  2646. func->parameterTypes[p-1].MakeReadOnly(factory->parameterTypes[p].IsReadOnly());
  2647. }
  2648. else
  2649. {
  2650. func->parameterTypes[p-1] = factory->parameterTypes[p];
  2651. }
  2652. func->inOutFlags[p-1] = factory->inOutFlags[p];
  2653. }
  2654. func->objVariablesOnHeap = 0;
  2655. SetScriptFunction(func);
  2656. // Generate the bytecode for the factory stub
  2657. asUINT bcLength = asBCTypeSize[asBCInfo[asBC_OBJTYPE].type] +
  2658. asBCTypeSize[asBCInfo[asBC_CALLSYS].type] +
  2659. asBCTypeSize[asBCInfo[asBC_RET].type];
  2660. if( ep.includeJitInstructions )
  2661. bcLength += asBCTypeSize[asBCInfo[asBC_JitEntry].type];
  2662. func->byteCode.SetLength(bcLength);
  2663. asDWORD *bc = func->byteCode.AddressOf();
  2664. if( ep.includeJitInstructions )
  2665. {
  2666. *(asBYTE*)bc = asBC_JitEntry;
  2667. *(asPWORD*)(bc+1) = 0;
  2668. bc += asBCTypeSize[asBCInfo[asBC_JitEntry].type];
  2669. }
  2670. *(asBYTE*)bc = asBC_OBJTYPE;
  2671. *(asPWORD*)(bc+1) = (asPWORD)ot;
  2672. bc += asBCTypeSize[asBCInfo[asBC_OBJTYPE].type];
  2673. *(asBYTE*)bc = asBC_CALLSYS;
  2674. *(asDWORD*)(bc+1) = factoryId;
  2675. bc += asBCTypeSize[asBCInfo[asBC_CALLSYS].type];
  2676. *(asBYTE*)bc = asBC_RET;
  2677. *(((asWORD*)bc)+1) = (asWORD)func->GetSpaceNeededForArguments();
  2678. func->AddReferences();
  2679. func->stackNeeded = AS_PTR_SIZE;
  2680. // Tell the virtual machine not to clean up the object on exception
  2681. func->dontCleanUpOnException = true;
  2682. func->JITCompile();
  2683. return func;
  2684. }
  2685. bool asCScriptEngine::GenerateNewTemplateFunction(asCObjectType *templateType, asCObjectType *ot, asCDataType &subType, asCScriptFunction *func, asCScriptFunction **newFunc)
  2686. {
  2687. bool needNewFunc = false;
  2688. if( func->returnType.GetObjectType() == templateType->templateSubType.GetObjectType() ||
  2689. func->returnType.GetObjectType() == templateType )
  2690. needNewFunc = true;
  2691. else
  2692. {
  2693. for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
  2694. {
  2695. if( func->parameterTypes[p].GetObjectType() == templateType->templateSubType.GetObjectType() ||
  2696. func->parameterTypes[p].GetObjectType() == templateType )
  2697. {
  2698. needNewFunc = true;
  2699. break;
  2700. }
  2701. }
  2702. }
  2703. if( needNewFunc )
  2704. {
  2705. asCScriptFunction *func2 = asNEW(asCScriptFunction)(this, 0, func->funcType);
  2706. if( func2 == 0 )
  2707. {
  2708. // Out of memory
  2709. return false;
  2710. }
  2711. func2->name = func->name;
  2712. func2->id = GetNextScriptFunctionId();
  2713. if( func->returnType.GetObjectType() == templateType->templateSubType.GetObjectType() )
  2714. {
  2715. func2->returnType = subType;
  2716. if( func->returnType.IsObjectHandle() && !subType.IsObjectHandle() )
  2717. {
  2718. // The return type is a handle to the subtype
  2719. func2->returnType.MakeHandle(true, true);
  2720. func2->returnType.MakeReference(func->returnType.IsReference());
  2721. func2->returnType.MakeReadOnly(func->returnType.IsReadOnly());
  2722. }
  2723. else
  2724. {
  2725. // The return type is the subtype directly
  2726. func2->returnType.MakeReference(func->returnType.IsReference());
  2727. func2->returnType.MakeReadOnly(subType.IsReadOnly() || func->returnType.IsReadOnly());
  2728. }
  2729. }
  2730. else if( func->returnType.GetObjectType() == templateType )
  2731. {
  2732. if( func2->returnType.IsObjectHandle() )
  2733. func2->returnType = asCDataType::CreateObjectHandle(ot, false);
  2734. else
  2735. func2->returnType = asCDataType::CreateObject(ot, false);
  2736. func2->returnType.MakeReference(func->returnType.IsReference());
  2737. func2->returnType.MakeReadOnly(func->returnType.IsReadOnly());
  2738. }
  2739. else
  2740. func2->returnType = func->returnType;
  2741. func2->parameterTypes.SetLength(func->parameterTypes.GetLength());
  2742. for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
  2743. {
  2744. if( func->parameterTypes[p].GetObjectType() == templateType->templateSubType.GetObjectType() )
  2745. {
  2746. func2->parameterTypes[p] = subType;
  2747. if( func->parameterTypes[p].IsObjectHandle() )
  2748. {
  2749. // The parameter is a handle to the subtype
  2750. func2->parameterTypes[p].MakeHandle(true);
  2751. func2->parameterTypes[p].MakeReference(func->parameterTypes[p].IsReference());
  2752. func2->parameterTypes[p].MakeReadOnly(func->parameterTypes[p].IsReadOnly());
  2753. }
  2754. else
  2755. {
  2756. // The parameter is the subtype directly
  2757. func2->parameterTypes[p].MakeReference(func->parameterTypes[p].IsReference());
  2758. func2->parameterTypes[p].MakeReadOnly(subType.IsReadOnly() || func->parameterTypes[p].IsReference());
  2759. }
  2760. }
  2761. else if( func->parameterTypes[p].GetObjectType() == templateType )
  2762. {
  2763. if( func->parameterTypes[p].IsObjectHandle() )
  2764. func2->parameterTypes[p] = asCDataType::CreateObjectHandle(ot, false);
  2765. else
  2766. func2->parameterTypes[p] = asCDataType::CreateObject(ot, false);
  2767. func2->parameterTypes[p].MakeReference(func->parameterTypes[p].IsReference());
  2768. func2->parameterTypes[p].MakeReadOnly(func->parameterTypes[p].IsReadOnly());
  2769. }
  2770. else
  2771. func2->parameterTypes[p] = func->parameterTypes[p];
  2772. }
  2773. // TODO: template: Must be careful when instanciating templates for garbage collected types
  2774. // If the template hasn't been registered with the behaviours, it shouldn't
  2775. // permit instanciation of garbage collected types that in turn may refer to
  2776. // this instance.
  2777. func2->inOutFlags = func->inOutFlags;
  2778. func2->isReadOnly = func->isReadOnly;
  2779. func2->objectType = ot;
  2780. func2->stackNeeded = func->stackNeeded;
  2781. func2->sysFuncIntf = asNEW(asSSystemFunctionInterface)(*func->sysFuncIntf);
  2782. SetScriptFunction(func2);
  2783. // Return the new function
  2784. *newFunc = func2;
  2785. }
  2786. return needNewFunc;
  2787. }
  2788. void asCScriptEngine::CallObjectMethod(void *obj, int func)
  2789. {
  2790. asCScriptFunction *s = scriptFunctions[func];
  2791. asASSERT( s != 0 );
  2792. CallObjectMethod(obj, s->sysFuncIntf, s);
  2793. }
  2794. void asCScriptEngine::CallObjectMethod(void *obj, asSSystemFunctionInterface *i, asCScriptFunction *s)
  2795. {
  2796. #ifdef __GNUC__
  2797. if( i->callConv == ICC_GENERIC_METHOD )
  2798. {
  2799. asCGeneric gen(this, s, obj, 0);
  2800. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  2801. f(&gen);
  2802. }
  2803. else if( i->callConv == ICC_VIRTUAL_THISCALL )
  2804. {
  2805. // For virtual thiscalls we must call the method as a true class method
  2806. // so that the compiler will lookup the function address in the vftable
  2807. union
  2808. {
  2809. asSIMPLEMETHOD_t mthd;
  2810. struct
  2811. {
  2812. asFUNCTION_t func;
  2813. asPWORD baseOffset; // Same size as the pointer
  2814. } f;
  2815. } p;
  2816. p.f.func = (void (*)())(i->func);
  2817. p.f.baseOffset = asPWORD(i->baseOffset);
  2818. void (asCSimpleDummy::*f)() = p.mthd;
  2819. (((asCSimpleDummy*)obj)->*f)();
  2820. }
  2821. else /*if( i->callConv == ICC_THISCALL || i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  2822. {
  2823. // Non-virtual thiscall can be called just like any global function, passing the object as the first parameter
  2824. void (*f)(void *) = (void (*)(void *))(i->func);
  2825. f(obj);
  2826. }
  2827. #else
  2828. #ifndef AS_NO_CLASS_METHODS
  2829. if( i->callConv == ICC_THISCALL )
  2830. {
  2831. union
  2832. {
  2833. asSIMPLEMETHOD_t mthd;
  2834. asFUNCTION_t func;
  2835. } p;
  2836. p.func = (void (*)())(i->func);
  2837. void (asCSimpleDummy::*f)() = p.mthd;
  2838. obj = (void*)(asPWORD(obj) + i->baseOffset);
  2839. (((asCSimpleDummy*)obj)->*f)();
  2840. }
  2841. else
  2842. #endif
  2843. if( i->callConv == ICC_GENERIC_METHOD )
  2844. {
  2845. asCGeneric gen(this, s, obj, 0);
  2846. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  2847. f(&gen);
  2848. }
  2849. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  2850. {
  2851. void (*f)(void *) = (void (*)(void *))(i->func);
  2852. f(obj);
  2853. }
  2854. #endif
  2855. }
  2856. bool asCScriptEngine::CallObjectMethodRetBool(void *obj, int func)
  2857. {
  2858. asCScriptFunction *s = scriptFunctions[func];
  2859. asASSERT( s != 0 );
  2860. asSSystemFunctionInterface *i = s->sysFuncIntf;
  2861. #ifdef __GNUC__
  2862. if( i->callConv == ICC_GENERIC_METHOD )
  2863. {
  2864. asCGeneric gen(this, s, obj, 0);
  2865. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  2866. f(&gen);
  2867. return *(bool*)gen.GetReturnPointer();
  2868. }
  2869. else if( i->callConv == ICC_VIRTUAL_THISCALL )
  2870. {
  2871. // 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
  2872. union
  2873. {
  2874. asSIMPLEMETHOD_t mthd;
  2875. struct
  2876. {
  2877. asFUNCTION_t func;
  2878. asDWORD baseOffset;
  2879. } f;
  2880. } p;
  2881. p.f.func = (void (*)())(i->func);
  2882. p.f.baseOffset = i->baseOffset;
  2883. bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())(p.mthd);
  2884. return (((asCSimpleDummy*)obj)->*f)();
  2885. }
  2886. else /*if( i->callConv == ICC_THISCALL || i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  2887. {
  2888. // Non-virtual thiscall can be called just like any global function, passing the object as the first parameter
  2889. bool (*f)(void *) = (bool (*)(void *))(i->func);
  2890. return f(obj);
  2891. }
  2892. #else
  2893. #ifndef AS_NO_CLASS_METHODS
  2894. if( i->callConv == ICC_THISCALL )
  2895. {
  2896. union
  2897. {
  2898. asSIMPLEMETHOD_t mthd;
  2899. asFUNCTION_t func;
  2900. } p;
  2901. p.func = (void (*)())(i->func);
  2902. bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())p.mthd;
  2903. obj = (void*)(asPWORD(obj) + i->baseOffset);
  2904. return (((asCSimpleDummy*)obj)->*f)();
  2905. }
  2906. else
  2907. #endif
  2908. if( i->callConv == ICC_GENERIC_METHOD )
  2909. {
  2910. asCGeneric gen(this, s, obj, 0);
  2911. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  2912. f(&gen);
  2913. return *(bool*)gen.GetReturnPointer();
  2914. }
  2915. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  2916. {
  2917. bool (*f)(void *) = (bool (*)(void *))(i->func);
  2918. return f(obj);
  2919. }
  2920. #endif
  2921. }
  2922. int asCScriptEngine::CallObjectMethodRetInt(void *obj, int func)
  2923. {
  2924. asCScriptFunction *s = scriptFunctions[func];
  2925. asASSERT( s != 0 );
  2926. asSSystemFunctionInterface *i = s->sysFuncIntf;
  2927. #ifdef __GNUC__
  2928. if( i->callConv == ICC_GENERIC_METHOD )
  2929. {
  2930. asCGeneric gen(this, s, obj, 0);
  2931. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  2932. f(&gen);
  2933. return *(int*)gen.GetReturnPointer();
  2934. }
  2935. else if( i->callConv == ICC_VIRTUAL_THISCALL )
  2936. {
  2937. // 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
  2938. union
  2939. {
  2940. asSIMPLEMETHOD_t mthd;
  2941. struct
  2942. {
  2943. asFUNCTION_t func;
  2944. asDWORD baseOffset;
  2945. } f;
  2946. } p;
  2947. p.f.func = (void (*)())(i->func);
  2948. p.f.baseOffset = i->baseOffset;
  2949. int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())(p.mthd);
  2950. return (((asCSimpleDummy*)obj)->*f)();
  2951. }
  2952. else /*if( i->callConv == ICC_THISCALL || i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  2953. {
  2954. // Non-virtual thiscall can be called just like any global function, passing the object as the first parameter
  2955. int (*f)(void *) = (int (*)(void *))(i->func);
  2956. return f(obj);
  2957. }
  2958. #else
  2959. #ifndef AS_NO_CLASS_METHODS
  2960. if( i->callConv == ICC_THISCALL )
  2961. {
  2962. union
  2963. {
  2964. asSIMPLEMETHOD_t mthd;
  2965. asFUNCTION_t func;
  2966. } p;
  2967. p.func = (void (*)())(i->func);
  2968. int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())p.mthd;
  2969. obj = (void*)(asPWORD(obj) + i->baseOffset);
  2970. return (((asCSimpleDummy*)obj)->*f)();
  2971. }
  2972. else
  2973. #endif
  2974. if( i->callConv == ICC_GENERIC_METHOD )
  2975. {
  2976. asCGeneric gen(this, s, obj, 0);
  2977. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  2978. f(&gen);
  2979. return *(int*)gen.GetReturnPointer();
  2980. }
  2981. else /*if( i->callConv == ICC_CDECL_OBJLAST || i->callConv == ICC_CDECL_OBJFIRST )*/
  2982. {
  2983. int (*f)(void *) = (int (*)(void *))(i->func);
  2984. return f(obj);
  2985. }
  2986. #endif
  2987. }
  2988. void *asCScriptEngine::CallGlobalFunctionRetPtr(int func)
  2989. {
  2990. asCScriptFunction *s = scriptFunctions[func];
  2991. asASSERT( s != 0 );
  2992. return CallGlobalFunctionRetPtr(s->sysFuncIntf, s);
  2993. }
  2994. void *asCScriptEngine::CallGlobalFunctionRetPtr(int func, void *param1)
  2995. {
  2996. asCScriptFunction *s = scriptFunctions[func];
  2997. asASSERT( s != 0 );
  2998. return CallGlobalFunctionRetPtr(s->sysFuncIntf, s, param1);
  2999. }
  3000. void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s)
  3001. {
  3002. if( i->callConv == ICC_CDECL )
  3003. {
  3004. void *(*f)() = (void *(*)())(i->func);
  3005. return f();
  3006. }
  3007. else if( i->callConv == ICC_STDCALL )
  3008. {
  3009. void *(STDCALL *f)() = (void *(STDCALL *)())(i->func);
  3010. return f();
  3011. }
  3012. else
  3013. {
  3014. asCGeneric gen(this, s, 0, 0);
  3015. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3016. f(&gen);
  3017. return *(void**)gen.GetReturnPointer();
  3018. }
  3019. }
  3020. void *asCScriptEngine::CallGlobalFunctionRetPtr(asSSystemFunctionInterface *i, asCScriptFunction *s, void *param1)
  3021. {
  3022. if( i->callConv == ICC_CDECL )
  3023. {
  3024. void *(*f)(void *) = (void *(*)(void *))(i->func);
  3025. return f(param1);
  3026. }
  3027. else if( i->callConv == ICC_STDCALL )
  3028. {
  3029. void *(STDCALL *f)(void *) = (void *(STDCALL *)(void *))(i->func);
  3030. return f(param1);
  3031. }
  3032. else
  3033. {
  3034. asCGeneric gen(this, s, 0, (asDWORD*)&param1);
  3035. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3036. f(&gen);
  3037. return *(void**)gen.GetReturnPointer();
  3038. }
  3039. }
  3040. void asCScriptEngine::CallObjectMethod(void *obj, void *param, int func)
  3041. {
  3042. asCScriptFunction *s = scriptFunctions[func];
  3043. asASSERT( s != 0 );
  3044. CallObjectMethod(obj, param, s->sysFuncIntf, s);
  3045. }
  3046. void asCScriptEngine::CallObjectMethod(void *obj, void *param, asSSystemFunctionInterface *i, asCScriptFunction *s)
  3047. {
  3048. #ifdef __GNUC__
  3049. if( i->callConv == ICC_CDECL_OBJLAST )
  3050. {
  3051. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3052. f(param, obj);
  3053. }
  3054. else if( i->callConv == ICC_GENERIC_METHOD )
  3055. {
  3056. asCGeneric gen(this, s, obj, (asDWORD*)&param);
  3057. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3058. f(&gen);
  3059. }
  3060. else if( i->callConv == ICC_VIRTUAL_THISCALL )
  3061. {
  3062. // For virtual thiscalls we must call the method as a true class method
  3063. // so that the compiler will lookup the function address in the vftable
  3064. union
  3065. {
  3066. asSIMPLEMETHOD_t mthd;
  3067. struct
  3068. {
  3069. asFUNCTION_t func;
  3070. asPWORD baseOffset; // Same size as the pointer
  3071. } f;
  3072. } p;
  3073. p.f.func = (void (*)())(i->func);
  3074. p.f.baseOffset = asPWORD(i->baseOffset);
  3075. void (asCSimpleDummy::*f)(void*) = (void (asCSimpleDummy::*)(void*))(p.mthd);
  3076. (((asCSimpleDummy*)obj)->*f)(param);
  3077. }
  3078. else /*if( i->callConv == ICC_CDECL_OBJFIRST || i->callConv == ICC_THISCALL )*/
  3079. {
  3080. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3081. f(obj, param);
  3082. }
  3083. #else
  3084. #ifndef AS_NO_CLASS_METHODS
  3085. if( i->callConv == ICC_THISCALL )
  3086. {
  3087. union
  3088. {
  3089. asSIMPLEMETHOD_t mthd;
  3090. asFUNCTION_t func;
  3091. } p;
  3092. p.func = (void (*)())(i->func);
  3093. void (asCSimpleDummy::*f)(void *) = (void (asCSimpleDummy::*)(void *))(p.mthd);
  3094. obj = (void*)(asPWORD(obj) + i->baseOffset);
  3095. (((asCSimpleDummy*)obj)->*f)(param);
  3096. }
  3097. else
  3098. #endif
  3099. if( i->callConv == ICC_CDECL_OBJLAST )
  3100. {
  3101. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3102. f(param, obj);
  3103. }
  3104. else if( i->callConv == ICC_GENERIC_METHOD )
  3105. {
  3106. asCGeneric gen(this, s, obj, (asDWORD*)&param);
  3107. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3108. f(&gen);
  3109. }
  3110. else /*if( i->callConv == ICC_CDECL_OBJFIRST )*/
  3111. {
  3112. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3113. f(obj, param);
  3114. }
  3115. #endif
  3116. }
  3117. void asCScriptEngine::CallGlobalFunction(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s)
  3118. {
  3119. if( i->callConv == ICC_CDECL )
  3120. {
  3121. void (*f)(void *, void *) = (void (*)(void *, void *))(i->func);
  3122. f(param1, param2);
  3123. }
  3124. else if( i->callConv == ICC_STDCALL )
  3125. {
  3126. void (STDCALL *f)(void *, void *) = (void (STDCALL *)(void *, void *))(i->func);
  3127. f(param1, param2);
  3128. }
  3129. else
  3130. {
  3131. asCGeneric gen(this, s, 0, (asDWORD*)&param1);
  3132. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3133. f(&gen);
  3134. }
  3135. }
  3136. bool asCScriptEngine::CallGlobalFunctionRetBool(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s)
  3137. {
  3138. if( i->callConv == ICC_CDECL )
  3139. {
  3140. bool (*f)(void *, void *) = (bool (*)(void *, void *))(i->func);
  3141. return f(param1, param2);
  3142. }
  3143. else if( i->callConv == ICC_STDCALL )
  3144. {
  3145. bool (STDCALL *f)(void *, void *) = (bool (STDCALL *)(void *, void *))(i->func);
  3146. return f(param1, param2);
  3147. }
  3148. else
  3149. {
  3150. // TODO: When simulating a 64bit environment by defining AS_64BIT_PTR on a 32bit platform this code
  3151. // fails, because the stack given to asCGeneric is not prepared with two 64bit arguments.
  3152. asCGeneric gen(this, s, 0, (asDWORD*)&param1);
  3153. void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
  3154. f(&gen);
  3155. return *(bool*)gen.GetReturnPointer();
  3156. }
  3157. }
  3158. void *asCScriptEngine::CallAlloc(asCObjectType *type) const
  3159. {
  3160. // Allocate 4 bytes as the smallest size. Otherwise CallSystemFunction may try to
  3161. // copy a DWORD onto a smaller memory block, in case the object type is return in registers.
  3162. #if defined(AS_DEBUG)
  3163. return ((asALLOCFUNCDEBUG_t)(userAlloc))(type->size < 4 ? 4 : type->size, __FILE__, __LINE__);
  3164. #else
  3165. return userAlloc(type->size < 4 ? 4 : type->size);
  3166. #endif
  3167. }
  3168. void asCScriptEngine::CallFree(void *obj) const
  3169. {
  3170. userFree(obj);
  3171. }
  3172. // interface
  3173. void asCScriptEngine::NotifyGarbageCollectorOfNewObject(void *obj, asIObjectType *type)
  3174. {
  3175. gc.AddScriptObjectToGC(obj, static_cast<asCObjectType*>(type));
  3176. }
  3177. // interface
  3178. int asCScriptEngine::GarbageCollect(asDWORD flags)
  3179. {
  3180. return gc.GarbageCollect(flags);
  3181. }
  3182. // interface
  3183. void asCScriptEngine::GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const
  3184. {
  3185. gc.GetStatistics(currentSize, totalDestroyed, totalDetected, newObjects, totalNewDestroyed);
  3186. }
  3187. // interface
  3188. void asCScriptEngine::GCEnumCallback(void *reference)
  3189. {
  3190. gc.GCEnumCallback(reference);
  3191. }
  3192. // TODO: multithread: The mapTypeIdToDataType must be protected with critical sections in all functions that access it
  3193. // Urho3D: modified for type ID caching
  3194. int asCScriptEngine::GetTypeIdFromDataType(const asCDataType &dtIn) const
  3195. {
  3196. if( dtIn.IsNullHandle() ) return 0;
  3197. /// Urho3D: check cached type ID first
  3198. int typeId = dtIn.GetCachedTypeId();
  3199. if( typeId )
  3200. return typeId;
  3201. // Register the base form
  3202. asCDataType dt(dtIn);
  3203. if( dt.GetObjectType() )
  3204. dt.MakeHandle(false);
  3205. // Find the existing type id
  3206. asSMapNode<int,asCDataType*> *cursor = 0;
  3207. mapTypeIdToDataType.MoveFirst(&cursor);
  3208. while( cursor )
  3209. {
  3210. if( mapTypeIdToDataType.GetValue(cursor)->IsEqualExceptRefAndConst(dt) )
  3211. {
  3212. typeId = mapTypeIdToDataType.GetKey(cursor);
  3213. if( dtIn.GetObjectType() && !(dtIn.GetObjectType()->flags & asOBJ_ASHANDLE) )
  3214. {
  3215. // The the ASHANDLE types behave like handles, but are really
  3216. // value types so the typeId is never returned as a handle
  3217. if( dtIn.IsObjectHandle() )
  3218. typeId |= asTYPEID_OBJHANDLE;
  3219. if( dtIn.IsHandleToConst() )
  3220. typeId |= asTYPEID_HANDLETOCONST;
  3221. }
  3222. // Urho3D: cache the type ID for next query
  3223. dtIn.SetCachedTypeId(typeId);
  3224. return typeId;
  3225. }
  3226. mapTypeIdToDataType.MoveNext(&cursor, cursor);
  3227. }
  3228. // The type id doesn't exist, create it
  3229. // Setup the basic type id
  3230. typeId = typeIdSeqNbr++;
  3231. if( dt.GetObjectType() )
  3232. {
  3233. if( dt.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT;
  3234. else if( dt.GetObjectType()->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE;
  3235. else if( dt.GetObjectType()->flags & asOBJ_ENUM ) {} // TODO: Should we have a specific bit for this?
  3236. else typeId |= asTYPEID_APPOBJECT;
  3237. }
  3238. // Insert the basic object type
  3239. asCDataType *newDt = asNEW(asCDataType)(dt);
  3240. if( newDt == 0 )
  3241. {
  3242. // Out of memory
  3243. return 0;
  3244. }
  3245. newDt->MakeReference(false);
  3246. newDt->MakeReadOnly(false);
  3247. newDt->MakeHandle(false);
  3248. mapTypeIdToDataType.Insert(typeId, newDt);
  3249. // Call recursively to get the correct typeId
  3250. return GetTypeIdFromDataType(dtIn);
  3251. }
  3252. asCDataType asCScriptEngine::GetDataTypeFromTypeId(int typeId) const
  3253. {
  3254. int baseId = typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR);
  3255. asSMapNode<int,asCDataType*> *cursor = 0;
  3256. if( mapTypeIdToDataType.MoveTo(&cursor, baseId) )
  3257. {
  3258. asCDataType dt(*mapTypeIdToDataType.GetValue(cursor));
  3259. if( typeId & asTYPEID_OBJHANDLE )
  3260. dt.MakeHandle(true);
  3261. if( typeId & asTYPEID_HANDLETOCONST )
  3262. dt.MakeHandleToConst(true);
  3263. return dt;
  3264. }
  3265. return asCDataType();
  3266. }
  3267. asCObjectType *asCScriptEngine::GetObjectTypeFromTypeId(int typeId) const
  3268. {
  3269. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3270. return dt.GetObjectType();
  3271. }
  3272. void asCScriptEngine::RemoveFromTypeIdMap(asCObjectType *type)
  3273. {
  3274. asSMapNode<int,asCDataType*> *cursor = 0;
  3275. mapTypeIdToDataType.MoveFirst(&cursor);
  3276. while( cursor )
  3277. {
  3278. asCDataType *dt = mapTypeIdToDataType.GetValue(cursor);
  3279. asSMapNode<int,asCDataType*> *old = cursor;
  3280. mapTypeIdToDataType.MoveNext(&cursor, cursor);
  3281. if( dt->GetObjectType() == type )
  3282. {
  3283. asDELETE(dt,asCDataType);
  3284. mapTypeIdToDataType.Erase(old);
  3285. }
  3286. }
  3287. }
  3288. // interface
  3289. int asCScriptEngine::GetTypeIdByDecl(const char *decl) const
  3290. {
  3291. asCDataType dt;
  3292. // This cast is ok, because we are not changing anything in the engine
  3293. asCBuilder bld(const_cast<asCScriptEngine*>(this), 0);
  3294. int r = bld.ParseDataType(decl, &dt, defaultNamespace);
  3295. if( r < 0 )
  3296. return asINVALID_TYPE;
  3297. return GetTypeIdFromDataType(dt);
  3298. }
  3299. // interface
  3300. const char *asCScriptEngine::GetTypeDeclaration(int typeId, bool includeNamespace) const
  3301. {
  3302. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3303. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  3304. *tempString = dt.Format(includeNamespace);
  3305. return tempString->AddressOf();
  3306. }
  3307. // TODO: interface: Deprecate. This function is not necessary now that all primitive types have fixed typeIds
  3308. int asCScriptEngine::GetSizeOfPrimitiveType(int typeId) const
  3309. {
  3310. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3311. if( !dt.IsPrimitive() ) return 0;
  3312. return dt.GetSizeInMemoryBytes();
  3313. }
  3314. // TODO: interface: Should deprecate this. The application should be calling the factory directly
  3315. void *asCScriptEngine::CreateScriptObject(int typeId)
  3316. {
  3317. // Make sure the type id is for an object type, and not a primitive or a handle
  3318. if( (typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR)) != typeId ) return 0;
  3319. if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return 0;
  3320. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3321. // Is the type id valid?
  3322. if( !dt.IsValid() ) return 0;
  3323. asCObjectType *objType = dt.GetObjectType();
  3324. void *ptr = 0;
  3325. // Construct the object
  3326. if( objType->flags & asOBJ_SCRIPT_OBJECT )
  3327. {
  3328. // Call the script class' default factory with a context
  3329. ptr = ScriptObjectFactory(objType, this);
  3330. }
  3331. else if( objType->flags & asOBJ_TEMPLATE )
  3332. {
  3333. // The registered factory that takes the object type is moved
  3334. // to the construct behaviour when the type is instanciated
  3335. ptr = CallGlobalFunctionRetPtr(objType->beh.construct, objType);
  3336. }
  3337. else if( objType->flags & asOBJ_REF )
  3338. {
  3339. // Call the default factory directly
  3340. ptr = CallGlobalFunctionRetPtr(objType->beh.factory);
  3341. }
  3342. else
  3343. {
  3344. // Manually allocate the memory, then
  3345. // call the default constructor
  3346. ptr = CallAlloc(objType);
  3347. int funcIndex = objType->beh.construct;
  3348. if( funcIndex )
  3349. CallObjectMethod(ptr, funcIndex);
  3350. }
  3351. return ptr;
  3352. }
  3353. // interface
  3354. void *asCScriptEngine::CreateUninitializedScriptObject(int typeId)
  3355. {
  3356. // Make sure the type id is for an object type, and not a primitive or a handle.
  3357. // This function only works for script classes. Registered types cannot be created this way.
  3358. if( (typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR)) != typeId ) return 0;
  3359. if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return 0;
  3360. if( (typeId & asTYPEID_SCRIPTOBJECT) == 0 ) return 0;
  3361. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3362. // Is the type id valid?
  3363. if( !dt.IsValid() ) return 0;
  3364. asCObjectType *objType = dt.GetObjectType();
  3365. asASSERT( objType->flags & asOBJ_SCRIPT_OBJECT );
  3366. // Construct the object, but do not call the actual constructor that initializes the members
  3367. // The initialization will be done by the application afterwards, e.g. through serialization.
  3368. asCScriptObject *obj = reinterpret_cast<asCScriptObject*>(CallAlloc(objType));
  3369. // Pre-initialize the memory so there are no invalid pointers
  3370. ScriptObject_ConstructUnitialized(objType, obj);
  3371. return obj;
  3372. }
  3373. // TODO: interface: Should deprecate this. The application should be calling the factory directly
  3374. void *asCScriptEngine::CreateScriptObjectCopy(void *origObj, int typeId)
  3375. {
  3376. void *newObj = CreateScriptObject(typeId);
  3377. if( newObj == 0 ) return 0;
  3378. AssignScriptObject(newObj, origObj, typeId);
  3379. return newObj;
  3380. }
  3381. // internal
  3382. void asCScriptEngine::ConstructScriptObjectCopy(void *mem, void *obj, asCObjectType *type)
  3383. {
  3384. // This function is only meant to be used for value types
  3385. asASSERT( type->flags & asOBJ_VALUE );
  3386. // TODO: runtime optimize: Should use the copy constructor when available
  3387. int funcIndex = type->beh.construct;
  3388. if( funcIndex )
  3389. CallObjectMethod(mem, funcIndex);
  3390. AssignScriptObject(mem, obj, type->GetTypeId());
  3391. }
  3392. #ifdef AS_DEPRECATED
  3393. // Deprecated since 2.24.0 - 2012-06-07
  3394. void asCScriptEngine::CopyScriptObject(void *dstObj, void *srcObj, int typeId)
  3395. {
  3396. AssignScriptObject(dstObj, srcObj, typeId);
  3397. }
  3398. #endif
  3399. // interface
  3400. void asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, int typeId)
  3401. {
  3402. // Make sure the type id is for an object type, and not a primitive or a handle
  3403. if( (typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR)) != typeId ) return;
  3404. if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return;
  3405. // Copy the contents from the original object, using the assignment operator
  3406. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3407. // Is the type id valid?
  3408. if( !dt.IsValid() ) return;
  3409. asCObjectType *objType = dt.GetObjectType();
  3410. // Must not copy if the opAssign is not available and the object is not a POD object
  3411. if( objType->beh.copy )
  3412. {
  3413. CallObjectMethod(dstObj, srcObj, objType->beh.copy);
  3414. }
  3415. else if( objType->size && (objType->flags & asOBJ_POD) )
  3416. {
  3417. memcpy(dstObj, srcObj, objType->size);
  3418. }
  3419. }
  3420. // interface
  3421. void asCScriptEngine::AddRefScriptObject(void *obj, int typeId)
  3422. {
  3423. // Make sure it is not a null pointer
  3424. if( obj == 0 ) return;
  3425. // Make sure the type id is for an object type or a handle
  3426. if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return;
  3427. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3428. // Is the type id valid?
  3429. if( !dt.IsValid() ) return;
  3430. asCObjectType *objType = dt.GetObjectType();
  3431. if( objType->beh.addref )
  3432. {
  3433. // Call the addref behaviour
  3434. CallObjectMethod(obj, objType->beh.addref);
  3435. }
  3436. }
  3437. // interface
  3438. void asCScriptEngine::AddRefScriptObject(void *obj, const asIObjectType *type)
  3439. {
  3440. // Make sure it is not a null pointer
  3441. if( obj == 0 ) return;
  3442. const asCObjectType *objType = static_cast<const asCObjectType *>(type);
  3443. if( objType->beh.addref )
  3444. {
  3445. // Call the addref behaviour
  3446. CallObjectMethod(obj, objType->beh.addref);
  3447. }
  3448. }
  3449. // interface
  3450. void asCScriptEngine::ReleaseScriptObject(void *obj, int typeId)
  3451. {
  3452. // Make sure it is not a null pointer
  3453. if( obj == 0 ) return;
  3454. // Make sure the type id is for an object type or a handle
  3455. if( (typeId & asTYPEID_MASK_OBJECT) == 0 ) return;
  3456. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3457. // Is the type id valid?
  3458. if( !dt.IsValid() ) return;
  3459. asCObjectType *objType = dt.GetObjectType();
  3460. ReleaseScriptObject(obj, objType);
  3461. }
  3462. // interface
  3463. void asCScriptEngine::ReleaseScriptObject(void *obj, const asIObjectType *type)
  3464. {
  3465. // Make sure it is not a null pointer
  3466. if( obj == 0 ) return;
  3467. const asCObjectType *objType = static_cast<const asCObjectType *>(type);
  3468. if( objType->flags & asOBJ_REF )
  3469. {
  3470. asASSERT( (objType->flags & asOBJ_NOCOUNT) || objType->beh.release );
  3471. if( objType->beh.release )
  3472. {
  3473. // Call the release behaviour
  3474. CallObjectMethod(obj, objType->beh.release);
  3475. }
  3476. }
  3477. else
  3478. {
  3479. // TODO: interface: shouldn't work on non reference types
  3480. // Call the destructor
  3481. if( objType->beh.destruct )
  3482. CallObjectMethod(obj, objType->beh.destruct);
  3483. // Then free the memory
  3484. CallFree(obj);
  3485. }
  3486. }
  3487. // interface
  3488. bool asCScriptEngine::IsHandleCompatibleWithObject(void *obj, int objTypeId, int handleTypeId) const
  3489. {
  3490. // if equal, then it is obvious they are compatible
  3491. if( objTypeId == handleTypeId )
  3492. return true;
  3493. // Get the actual data types from the type ids
  3494. asCDataType objDt = GetDataTypeFromTypeId(objTypeId);
  3495. asCDataType hdlDt = GetDataTypeFromTypeId(handleTypeId);
  3496. // A handle to const cannot be passed to a handle that is not referencing a const object
  3497. if( objDt.IsHandleToConst() && !hdlDt.IsHandleToConst() )
  3498. return false;
  3499. if( objDt.GetObjectType() == hdlDt.GetObjectType() )
  3500. {
  3501. // The object type is equal
  3502. return true;
  3503. }
  3504. else if( objDt.IsScriptObject() && obj )
  3505. {
  3506. // Get the true type from the object instance
  3507. asCObjectType *objType = ((asCScriptObject*)obj)->objType;
  3508. // Check if the object implements the interface, or derives from the base class
  3509. // This will also return true, if the requested handle type is an exact match for the object type
  3510. if( objType->Implements(hdlDt.GetObjectType()) ||
  3511. objType->DerivesFrom(hdlDt.GetObjectType()) )
  3512. return true;
  3513. }
  3514. return false;
  3515. }
  3516. // interface
  3517. int asCScriptEngine::BeginConfigGroup(const char *groupName)
  3518. {
  3519. // Make sure the group name doesn't already exist
  3520. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  3521. {
  3522. if( configGroups[n]->groupName == groupName )
  3523. return asNAME_TAKEN;
  3524. }
  3525. if( currentGroup != &defaultGroup )
  3526. return asNOT_SUPPORTED;
  3527. asCConfigGroup *group = asNEW(asCConfigGroup)();
  3528. if( group == 0 )
  3529. return asOUT_OF_MEMORY;
  3530. group->groupName = groupName;
  3531. configGroups.PushLast(group);
  3532. currentGroup = group;
  3533. return 0;
  3534. }
  3535. // interface
  3536. int asCScriptEngine::EndConfigGroup()
  3537. {
  3538. // Raise error if trying to end the default config
  3539. if( currentGroup == &defaultGroup )
  3540. return asERROR;
  3541. currentGroup = &defaultGroup;
  3542. return 0;
  3543. }
  3544. // interface
  3545. int asCScriptEngine::RemoveConfigGroup(const char *groupName)
  3546. {
  3547. // It is not allowed to remove a group that is still in use.
  3548. // It would be possible to change the code in such a way that
  3549. // the group could be removed even though it was still in use,
  3550. // but that would cause severe negative impact on runtime
  3551. // performance, since the VM would then have to be able handle
  3552. // situations where the types, functions, and global variables
  3553. // can be removed at any time.
  3554. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  3555. {
  3556. if( configGroups[n]->groupName == groupName )
  3557. {
  3558. asCConfigGroup *group = configGroups[n];
  3559. // Make sure the group isn't referenced by anyone
  3560. if( group->refCount > 0 )
  3561. return asCONFIG_GROUP_IS_IN_USE;
  3562. // Verify if any objects registered in this group is still alive
  3563. if( group->HasLiveObjects() )
  3564. return asCONFIG_GROUP_IS_IN_USE;
  3565. // Remove the group from the list
  3566. if( n == configGroups.GetLength() - 1 )
  3567. configGroups.PopLast();
  3568. else
  3569. configGroups[n] = configGroups.PopLast();
  3570. // Remove the configurations registered with this group
  3571. group->RemoveConfiguration(this);
  3572. asDELETE(group,asCConfigGroup);
  3573. }
  3574. }
  3575. return 0;
  3576. }
  3577. asCConfigGroup *asCScriptEngine::FindConfigGroupForFunction(int funcId) const
  3578. {
  3579. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  3580. {
  3581. // Check global functions
  3582. asUINT m;
  3583. for( m = 0; m < configGroups[n]->scriptFunctions.GetLength(); m++ )
  3584. {
  3585. if( configGroups[n]->scriptFunctions[m]->id == funcId )
  3586. return configGroups[n];
  3587. }
  3588. }
  3589. return 0;
  3590. }
  3591. asCConfigGroup *asCScriptEngine::FindConfigGroupForGlobalVar(int gvarId) const
  3592. {
  3593. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  3594. {
  3595. for( asUINT m = 0; m < configGroups[n]->globalProps.GetLength(); m++ )
  3596. {
  3597. if( int(configGroups[n]->globalProps[m]->id) == gvarId )
  3598. return configGroups[n];
  3599. }
  3600. }
  3601. return 0;
  3602. }
  3603. asCConfigGroup *asCScriptEngine::FindConfigGroupForObjectType(const asCObjectType *objType) const
  3604. {
  3605. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  3606. {
  3607. for( asUINT m = 0; m < configGroups[n]->objTypes.GetLength(); m++ )
  3608. {
  3609. if( configGroups[n]->objTypes[m] == objType )
  3610. return configGroups[n];
  3611. }
  3612. }
  3613. return 0;
  3614. }
  3615. asCConfigGroup *asCScriptEngine::FindConfigGroupForFuncDef(const asCScriptFunction *funcDef) const
  3616. {
  3617. for( asUINT n = 0; n < configGroups.GetLength(); n++ )
  3618. {
  3619. asCScriptFunction *f = const_cast<asCScriptFunction*>(funcDef);
  3620. if( configGroups[n]->funcDefs.Exists(f) )
  3621. return configGroups[n];
  3622. }
  3623. return 0;
  3624. }
  3625. // interface
  3626. asDWORD asCScriptEngine::SetDefaultAccessMask(asDWORD defaultMask)
  3627. {
  3628. asDWORD old = defaultAccessMask;
  3629. defaultAccessMask = defaultMask;
  3630. return old;
  3631. }
  3632. int asCScriptEngine::GetNextScriptFunctionId()
  3633. {
  3634. if( freeScriptFunctionIds.GetLength() )
  3635. return freeScriptFunctionIds.PopLast();
  3636. int id = (int)scriptFunctions.GetLength();
  3637. scriptFunctions.PushLast(0);
  3638. return id;
  3639. }
  3640. void asCScriptEngine::SetScriptFunction(asCScriptFunction *func)
  3641. {
  3642. scriptFunctions[func->id] = func;
  3643. }
  3644. void asCScriptEngine::FreeScriptFunctionId(int id)
  3645. {
  3646. if( id < 0 ) return;
  3647. id &= 0xFFFF;
  3648. if( id >= (int)scriptFunctions.GetLength() ) return;
  3649. if( scriptFunctions[id] )
  3650. {
  3651. asCScriptFunction *func = scriptFunctions[id];
  3652. // Remove the function from the list of script functions
  3653. if( id == (int)scriptFunctions.GetLength() - 1 )
  3654. {
  3655. scriptFunctions.PopLast();
  3656. }
  3657. else
  3658. {
  3659. scriptFunctions[id] = 0;
  3660. freeScriptFunctionIds.PushLast(id);
  3661. }
  3662. // Is the function used as signature id?
  3663. if( func->signatureId == id )
  3664. {
  3665. // Remove the signature id
  3666. signatureIds.RemoveValue(func);
  3667. // Update all functions using the signature id
  3668. int newSigId = 0;
  3669. for( asUINT n = 0; n < scriptFunctions.GetLength(); n++ )
  3670. {
  3671. if( scriptFunctions[n] && scriptFunctions[n]->signatureId == id )
  3672. {
  3673. if( newSigId == 0 )
  3674. {
  3675. newSigId = scriptFunctions[n]->id;
  3676. signatureIds.PushLast(scriptFunctions[n]);
  3677. }
  3678. scriptFunctions[n]->signatureId = newSigId;
  3679. }
  3680. }
  3681. }
  3682. }
  3683. }
  3684. // interface
  3685. int asCScriptEngine::RegisterFuncdef(const char *decl)
  3686. {
  3687. if( decl == 0 ) return ConfigError(asINVALID_ARG, "RegisterFuncdef", decl, 0);
  3688. // Parse the function declaration
  3689. asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_FUNCDEF);
  3690. if( func == 0 )
  3691. return ConfigError(asOUT_OF_MEMORY, "RegisterFuncdef", decl, 0);
  3692. asCBuilder bld(this, 0);
  3693. int r = bld.ParseFunctionDeclaration(0, decl, func, false, 0, 0, defaultNamespace);
  3694. if( r < 0 )
  3695. {
  3696. // Set as dummy function before deleting
  3697. func->funcType = asFUNC_DUMMY;
  3698. asDELETE(func,asCScriptFunction);
  3699. return ConfigError(asINVALID_DECLARATION, "RegisterFuncdef", decl, 0);
  3700. }
  3701. // Check name conflicts
  3702. r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace);
  3703. if( r < 0 )
  3704. {
  3705. asDELETE(func,asCScriptFunction);
  3706. return ConfigError(asNAME_TAKEN, "RegisterFuncdef", decl, 0);
  3707. }
  3708. func->id = GetNextScriptFunctionId();
  3709. SetScriptFunction(func);
  3710. funcDefs.PushLast(func);
  3711. registeredFuncDefs.PushLast(func);
  3712. currentGroup->funcDefs.PushLast(func);
  3713. // If parameter type from other groups are used, add references
  3714. if( func->returnType.GetObjectType() )
  3715. {
  3716. asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
  3717. currentGroup->RefConfigGroup(group);
  3718. }
  3719. for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
  3720. {
  3721. if( func->parameterTypes[n].GetObjectType() )
  3722. {
  3723. asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
  3724. currentGroup->RefConfigGroup(group);
  3725. }
  3726. }
  3727. // Return the function id as success
  3728. return func->id;
  3729. }
  3730. // interface
  3731. asUINT asCScriptEngine::GetFuncdefCount() const
  3732. {
  3733. return asUINT(registeredFuncDefs.GetLength());
  3734. }
  3735. // interface
  3736. asIScriptFunction *asCScriptEngine::GetFuncdefByIndex(asUINT index) const
  3737. {
  3738. if( index >= registeredFuncDefs.GetLength() )
  3739. return 0;
  3740. return registeredFuncDefs[index];
  3741. }
  3742. // interface
  3743. // TODO: typedef: Accept complex types for the typedefs
  3744. int asCScriptEngine::RegisterTypedef(const char *type, const char *decl)
  3745. {
  3746. if( type == 0 ) return ConfigError(asINVALID_NAME, "RegisterTypedef", type, decl);
  3747. // Verify if the name has been registered as a type already
  3748. asUINT n;
  3749. for( n = 0; n < objectTypes.GetLength(); n++ )
  3750. {
  3751. if( objectTypes[n] && objectTypes[n]->name == type && objectTypes[n]->nameSpace == defaultNamespace )
  3752. // Let the application recover from this error, for example if the same typedef is registered twice
  3753. return asALREADY_REGISTERED;
  3754. }
  3755. // Grab the data type
  3756. size_t tokenLen;
  3757. eTokenType token;
  3758. asCDataType dataType;
  3759. // Create the data type
  3760. token = tok.GetToken(decl, strlen(decl), &tokenLen);
  3761. switch(token)
  3762. {
  3763. case ttBool:
  3764. case ttInt:
  3765. case ttInt8:
  3766. case ttInt16:
  3767. case ttInt64:
  3768. case ttUInt:
  3769. case ttUInt8:
  3770. case ttUInt16:
  3771. case ttUInt64:
  3772. case ttFloat:
  3773. case ttDouble:
  3774. if( strlen(decl) != tokenLen )
  3775. {
  3776. return ConfigError(asINVALID_TYPE, "RegisterTypedef", type, decl);
  3777. }
  3778. break;
  3779. default:
  3780. return ConfigError(asINVALID_TYPE, "RegisterTypedef", type, decl);
  3781. }
  3782. dataType = asCDataType::CreatePrimitive(token, false);
  3783. // Make sure the name is not a reserved keyword
  3784. token = tok.GetToken(type, strlen(type), &tokenLen);
  3785. if( token != ttIdentifier || strlen(type) != tokenLen )
  3786. return ConfigError(asINVALID_NAME, "RegisterTypedef", type, decl);
  3787. asCBuilder bld(this, 0);
  3788. int r = bld.CheckNameConflict(type, 0, 0, defaultNamespace);
  3789. if( r < 0 )
  3790. return ConfigError(asNAME_TAKEN, "RegisterTypedef", type, decl);
  3791. // Don't have to check against members of object
  3792. // types as they are allowed to use the names
  3793. // Put the data type in the list
  3794. asCObjectType *object = asNEW(asCObjectType)(this);
  3795. if( object == 0 )
  3796. return ConfigError(asOUT_OF_MEMORY, "RegisterTypedef", type, decl);
  3797. object->flags = asOBJ_TYPEDEF;
  3798. object->size = dataType.GetSizeInMemoryBytes();
  3799. object->name = type;
  3800. object->nameSpace = defaultNamespace;
  3801. object->templateSubType = dataType;
  3802. objectTypes.PushLast(object);
  3803. registeredTypeDefs.PushLast(object);
  3804. currentGroup->objTypes.PushLast(object);
  3805. return asSUCCESS;
  3806. }
  3807. // interface
  3808. asUINT asCScriptEngine::GetTypedefCount() const
  3809. {
  3810. return asUINT(registeredTypeDefs.GetLength());
  3811. }
  3812. // interface
  3813. const char *asCScriptEngine::GetTypedefByIndex(asUINT index, int *typeId, const char **nameSpace, const char **configGroup, asDWORD *accessMask) const
  3814. {
  3815. if( index >= registeredTypeDefs.GetLength() )
  3816. return 0;
  3817. if( typeId )
  3818. *typeId = GetTypeIdFromDataType(registeredTypeDefs[index]->templateSubType);
  3819. if( configGroup )
  3820. {
  3821. asCConfigGroup *group = FindConfigGroupForObjectType(registeredTypeDefs[index]);
  3822. if( group )
  3823. *configGroup = group->groupName.AddressOf();
  3824. else
  3825. *configGroup = 0;
  3826. }
  3827. if( accessMask )
  3828. *accessMask = registeredTypeDefs[index]->accessMask;
  3829. if( nameSpace )
  3830. *nameSpace = registeredTypeDefs[index]->nameSpace->name.AddressOf();
  3831. return registeredTypeDefs[index]->name.AddressOf();
  3832. }
  3833. // interface
  3834. int asCScriptEngine::RegisterEnum(const char *name)
  3835. {
  3836. // Check the name
  3837. if( NULL == name )
  3838. return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0);
  3839. // Verify if the name has been registered as a type already
  3840. asUINT n;
  3841. for( n = 0; n < objectTypes.GetLength(); n++ )
  3842. if( objectTypes[n] && objectTypes[n]->name == name && objectTypes[n]->nameSpace == defaultNamespace )
  3843. return asALREADY_REGISTERED;
  3844. // Use builder to parse the datatype
  3845. asCDataType dt;
  3846. asCBuilder bld(this, 0);
  3847. bool oldMsgCallback = msgCallback; msgCallback = false;
  3848. int r = bld.ParseDataType(name, &dt, defaultNamespace);
  3849. msgCallback = oldMsgCallback;
  3850. if( r >= 0 )
  3851. return ConfigError(asERROR, "RegisterEnum", name, 0);
  3852. // Make sure the name is not a reserved keyword
  3853. size_t tokenLen;
  3854. int token = tok.GetToken(name, strlen(name), &tokenLen);
  3855. if( token != ttIdentifier || strlen(name) != tokenLen )
  3856. return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0);
  3857. r = bld.CheckNameConflict(name, 0, 0, defaultNamespace);
  3858. if( r < 0 )
  3859. return ConfigError(asNAME_TAKEN, "RegisterEnum", name, 0);
  3860. asCObjectType *st = asNEW(asCObjectType)(this);
  3861. if( st == 0 )
  3862. return ConfigError(asOUT_OF_MEMORY, "RegisterEnum", name, 0);
  3863. asCDataType dataType;
  3864. dataType.CreatePrimitive(ttInt, false);
  3865. st->flags = asOBJ_ENUM | asOBJ_SHARED;
  3866. st->size = 4;
  3867. st->name = name;
  3868. st->nameSpace = defaultNamespace;
  3869. objectTypes.PushLast(st);
  3870. registeredEnums.PushLast(st);
  3871. currentGroup->objTypes.PushLast(st);
  3872. return asSUCCESS;
  3873. }
  3874. // interface
  3875. int asCScriptEngine::RegisterEnumValue(const char *typeName, const char *valueName, int value)
  3876. {
  3877. // Verify that the correct config group is used
  3878. if( currentGroup->FindType(typeName) == 0 )
  3879. return ConfigError(asWRONG_CONFIG_GROUP, "RegisterEnumValue", typeName, valueName);
  3880. asCDataType dt;
  3881. int r;
  3882. asCBuilder bld(this, 0);
  3883. r = bld.ParseDataType(typeName, &dt, defaultNamespace);
  3884. if( r < 0 )
  3885. return ConfigError(r, "RegisterEnumValue", typeName, valueName);
  3886. // Store the enum value
  3887. asCObjectType *ot = dt.GetObjectType();
  3888. if( ot == 0 || !(ot->flags & asOBJ_ENUM) )
  3889. return ConfigError(asINVALID_TYPE, "RegisterEnumValue", typeName, valueName);
  3890. if( NULL == valueName )
  3891. return ConfigError(asINVALID_NAME, "RegisterEnumValue", typeName, valueName);
  3892. int tokenLen;
  3893. asETokenClass tokenClass = ParseToken(valueName, 0, &tokenLen);
  3894. if( tokenClass != asTC_IDENTIFIER || tokenLen != (int)strlen(valueName) )
  3895. return ConfigError(asINVALID_NAME, "RegisterEnumValue", typeName, valueName);
  3896. for( unsigned int n = 0; n < ot->enumValues.GetLength(); n++ )
  3897. {
  3898. if( ot->enumValues[n]->name == valueName )
  3899. return ConfigError(asALREADY_REGISTERED, "RegisterEnumValue", typeName, valueName);
  3900. }
  3901. asSEnumValue *e = asNEW(asSEnumValue);
  3902. if( e == 0 )
  3903. return ConfigError(asOUT_OF_MEMORY, "RegisterEnumValue", typeName, valueName);
  3904. e->name = valueName;
  3905. e->value = value;
  3906. ot->enumValues.PushLast(e);
  3907. return asSUCCESS;
  3908. }
  3909. // interface
  3910. asUINT asCScriptEngine::GetEnumCount() const
  3911. {
  3912. return asUINT(registeredEnums.GetLength());
  3913. }
  3914. // interface
  3915. const char *asCScriptEngine::GetEnumByIndex(asUINT index, int *enumTypeId, const char **nameSpace, const char **configGroup, asDWORD *accessMask) const
  3916. {
  3917. if( index >= registeredEnums.GetLength() )
  3918. return 0;
  3919. if( configGroup )
  3920. {
  3921. asCConfigGroup *group = FindConfigGroupForObjectType(registeredEnums[index]);
  3922. if( group )
  3923. *configGroup = group->groupName.AddressOf();
  3924. else
  3925. *configGroup = 0;
  3926. }
  3927. if( accessMask )
  3928. *accessMask = registeredEnums[index]->accessMask;
  3929. if( enumTypeId )
  3930. *enumTypeId = GetTypeIdFromDataType(asCDataType::CreateObject(registeredEnums[index], false));
  3931. if( nameSpace )
  3932. *nameSpace = registeredEnums[index]->nameSpace->name.AddressOf();
  3933. return registeredEnums[index]->name.AddressOf();
  3934. }
  3935. // interface
  3936. int asCScriptEngine::GetEnumValueCount(int enumTypeId) const
  3937. {
  3938. asCDataType dt = GetDataTypeFromTypeId(enumTypeId);
  3939. asCObjectType *t = dt.GetObjectType();
  3940. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  3941. return asINVALID_TYPE;
  3942. return (int)t->enumValues.GetLength();
  3943. }
  3944. // interface
  3945. const char *asCScriptEngine::GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const
  3946. {
  3947. // TODO: This same function is implemented in as_module.cpp as well. Perhaps it should be moved to asCObjectType?
  3948. asCDataType dt = GetDataTypeFromTypeId(enumTypeId);
  3949. asCObjectType *t = dt.GetObjectType();
  3950. if( t == 0 || !(t->GetFlags() & asOBJ_ENUM) )
  3951. return 0;
  3952. if( index >= t->enumValues.GetLength() )
  3953. return 0;
  3954. if( outValue )
  3955. *outValue = t->enumValues[index]->value;
  3956. return t->enumValues[index]->name.AddressOf();
  3957. }
  3958. // interface
  3959. asUINT asCScriptEngine::GetObjectTypeCount() const
  3960. {
  3961. return asUINT(registeredObjTypes.GetLength());
  3962. }
  3963. // interface
  3964. asIObjectType *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const
  3965. {
  3966. if( index >= registeredObjTypes.GetLength() )
  3967. return 0;
  3968. return registeredObjTypes[index];
  3969. }
  3970. // interface
  3971. asIObjectType *asCScriptEngine::GetObjectTypeByName(const char *name) const
  3972. {
  3973. for( asUINT n = 0; n < registeredObjTypes.GetLength(); n++ )
  3974. {
  3975. if( registeredObjTypes[n]->name == name &&
  3976. registeredObjTypes[n]->nameSpace == defaultNamespace )
  3977. return registeredObjTypes[n];
  3978. }
  3979. return 0;
  3980. }
  3981. // interface
  3982. asIObjectType *asCScriptEngine::GetObjectTypeById(int typeId) const
  3983. {
  3984. asCDataType dt = GetDataTypeFromTypeId(typeId);
  3985. // Is the type id valid?
  3986. if( !dt.IsValid() ) return 0;
  3987. // Enum types are not objects, so we shouldn't return an object type for them
  3988. if( dt.GetObjectType() && dt.GetObjectType()->GetFlags() & asOBJ_ENUM )
  3989. return 0;
  3990. return dt.GetObjectType();
  3991. }
  3992. // interface
  3993. asIScriptFunction *asCScriptEngine::GetFunctionById(int funcId) const
  3994. {
  3995. return GetScriptFunction(funcId);
  3996. }
  3997. // internal
  3998. bool asCScriptEngine::IsTemplateType(const char *name) const
  3999. {
  4000. // TODO: optimize: Improve linear search
  4001. for( unsigned int n = 0; n < objectTypes.GetLength(); n++ )
  4002. {
  4003. if( objectTypes[n] && objectTypes[n]->name == name )
  4004. {
  4005. return objectTypes[n]->flags & asOBJ_TEMPLATE ? true : false;
  4006. }
  4007. }
  4008. return false;
  4009. }
  4010. // internal
  4011. int asCScriptEngine::AddConstantString(const char *str, size_t len)
  4012. {
  4013. // This is only called when build a script module, so it is
  4014. // known that only one thread can enter the function at a time.
  4015. asASSERT( isBuilding );
  4016. // The str may contain null chars, so we cannot use strlen, or strcmp, or strcpy
  4017. // Has the string been registered before?
  4018. asSMapNode<asCStringPointer, int> *cursor = 0;
  4019. if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str, len)))
  4020. return cursor->value;
  4021. // No match was found, add the string
  4022. asCString *cstr = asNEW(asCString)(str, len);
  4023. if( cstr )
  4024. {
  4025. stringConstants.PushLast(cstr);
  4026. int index = (int)stringConstants.GetLength() - 1;
  4027. stringToIdMap.Insert(asCStringPointer(cstr), index);
  4028. // The VM currently doesn't handle string ids larger than 65535
  4029. asASSERT(stringConstants.GetLength() <= 65536);
  4030. return index;
  4031. }
  4032. return 0;
  4033. }
  4034. // internal
  4035. const asCString &asCScriptEngine::GetConstantString(int id)
  4036. {
  4037. return *stringConstants[id];
  4038. }
  4039. // internal
  4040. int asCScriptEngine::GetScriptSectionNameIndex(const char *name)
  4041. {
  4042. ACQUIREEXCLUSIVE(engineRWLock);
  4043. // TODO: These names are only released when the engine is freed. The assumption is that
  4044. // the same script section names will be reused instead of there always being new
  4045. // names. Is this assumption valid? Do we need to add reference counting?
  4046. // Store the script section names for future reference
  4047. for( asUINT n = 0; n < scriptSectionNames.GetLength(); n++ )
  4048. {
  4049. if( scriptSectionNames[n]->Compare(name) == 0 )
  4050. {
  4051. RELEASEEXCLUSIVE(engineRWLock);
  4052. return n;
  4053. }
  4054. }
  4055. asCString *str = asNEW(asCString)(name);
  4056. if( str )
  4057. scriptSectionNames.PushLast(str);
  4058. int r = int(scriptSectionNames.GetLength()-1);
  4059. RELEASEEXCLUSIVE(engineRWLock);
  4060. return r;
  4061. }
  4062. // interface
  4063. void asCScriptEngine::SetEngineUserDataCleanupCallback(asCLEANENGINEFUNC_t callback, asPWORD type)
  4064. {
  4065. ACQUIREEXCLUSIVE(engineRWLock);
  4066. for( asUINT n = 0; n < cleanEngineFuncs.GetLength(); n++ )
  4067. {
  4068. if( cleanEngineFuncs[n].type == type )
  4069. {
  4070. cleanEngineFuncs[n].cleanFunc = callback;
  4071. RELEASEEXCLUSIVE(engineRWLock);
  4072. return;
  4073. }
  4074. }
  4075. SEngineClean otc = {type, callback};
  4076. cleanEngineFuncs.PushLast(otc);
  4077. RELEASEEXCLUSIVE(engineRWLock);
  4078. }
  4079. // interface
  4080. void asCScriptEngine::SetModuleUserDataCleanupCallback(asCLEANMODULEFUNC_t callback)
  4081. {
  4082. cleanModuleFunc = callback;
  4083. }
  4084. // interface
  4085. void asCScriptEngine::SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback)
  4086. {
  4087. cleanContextFunc = callback;
  4088. }
  4089. // interface
  4090. void asCScriptEngine::SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback)
  4091. {
  4092. cleanFunctionFunc = callback;
  4093. }
  4094. // interface
  4095. void asCScriptEngine::SetObjectTypeUserDataCleanupCallback(asCLEANOBJECTTYPEFUNC_t callback, asPWORD type)
  4096. {
  4097. ACQUIREEXCLUSIVE(engineRWLock);
  4098. for( asUINT n = 0; n < cleanObjectTypeFuncs.GetLength(); n++ )
  4099. {
  4100. if( cleanObjectTypeFuncs[n].type == type )
  4101. {
  4102. cleanObjectTypeFuncs[n].cleanFunc = callback;
  4103. RELEASEEXCLUSIVE(engineRWLock);
  4104. return;
  4105. }
  4106. }
  4107. SObjTypeClean otc = {type, callback};
  4108. cleanObjectTypeFuncs.PushLast(otc);
  4109. RELEASEEXCLUSIVE(engineRWLock);
  4110. }
  4111. // Urho3D: modified for smaller executable size
  4112. asSFuncPtr::asSFuncPtr()
  4113. {
  4114. asMemClear(this, sizeof(asSFuncPtr));
  4115. }
  4116. asSFuncPtr::asSFuncPtr(asBYTE f)
  4117. {
  4118. asMemClear(this, sizeof(asSFuncPtr));
  4119. flag = f;
  4120. }
  4121. END_AS_NAMESPACE