as_scriptengine.cpp 149 KB

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