as_scriptengine.cpp 125 KB

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