as_scriptengine.cpp 177 KB

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