as_scriptengine.cpp 170 KB

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