as_builder.cpp 166 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2015 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. // Modified by Lasse Oorni for Urho3D
  24. //
  25. // as_builder.cpp
  26. //
  27. // This is the class that manages the compilation of the scripts
  28. //
  29. #include "as_config.h"
  30. #include "as_builder.h"
  31. #include "as_parser.h"
  32. #include "as_compiler.h"
  33. #include "as_tokendef.h"
  34. #include "as_string_util.h"
  35. #include "as_outputbuffer.h"
  36. #include "as_texts.h"
  37. #include "as_scriptobject.h"
  38. #include "as_debug.h"
  39. BEGIN_AS_NAMESPACE
  40. #ifndef AS_NO_COMPILER
  41. // asCSymbolTable template specializations for sGlobalVariableDescription entries
  42. template<>
  43. void asCSymbolTable<sGlobalVariableDescription>::GetKey(const sGlobalVariableDescription *entry, asSNameSpaceNamePair &key) const
  44. {
  45. asSNameSpace *ns = entry->ns;
  46. asCString name = entry->name;
  47. key = asSNameSpaceNamePair(ns, name);
  48. }
  49. // Comparator for exact variable search
  50. class asCCompGlobVarType : public asIFilter
  51. {
  52. public:
  53. const asCDataType &m_type;
  54. asCCompGlobVarType(const asCDataType &type) : m_type(type) {}
  55. bool operator()(const void *p) const
  56. {
  57. const sGlobalVariableDescription* desc = reinterpret_cast<const sGlobalVariableDescription*>(p);
  58. return desc->datatype == m_type;
  59. }
  60. private:
  61. // The assignment operator is required for MSVC9, otherwise it will complain that it is not possible to auto generate the operator
  62. asCCompGlobVarType &operator=(const asCCompGlobVarType &) {return *this;}
  63. };
  64. #endif
  65. asCBuilder::asCBuilder(asCScriptEngine *_engine, asCModule *_module)
  66. {
  67. this->engine = _engine;
  68. this->module = _module;
  69. silent = false;
  70. }
  71. asCBuilder::~asCBuilder()
  72. {
  73. #ifndef AS_NO_COMPILER
  74. asUINT n;
  75. // Free all functions
  76. for( n = 0; n < functions.GetLength(); n++ )
  77. {
  78. if( functions[n] )
  79. {
  80. if( functions[n]->node )
  81. functions[n]->node->Destroy(engine);
  82. asDELETE(functions[n],sFunctionDescription);
  83. }
  84. functions[n] = 0;
  85. }
  86. // Free all global variables
  87. asCSymbolTable<sGlobalVariableDescription>::iterator it = globVariables.List();
  88. while( it )
  89. {
  90. if( (*it)->declaredAtNode )
  91. (*it)->declaredAtNode->Destroy(engine);
  92. if( (*it)->initializationNode )
  93. (*it)->initializationNode->Destroy(engine);
  94. asDELETE((*it),sGlobalVariableDescription);
  95. it++;
  96. }
  97. globVariables.Clear();
  98. // Free all the loaded files
  99. for( n = 0; n < scripts.GetLength(); n++ )
  100. {
  101. if( scripts[n] )
  102. asDELETE(scripts[n],asCScriptCode);
  103. scripts[n] = 0;
  104. }
  105. // Free all class declarations
  106. for( n = 0; n < classDeclarations.GetLength(); n++ )
  107. {
  108. if( classDeclarations[n] )
  109. {
  110. if( classDeclarations[n]->node )
  111. classDeclarations[n]->node->Destroy(engine);
  112. asDELETE(classDeclarations[n],sClassDeclaration);
  113. classDeclarations[n] = 0;
  114. }
  115. }
  116. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  117. {
  118. if( interfaceDeclarations[n] )
  119. {
  120. if( interfaceDeclarations[n]->node )
  121. interfaceDeclarations[n]->node->Destroy(engine);
  122. asDELETE(interfaceDeclarations[n],sClassDeclaration);
  123. interfaceDeclarations[n] = 0;
  124. }
  125. }
  126. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  127. {
  128. if( namedTypeDeclarations[n] )
  129. {
  130. if( namedTypeDeclarations[n]->node )
  131. namedTypeDeclarations[n]->node->Destroy(engine);
  132. asDELETE(namedTypeDeclarations[n],sClassDeclaration);
  133. namedTypeDeclarations[n] = 0;
  134. }
  135. }
  136. for( n = 0; n < funcDefs.GetLength(); n++ )
  137. {
  138. if( funcDefs[n] )
  139. {
  140. if( funcDefs[n]->node )
  141. funcDefs[n]->node->Destroy(engine);
  142. asDELETE(funcDefs[n],sFuncDef);
  143. funcDefs[n] = 0;
  144. }
  145. }
  146. for( n = 0; n < mixinClasses.GetLength(); n++ )
  147. {
  148. if( mixinClasses[n] )
  149. {
  150. if( mixinClasses[n]->node )
  151. mixinClasses[n]->node->Destroy(engine);
  152. asDELETE(mixinClasses[n],sMixinClass);
  153. mixinClasses[n] = 0;
  154. }
  155. }
  156. #endif // AS_NO_COMPILER
  157. }
  158. void asCBuilder::Reset()
  159. {
  160. numErrors = 0;
  161. numWarnings = 0;
  162. engine->preMessage.isSet = false;
  163. #ifndef AS_NO_COMPILER
  164. // Clear the cache of known types
  165. hasCachedKnownTypes = false;
  166. knownTypes.EraseAll();
  167. #endif
  168. }
  169. #ifndef AS_NO_COMPILER
  170. int asCBuilder::AddCode(const char *name, const char *code, int codeLength, int lineOffset, int sectionIdx, bool makeCopy)
  171. {
  172. asCScriptCode *script = asNEW(asCScriptCode);
  173. if( script == 0 )
  174. return asOUT_OF_MEMORY;
  175. int r = script->SetCode(name, code, codeLength, makeCopy);
  176. if( r < 0 )
  177. {
  178. asDELETE(script, asCScriptCode);
  179. return r;
  180. }
  181. script->lineOffset = lineOffset;
  182. script->idx = sectionIdx;
  183. scripts.PushLast(script);
  184. return 0;
  185. }
  186. void asCBuilder::EvaluateTemplateInstances(asUINT startIdx, bool keepSilent)
  187. {
  188. // Backup the original message stream
  189. bool msgCallback = engine->msgCallback;
  190. asSSystemFunctionInterface msgCallbackFunc = engine->msgCallbackFunc;
  191. void *msgCallbackObj = engine->msgCallbackObj;
  192. // Set the new temporary message stream
  193. asCOutputBuffer outBuffer;
  194. if( keepSilent )
  195. engine->SetMessageCallback(asMETHOD(asCOutputBuffer, Callback), &outBuffer, asCALL_THISCALL);
  196. // Evaluate each of the template instances that have been created since the start of the build
  197. // TODO: This is not exactly correct, since another thread may have created template instances in parallel
  198. for( asUINT n = startIdx; n < engine->templateInstanceTypes.GetLength(); n++ )
  199. {
  200. bool dontGarbageCollect = false;
  201. asCObjectType *tmpl = engine->templateInstanceTypes[n];
  202. asCScriptFunction *callback = engine->scriptFunctions[tmpl->beh.templateCallback];
  203. if( callback && !engine->CallGlobalFunctionRetBool(tmpl, &dontGarbageCollect, callback->sysFuncIntf, callback) )
  204. {
  205. asCString sub = tmpl->templateSubTypes[0].Format(engine->nameSpaces[0]);
  206. for( asUINT n = 1; n < tmpl->templateSubTypes.GetLength(); n++ )
  207. {
  208. sub += ",";
  209. sub += tmpl->templateSubTypes[n].Format(engine->nameSpaces[0]);
  210. }
  211. asCString str;
  212. str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, tmpl->name.AddressOf(), sub.AddressOf());
  213. WriteError(tmpl->scriptSectionIdx >= 0 ? engine->scriptSectionNames[tmpl->scriptSectionIdx]->AddressOf() : "", str, tmpl->declaredAt&0xFFFFF, (tmpl->declaredAt>>20)&0xFFF);
  214. }
  215. else
  216. {
  217. // If the callback said this template instance won't be garbage collected then remove the flag
  218. if( dontGarbageCollect )
  219. tmpl->flags &= ~asOBJ_GC;
  220. }
  221. }
  222. // Restore message callback
  223. if( keepSilent )
  224. {
  225. engine->msgCallback = msgCallback;
  226. engine->msgCallbackFunc = msgCallbackFunc;
  227. engine->msgCallbackObj = msgCallbackObj;
  228. }
  229. }
  230. int asCBuilder::Build()
  231. {
  232. Reset();
  233. // The template callbacks must only be called after the subtypes have a known structure,
  234. // otherwise the callback may think it is not possible to create the template instance,
  235. // even though it is.
  236. // TODO: This flag shouldn't be set globally in the engine, as it would mean that another
  237. // thread requesting a template instance in parallel to the compilation wouldn't
  238. // evaluate the template instance.
  239. engine->deferValidationOfTemplateTypes = true;
  240. asUINT numTempl = (asUINT)engine->templateInstanceTypes.GetLength();
  241. ParseScripts();
  242. // Compile the types first
  243. CompileInterfaces();
  244. CompileClasses(numTempl);
  245. // Evaluate the template instances one last time, this time with error messages, as we know
  246. // all classes have been fully built and it is known which ones will need garbage collection.
  247. EvaluateTemplateInstances(numTempl, false);
  248. engine->deferValidationOfTemplateTypes = false;
  249. // Then the global variables. Here the variables declared with auto
  250. // will be resolved, so they can be accessed properly in the functions
  251. CompileGlobalVariables();
  252. // Finally the global functions and class methods
  253. CompileFunctions();
  254. // TODO: Attempt to reorder the initialization of global variables so that
  255. // they do not access other uninitialized global variables out-of-order
  256. // The builder needs to check for each of the global variable, what functions
  257. // that are accessed, and what global variables are access by these functions.
  258. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  259. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  260. if( numErrors > 0 )
  261. return asERROR;
  262. // Make sure something was compiled, otherwise return an error
  263. if( module->IsEmpty() )
  264. {
  265. WriteError(TXT_NOTHING_WAS_BUILT, 0, 0);
  266. return asERROR;
  267. }
  268. return asSUCCESS;
  269. }
  270. int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  271. {
  272. Reset();
  273. // Add the string to the script code
  274. asCScriptCode *script = asNEW(asCScriptCode);
  275. if( script == 0 )
  276. return asOUT_OF_MEMORY;
  277. script->SetCode(sectionName, code, true);
  278. script->lineOffset = lineOffset;
  279. script->idx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  280. scripts.PushLast(script);
  281. // Parse the string
  282. asCParser parser(this);
  283. if( parser.ParseScript(scripts[0]) < 0 )
  284. return asERROR;
  285. asCScriptNode *node = parser.GetScriptNode();
  286. // Make sure there is nothing else than the global variable in the script code
  287. if( node == 0 ||
  288. node->firstChild == 0 ||
  289. node->firstChild != node->lastChild ||
  290. node->firstChild->nodeType != snDeclaration )
  291. {
  292. WriteError(TXT_ONLY_ONE_VARIABLE_ALLOWED, script, 0);
  293. return asERROR;
  294. }
  295. node = node->firstChild;
  296. node->DisconnectParent();
  297. RegisterGlobalVar(node, script, module->defaultNamespace);
  298. CompileGlobalVariables();
  299. // It is possible that the global variable initialization included anonymous functions that must be compiled too
  300. for( asUINT n = 0; n < functions.GetLength(); n++ )
  301. {
  302. asCCompiler compiler(engine);
  303. asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
  304. int r = compiler.CompileFunction(this, functions[n]->script, func->parameterNames, functions[n]->node, func, 0);
  305. if( r < 0 )
  306. break;
  307. }
  308. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  309. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  310. // None of the functions should be added to the module if any error occurred,
  311. // or it was requested that the functions wouldn't be added to the scope
  312. if( numErrors > 0 )
  313. {
  314. for( asUINT n = 0; n < functions.GetLength(); n++ )
  315. {
  316. asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
  317. if( module->globalFunctions.GetIndex(func) >= 0 )
  318. {
  319. module->globalFunctions.Erase(module->globalFunctions.GetIndex(func));
  320. module->scriptFunctions.RemoveValue(func);
  321. func->ReleaseInternal();
  322. }
  323. }
  324. }
  325. if( numErrors > 0 )
  326. {
  327. // Remove the variable from the module, if it was registered
  328. if( globVariables.GetSize() > 0 )
  329. module->RemoveGlobalVar(module->GetGlobalVarCount()-1);
  330. return asERROR;
  331. }
  332. return 0;
  333. }
  334. #endif
  335. int asCBuilder::ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func)
  336. {
  337. int firstArgWithDefaultValue = -1;
  338. for( asUINT n = 0; n < func->defaultArgs.GetLength(); n++ )
  339. {
  340. if( func->defaultArgs[n] )
  341. firstArgWithDefaultValue = n;
  342. else if( firstArgWithDefaultValue >= 0 )
  343. {
  344. asCString str;
  345. str.Format(TXT_DEF_ARG_MISSING_IN_FUNC_s, func->GetDeclaration());
  346. WriteError(str, script, node);
  347. return asINVALID_DECLARATION;
  348. }
  349. }
  350. return 0;
  351. }
  352. #ifndef AS_NO_COMPILER
  353. // This function will verify if the newly created function will conflict another overload due to having
  354. // identical function arguments that are not default args, e.g: foo(int) and foo(int, int=0)
  355. int asCBuilder::CheckForConflictsDueToDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func, asCObjectType *objType)
  356. {
  357. // TODO: Implement for global functions too
  358. if( func->objectType == 0 || objType == 0 ) return 0;
  359. asCArray<int> funcs;
  360. GetObjectMethodDescriptions(func->name.AddressOf(), objType, funcs, false);
  361. for( asUINT n = 0; n < funcs.GetLength(); n++ )
  362. {
  363. asCScriptFunction *func2 = engine->scriptFunctions[funcs[n]];
  364. if( func == func2 )
  365. continue;
  366. if( func->IsReadOnly() != func2->IsReadOnly() )
  367. continue;
  368. bool match = true;
  369. asUINT p = 0;
  370. for( ; p < func->parameterTypes.GetLength() && p < func2->parameterTypes.GetLength(); p++ )
  371. {
  372. // Only verify until the first argument with default args
  373. if( (func->defaultArgs.GetLength() > p && func->defaultArgs[p]) ||
  374. (func2->defaultArgs.GetLength() > p && func2->defaultArgs[p]) )
  375. break;
  376. if( func->parameterTypes[p] != func2->parameterTypes[p] ||
  377. func->inOutFlags[p] != func2->inOutFlags[p] )
  378. {
  379. match = false;
  380. break;
  381. }
  382. }
  383. if( match )
  384. {
  385. if( !((p >= func->parameterTypes.GetLength() && p < func2->defaultArgs.GetLength() && func2->defaultArgs[p]) ||
  386. (p >= func2->parameterTypes.GetLength() && p < func->defaultArgs.GetLength() && func->defaultArgs[p])) )
  387. {
  388. // The argument lists match for the full length of the shorter, but the next
  389. // argument on the longer does not have a default arg so there is no conflict
  390. match = false;
  391. }
  392. }
  393. if( match )
  394. {
  395. WriteWarning(TXT_OVERLOAD_CONFLICTS_DUE_TO_DEFAULT_ARGS, script, node);
  396. WriteInfo(func->GetDeclaration(), script, node);
  397. WriteInfo(func2->GetDeclaration(), script, node);
  398. break;
  399. }
  400. }
  401. return 0;
  402. }
  403. int asCBuilder::CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asCScriptFunction **outFunc)
  404. {
  405. asASSERT(outFunc != 0);
  406. Reset();
  407. // Add the string to the script code
  408. asCScriptCode *script = asNEW(asCScriptCode);
  409. if( script == 0 )
  410. return asOUT_OF_MEMORY;
  411. script->SetCode(sectionName, code, true);
  412. script->lineOffset = lineOffset;
  413. script->idx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  414. scripts.PushLast(script);
  415. // Parse the string
  416. asCParser parser(this);
  417. if( parser.ParseScript(scripts[0]) < 0 )
  418. return asERROR;
  419. asCScriptNode *node = parser.GetScriptNode();
  420. // Make sure there is nothing else than the function in the script code
  421. if( node == 0 ||
  422. node->firstChild == 0 ||
  423. node->firstChild != node->lastChild ||
  424. node->firstChild->nodeType != snFunction )
  425. {
  426. WriteError(TXT_ONLY_ONE_FUNCTION_ALLOWED, script, 0);
  427. return asERROR;
  428. }
  429. // Find the function node
  430. node = node->firstChild;
  431. // Create the function
  432. bool isConstructor, isDestructor, isPrivate, isProtected, isFinal, isOverride, isShared;
  433. asCScriptFunction *func = asNEW(asCScriptFunction)(engine, compileFlags & asCOMP_ADD_TO_MODULE ? module : 0, asFUNC_SCRIPT);
  434. if( func == 0 )
  435. return asOUT_OF_MEMORY;
  436. GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate, isProtected, isFinal, isOverride, isShared, module->defaultNamespace);
  437. func->id = engine->GetNextScriptFunctionId();
  438. func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
  439. int row, col;
  440. scripts[0]->ConvertPosToRowCol(node->tokenPos, &row, &col);
  441. func->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20);
  442. func->nameSpace = module->defaultNamespace;
  443. // Make sure the default args are declared correctly
  444. int r = ValidateDefaultArgs(script, node, func);
  445. if( r < 0 )
  446. {
  447. func->ReleaseInternal();
  448. return asERROR;
  449. }
  450. // Tell the engine that the function exists already so the compiler can access it
  451. if( compileFlags & asCOMP_ADD_TO_MODULE )
  452. {
  453. int r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->defaultNamespace);
  454. if( r < 0 )
  455. {
  456. func->ReleaseInternal();
  457. return asERROR;
  458. }
  459. module->globalFunctions.Put(func);
  460. module->AddScriptFunction(func);
  461. }
  462. else
  463. engine->AddScriptFunction(func);
  464. // Fill in the function info for the builder too
  465. node->DisconnectParent();
  466. sFunctionDescription *funcDesc = asNEW(sFunctionDescription);
  467. if( funcDesc == 0 )
  468. {
  469. func->ReleaseInternal();
  470. return asOUT_OF_MEMORY;
  471. }
  472. functions.PushLast(funcDesc);
  473. funcDesc->script = scripts[0];
  474. funcDesc->node = node;
  475. funcDesc->name = func->name;
  476. funcDesc->funcId = func->id;
  477. funcDesc->paramNames = func->parameterNames;
  478. funcDesc->isExistingShared = false;
  479. // This must be done in a loop, as it is possible that additional functions get declared as lambda's in the code
  480. for( asUINT n = 0; n < functions.GetLength(); n++ )
  481. {
  482. asCCompiler compiler(engine);
  483. asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
  484. int r = compiler.CompileFunction(this, functions[n]->script, func->parameterNames, functions[n]->node, func, 0);
  485. if( r < 0 )
  486. break;
  487. }
  488. if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
  489. WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
  490. // None of the functions should be added to the module if any error occurred,
  491. // or it was requested that the functions wouldn't be added to the scope
  492. if( !(compileFlags & asCOMP_ADD_TO_MODULE) || numErrors > 0 )
  493. {
  494. for( asUINT n = 0; n < functions.GetLength(); n++ )
  495. {
  496. asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
  497. if( module->globalFunctions.GetIndex(func) >= 0 )
  498. {
  499. module->globalFunctions.Erase(module->globalFunctions.GetIndex(func));
  500. module->scriptFunctions.RemoveValue(func);
  501. func->ReleaseInternal();
  502. }
  503. }
  504. }
  505. if( numErrors > 0 )
  506. {
  507. // Release the function pointer that would otherwise be returned if no errors occured
  508. func->ReleaseInternal();
  509. return asERROR;
  510. }
  511. // Return the function
  512. *outFunc = func;
  513. return asSUCCESS;
  514. }
  515. void asCBuilder::ParseScripts()
  516. {
  517. TimeIt("asCBuilder::ParseScripts");
  518. asCArray<asCParser*> parsers((int)scripts.GetLength());
  519. // Parse all the files as if they were one
  520. asUINT n = 0;
  521. for( n = 0; n < scripts.GetLength(); n++ )
  522. {
  523. asCParser *parser = asNEW(asCParser)(this);
  524. if( parser != 0 )
  525. {
  526. parsers.PushLast(parser);
  527. // Parse the script file
  528. parser->ParseScript(scripts[n]);
  529. }
  530. }
  531. if( numErrors == 0 )
  532. {
  533. // Find all type declarations
  534. for( n = 0; n < scripts.GetLength(); n++ )
  535. {
  536. asCScriptNode *node = parsers[n]->GetScriptNode();
  537. RegisterTypesFromScript(node, scripts[n], engine->nameSpaces[0]);
  538. }
  539. // Register the complete function definitions
  540. for( n = 0; n < funcDefs.GetLength(); n++ )
  541. CompleteFuncDef(funcDefs[n]);
  542. // Register script methods found in the interfaces
  543. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  544. {
  545. sClassDeclaration *decl = interfaceDeclarations[n];
  546. asCScriptNode *node = decl->node->firstChild->next;
  547. // Skip list of inherited interfaces
  548. while( node && node->nodeType == snIdentifier )
  549. node = node->next;
  550. while( node )
  551. {
  552. asCScriptNode *next = node->next;
  553. if( node->nodeType == snFunction )
  554. {
  555. node->DisconnectParent();
  556. RegisterScriptFunctionFromNode(node, decl->script, decl->objType, true, false, 0, decl->isExistingShared);
  557. }
  558. else if( node->nodeType == snVirtualProperty )
  559. {
  560. node->DisconnectParent();
  561. RegisterVirtualProperty(node, decl->script, decl->objType, true, false, 0, decl->isExistingShared);
  562. }
  563. node = next;
  564. }
  565. }
  566. // Register script methods found in the classes
  567. for( n = 0; n < classDeclarations.GetLength(); n++ )
  568. {
  569. sClassDeclaration *decl = classDeclarations[n];
  570. asCScriptNode *node = decl->node->firstChild->next;
  571. // Skip list of classes and interfaces
  572. while( node && node->nodeType == snIdentifier )
  573. node = node->next;
  574. while( node )
  575. {
  576. asCScriptNode *next = node->next;
  577. if( node->nodeType == snFunction )
  578. {
  579. node->DisconnectParent();
  580. RegisterScriptFunctionFromNode(node, decl->script, decl->objType, false, false, 0, decl->isExistingShared);
  581. }
  582. else if( node->nodeType == snVirtualProperty )
  583. {
  584. node->DisconnectParent();
  585. RegisterVirtualProperty(node, decl->script, decl->objType, false, false, 0, decl->isExistingShared);
  586. }
  587. node = next;
  588. }
  589. // Make sure the default factory & constructor exists for classes
  590. if( decl->objType->beh.construct == engine->scriptTypeBehaviours.beh.construct )
  591. {
  592. if( decl->objType->beh.constructors.GetLength() == 1 || engine->ep.alwaysImplDefaultConstruct )
  593. {
  594. AddDefaultConstructor(decl->objType, decl->script);
  595. }
  596. else
  597. {
  598. // As the class has another constructor we shouldn't provide the default constructor
  599. if( decl->objType->beh.construct )
  600. {
  601. engine->scriptFunctions[decl->objType->beh.construct]->ReleaseInternal();
  602. decl->objType->beh.construct = 0;
  603. decl->objType->beh.constructors.RemoveIndex(0);
  604. }
  605. if( decl->objType->beh.factory )
  606. {
  607. engine->scriptFunctions[decl->objType->beh.factory]->ReleaseInternal();
  608. decl->objType->beh.factory = 0;
  609. decl->objType->beh.factories.RemoveIndex(0);
  610. }
  611. // Only remove the opAssign method if the script hasn't provided one
  612. if( decl->objType->beh.copy == engine->scriptTypeBehaviours.beh.copy )
  613. {
  614. engine->scriptFunctions[decl->objType->beh.copy]->ReleaseInternal();
  615. decl->objType->beh.copy = 0;
  616. }
  617. }
  618. }
  619. }
  620. // Find other global nodes
  621. for( n = 0; n < scripts.GetLength(); n++ )
  622. {
  623. // Find other global nodes
  624. asCScriptNode *node = parsers[n]->GetScriptNode();
  625. RegisterNonTypesFromScript(node, scripts[n], engine->nameSpaces[0]);
  626. }
  627. }
  628. for( n = 0; n < parsers.GetLength(); n++ )
  629. {
  630. asDELETE(parsers[n],asCParser);
  631. }
  632. }
  633. void asCBuilder::RegisterTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns)
  634. {
  635. asASSERT(node->nodeType == snScript);
  636. // Find structure definitions first
  637. node = node->firstChild;
  638. while( node )
  639. {
  640. asCScriptNode *next = node->next;
  641. if( node->nodeType == snNamespace )
  642. {
  643. // Recursively register the entities defined in the namespace
  644. asCString nsName;
  645. nsName.Assign(&script->code[node->firstChild->tokenPos], node->firstChild->tokenLength);
  646. if( ns->name != "" )
  647. nsName = ns->name + "::" + nsName;
  648. asSNameSpace *nsChild = engine->AddNameSpace(nsName.AddressOf());
  649. RegisterTypesFromScript(node->lastChild, script, nsChild);
  650. }
  651. else
  652. {
  653. if( node->nodeType == snClass )
  654. {
  655. node->DisconnectParent();
  656. RegisterClass(node, script, ns);
  657. }
  658. else if( node->nodeType == snInterface )
  659. {
  660. node->DisconnectParent();
  661. RegisterInterface(node, script, ns);
  662. }
  663. else if( node->nodeType == snEnum )
  664. {
  665. node->DisconnectParent();
  666. RegisterEnum(node, script, ns);
  667. }
  668. else if( node->nodeType == snTypedef )
  669. {
  670. node->DisconnectParent();
  671. RegisterTypedef(node, script, ns);
  672. }
  673. else if( node->nodeType == snFuncDef )
  674. {
  675. node->DisconnectParent();
  676. RegisterFuncDef(node, script, ns);
  677. }
  678. else if( node->nodeType == snMixin )
  679. {
  680. node->DisconnectParent();
  681. RegisterMixinClass(node, script, ns);
  682. }
  683. }
  684. node = next;
  685. }
  686. }
  687. void asCBuilder::RegisterNonTypesFromScript(asCScriptNode *node, asCScriptCode *script, asSNameSpace *ns)
  688. {
  689. node = node->firstChild;
  690. while( node )
  691. {
  692. asCScriptNode *next = node->next;
  693. if( node->nodeType == snNamespace )
  694. {
  695. // Determine the name of the namespace
  696. asCString nsName;
  697. nsName.Assign(&script->code[node->firstChild->tokenPos], node->firstChild->tokenLength);
  698. if( ns->name != "" )
  699. nsName = ns->name + "::" + nsName;
  700. // Declare the namespace, then add the entities
  701. asSNameSpace *nsChild = engine->AddNameSpace(nsName.AddressOf());
  702. RegisterNonTypesFromScript(node->lastChild, script, nsChild);
  703. }
  704. else
  705. {
  706. node->DisconnectParent();
  707. if( node->nodeType == snFunction )
  708. RegisterScriptFunctionFromNode(node, script, 0, false, true, ns);
  709. else if( node->nodeType == snDeclaration )
  710. RegisterGlobalVar(node, script, ns);
  711. else if( node->nodeType == snVirtualProperty )
  712. RegisterVirtualProperty(node, script, 0, false, true, ns);
  713. else if( node->nodeType == snImport )
  714. RegisterImportedFunction(module->GetNextImportedFunctionId(), node, script, ns);
  715. else
  716. {
  717. // Unused script node
  718. int r, c;
  719. script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  720. WriteWarning(script->name, TXT_UNUSED_SCRIPT_NODE, r, c);
  721. node->Destroy(engine);
  722. }
  723. }
  724. node = next;
  725. }
  726. }
  727. void asCBuilder::CompileFunctions()
  728. {
  729. // Compile each function
  730. for( asUINT n = 0; n < functions.GetLength(); n++ )
  731. {
  732. sFunctionDescription *current = functions[n];
  733. if( current == 0 ) continue;
  734. // Don't compile the function again if it was an existing shared function
  735. if( current->isExistingShared ) continue;
  736. asCCompiler compiler(engine);
  737. asCScriptFunction *func = engine->scriptFunctions[current->funcId];
  738. // Find the class declaration for constructors
  739. sClassDeclaration *classDecl = 0;
  740. if( current->objType && current->name == current->objType->name )
  741. {
  742. for( asUINT n = 0; n < classDeclarations.GetLength(); n++ )
  743. {
  744. if( classDeclarations[n]->objType == current->objType )
  745. {
  746. classDecl = classDeclarations[n];
  747. break;
  748. }
  749. }
  750. asASSERT( classDecl );
  751. }
  752. if( current->node )
  753. {
  754. int r, c;
  755. current->script->ConvertPosToRowCol(current->node->tokenPos, &r, &c);
  756. asCString str = func->GetDeclarationStr();
  757. str.Format(TXT_COMPILING_s, str.AddressOf());
  758. WriteInfo(current->script->name, str, r, c, true);
  759. // When compiling a constructor need to pass the class declaration for member initializations
  760. compiler.CompileFunction(this, current->script, current->paramNames, current->node, func, classDecl);
  761. engine->preMessage.isSet = false;
  762. }
  763. else if( current->objType && current->name == current->objType->name )
  764. {
  765. asCScriptNode *node = classDecl->node;
  766. int r = 0, c = 0;
  767. if( node )
  768. current->script->ConvertPosToRowCol(node->tokenPos, &r, &c);
  769. asCString str = func->GetDeclarationStr();
  770. str.Format(TXT_COMPILING_s, str.AddressOf());
  771. WriteInfo(current->script->name, str, r, c, true);
  772. // This is the default constructor that is generated
  773. // automatically if not implemented by the user.
  774. compiler.CompileDefaultConstructor(this, current->script, node, func, classDecl);
  775. engine->preMessage.isSet = false;
  776. }
  777. else
  778. {
  779. asASSERT( false );
  780. }
  781. }
  782. }
  783. #endif
  784. // Called from module and engine
  785. int asCBuilder::ParseDataType(const char *datatype, asCDataType *result, asSNameSpace *implicitNamespace, bool isReturnType)
  786. {
  787. Reset();
  788. asCScriptCode source;
  789. source.SetCode("", datatype, true);
  790. asCParser parser(this);
  791. int r = parser.ParseDataType(&source, isReturnType);
  792. if( r < 0 )
  793. return asINVALID_TYPE;
  794. // Get data type and property name
  795. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  796. *result = CreateDataTypeFromNode(dataType, &source, implicitNamespace, true);
  797. if( isReturnType )
  798. *result = ModifyDataTypeFromNode(*result, dataType->next, &source, 0, 0);
  799. if( numErrors > 0 )
  800. return asINVALID_TYPE;
  801. return asSUCCESS;
  802. }
  803. int asCBuilder::ParseTemplateDecl(const char *decl, asCString *name, asCArray<asCString> &subtypeNames)
  804. {
  805. Reset();
  806. asCScriptCode source;
  807. source.SetCode("", decl, true);
  808. asCParser parser(this);
  809. int r = parser.ParseTemplateDecl(&source);
  810. if( r < 0 )
  811. return asINVALID_TYPE;
  812. // Get the template name and subtype names
  813. asCScriptNode *node = parser.GetScriptNode()->firstChild;
  814. name->Assign(&decl[node->tokenPos], node->tokenLength);
  815. while( (node = node->next) != 0 )
  816. {
  817. asCString subtypeName;
  818. subtypeName.Assign(&decl[node->tokenPos], node->tokenLength);
  819. subtypeNames.PushLast(subtypeName);
  820. }
  821. // TODO: template: check for name conflicts
  822. if( numErrors > 0 )
  823. return asINVALID_DECLARATION;
  824. return asSUCCESS;
  825. }
  826. int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &name, asCDataType &type, asSNameSpace *ns)
  827. {
  828. // Either datatype or namespace must be informed
  829. asASSERT( dt || ns );
  830. Reset();
  831. if( dt )
  832. {
  833. // Verify that the object type exist
  834. if( dt->GetObjectType() == 0 )
  835. return asINVALID_OBJECT;
  836. }
  837. // Check property declaration and type
  838. asCScriptCode source;
  839. source.SetCode(TXT_PROPERTY, decl, true);
  840. asCParser parser(this);
  841. int r = parser.ParsePropertyDeclaration(&source);
  842. if( r < 0 )
  843. return asINVALID_DECLARATION;
  844. // Get data type
  845. asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
  846. // Check if the property is declared 'by reference'
  847. bool isReference = (dataType->next->tokenType == ttAmp);
  848. // Get the name of the property
  849. asCScriptNode *nameNode = isReference ? dataType->next->next : dataType->next;
  850. // If an object property is registered, then use the
  851. // object's namespace, otherwise use the specified namespace
  852. type = CreateDataTypeFromNode(dataType, &source, dt ? dt->GetObjectType()->nameSpace : ns);
  853. name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength);
  854. type.MakeReference(isReference);
  855. // Validate that the type really can be a registered property
  856. // We cannot use CanBeInstantiated, as it is allowed to register
  857. // properties of type that cannot otherwise be instantiated
  858. if( type.GetFuncDef() && !type.IsObjectHandle() )
  859. {
  860. // Function definitions must always be handles
  861. return asINVALID_DECLARATION;
  862. }
  863. // Verify property name
  864. if( dt )
  865. {
  866. if( CheckNameConflictMember(dt->GetObjectType(), name.AddressOf(), nameNode, &source, true) < 0 )
  867. return asNAME_TAKEN;
  868. }
  869. else
  870. {
  871. if( CheckNameConflict(name.AddressOf(), nameNode, &source, ns) < 0 )
  872. return asNAME_TAKEN;
  873. }
  874. if( numErrors > 0 )
  875. return asINVALID_DECLARATION;
  876. return asSUCCESS;
  877. }
  878. #ifndef AS_NO_COMPILER
  879. asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *prop)
  880. {
  881. asASSERT(obj.GetObjectType() != 0);
  882. // TODO: optimize: Improve linear search
  883. asCArray<asCObjectProperty *> &props = obj.GetObjectType()->properties;
  884. for( asUINT n = 0; n < props.GetLength(); n++ )
  885. {
  886. if( props[n]->name == prop )
  887. {
  888. if( module->accessMask & props[n]->accessMask )
  889. return props[n];
  890. else
  891. return 0;
  892. }
  893. }
  894. return 0;
  895. }
  896. #endif
  897. bool asCBuilder::DoesGlobalPropertyExist(const char *prop, asSNameSpace *ns, asCGlobalProperty **outProp, sGlobalVariableDescription **outDesc, bool *isAppProp)
  898. {
  899. if( outProp ) *outProp = 0;
  900. if( outDesc ) *outDesc = 0;
  901. if( isAppProp ) *isAppProp = false;
  902. // Check application registered properties
  903. asCString name(prop);
  904. asCGlobalProperty *globProp = engine->registeredGlobalProps.GetFirst(ns, name);
  905. if( globProp )
  906. {
  907. if( isAppProp ) *isAppProp = true;
  908. if( outProp ) *outProp = globProp;
  909. return true;
  910. }
  911. #ifndef AS_NO_COMPILER
  912. // Check properties being compiled now
  913. sGlobalVariableDescription* desc = globVariables.GetFirst(ns, prop);
  914. if( desc && !desc->isEnumValue )
  915. {
  916. if( outProp ) *outProp = desc->property;
  917. if( outDesc ) *outDesc = desc;
  918. return true;
  919. }
  920. #endif
  921. // Check previously compiled global variables
  922. if( module )
  923. {
  924. globProp = module->scriptGlobals.GetFirst(ns, prop);
  925. if( globProp )
  926. {
  927. if( outProp ) *outProp = globProp;
  928. return true;
  929. }
  930. }
  931. return false;
  932. }
  933. asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace *ns, bool *isCompiled, bool *isPureConstant, asQWORD *constantValue, bool *isAppProp)
  934. {
  935. if( isCompiled ) *isCompiled = true;
  936. if( isPureConstant ) *isPureConstant = false;
  937. if( isAppProp ) *isAppProp = false;
  938. if( constantValue ) *constantValue = 0;
  939. asCGlobalProperty *globProp = 0;
  940. sGlobalVariableDescription *globDesc = 0;
  941. if( DoesGlobalPropertyExist(prop, ns, &globProp, &globDesc, isAppProp) )
  942. {
  943. #ifndef AS_NO_COMPILER
  944. if( globDesc )
  945. {
  946. // The property was declared in this build call, check if it has been compiled successfully already
  947. if( isCompiled ) *isCompiled = globDesc->isCompiled;
  948. if( isPureConstant ) *isPureConstant = globDesc->isPureConstant;
  949. if( constantValue ) *constantValue = globDesc->constantValue;
  950. }
  951. else
  952. #endif
  953. if( isAppProp )
  954. {
  955. // Don't return the property if the module doesn't have access to it
  956. if( !(module->accessMask & globProp->accessMask) )
  957. globProp = 0;
  958. }
  959. return globProp;
  960. }
  961. return 0;
  962. }
  963. int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern)
  964. {
  965. asASSERT( objType || ns );
  966. // TODO: Can't we use GetParsedFunctionDetails to do most of what is done in this function?
  967. Reset();
  968. asCScriptCode source;
  969. source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);
  970. asCParser parser(this);
  971. int r = parser.ParseFunctionDefinition(&source, listPattern != 0);
  972. if( r < 0 )
  973. return asINVALID_DECLARATION;
  974. asCScriptNode *node = parser.GetScriptNode();
  975. // Determine scope
  976. asCScriptNode *n = node->firstChild->next->next;
  977. asCString scope = GetScopeFromNode(n, &source, &n);
  978. if( scope == "::" )
  979. func->nameSpace = engine->nameSpaces[0];
  980. else
  981. func->nameSpace = engine->FindNameSpace(scope.AddressOf());
  982. if( func->nameSpace == 0 )
  983. return asINVALID_DECLARATION;
  984. // Find name
  985. func->name.Assign(&source.code[n->tokenPos], n->tokenLength);
  986. // Initialize a script function object for registration
  987. bool autoHandle;
  988. // Scoped reference types are allowed to use handle when returned from application functions
  989. func->returnType = CreateDataTypeFromNode(node->firstChild, &source, objType ? objType->nameSpace : ns, true, objType);
  990. func->returnType = ModifyDataTypeFromNode(func->returnType, node->firstChild->next, &source, 0, &autoHandle);
  991. if( autoHandle && (!func->returnType.IsObjectHandle() || func->returnType.IsReference()) )
  992. return asINVALID_DECLARATION;
  993. if( returnAutoHandle ) *returnAutoHandle = autoHandle;
  994. // Reference types cannot be returned by value from system functions
  995. if( isSystemFunction &&
  996. (func->returnType.GetObjectType() &&
  997. (func->returnType.GetObjectType()->flags & asOBJ_REF)) &&
  998. !(func->returnType.IsReference() ||
  999. func->returnType.IsObjectHandle()) )
  1000. return asINVALID_DECLARATION;
  1001. // Count number of parameters
  1002. int paramCount = 0;
  1003. asCScriptNode *paramList = n->next;
  1004. n = paramList->firstChild;
  1005. while( n )
  1006. {
  1007. paramCount++;
  1008. n = n->next->next;
  1009. if( n && n->nodeType == snIdentifier )
  1010. n = n->next;
  1011. if( n && n->nodeType == snExpression )
  1012. n = n->next;
  1013. }
  1014. // Preallocate memory
  1015. func->parameterTypes.Allocate(paramCount, false);
  1016. func->parameterNames.SetLength(paramCount);
  1017. func->inOutFlags.Allocate(paramCount, false);
  1018. func->defaultArgs.Allocate(paramCount, false);
  1019. if( paramAutoHandles ) paramAutoHandles->Allocate(paramCount, false);
  1020. n = paramList->firstChild;
  1021. asUINT index = 0;
  1022. while( n )
  1023. {
  1024. asETypeModifiers inOutFlags;
  1025. asCDataType type = CreateDataTypeFromNode(n, &source, objType ? objType->nameSpace : ns, false, objType);
  1026. type = ModifyDataTypeFromNode(type, n->next, &source, &inOutFlags, &autoHandle);
  1027. // Reference types cannot be passed by value to system functions
  1028. if( isSystemFunction &&
  1029. (type.GetObjectType() &&
  1030. (type.GetObjectType()->flags & asOBJ_REF)) &&
  1031. !(type.IsReference() ||
  1032. type.IsObjectHandle()) )
  1033. return asINVALID_DECLARATION;
  1034. // Store the parameter type
  1035. func->parameterTypes.PushLast(type);
  1036. func->inOutFlags.PushLast(inOutFlags);
  1037. // Don't permit void parameters
  1038. if( type.GetTokenType() == ttVoid )
  1039. return asINVALID_DECLARATION;
  1040. if( autoHandle && (!type.IsObjectHandle() || type.IsReference()) )
  1041. return asINVALID_DECLARATION;
  1042. if( paramAutoHandles ) paramAutoHandles->PushLast(autoHandle);
  1043. // Make sure that var type parameters are references
  1044. if( type.GetTokenType() == ttQuestion &&
  1045. !type.IsReference() )
  1046. return asINVALID_DECLARATION;
  1047. // Move to next parameter
  1048. n = n->next->next;
  1049. if( n && n->nodeType == snIdentifier )
  1050. {
  1051. func->parameterNames[index] = asCString(&source.code[n->tokenPos], n->tokenLength);
  1052. n = n->next;
  1053. }
  1054. ++index;
  1055. if( n && n->nodeType == snExpression )
  1056. {
  1057. // Strip out white space and comments to better share the string
  1058. asCString *defaultArgStr = asNEW(asCString);
  1059. if( defaultArgStr )
  1060. {
  1061. *defaultArgStr = GetCleanExpressionString(n, &source);
  1062. func->defaultArgs.PushLast(defaultArgStr);
  1063. }
  1064. n = n->next;
  1065. }
  1066. else
  1067. func->defaultArgs.PushLast(0);
  1068. }
  1069. // Set the read-only flag if const is declared after parameter list
  1070. n = paramList->next;
  1071. if( n && n->nodeType == snUndefined && n->tokenType == ttConst )
  1072. {
  1073. if( objType == 0 )
  1074. return asINVALID_DECLARATION;
  1075. func->isReadOnly = true;
  1076. n = n->next;
  1077. }
  1078. else
  1079. func->isReadOnly = false;
  1080. // If the caller expects a list pattern, check for the existence, else report an error if not
  1081. if( listPattern )
  1082. {
  1083. if( n == 0 || n->nodeType != snListPattern )
  1084. return asINVALID_DECLARATION;
  1085. else
  1086. {
  1087. *listPattern = n;
  1088. n->DisconnectParent();
  1089. }
  1090. }
  1091. else
  1092. {
  1093. if( n )
  1094. return asINVALID_DECLARATION;
  1095. }
  1096. // Make sure the default args are declared correctly
  1097. ValidateDefaultArgs(&source, node, func);
  1098. if( numErrors > 0 || numWarnings > 0 )
  1099. return asINVALID_DECLARATION;
  1100. return 0;
  1101. }
  1102. int asCBuilder::ParseVariableDeclaration(const char *decl, asSNameSpace *implicitNamespace, asCString &outName, asSNameSpace *&outNamespace, asCDataType &outDt)
  1103. {
  1104. Reset();
  1105. asCScriptCode source;
  1106. source.SetCode(TXT_VARIABLE_DECL, decl, true);
  1107. asCParser parser(this);
  1108. int r = parser.ParsePropertyDeclaration(&source);
  1109. if( r < 0 )
  1110. return asINVALID_DECLARATION;
  1111. asCScriptNode *node = parser.GetScriptNode();
  1112. // Determine the scope from declaration
  1113. asCScriptNode *n = node->firstChild->next;
  1114. outNamespace = GetNameSpaceFromNode(n, &source, implicitNamespace, &n);
  1115. if( outNamespace == 0 )
  1116. return asINVALID_DECLARATION;
  1117. // Find name
  1118. outName.Assign(&source.code[n->tokenPos], n->tokenLength);
  1119. // Initialize a script variable object for registration
  1120. outDt = CreateDataTypeFromNode(node->firstChild, &source, implicitNamespace);
  1121. if( numErrors > 0 || numWarnings > 0 )
  1122. return asINVALID_DECLARATION;
  1123. return 0;
  1124. }
  1125. int asCBuilder::CheckNameConflictMember(asCObjectType *t, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty)
  1126. {
  1127. // It's not necessary to check against object types
  1128. // TODO: optimize: Improve linear search
  1129. asCArray<asCObjectProperty *> &props = t->properties;
  1130. for( asUINT n = 0; n < props.GetLength(); n++ )
  1131. {
  1132. if( props[n]->name == name )
  1133. {
  1134. if( code )
  1135. {
  1136. asCString str;
  1137. str.Format(TXT_NAME_CONFLICT_s_OBJ_PROPERTY, name);
  1138. WriteError(str, code, node);
  1139. }
  1140. return -1;
  1141. }
  1142. }
  1143. // Property names must be checked against method names
  1144. if( isProperty )
  1145. {
  1146. asCArray<int> methods = t->methods;
  1147. for( asUINT n = 0; n < methods.GetLength(); n++ )
  1148. {
  1149. if( engine->scriptFunctions[methods[n]]->name == name )
  1150. {
  1151. if( code )
  1152. {
  1153. asCString str;
  1154. str.Format(TXT_NAME_CONFLICT_s_METHOD, name);
  1155. WriteError(str, code, node);
  1156. }
  1157. return -1;
  1158. }
  1159. }
  1160. }
  1161. return 0;
  1162. }
  1163. int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns)
  1164. {
  1165. // Check against registered object types
  1166. // TODO: Must check against registered funcdefs too
  1167. if( engine->GetRegisteredObjectType(name, ns) != 0 )
  1168. {
  1169. if( code )
  1170. {
  1171. asCString str;
  1172. str.Format(TXT_NAME_CONFLICT_s_EXTENDED_TYPE, name);
  1173. WriteError(str, code, node);
  1174. }
  1175. return -1;
  1176. }
  1177. // Check against global properties
  1178. if( DoesGlobalPropertyExist(name, ns) )
  1179. {
  1180. if( code )
  1181. {
  1182. asCString str;
  1183. str.Format(TXT_NAME_CONFLICT_s_GLOBAL_PROPERTY, name);
  1184. WriteError(str, code, node);
  1185. }
  1186. return -1;
  1187. }
  1188. // TODO: Property names must be checked against function names
  1189. #ifndef AS_NO_COMPILER
  1190. // Check against class types
  1191. asUINT n;
  1192. for( n = 0; n < classDeclarations.GetLength(); n++ )
  1193. {
  1194. if( classDeclarations[n]->name == name &&
  1195. classDeclarations[n]->objType->nameSpace == ns )
  1196. {
  1197. if( code )
  1198. {
  1199. asCString str;
  1200. str.Format(TXT_NAME_CONFLICT_s_STRUCT, name);
  1201. WriteError(str, code, node);
  1202. }
  1203. return -1;
  1204. }
  1205. }
  1206. // Check against named types
  1207. for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
  1208. {
  1209. if( namedTypeDeclarations[n]->name == name &&
  1210. namedTypeDeclarations[n]->objType->nameSpace == ns )
  1211. {
  1212. if( code )
  1213. {
  1214. asCString str;
  1215. str.Format(TXT_NAME_CONFLICT_s_IS_NAMED_TYPE, name);
  1216. WriteError(str, code, node);
  1217. }
  1218. return -1;
  1219. }
  1220. }
  1221. // Must check for name conflicts with funcdefs
  1222. for( n = 0; n < funcDefs.GetLength(); n++ )
  1223. {
  1224. if( funcDefs[n]->name == name &&
  1225. module->funcDefs[funcDefs[n]->idx]->nameSpace == ns )
  1226. {
  1227. if( code )
  1228. {
  1229. asCString str;
  1230. str.Format(TXT_NAME_CONFLICT_s_IS_FUNCDEF, name);
  1231. WriteError(str, code, node);
  1232. }
  1233. return -1;
  1234. }
  1235. }
  1236. // Check against mixin classes
  1237. if( GetMixinClass(name, ns) )
  1238. {
  1239. if( code )
  1240. {
  1241. asCString str;
  1242. str.Format(TXT_NAME_CONFLICT_s_IS_MIXIN, name);
  1243. WriteError(str, code, node);
  1244. }
  1245. return -1;
  1246. }
  1247. #endif
  1248. return 0;
  1249. }
  1250. #ifndef AS_NO_COMPILER
  1251. sMixinClass *asCBuilder::GetMixinClass(const char *name, asSNameSpace *ns)
  1252. {
  1253. for( asUINT n = 0; n < mixinClasses.GetLength(); n++ )
  1254. if( mixinClasses[n]->name == name &&
  1255. mixinClasses[n]->ns == ns )
  1256. return mixinClasses[n];
  1257. return 0;
  1258. }
  1259. int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1260. {
  1261. // TODO: redesign: Allow funcdefs to be explicitly declared as 'shared'. In this case
  1262. // an error should be given if any of the arguments/return type is not
  1263. // shared.
  1264. // Find the name
  1265. asASSERT( node->firstChild->nodeType == snDataType );
  1266. asCScriptNode *n = node->firstChild->next->next;
  1267. asCString name;
  1268. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  1269. // Check for name conflict with other types
  1270. int r = CheckNameConflict(name.AddressOf(), node, file, ns);
  1271. if( asSUCCESS != r )
  1272. {
  1273. node->Destroy(engine);
  1274. return r;
  1275. }
  1276. // The function definition should be stored as a asCScriptFunction so that the application
  1277. // can use the asIScriptFunction interface to enumerate the return type and parameters
  1278. // The return type and parameter types aren't determined in this function. A second pass is
  1279. // necessary after all type declarations have been identified. The second pass is implemented
  1280. // in CompleteFuncDef().
  1281. sFuncDef *fd = asNEW(sFuncDef);
  1282. if( fd == 0 )
  1283. {
  1284. node->Destroy(engine);
  1285. return asOUT_OF_MEMORY;
  1286. }
  1287. fd->name = name;
  1288. fd->node = node;
  1289. fd->script = file;
  1290. fd->idx = module->AddFuncDef(name, ns);
  1291. funcDefs.PushLast(fd);
  1292. return 0;
  1293. }
  1294. void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
  1295. {
  1296. asCArray<asCString *> defaultArgs;
  1297. bool isConstMethod;
  1298. bool isConstructor;
  1299. bool isDestructor;
  1300. bool isProtected;
  1301. bool isPrivate;
  1302. bool isOverride;
  1303. bool isFinal;
  1304. bool isShared;
  1305. asCScriptFunction *func = module->funcDefs[funcDef->idx];
  1306. asASSERT( func );
  1307. // TODO: It should be possible to declare funcdef as shared. In this case a compiler error will be given if any of the types it uses are not shared
  1308. GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, func->nameSpace);
  1309. // There should not be any defaultArgs, but if there are any we need to delete them to avoid leaks
  1310. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1311. if( defaultArgs[n] )
  1312. asDELETE(defaultArgs[n], asCString);
  1313. // All funcdefs are shared, unless one of the parameter types or return type is not shared
  1314. isShared = true;
  1315. if( func->returnType.GetObjectType() && !func->returnType.GetObjectType()->IsShared() )
  1316. isShared = false;
  1317. if( func->returnType.GetFuncDef() && !func->returnType.GetFuncDef()->IsShared() )
  1318. isShared = false;
  1319. for( asUINT n = 0; isShared && n < func->parameterTypes.GetLength(); n++ )
  1320. {
  1321. if( func->parameterTypes[n].GetObjectType() && !func->parameterTypes[n].GetObjectType()->IsShared() )
  1322. isShared = false;
  1323. if( func->parameterTypes[n].GetFuncDef() && !func->parameterTypes[n].GetFuncDef()->IsShared() )
  1324. isShared = false;
  1325. }
  1326. func->isShared = isShared;
  1327. // Check if there is another identical funcdef from another module and if so reuse that instead
  1328. if( func->isShared )
  1329. {
  1330. for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
  1331. {
  1332. asCScriptFunction *f2 = engine->funcDefs[n];
  1333. if( f2 == 0 || func == f2 )
  1334. continue;
  1335. if( !f2->isShared )
  1336. continue;
  1337. if( f2->name == func->name &&
  1338. f2->nameSpace == func->nameSpace &&
  1339. f2->IsSignatureExceptNameEqual(func) )
  1340. {
  1341. // Replace our funcdef for the existing one
  1342. funcDef->idx = f2->id;
  1343. module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
  1344. f2->AddRefInternal();
  1345. engine->funcDefs.RemoveValue(func);
  1346. func->ReleaseInternal();
  1347. break;
  1348. }
  1349. }
  1350. }
  1351. }
  1352. int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1353. {
  1354. // Has the application disabled global vars?
  1355. if( engine->ep.disallowGlobalVars )
  1356. WriteError(TXT_GLOBAL_VARS_NOT_ALLOWED, file, node);
  1357. // What data type is it?
  1358. asCDataType type = CreateDataTypeFromNode(node->firstChild, file, ns);
  1359. if( !type.CanBeInstantiated() )
  1360. {
  1361. asCString str;
  1362. if( type.IsAbstractClass() )
  1363. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, type.Format(ns).AddressOf());
  1364. else if( type.IsInterface() )
  1365. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, type.Format(ns).AddressOf());
  1366. else
  1367. // TODO: Improve error message to explain why
  1368. str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format(ns).AddressOf());
  1369. WriteError(str, file, node);
  1370. }
  1371. asCScriptNode *n = node->firstChild->next;
  1372. while( n )
  1373. {
  1374. // Verify that the name isn't taken
  1375. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1376. CheckNameConflict(name.AddressOf(), n, file, ns);
  1377. // Register the global variable
  1378. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  1379. if( gvar == 0 )
  1380. {
  1381. node->Destroy(engine);
  1382. return asOUT_OF_MEMORY;
  1383. }
  1384. gvar->script = file;
  1385. gvar->name = name;
  1386. gvar->isCompiled = false;
  1387. gvar->datatype = type;
  1388. gvar->isEnumValue = false;
  1389. gvar->ns = ns;
  1390. // TODO: Give error message if wrong
  1391. asASSERT(!gvar->datatype.IsReference());
  1392. // Allocation is done when the variable is compiled, to allow for autos
  1393. gvar->property = 0;
  1394. gvar->index = 0;
  1395. globVariables.Put(gvar);
  1396. gvar->declaredAtNode = n;
  1397. n = n->next;
  1398. gvar->declaredAtNode->DisconnectParent();
  1399. gvar->initializationNode = 0;
  1400. if( n &&
  1401. ( n->nodeType == snAssignment ||
  1402. n->nodeType == snArgList ||
  1403. n->nodeType == snInitList ) )
  1404. {
  1405. gvar->initializationNode = n;
  1406. n = n->next;
  1407. gvar->initializationNode->DisconnectParent();
  1408. }
  1409. }
  1410. node->Destroy(engine);
  1411. return 0;
  1412. }
  1413. int asCBuilder::RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1414. {
  1415. asCScriptNode *cl = node->firstChild;
  1416. asASSERT( cl->nodeType == snClass );
  1417. asCScriptNode *n = cl->firstChild;
  1418. // Skip potential 'final' and 'shared' tokens
  1419. while( n->tokenType == ttIdentifier &&
  1420. (file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) ||
  1421. file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN)) )
  1422. {
  1423. // Report error, because mixin class cannot be final or shared
  1424. asCString msg;
  1425. msg.Format(TXT_MIXIN_CANNOT_BE_DECLARED_AS_s, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1426. WriteError(msg, file, n);
  1427. asCScriptNode *tmp = n;
  1428. n = n->next;
  1429. // Remove the invalid node, so compilation can continue as if it wasn't there
  1430. tmp->DisconnectParent();
  1431. tmp->Destroy(engine);
  1432. }
  1433. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1434. int r, c;
  1435. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1436. CheckNameConflict(name.AddressOf(), n, file, ns);
  1437. sMixinClass *decl = asNEW(sMixinClass);
  1438. if( decl == 0 )
  1439. {
  1440. node->Destroy(engine);
  1441. return asOUT_OF_MEMORY;
  1442. }
  1443. mixinClasses.PushLast(decl);
  1444. decl->name = name;
  1445. decl->ns = ns;
  1446. decl->node = cl;
  1447. decl->script = file;
  1448. // Clean up memory
  1449. cl->DisconnectParent();
  1450. node->Destroy(engine);
  1451. return 0;
  1452. }
  1453. int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1454. {
  1455. asCScriptNode *n = node->firstChild;
  1456. bool isFinal = false;
  1457. bool isShared = false;
  1458. bool isAbstract = false;
  1459. // Check the class modifiers
  1460. while( n->tokenType == ttIdentifier )
  1461. {
  1462. if( file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) )
  1463. {
  1464. if( isAbstract )
  1465. WriteError(TXT_CLASS_CANT_BE_FINAL_AND_ABSTRACT, file, n);
  1466. else
  1467. {
  1468. if( isFinal )
  1469. {
  1470. asCString msg;
  1471. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1472. WriteWarning(msg, file, n);
  1473. }
  1474. isFinal = true;
  1475. }
  1476. }
  1477. else if( file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN) )
  1478. {
  1479. if( isShared )
  1480. {
  1481. asCString msg;
  1482. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1483. WriteWarning(msg, file, n);
  1484. }
  1485. isShared = true;
  1486. }
  1487. else if( file->TokenEquals(n->tokenPos, n->tokenLength, ABSTRACT_TOKEN) )
  1488. {
  1489. if( isFinal )
  1490. WriteError(TXT_CLASS_CANT_BE_FINAL_AND_ABSTRACT, file, n);
  1491. else
  1492. {
  1493. if( isAbstract )
  1494. {
  1495. asCString msg;
  1496. msg.Format(TXT_ATTR_s_INFORMED_MULTIPLE_TIMES, asCString(&file->code[n->tokenPos], n->tokenLength).AddressOf());
  1497. WriteWarning(msg, file, n);
  1498. }
  1499. isAbstract = true;
  1500. }
  1501. }
  1502. else
  1503. {
  1504. // This is the name of the class
  1505. break;
  1506. }
  1507. n = n->next;
  1508. }
  1509. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1510. int r, c;
  1511. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1512. CheckNameConflict(name.AddressOf(), n, file, ns);
  1513. sClassDeclaration *decl = asNEW(sClassDeclaration);
  1514. if( decl == 0 )
  1515. {
  1516. node->Destroy(engine);
  1517. return asOUT_OF_MEMORY;
  1518. }
  1519. classDeclarations.PushLast(decl);
  1520. decl->name = name;
  1521. decl->script = file;
  1522. decl->node = node;
  1523. // If this type is shared and there already exist another shared
  1524. // type of the same name, then that one should be used instead of
  1525. // creating a new one.
  1526. if( isShared )
  1527. {
  1528. for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ )
  1529. {
  1530. asCObjectType *st = engine->sharedScriptTypes[n];
  1531. if( st &&
  1532. st->IsShared() &&
  1533. st->name == name &&
  1534. st->nameSpace == ns &&
  1535. !st->IsInterface() )
  1536. {
  1537. // We'll use the existing type
  1538. decl->isExistingShared = true;
  1539. decl->objType = st;
  1540. module->classTypes.PushLast(st);
  1541. st->AddRefInternal();
  1542. return 0;
  1543. }
  1544. }
  1545. }
  1546. // Create a new object type for this class
  1547. asCObjectType *st = asNEW(asCObjectType)(engine);
  1548. if( st == 0 )
  1549. return asOUT_OF_MEMORY;
  1550. // By default all script classes are marked as garbage collected.
  1551. // Only after the complete structure and relationship between classes
  1552. // is known, can the flag be cleared for those objects that truly cannot
  1553. // form circular references. This is important because a template
  1554. // callback may be called with a script class before the compilation
  1555. // completes, and until it is known, the callback must assume the class
  1556. // is garbage collected.
  1557. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT | asOBJ_GC;
  1558. if( isShared )
  1559. st->flags |= asOBJ_SHARED;
  1560. if( isFinal )
  1561. st->flags |= asOBJ_NOINHERIT;
  1562. if( isAbstract )
  1563. st->flags |= asOBJ_ABSTRACT;
  1564. if( node->tokenType == ttHandle )
  1565. st->flags |= asOBJ_IMPLICIT_HANDLE;
  1566. st->size = sizeof(asCScriptObject);
  1567. st->name = name;
  1568. st->nameSpace = ns;
  1569. st->module = module;
  1570. module->classTypes.PushLast(st);
  1571. if( isShared )
  1572. {
  1573. engine->sharedScriptTypes.PushLast(st);
  1574. st->AddRefInternal();
  1575. }
  1576. decl->objType = st;
  1577. // Use the default script class behaviours
  1578. st->beh = engine->scriptTypeBehaviours.beh;
  1579. // TODO: Move this to asCObjectType so that the asCRestore can reuse it
  1580. engine->scriptFunctions[st->beh.addref]->AddRefInternal();
  1581. engine->scriptFunctions[st->beh.release]->AddRefInternal();
  1582. engine->scriptFunctions[st->beh.gcEnumReferences]->AddRefInternal();
  1583. engine->scriptFunctions[st->beh.gcGetFlag]->AddRefInternal();
  1584. engine->scriptFunctions[st->beh.gcGetRefCount]->AddRefInternal();
  1585. engine->scriptFunctions[st->beh.gcReleaseAllReferences]->AddRefInternal();
  1586. engine->scriptFunctions[st->beh.gcSetFlag]->AddRefInternal();
  1587. engine->scriptFunctions[st->beh.copy]->AddRefInternal();
  1588. engine->scriptFunctions[st->beh.factory]->AddRefInternal();
  1589. engine->scriptFunctions[st->beh.construct]->AddRefInternal();
  1590. // TODO: weak: Should not do this if the class has been declared with noweak
  1591. engine->scriptFunctions[st->beh.getWeakRefFlag]->AddRefInternal();
  1592. return 0;
  1593. }
  1594. int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  1595. {
  1596. asCScriptNode *n = node->firstChild;
  1597. asCString name(&file->code[n->tokenPos], n->tokenLength);
  1598. bool isShared = false;
  1599. if( name == SHARED_TOKEN )
  1600. {
  1601. isShared = true;
  1602. n = n->next;
  1603. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  1604. }
  1605. int r, c;
  1606. file->ConvertPosToRowCol(n->tokenPos, &r, &c);
  1607. CheckNameConflict(name.AddressOf(), n, file, ns);
  1608. sClassDeclaration *decl = asNEW(sClassDeclaration);
  1609. if( decl == 0 )
  1610. {
  1611. node->Destroy(engine);
  1612. return asOUT_OF_MEMORY;
  1613. }
  1614. interfaceDeclarations.PushLast(decl);
  1615. decl->name = name;
  1616. decl->script = file;
  1617. decl->node = node;
  1618. // If this type is shared and there already exist another shared
  1619. // type of the same name, then that one should be used instead of
  1620. // creating a new one.
  1621. if( isShared )
  1622. {
  1623. for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ )
  1624. {
  1625. asCObjectType *st = engine->sharedScriptTypes[n];
  1626. if( st &&
  1627. st->IsShared() &&
  1628. st->name == name &&
  1629. st->nameSpace == ns &&
  1630. st->IsInterface() )
  1631. {
  1632. // We'll use the existing type
  1633. decl->isExistingShared = true;
  1634. decl->objType = st;
  1635. module->classTypes.PushLast(st);
  1636. st->AddRefInternal();
  1637. return 0;
  1638. }
  1639. }
  1640. }
  1641. // Register the object type for the interface
  1642. asCObjectType *st = asNEW(asCObjectType)(engine);
  1643. if( st == 0 )
  1644. return asOUT_OF_MEMORY;
  1645. st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
  1646. if( isShared )
  1647. st->flags |= asOBJ_SHARED;
  1648. st->size = 0; // Cannot be instantiated
  1649. st->name = name;
  1650. st->nameSpace = ns;
  1651. st->module = module;
  1652. module->classTypes.PushLast(st);
  1653. if( isShared )
  1654. {
  1655. engine->sharedScriptTypes.PushLast(st);
  1656. st->AddRefInternal();
  1657. }
  1658. decl->objType = st;
  1659. // Use the default script class behaviours
  1660. st->beh.construct = 0;
  1661. st->beh.addref = engine->scriptTypeBehaviours.beh.addref;
  1662. engine->scriptFunctions[st->beh.addref]->AddRefInternal();
  1663. st->beh.release = engine->scriptTypeBehaviours.beh.release;
  1664. engine->scriptFunctions[st->beh.release]->AddRefInternal();
  1665. st->beh.copy = 0;
  1666. return 0;
  1667. }
  1668. void asCBuilder::CompileGlobalVariables()
  1669. {
  1670. bool compileSucceeded = true;
  1671. // Store state of compilation (errors, warning, output)
  1672. int currNumErrors = numErrors;
  1673. int currNumWarnings = numWarnings;
  1674. // Backup the original message stream
  1675. bool msgCallback = engine->msgCallback;
  1676. asSSystemFunctionInterface msgCallbackFunc = engine->msgCallbackFunc;
  1677. void *msgCallbackObj = engine->msgCallbackObj;
  1678. // Set the new temporary message stream
  1679. asCOutputBuffer outBuffer;
  1680. engine->SetMessageCallback(asMETHOD(asCOutputBuffer, Callback), &outBuffer, asCALL_THISCALL);
  1681. asCOutputBuffer finalOutput;
  1682. asCScriptFunction *initFunc = 0;
  1683. asCSymbolTable<asCGlobalProperty> initOrder;
  1684. // We first try to compile all the primitive global variables, and only after that
  1685. // compile the non-primitive global variables. This permits the constructors
  1686. // for the complex types to use the already initialized variables of primitive
  1687. // type. Note, we currently don't know which global variables are used in the
  1688. // constructors, so we cannot guarantee that variables of complex types are
  1689. // initialized in the correct order, so we won't reorder those.
  1690. bool compilingPrimitives = true;
  1691. // Compile each global variable
  1692. while( compileSucceeded )
  1693. {
  1694. compileSucceeded = false;
  1695. int accumErrors = 0;
  1696. int accumWarnings = 0;
  1697. // Restore state of compilation
  1698. finalOutput.Clear();
  1699. asCSymbolTable<sGlobalVariableDescription>::iterator it = globVariables.List();
  1700. for( ; it; it++ )
  1701. {
  1702. sGlobalVariableDescription *gvar = *it;
  1703. if( gvar->isCompiled )
  1704. continue;
  1705. asCByteCode init(engine);
  1706. numWarnings = 0;
  1707. numErrors = 0;
  1708. outBuffer.Clear();
  1709. // Skip this for now if we're not compiling complex types yet
  1710. if( compilingPrimitives && !gvar->datatype.IsPrimitive() )
  1711. continue;
  1712. if( gvar->declaredAtNode )
  1713. {
  1714. int r, c;
  1715. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &r, &c);
  1716. asCString str = gvar->datatype.Format(gvar->ns);
  1717. str += " " + gvar->name;
  1718. str.Format(TXT_COMPILING_s, str.AddressOf());
  1719. WriteInfo(gvar->script->name, str, r, c, true);
  1720. }
  1721. if( gvar->isEnumValue )
  1722. {
  1723. int r;
  1724. if( gvar->initializationNode )
  1725. {
  1726. asCCompiler comp(engine);
  1727. asCScriptFunction func(engine, module, asFUNC_SCRIPT);
  1728. // Set the namespace that should be used during the compilation
  1729. func.nameSpace = gvar->datatype.GetObjectType()->nameSpace;
  1730. // Temporarily switch the type of the variable to int so it can be compiled properly
  1731. asCDataType saveType;
  1732. saveType = gvar->datatype;
  1733. gvar->datatype = asCDataType::CreatePrimitive(ttInt, true);
  1734. r = comp.CompileGlobalVariable(this, gvar->script, gvar->initializationNode, gvar, &func);
  1735. gvar->datatype = saveType;
  1736. // Make the function a dummy so it doesn't try to release objects while destroying the function
  1737. func.funcType = asFUNC_DUMMY;
  1738. }
  1739. else
  1740. {
  1741. r = 0;
  1742. // When there is no assignment the value is the last + 1
  1743. int enumVal = 0;
  1744. asCSymbolTable<sGlobalVariableDescription>::iterator prev_it = it;
  1745. prev_it--;
  1746. if( prev_it )
  1747. {
  1748. sGlobalVariableDescription *gvar2 = *prev_it;
  1749. if(gvar2->datatype == gvar->datatype )
  1750. {
  1751. // The integer value is stored in the lower bytes
  1752. enumVal = (*(int*)&gvar2->constantValue) + 1;
  1753. if( !gvar2->isCompiled )
  1754. {
  1755. int row, col;
  1756. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &row, &col);
  1757. asCString str = gvar->datatype.Format(gvar->ns);
  1758. str += " " + gvar->name;
  1759. str.Format(TXT_COMPILING_s, str.AddressOf());
  1760. WriteInfo(gvar->script->name, str, row, col, true);
  1761. str.Format(TXT_UNINITIALIZED_GLOBAL_VAR_s, gvar2->name.AddressOf());
  1762. WriteError(gvar->script->name, str, row, col);
  1763. r = -1;
  1764. }
  1765. }
  1766. }
  1767. // The integer value is stored in the lower bytes
  1768. *(int*)&gvar->constantValue = enumVal;
  1769. }
  1770. if( r >= 0 )
  1771. {
  1772. // Set the value as compiled
  1773. gvar->isCompiled = true;
  1774. compileSucceeded = true;
  1775. }
  1776. }
  1777. else
  1778. {
  1779. // Compile the global variable
  1780. initFunc = asNEW(asCScriptFunction)(engine, module, asFUNC_SCRIPT);
  1781. if( initFunc == 0 )
  1782. {
  1783. // Out of memory
  1784. return;
  1785. }
  1786. // Set the namespace that should be used for this function
  1787. initFunc->nameSpace = gvar->ns;
  1788. asCCompiler comp(engine);
  1789. int r = comp.CompileGlobalVariable(this, gvar->script, gvar->initializationNode, gvar, initFunc);
  1790. if( r >= 0 )
  1791. {
  1792. // Compilation succeeded
  1793. gvar->isCompiled = true;
  1794. compileSucceeded = true;
  1795. }
  1796. else
  1797. {
  1798. // Compilation failed
  1799. initFunc->funcType = asFUNC_DUMMY;
  1800. asDELETE(initFunc, asCScriptFunction);
  1801. initFunc = 0;
  1802. }
  1803. }
  1804. if( gvar->isCompiled )
  1805. {
  1806. // Add warnings for this constant to the total build
  1807. if( numWarnings )
  1808. {
  1809. currNumWarnings += numWarnings;
  1810. if( msgCallback )
  1811. outBuffer.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  1812. }
  1813. // Determine order of variable initializations
  1814. if( gvar->property && !gvar->isEnumValue )
  1815. initOrder.Put(gvar->property);
  1816. // Does the function contain more than just a SUSPEND followed by a RET instruction?
  1817. if( initFunc && initFunc->scriptData->byteCode.GetLength() > 2 )
  1818. {
  1819. // Create the init function for this variable
  1820. initFunc->id = engine->GetNextScriptFunctionId();
  1821. engine->AddScriptFunction(initFunc);
  1822. // Finalize the init function for this variable
  1823. initFunc->returnType = asCDataType::CreatePrimitive(ttVoid, false);
  1824. initFunc->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(gvar->script->name.AddressOf());
  1825. if( gvar->declaredAtNode )
  1826. {
  1827. int row, col;
  1828. gvar->script->ConvertPosToRowCol(gvar->declaredAtNode->tokenPos, &row, &col);
  1829. initFunc->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20);
  1830. }
  1831. gvar->property->SetInitFunc(initFunc);
  1832. initFunc->ReleaseInternal();
  1833. initFunc = 0;
  1834. }
  1835. else if( initFunc )
  1836. {
  1837. // Destroy the function as it won't be used
  1838. initFunc->funcType = asFUNC_DUMMY;
  1839. asDELETE(initFunc, asCScriptFunction);
  1840. initFunc = 0;
  1841. }
  1842. // Convert enums to true enum values, so subsequent compilations can access it as an enum
  1843. if( gvar->isEnumValue )
  1844. {
  1845. asCObjectType *objectType = gvar->datatype.GetObjectType();
  1846. asASSERT(NULL != objectType);
  1847. asSEnumValue *e = asNEW(asSEnumValue);
  1848. if( e == 0 )
  1849. {
  1850. // Out of memory
  1851. numErrors++;
  1852. return;
  1853. }
  1854. e->name = gvar->name;
  1855. e->value = *(int*)&gvar->constantValue;
  1856. objectType->enumValues.PushLast(e);
  1857. }
  1858. }
  1859. else
  1860. {
  1861. // Add output to final output
  1862. finalOutput.Append(outBuffer);
  1863. accumErrors += numErrors;
  1864. accumWarnings += numWarnings;
  1865. }
  1866. engine->preMessage.isSet = false;
  1867. }
  1868. if( !compileSucceeded )
  1869. {
  1870. if( compilingPrimitives )
  1871. {
  1872. // No more primitives could be compiled, so
  1873. // switch to compiling the complex variables
  1874. compilingPrimitives = false;
  1875. compileSucceeded = true;
  1876. }
  1877. else
  1878. {
  1879. // No more variables can be compiled
  1880. // Add errors and warnings to total build
  1881. currNumWarnings += accumWarnings;
  1882. currNumErrors += accumErrors;
  1883. if( msgCallback )
  1884. finalOutput.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
  1885. }
  1886. }
  1887. }
  1888. // Restore states
  1889. engine->msgCallback = msgCallback;
  1890. engine->msgCallbackFunc = msgCallbackFunc;
  1891. engine->msgCallbackObj = msgCallbackObj;
  1892. numWarnings = currNumWarnings;
  1893. numErrors = currNumErrors;
  1894. // Set the correct order of initialization
  1895. if( numErrors == 0 )
  1896. {
  1897. // If the length of the arrays are not the same, then this is the compilation
  1898. // of a single variable, in which case the initialization order of the previous
  1899. // variables must be preserved.
  1900. if( module->scriptGlobals.GetSize() == initOrder.GetSize() )
  1901. module->scriptGlobals.SwapWith(initOrder);
  1902. }
  1903. // Delete the enum expressions
  1904. asCSymbolTableIterator<sGlobalVariableDescription> it = globVariables.List();
  1905. while( it )
  1906. {
  1907. sGlobalVariableDescription *gvar = *it;
  1908. if( gvar->isEnumValue )
  1909. {
  1910. // Remove from symboltable. This has to be done prior to freeing the memeory
  1911. globVariables.Erase(it.GetIndex());
  1912. // Destroy the gvar property
  1913. if( gvar->declaredAtNode )
  1914. {
  1915. gvar->declaredAtNode->Destroy(engine);
  1916. gvar->declaredAtNode = 0;
  1917. }
  1918. if( gvar->initializationNode )
  1919. {
  1920. gvar->initializationNode->Destroy(engine);
  1921. gvar->initializationNode = 0;
  1922. }
  1923. if( gvar->property )
  1924. {
  1925. asDELETE(gvar->property, asCGlobalProperty);
  1926. gvar->property = 0;
  1927. }
  1928. asDELETE(gvar, sGlobalVariableDescription);
  1929. }
  1930. else
  1931. it++;
  1932. }
  1933. }
  1934. int asCBuilder::GetNamespaceAndNameFromNode(asCScriptNode *n, asCScriptCode *script, asSNameSpace *implicitNs, asSNameSpace *&outNs, asCString &outName)
  1935. {
  1936. asASSERT( n->nodeType == snIdentifier );
  1937. // Get the optional scope from the node
  1938. asSNameSpace *ns = GetNameSpaceFromNode(n->firstChild, script, implicitNs, 0);
  1939. if( ns == 0 )
  1940. return -1;
  1941. // Get the name
  1942. asCString name(&script->code[n->lastChild->tokenPos], n->lastChild->tokenLength);
  1943. outNs = ns;
  1944. outName = name;
  1945. return 0;
  1946. }
  1947. void asCBuilder::AddInterfaceFromMixinToClass(sClassDeclaration *decl, asCScriptNode *errNode, sMixinClass *mixin)
  1948. {
  1949. // Determine what interfaces that the mixin implements
  1950. asCScriptNode *node = mixin->node;
  1951. asASSERT(node->nodeType == snClass);
  1952. // Skip the name of the mixin
  1953. node = node->firstChild->next;
  1954. while( node && node->nodeType == snIdentifier )
  1955. {
  1956. bool ok = true;
  1957. asSNameSpace *ns;
  1958. asCString name;
  1959. if( GetNamespaceAndNameFromNode(node, mixin->script, mixin->ns, ns, name) < 0 )
  1960. ok = false;
  1961. else
  1962. {
  1963. // Find the object type for the interface
  1964. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  1965. // Check that the object type is an interface
  1966. if( objType && objType->IsInterface() )
  1967. {
  1968. // Only add the interface if the class doesn't already implement it
  1969. if( !decl->objType->Implements(objType) )
  1970. AddInterfaceToClass(decl, errNode, objType);
  1971. }
  1972. else
  1973. {
  1974. WriteError(TXT_MIXIN_CLASS_CANNOT_INHERIT, mixin->script, node);
  1975. ok = false;
  1976. }
  1977. }
  1978. if( !ok )
  1979. {
  1980. // Remove this node so the error isn't reported again
  1981. asCScriptNode *delNode = node;
  1982. node = node->prev;
  1983. delNode->DisconnectParent();
  1984. delNode->Destroy(engine);
  1985. }
  1986. node = node->next;
  1987. }
  1988. }
  1989. void asCBuilder::AddInterfaceToClass(sClassDeclaration *decl, asCScriptNode *errNode, asCObjectType *intfType)
  1990. {
  1991. // A shared type may only implement from shared interfaces
  1992. if( decl->objType->IsShared() && !intfType->IsShared() )
  1993. {
  1994. asCString msg;
  1995. msg.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, intfType->name.AddressOf());
  1996. WriteError(msg, decl->script, errNode);
  1997. return;
  1998. }
  1999. if( decl->isExistingShared )
  2000. {
  2001. // If the class is an existing shared class, then just check if the
  2002. // interface exists in the original declaration too
  2003. if( !decl->objType->Implements(intfType) )
  2004. {
  2005. asCString str;
  2006. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  2007. WriteError(str, decl->script, errNode);
  2008. return;
  2009. }
  2010. }
  2011. else
  2012. {
  2013. // If the interface is already in the class then don't add it again
  2014. if( decl->objType->Implements(intfType) )
  2015. return;
  2016. // Add the interface to the class
  2017. decl->objType->interfaces.PushLast(intfType);
  2018. // Add the inherited interfaces too
  2019. // For interfaces this will be done outside to handle out-of-order declarations
  2020. if( !decl->objType->IsInterface() )
  2021. {
  2022. for( asUINT n = 0; n < intfType->interfaces.GetLength(); n++ )
  2023. AddInterfaceToClass(decl, errNode, intfType->interfaces[n]);
  2024. }
  2025. }
  2026. }
  2027. void asCBuilder::CompileInterfaces()
  2028. {
  2029. asUINT n;
  2030. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  2031. {
  2032. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  2033. asCObjectType *intfType = intfDecl->objType;
  2034. asCScriptNode *node = intfDecl->node;
  2035. asASSERT(node && node->nodeType == snInterface);
  2036. node = node->firstChild;
  2037. // Skip the 'shared' keyword
  2038. if( intfType->IsShared() )
  2039. node = node->next;
  2040. // Skip the name
  2041. node = node->next;
  2042. // Verify the inherited interfaces
  2043. while( node && node->nodeType == snIdentifier )
  2044. {
  2045. asSNameSpace *ns;
  2046. asCString name;
  2047. if( GetNamespaceAndNameFromNode(node, intfDecl->script, intfType->nameSpace, ns, name) < 0 )
  2048. {
  2049. node = node->next;
  2050. continue;
  2051. }
  2052. // Find the object type for the interface
  2053. asCObjectType *objType = 0;
  2054. while( ns )
  2055. {
  2056. objType = GetObjectType(name.AddressOf(), ns);
  2057. if( objType ) break;
  2058. ns = engine->GetParentNameSpace(ns);
  2059. }
  2060. // Check that the object type is an interface
  2061. bool ok = true;
  2062. if( objType && objType->IsInterface() )
  2063. {
  2064. // Check that the implemented interface is shared if the base interface is shared
  2065. if( intfType->IsShared() && !objType->IsShared() )
  2066. {
  2067. asCString str;
  2068. str.Format(TXT_SHARED_CANNOT_IMPLEMENT_NON_SHARED_s, objType->GetName());
  2069. WriteError(str, intfDecl->script, node);
  2070. ok = false;
  2071. }
  2072. }
  2073. else
  2074. {
  2075. WriteError(TXT_INTERFACE_CAN_ONLY_IMPLEMENT_INTERFACE, intfDecl->script, node);
  2076. ok = false;
  2077. }
  2078. if( ok )
  2079. {
  2080. // Make sure none of the implemented interfaces implement from this one
  2081. asCObjectType *base = objType;
  2082. while( base != 0 )
  2083. {
  2084. if( base == intfType )
  2085. {
  2086. WriteError(TXT_CANNOT_IMPLEMENT_SELF, intfDecl->script, node);
  2087. ok = false;
  2088. break;
  2089. }
  2090. // At this point there is at most one implemented interface
  2091. if( base->interfaces.GetLength() )
  2092. base = base->interfaces[0];
  2093. else
  2094. break;
  2095. }
  2096. }
  2097. if( ok )
  2098. AddInterfaceToClass(intfDecl, node, objType);
  2099. // Remove the nodes so they aren't parsed again
  2100. asCScriptNode *delNode = node;
  2101. node = node->next;
  2102. delNode->DisconnectParent();
  2103. delNode->Destroy(engine);
  2104. }
  2105. }
  2106. // Order the interfaces with inheritances so that the inherited
  2107. // of inherited interfaces can be added properly
  2108. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  2109. {
  2110. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  2111. asCObjectType *intfType = intfDecl->objType;
  2112. if( intfType->interfaces.GetLength() == 0 ) continue;
  2113. // If any of the derived interfaces are found after this interface, then move this to the end of the list
  2114. for( asUINT m = n+1; m < interfaceDeclarations.GetLength(); m++ )
  2115. {
  2116. if( intfType->Implements(interfaceDeclarations[m]->objType) )
  2117. {
  2118. interfaceDeclarations.RemoveIndex(n);
  2119. interfaceDeclarations.PushLast(intfDecl);
  2120. // Decrease index so that we don't skip an entry
  2121. n--;
  2122. break;
  2123. }
  2124. }
  2125. }
  2126. // Now recursively add the additional inherited interfaces
  2127. for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
  2128. {
  2129. sClassDeclaration *intfDecl = interfaceDeclarations[n];
  2130. asCObjectType *intfType = intfDecl->objType;
  2131. // TODO: Is this really at the correct place? Hasn't the vfTableIdx already been set here?
  2132. // Co-opt the vfTableIdx value in our own methods to indicate the
  2133. // index the function should have in the table chunk for this interface.
  2134. for( asUINT d = 0; d < intfType->methods.GetLength(); d++ )
  2135. {
  2136. asCScriptFunction *func = GetFunctionDescription(intfType->methods[d]);
  2137. func->vfTableIdx = d;
  2138. asASSERT(func->objectType == intfType);
  2139. }
  2140. // As new interfaces will be added to the end of the list, all
  2141. // interfaces will be traversed the same as recursively
  2142. for( asUINT m = 0; m < intfType->interfaces.GetLength(); m++ )
  2143. {
  2144. asCObjectType *base = intfType->interfaces[m];
  2145. // Add any interfaces not already implemented
  2146. for( asUINT l = 0; l < base->interfaces.GetLength(); l++ )
  2147. AddInterfaceToClass(intfDecl, intfDecl->node, base->interfaces[l]);
  2148. // Add the methods from the implemented interface
  2149. for( asUINT m = 0; m < base->methods.GetLength(); m++ )
  2150. {
  2151. // If the derived interface implements the same method, then don't add the base interface' method
  2152. asCScriptFunction *baseFunc = GetFunctionDescription(base->methods[m]);
  2153. asCScriptFunction *derivedFunc = 0;
  2154. bool found = false;
  2155. for( asUINT d = 0; d < intfType->methods.GetLength(); d++ )
  2156. {
  2157. derivedFunc = GetFunctionDescription(intfType->methods[d]);
  2158. if( derivedFunc->IsSignatureEqual(baseFunc) )
  2159. {
  2160. found = true;
  2161. break;
  2162. }
  2163. }
  2164. if( !found )
  2165. {
  2166. // Add the method
  2167. intfType->methods.PushLast(baseFunc->id);
  2168. baseFunc->AddRefInternal();
  2169. }
  2170. }
  2171. }
  2172. }
  2173. }
  2174. // numTempl is the number of template instances that existed in the engine before the build begun
  2175. void asCBuilder::CompileClasses(asUINT numTempl)
  2176. {
  2177. asUINT n;
  2178. asCArray<sClassDeclaration*> toValidate((int)classDeclarations.GetLength());
  2179. // Determine class inheritances and interfaces
  2180. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2181. {
  2182. sClassDeclaration *decl = classDeclarations[n];
  2183. asCScriptCode *file = decl->script;
  2184. // Find the base class that this class inherits from
  2185. bool multipleInheritance = false;
  2186. asCScriptNode *node = decl->node->firstChild;
  2187. while( file->TokenEquals(node->tokenPos, node->tokenLength, FINAL_TOKEN) ||
  2188. file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) ||
  2189. file->TokenEquals(node->tokenPos, node->tokenLength, ABSTRACT_TOKEN) )
  2190. {
  2191. node = node->next;
  2192. }
  2193. // Skip the name of the class
  2194. asASSERT(node->tokenType == ttIdentifier);
  2195. node = node->next;
  2196. while( node && node->nodeType == snIdentifier )
  2197. {
  2198. asSNameSpace *ns;
  2199. asCString name;
  2200. if( GetNamespaceAndNameFromNode(node, file, decl->objType->nameSpace, ns, name) < 0 )
  2201. {
  2202. node = node->next;
  2203. continue;
  2204. }
  2205. // Find the object type for the interface
  2206. asCObjectType *objType = 0;
  2207. sMixinClass *mixin = 0;
  2208. asSNameSpace *origNs = ns;
  2209. while( ns )
  2210. {
  2211. objType = GetObjectType(name.AddressOf(), ns);
  2212. if( objType == 0 )
  2213. mixin = GetMixinClass(name.AddressOf(), ns);
  2214. if( objType || mixin )
  2215. break;
  2216. ns = engine->GetParentNameSpace(ns);
  2217. }
  2218. if( objType == 0 && mixin == 0 )
  2219. {
  2220. asCString str;
  2221. if( origNs->name == "" )
  2222. str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, name.AddressOf());
  2223. else
  2224. str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, name.AddressOf(), origNs->name.AddressOf());
  2225. WriteError(str, file, node);
  2226. }
  2227. else if( mixin )
  2228. {
  2229. AddInterfaceFromMixinToClass(decl, node, mixin);
  2230. }
  2231. else if( !(objType->flags & asOBJ_SCRIPT_OBJECT) ||
  2232. (objType->flags & asOBJ_NOINHERIT) )
  2233. {
  2234. // Either the class is not a script class or interface
  2235. // or the class has been declared as 'final'
  2236. asCString str;
  2237. str.Format(TXT_CANNOT_INHERIT_FROM_s_FINAL, objType->name.AddressOf());
  2238. WriteError(str, file, node);
  2239. }
  2240. else if( objType->size != 0 )
  2241. {
  2242. // The class inherits from another script class
  2243. if( !decl->isExistingShared && decl->objType->derivedFrom != 0 )
  2244. {
  2245. if( !multipleInheritance )
  2246. {
  2247. WriteError(TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES, file, node);
  2248. multipleInheritance = true;
  2249. }
  2250. }
  2251. else
  2252. {
  2253. // Make sure none of the base classes inherit from this one
  2254. asCObjectType *base = objType;
  2255. bool error = false;
  2256. while( base != 0 )
  2257. {
  2258. if( base == decl->objType )
  2259. {
  2260. WriteError(TXT_CANNOT_INHERIT_FROM_SELF, file, node);
  2261. error = true;
  2262. break;
  2263. }
  2264. base = base->derivedFrom;
  2265. }
  2266. if( !error )
  2267. {
  2268. // A shared type may only inherit from other shared types
  2269. if( (decl->objType->IsShared()) && !(objType->IsShared()) )
  2270. {
  2271. asCString msg;
  2272. msg.Format(TXT_SHARED_CANNOT_INHERIT_FROM_NON_SHARED_s, objType->name.AddressOf());
  2273. WriteError(msg, file, node);
  2274. error = true;
  2275. }
  2276. }
  2277. if( !error )
  2278. {
  2279. if( decl->isExistingShared )
  2280. {
  2281. // Verify that the base class is the same as the original shared type
  2282. if( decl->objType->derivedFrom != objType )
  2283. {
  2284. asCString str;
  2285. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  2286. WriteError(str, file, node);
  2287. }
  2288. }
  2289. else
  2290. {
  2291. // Set the base class
  2292. decl->objType->derivedFrom = objType;
  2293. objType->AddRefInternal();
  2294. }
  2295. }
  2296. }
  2297. }
  2298. else
  2299. {
  2300. // The class implements an interface
  2301. AddInterfaceToClass(decl, node, objType);
  2302. }
  2303. node = node->next;
  2304. }
  2305. }
  2306. // Order class declarations so that base classes are compiled before derived classes.
  2307. // This will allow the derived classes to copy properties and methods in the next step.
  2308. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2309. {
  2310. sClassDeclaration *decl = classDeclarations[n];
  2311. asCObjectType *derived = decl->objType;
  2312. asCObjectType *base = derived->derivedFrom;
  2313. if( base == 0 ) continue;
  2314. // If the base class is found after the derived class, then move the derived class to the end of the list
  2315. for( asUINT m = n+1; m < classDeclarations.GetLength(); m++ )
  2316. {
  2317. sClassDeclaration *declBase = classDeclarations[m];
  2318. if( base == declBase->objType )
  2319. {
  2320. classDeclarations.RemoveIndex(n);
  2321. classDeclarations.PushLast(decl);
  2322. // Decrease index so that we don't skip an entry
  2323. n--;
  2324. break;
  2325. }
  2326. }
  2327. }
  2328. // Go through each of the classes and register the object type descriptions
  2329. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2330. {
  2331. sClassDeclaration *decl = classDeclarations[n];
  2332. if( decl->isExistingShared )
  2333. {
  2334. // Set the declaration as validated already, so that other
  2335. // types that contain this will accept this type
  2336. decl->validState = 1;
  2337. // We'll still validate the declaration to make sure nothing new is
  2338. // added to the shared class that wasn't there in the previous
  2339. // compilation. We do not care if something that is there in the previous
  2340. // declaration is not included in the new declaration though.
  2341. asASSERT( decl->objType->interfaces.GetLength() == decl->objType->interfaceVFTOffsets.GetLength() );
  2342. }
  2343. // Methods included from mixin classes should take precedence over inherited methods
  2344. IncludeMethodsFromMixins(decl);
  2345. // Add all properties and methods from the base class
  2346. if( !decl->isExistingShared && decl->objType->derivedFrom )
  2347. {
  2348. asCObjectType *baseType = decl->objType->derivedFrom;
  2349. // The derived class inherits all interfaces from the base class
  2350. for( unsigned int n = 0; n < baseType->interfaces.GetLength(); n++ )
  2351. {
  2352. if( !decl->objType->Implements(baseType->interfaces[n]) )
  2353. decl->objType->interfaces.PushLast(baseType->interfaces[n]);
  2354. }
  2355. // TODO: Need to check for name conflict with new class methods
  2356. // Copy properties from base class to derived class
  2357. for( asUINT p = 0; p < baseType->properties.GetLength(); p++ )
  2358. {
  2359. asCObjectProperty *prop = AddPropertyToClass(decl, baseType->properties[p]->name, baseType->properties[p]->type, baseType->properties[p]->isPrivate, baseType->properties[p]->isProtected, true);
  2360. // The properties must maintain the same offset
  2361. asASSERT(prop && prop->byteOffset == baseType->properties[p]->byteOffset); UNUSED_VAR(prop);
  2362. }
  2363. // Copy methods from base class to derived class
  2364. for( asUINT m = 0; m < baseType->methods.GetLength(); m++ )
  2365. {
  2366. // If the derived class implements the same method, then don't add the base class' method
  2367. asCScriptFunction *baseFunc = GetFunctionDescription(baseType->methods[m]);
  2368. asCScriptFunction *derivedFunc = 0;
  2369. bool found = false;
  2370. for( asUINT d = 0; d < decl->objType->methods.GetLength(); d++ )
  2371. {
  2372. derivedFunc = GetFunctionDescription(decl->objType->methods[d]);
  2373. if( baseFunc->name == "opConv" || baseFunc->name == "opImplConv" ||
  2374. baseFunc->name == "opCast" || baseFunc->name == "opImplCast" )
  2375. {
  2376. // For the opConv and opCast methods, the return type can differ if they are different methods
  2377. if( derivedFunc->name == baseFunc->name &&
  2378. derivedFunc->IsSignatureExceptNameEqual(baseFunc) )
  2379. {
  2380. if( baseFunc->IsFinal() )
  2381. {
  2382. asCString msg;
  2383. msg.Format(TXT_METHOD_CANNOT_OVERRIDE_s, baseFunc->GetDeclaration());
  2384. WriteError(msg, decl->script, decl->node);
  2385. }
  2386. // Move the function from the methods array to the virtualFunctionTable
  2387. decl->objType->methods.RemoveIndex(d);
  2388. decl->objType->virtualFunctionTable.PushLast(derivedFunc);
  2389. found = true;
  2390. break;
  2391. }
  2392. }
  2393. else
  2394. {
  2395. if( derivedFunc->name == baseFunc->name &&
  2396. derivedFunc->IsSignatureExceptNameAndReturnTypeEqual(baseFunc) )
  2397. {
  2398. if( baseFunc->returnType != derivedFunc->returnType )
  2399. {
  2400. asCString msg;
  2401. msg.Format(TXT_DERIVED_METHOD_MUST_HAVE_SAME_RETTYPE_s, baseFunc->GetDeclaration());
  2402. WriteError(msg, decl->script, decl->node);
  2403. }
  2404. if( baseFunc->IsFinal() )
  2405. {
  2406. asCString msg;
  2407. msg.Format(TXT_METHOD_CANNOT_OVERRIDE_s, baseFunc->GetDeclaration());
  2408. WriteError(msg, decl->script, decl->node);
  2409. }
  2410. // Move the function from the methods array to the virtualFunctionTable
  2411. decl->objType->methods.RemoveIndex(d);
  2412. decl->objType->virtualFunctionTable.PushLast(derivedFunc);
  2413. found = true;
  2414. break;
  2415. }
  2416. }
  2417. }
  2418. if( !found )
  2419. {
  2420. // Push the base class function on the virtual function table
  2421. decl->objType->virtualFunctionTable.PushLast(baseType->virtualFunctionTable[m]);
  2422. baseType->virtualFunctionTable[m]->AddRefInternal();
  2423. CheckForConflictsDueToDefaultArgs(decl->script, decl->node, baseType->virtualFunctionTable[m], decl->objType);
  2424. }
  2425. decl->objType->methods.PushLast(baseType->methods[m]);
  2426. engine->scriptFunctions[baseType->methods[m]]->AddRefInternal();
  2427. }
  2428. }
  2429. if( !decl->isExistingShared )
  2430. {
  2431. // Move this class' methods into the virtual function table
  2432. for( asUINT m = 0; m < decl->objType->methods.GetLength(); m++ )
  2433. {
  2434. asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[m]);
  2435. if( func->funcType != asFUNC_VIRTUAL )
  2436. {
  2437. // Move the reference from the method list to the virtual function list
  2438. decl->objType->methods.RemoveIndex(m);
  2439. decl->objType->virtualFunctionTable.PushLast(func);
  2440. // Substitute the function description in the method list for a virtual method
  2441. // Make sure the methods are in the same order as the virtual function table
  2442. decl->objType->methods.PushLast(CreateVirtualFunction(func, (int)decl->objType->virtualFunctionTable.GetLength() - 1));
  2443. m--;
  2444. }
  2445. }
  2446. // Make virtual function table chunks for each implemented interface
  2447. for( asUINT n = 0; n < decl->objType->interfaces.GetLength(); n++ )
  2448. {
  2449. asCObjectType *intf = decl->objType->interfaces[n];
  2450. // Add all the interface's functions to the virtual function table
  2451. asUINT offset = asUINT(decl->objType->virtualFunctionTable.GetLength());
  2452. decl->objType->interfaceVFTOffsets.PushLast(offset);
  2453. for( asUINT j = 0; j < intf->methods.GetLength(); j++ )
  2454. {
  2455. asCScriptFunction *intfFunc = GetFunctionDescription(intf->methods[j]);
  2456. // Only create the table for functions that are explicitly from this interface,
  2457. // inherited interface methods will be put in that interface's table.
  2458. if( intfFunc->objectType != intf )
  2459. continue;
  2460. asASSERT((asUINT)intfFunc->vfTableIdx == j);
  2461. //Find the interface function in the list of methods
  2462. asCScriptFunction *realFunc = 0;
  2463. for( asUINT p = 0; p < decl->objType->methods.GetLength(); p++ )
  2464. {
  2465. asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[p]);
  2466. if( func->signatureId == intfFunc->signatureId )
  2467. {
  2468. if( func->funcType == asFUNC_VIRTUAL )
  2469. {
  2470. realFunc = decl->objType->virtualFunctionTable[func->vfTableIdx];
  2471. }
  2472. else
  2473. {
  2474. // This should not happen, all methods were moved into the virtual table
  2475. asASSERT(false);
  2476. }
  2477. break;
  2478. }
  2479. }
  2480. // If realFunc is still null, the interface was not
  2481. // implemented and we error out later in the checks.
  2482. decl->objType->virtualFunctionTable.PushLast(realFunc);
  2483. if( realFunc )
  2484. realFunc->AddRefInternal();
  2485. }
  2486. }
  2487. }
  2488. // Enumerate each of the declared properties
  2489. asCScriptNode *node = decl->node->firstChild->next;
  2490. // Skip list of classes and interfaces
  2491. while( node && node->nodeType == snIdentifier )
  2492. node = node->next;
  2493. while( node )
  2494. {
  2495. if( node->nodeType == snDeclaration )
  2496. {
  2497. asCScriptNode *n = node->firstChild;
  2498. // Is the property declared as private or protected?
  2499. bool isPrivate = false, isProtected = false;
  2500. if( n && n->tokenType == ttPrivate )
  2501. {
  2502. isPrivate = true;
  2503. n = n->next;
  2504. }
  2505. else if( n && n->tokenType == ttProtected )
  2506. {
  2507. isProtected = true;
  2508. n = n->next;
  2509. }
  2510. // Determine the type of the property
  2511. asCScriptCode *file = decl->script;
  2512. asCDataType dt = CreateDataTypeFromNode(n, file, decl->objType->nameSpace);
  2513. if( decl->objType->IsShared() && dt.GetObjectType() && !dt.GetObjectType()->IsShared() )
  2514. {
  2515. asCString msg;
  2516. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf());
  2517. WriteError(msg, file, node);
  2518. }
  2519. if( dt.IsReadOnly() )
  2520. WriteError(TXT_PROPERTY_CANT_BE_CONST, file, node);
  2521. // Multiple properties can be declared separated by ,
  2522. n = n->next;
  2523. while( n )
  2524. {
  2525. asCString name(&file->code[n->tokenPos], n->tokenLength);
  2526. if( !decl->isExistingShared )
  2527. {
  2528. CheckNameConflictMember(decl->objType, name.AddressOf(), n, file, true);
  2529. AddPropertyToClass(decl, name, dt, isPrivate, isProtected, false, file, n);
  2530. }
  2531. else
  2532. {
  2533. // Verify that the property exists in the original declaration
  2534. bool found = false;
  2535. for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ )
  2536. {
  2537. asCObjectProperty *prop = decl->objType->properties[p];
  2538. if( prop->isPrivate == isPrivate &&
  2539. prop->isProtected == isProtected &&
  2540. prop->name == name &&
  2541. prop->type.IsEqualExceptRef(dt) )
  2542. {
  2543. found = true;
  2544. break;
  2545. }
  2546. }
  2547. if( !found )
  2548. {
  2549. asCString str;
  2550. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  2551. WriteError(str, file, n);
  2552. }
  2553. }
  2554. // Skip the initialization node
  2555. if( n->next && n->next->nodeType != snIdentifier )
  2556. n = n->next;
  2557. n = n->next;
  2558. }
  2559. }
  2560. else
  2561. asASSERT(false);
  2562. node = node->next;
  2563. }
  2564. // Add properties from included mixin classes that don't conflict with existing properties
  2565. IncludePropertiesFromMixins(decl);
  2566. if( !decl->isExistingShared )
  2567. toValidate.PushLast(decl);
  2568. asASSERT( decl->objType->interfaces.GetLength() == decl->objType->interfaceVFTOffsets.GetLength() );
  2569. }
  2570. // TODO: Warn if a method overrides a base method without marking it as 'override'.
  2571. // It must be possible to turn off this warning through engine property.
  2572. // TODO: A base class should be able to mark a method as 'abstract'. This will
  2573. // allow a base class to provide a partial implementation, but still force
  2574. // derived classes to implement specific methods.
  2575. // Verify that all interface methods are implemented in the classes
  2576. // We do this here so the base class' methods have already been inherited
  2577. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2578. {
  2579. sClassDeclaration *decl = classDeclarations[n];
  2580. if( decl->isExistingShared ) continue;
  2581. asCArray<bool> overrideValidations(decl->objType->GetMethodCount());
  2582. for( asUINT k = 0; k < decl->objType->methods.GetLength(); k++ )
  2583. overrideValidations.PushLast( !static_cast<asCScriptFunction*>(decl->objType->GetMethodByIndex(k, false))->IsOverride() );
  2584. for( asUINT m = 0; m < decl->objType->interfaces.GetLength(); m++ )
  2585. {
  2586. asCObjectType *objType = decl->objType->interfaces[m];
  2587. for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
  2588. {
  2589. // Only check the interface methods that was explicitly declared in this interface
  2590. // Methods that was inherited from other interfaces will be checked in those interfaces
  2591. if( objType != engine->scriptFunctions[objType->methods[i]]->objectType )
  2592. continue;
  2593. asUINT overrideIndex;
  2594. if( !DoesMethodExist(decl->objType, objType->methods[i], &overrideIndex) )
  2595. {
  2596. asCString str;
  2597. str.Format(TXT_MISSING_IMPLEMENTATION_OF_s,
  2598. engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
  2599. WriteError(str, decl->script, decl->node);
  2600. }
  2601. else
  2602. overrideValidations[overrideIndex] = true;
  2603. }
  2604. }
  2605. bool hasBaseClass = decl->objType->derivedFrom != 0;
  2606. for( asUINT j = 0; j < overrideValidations.GetLength(); j++ )
  2607. {
  2608. if( !overrideValidations[j] && (!hasBaseClass || !DoesMethodExist(decl->objType->derivedFrom, decl->objType->methods[j])) )
  2609. {
  2610. asCString msg;
  2611. msg.Format(TXT_METHOD_s_DOES_NOT_OVERRIDE, decl->objType->GetMethodByIndex(j, false)->GetDeclaration());
  2612. WriteError(msg, decl->script, decl->node);
  2613. }
  2614. }
  2615. }
  2616. // Verify that the declared structures are valid, e.g. that the structure
  2617. // doesn't contain a member of its own type directly or indirectly
  2618. while( toValidate.GetLength() > 0 )
  2619. {
  2620. asUINT numClasses = (asUINT)toValidate.GetLength();
  2621. asCArray<sClassDeclaration*> toValidateNext((int)toValidate.GetLength());
  2622. while( toValidate.GetLength() > 0 )
  2623. {
  2624. sClassDeclaration *decl = toValidate[toValidate.GetLength()-1];
  2625. int validState = 1;
  2626. for( asUINT n = 0; n < decl->objType->properties.GetLength(); n++ )
  2627. {
  2628. // A valid structure is one that uses only primitives or other valid objects
  2629. asCObjectProperty *prop = decl->objType->properties[n];
  2630. asCDataType dt = prop->type;
  2631. // TODO: Add this check again, once solving the issues commented below
  2632. /*
  2633. if( dt.IsTemplate() )
  2634. {
  2635. // TODO: This must verify all sub types, not just the first one
  2636. // TODO: Just because the subtype is not a handle doesn't mean the template will actually instance the object
  2637. // this it shouldn't automatically raise an error for this, e.g. weakref<Object> should be legal as member
  2638. // of the Object class
  2639. asCDataType sub = dt;
  2640. while( sub.IsTemplate() && !sub.IsObjectHandle() )
  2641. sub = sub.GetSubType();
  2642. dt = sub;
  2643. }
  2644. */
  2645. if( dt.IsObject() && !dt.IsObjectHandle() )
  2646. {
  2647. // Find the class declaration
  2648. sClassDeclaration *pdecl = 0;
  2649. for( asUINT p = 0; p < classDeclarations.GetLength(); p++ )
  2650. {
  2651. if( classDeclarations[p]->objType == dt.GetObjectType() )
  2652. {
  2653. pdecl = classDeclarations[p];
  2654. break;
  2655. }
  2656. }
  2657. if( pdecl )
  2658. {
  2659. if( pdecl->objType == decl->objType )
  2660. {
  2661. WriteError(TXT_ILLEGAL_MEMBER_TYPE, decl->script, decl->node);
  2662. validState = 2;
  2663. break;
  2664. }
  2665. else if( pdecl->validState != 1 )
  2666. {
  2667. validState = pdecl->validState;
  2668. break;
  2669. }
  2670. }
  2671. }
  2672. }
  2673. if( validState == 1 )
  2674. {
  2675. decl->validState = 1;
  2676. toValidate.PopLast();
  2677. }
  2678. else if( validState == 2 )
  2679. {
  2680. decl->validState = 2;
  2681. toValidate.PopLast();
  2682. }
  2683. else
  2684. {
  2685. toValidateNext.PushLast(toValidate.PopLast());
  2686. }
  2687. }
  2688. toValidate = toValidateNext;
  2689. toValidateNext.SetLength(0);
  2690. if( numClasses == toValidate.GetLength() )
  2691. {
  2692. WriteError(TXT_ILLEGAL_MEMBER_TYPE, toValidate[0]->script, toValidate[0]->node);
  2693. break;
  2694. }
  2695. }
  2696. if( numErrors > 0 ) return;
  2697. // Verify which script classes can really form circular references, and mark only those as garbage collected.
  2698. // This must be done in the correct order, so that a class that contains another class isn't needlessly marked
  2699. // as garbage collected, just because the contained class was evaluated afterwards.
  2700. // TODO: runtime optimize: This algorithm can be further improved by checking the types that inherits from
  2701. // a base class. If the base class is not shared all the classes that derive from it
  2702. // are known at compile time, and can thus be checked for potential circular references too.
  2703. //
  2704. // Observe, that doing this would conflict with another potential future feature, which is to
  2705. // allow incremental builds, i.e. allow application to add or replace classes in an
  2706. // existing module. However, the applications that want to use that should use a special
  2707. // build flag to not finalize the module.
  2708. // Urho3D: disable garbage collection from script classes
  2709. /*
  2710. for( n = 0; n < classDeclarations.GetLength(); n++ )
  2711. {
  2712. // Existing shared classes won't need evaluating, nor interfaces
  2713. sClassDeclaration *decl = classDeclarations[n];
  2714. if( decl->isExistingShared ) continue;
  2715. if( decl->objType->IsInterface() ) continue;
  2716. typesToValidate.PushLast(decl->objType);
  2717. }
  2718. asUINT numReevaluations = 0;
  2719. while( typesToValidate.GetLength() )
  2720. {
  2721. if( numReevaluations > typesToValidate.GetLength() )
  2722. {
  2723. // No types could be completely evaluated in the last iteration so
  2724. // we consider the remaining types in the array as garbage collected
  2725. break;
  2726. }
  2727. asCObjectType *type = typesToValidate[0];
  2728. typesToValidate.RemoveIndex(0);
  2729. // If the type inherits from another type that is yet to be validated, then reinsert it at the end
  2730. if( type->derivedFrom && typesToValidate.Exists(type->derivedFrom) )
  2731. {
  2732. typesToValidate.PushLast(type);
  2733. numReevaluations++;
  2734. continue;
  2735. }
  2736. // If the type inherits from a known garbage collected type, then this type must also be garbage collected
  2737. if( type->derivedFrom && (type->derivedFrom->flags & asOBJ_GC) )
  2738. {
  2739. type->flags |= asOBJ_GC;
  2740. continue;
  2741. }
  2742. // Evaluate template instances (silently) before verifying each of the classes, since it is possible that
  2743. // a class will be marked as non-garbage collected, which in turn will mark the template instance that uses
  2744. // it as non-garbage collected, which in turn means the class that contains the array also do not have to be
  2745. // garbage collected
  2746. EvaluateTemplateInstances(numTempl, true);
  2747. // Is there some path in which this structure is involved in circular references?
  2748. // If the type contains a member of a type that is yet to be validated, then reinsert it at the end
  2749. bool mustReevaluate = false;
  2750. bool gc = false;
  2751. for( asUINT p = 0; p < type->properties.GetLength(); p++ )
  2752. {
  2753. asCDataType dt = type->properties[p]->type;
  2754. if( !dt.IsObject() )
  2755. continue;
  2756. if( typesToValidate.Exists(dt.GetObjectType()) )
  2757. mustReevaluate = true;
  2758. else
  2759. {
  2760. if( dt.IsTemplate() )
  2761. {
  2762. // Check if any of the subtypes are yet to be evaluated
  2763. bool skip = false;
  2764. for( asUINT s = 0; s < dt.GetObjectType()->GetSubTypeCount(); s++ )
  2765. {
  2766. asCObjectType *t = reinterpret_cast<asCObjectType*>(dt.GetObjectType()->GetSubType(s));
  2767. if( typesToValidate.Exists(t) )
  2768. {
  2769. mustReevaluate = true;
  2770. skip = true;
  2771. break;
  2772. }
  2773. }
  2774. if( skip )
  2775. continue;
  2776. }
  2777. if( dt.IsObjectHandle() )
  2778. {
  2779. // If it is known that the handle can't be involved in a circular reference
  2780. // then this object doesn't need to be marked as garbage collected.
  2781. asCObjectType *prop = dt.GetObjectType();
  2782. if( prop->flags & asOBJ_SCRIPT_OBJECT )
  2783. {
  2784. // For script objects, treat non-final classes as if they can contain references
  2785. // as it is not known what derived classes might do. For final types, check all
  2786. // properties to determine if any of those can cause a circular reference with this
  2787. // class.
  2788. if( prop->flags & asOBJ_NOINHERIT )
  2789. {
  2790. for( asUINT sp = 0; sp < prop->properties.GetLength(); sp++ )
  2791. {
  2792. asCDataType sdt = prop->properties[sp]->type;
  2793. if( sdt.IsObject() )
  2794. {
  2795. if( sdt.IsObjectHandle() )
  2796. {
  2797. // TODO: runtime optimize: If the handle is again to a final class, then we can recursively check if the circular reference can occur
  2798. if( sdt.GetObjectType()->flags & (asOBJ_SCRIPT_OBJECT | asOBJ_GC) )
  2799. {
  2800. gc = true;
  2801. break;
  2802. }
  2803. }
  2804. else if( sdt.GetObjectType()->flags & asOBJ_GC )
  2805. {
  2806. // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is.
  2807. // Only if the object is of a type that can reference this type, either directly or indirectly
  2808. gc = true;
  2809. break;
  2810. }
  2811. }
  2812. }
  2813. if( gc )
  2814. break;
  2815. }
  2816. else
  2817. {
  2818. // Assume it is garbage collected as it is not known at compile time what might inherit from this type
  2819. gc = true;
  2820. break;
  2821. }
  2822. }
  2823. else if( prop->flags & asOBJ_GC )
  2824. {
  2825. // If a type is not a script object, adopt its GC flag
  2826. // TODO: runtime optimize: Just because an application registered class is garbage collected, doesn't mean it
  2827. // can form a circular reference with this script class. Perhaps need a flag to tell
  2828. // if the script classes that contains the type should be garbage collected or not.
  2829. gc = true;
  2830. break;
  2831. }
  2832. }
  2833. else if( dt.GetObjectType()->flags & asOBJ_GC )
  2834. {
  2835. // TODO: runtime optimize: Just because the member type is a potential circle doesn't mean that this one is.
  2836. // Only if the object is of a type that can reference this type, either directly or indirectly
  2837. gc = true;
  2838. break;
  2839. }
  2840. }
  2841. }
  2842. // If the class wasn't found to require garbage collection, but it
  2843. // contains another type that has yet to be evaluated then it must be
  2844. // re-evaluated.
  2845. if( !gc && mustReevaluate )
  2846. {
  2847. typesToValidate.PushLast(type);
  2848. numReevaluations++;
  2849. continue;
  2850. }
  2851. // Update the flag in the object type
  2852. if( gc )
  2853. type->flags |= asOBJ_GC;
  2854. else
  2855. type->flags &= ~asOBJ_GC;
  2856. // Reset the counter
  2857. numReevaluations = 0;
  2858. }
  2859. */
  2860. }
  2861. void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl)
  2862. {
  2863. asCScriptNode *node = decl->node->firstChild;
  2864. // Skip the class attributes
  2865. while( node->nodeType == snIdentifier &&
  2866. !decl->script->TokenEquals(node->tokenPos, node->tokenLength, decl->name.AddressOf()) )
  2867. node = node->next;
  2868. // Skip the name of the class
  2869. node = node->next;
  2870. // Find the included mixin classes
  2871. while( node && node->nodeType == snIdentifier )
  2872. {
  2873. asSNameSpace *ns;
  2874. asCString name;
  2875. if( GetNamespaceAndNameFromNode(node, decl->script, decl->objType->nameSpace, ns, name) < 0 )
  2876. {
  2877. node = node->next;
  2878. continue;
  2879. }
  2880. sMixinClass *mixin = 0;
  2881. while( ns )
  2882. {
  2883. // Need to make sure the name is not an object type
  2884. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  2885. if( objType == 0 )
  2886. mixin = GetMixinClass(name.AddressOf(), ns);
  2887. if( objType || mixin )
  2888. break;
  2889. ns = engine->GetParentNameSpace(ns);
  2890. }
  2891. if( mixin )
  2892. {
  2893. // Find methods from mixin declaration
  2894. asCScriptNode *n = mixin->node->firstChild;
  2895. // Skip to the member declarations
  2896. // Possible keywords 'final' and 'shared' are removed in RegisterMixinClass so we don't need to worry about those here
  2897. while( n && n->nodeType == snIdentifier )
  2898. n = n->next;
  2899. // Add methods from the mixin that are not already existing in the class
  2900. while( n )
  2901. {
  2902. if( n->nodeType == snFunction )
  2903. {
  2904. // Instead of disconnecting the node, we need to clone it, otherwise other
  2905. // classes that include the same mixin will not see the methods
  2906. asCScriptNode *copy = n->CreateCopy(engine);
  2907. // Register the method, but only if it doesn't already exist in the class
  2908. RegisterScriptFunctionFromNode(copy, mixin->script, decl->objType, false, false, mixin->ns, false, true);
  2909. }
  2910. else if( n->nodeType == snVirtualProperty )
  2911. {
  2912. // TODO: mixin: Support virtual properties too
  2913. WriteError("The virtual property syntax is currently not supported for mixin classes", mixin->script, n);
  2914. //RegisterVirtualProperty(node, decl->script, decl->objType, false, false);
  2915. }
  2916. n = n->next;
  2917. }
  2918. }
  2919. node = node->next;
  2920. }
  2921. }
  2922. void asCBuilder::IncludePropertiesFromMixins(sClassDeclaration *decl)
  2923. {
  2924. asCScriptNode *node = decl->node->firstChild;
  2925. // Skip the class attributes
  2926. while( node->nodeType == snIdentifier &&
  2927. !decl->script->TokenEquals(node->tokenPos, node->tokenLength, decl->name.AddressOf()) )
  2928. node = node->next;
  2929. // Skip the name of the class
  2930. node = node->next;
  2931. // Find the included mixin classes
  2932. while( node && node->nodeType == snIdentifier )
  2933. {
  2934. asSNameSpace *ns;
  2935. asCString name;
  2936. if( GetNamespaceAndNameFromNode(node, decl->script, decl->objType->nameSpace, ns, name) < 0 )
  2937. {
  2938. node = node->next;
  2939. continue;
  2940. }
  2941. sMixinClass *mixin = 0;
  2942. while( ns )
  2943. {
  2944. // Need to make sure the name is not an object type
  2945. asCObjectType *objType = GetObjectType(name.AddressOf(), ns);
  2946. if( objType == 0 )
  2947. mixin = GetMixinClass(name.AddressOf(), ns);
  2948. if( objType || mixin )
  2949. break;
  2950. ns = engine->GetParentNameSpace(ns);
  2951. }
  2952. if( mixin )
  2953. {
  2954. // Find properties from mixin declaration
  2955. asCScriptNode *n = mixin->node->firstChild;
  2956. // Skip to the member declarations
  2957. // Possible keywords 'final' and 'shared' are removed in RegisterMixinClass so we don't need to worry about those here
  2958. while( n && n->nodeType == snIdentifier )
  2959. n = n->next;
  2960. // Add properties from the mixin that are not already existing in the class
  2961. while( n )
  2962. {
  2963. if( n->nodeType == snDeclaration )
  2964. {
  2965. asCScriptNode *n2 = n->firstChild;
  2966. bool isPrivate = false, isProtected = false;
  2967. if( n2 && n2->tokenType == ttPrivate )
  2968. {
  2969. isPrivate = true;
  2970. n2 = n2->next;
  2971. }
  2972. else if( n2 && n2->tokenType == ttProtected )
  2973. {
  2974. isProtected = true;
  2975. n2 = n2->next;
  2976. }
  2977. asCScriptCode *file = mixin->script;
  2978. asCDataType dt = CreateDataTypeFromNode(n2, file, mixin->ns);
  2979. if( decl->objType->IsShared() && dt.GetObjectType() && !dt.GetObjectType()->IsShared() )
  2980. {
  2981. asCString msg;
  2982. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, dt.GetObjectType()->name.AddressOf());
  2983. WriteError(msg, file, n);
  2984. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  2985. }
  2986. if( dt.IsReadOnly() )
  2987. WriteError(TXT_PROPERTY_CANT_BE_CONST, file, n);
  2988. n2 = n2->next;
  2989. while( n2 )
  2990. {
  2991. asCString name(&file->code[n2->tokenPos], n2->tokenLength);
  2992. // Add the property only if it doesn't already exist in the class
  2993. bool exists = false;
  2994. for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ )
  2995. if( decl->objType->properties[p]->name == name )
  2996. {
  2997. exists = true;
  2998. break;
  2999. }
  3000. if( !exists )
  3001. {
  3002. if( !decl->isExistingShared )
  3003. {
  3004. // It must not conflict with the name of methods
  3005. int r = CheckNameConflictMember(decl->objType, name.AddressOf(), n2, file, true);
  3006. if( r < 0 )
  3007. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  3008. AddPropertyToClass(decl, name, dt, isPrivate, isProtected, false, file, n2);
  3009. }
  3010. else
  3011. {
  3012. // Verify that the property exists in the original declaration
  3013. bool found = false;
  3014. for( asUINT p = 0; p < decl->objType->properties.GetLength(); p++ )
  3015. {
  3016. asCObjectProperty *prop = decl->objType->properties[p];
  3017. if( prop->isPrivate == isPrivate &&
  3018. prop->isProtected == isProtected &&
  3019. prop->name == name &&
  3020. prop->type == dt )
  3021. {
  3022. found = true;
  3023. break;
  3024. }
  3025. }
  3026. if( !found )
  3027. {
  3028. asCString str;
  3029. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, decl->objType->GetName());
  3030. WriteError(str, decl->script, decl->node);
  3031. WriteInfo(TXT_WHILE_INCLUDING_MIXIN, decl->script, node);
  3032. }
  3033. }
  3034. }
  3035. // Skip the initialization expression
  3036. if( n2->next && n2->next->nodeType != snIdentifier )
  3037. n2 = n2->next;
  3038. n2 = n2->next;
  3039. }
  3040. }
  3041. n = n->next;
  3042. }
  3043. }
  3044. node = node->next;
  3045. }
  3046. }
  3047. int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
  3048. {
  3049. asCScriptFunction *vf = asNEW(asCScriptFunction)(engine, module, asFUNC_VIRTUAL);
  3050. if( vf == 0 )
  3051. return asOUT_OF_MEMORY;
  3052. vf->name = func->name;
  3053. vf->returnType = func->returnType;
  3054. vf->parameterTypes = func->parameterTypes;
  3055. vf->inOutFlags = func->inOutFlags;
  3056. vf->id = engine->GetNextScriptFunctionId();
  3057. vf->isReadOnly = func->isReadOnly;
  3058. vf->objectType = func->objectType;
  3059. vf->objectType->AddRefInternal();
  3060. vf->signatureId = func->signatureId;
  3061. vf->isPrivate = func->isPrivate;
  3062. vf->isProtected = func->isProtected;
  3063. vf->isFinal = func->isFinal;
  3064. vf->isOverride = func->isOverride;
  3065. vf->vfTableIdx = idx;
  3066. // It is not necessary to copy the default args, as they have no meaning in the virtual function
  3067. module->AddScriptFunction(vf);
  3068. // Add a dummy to the builder so that it doesn't mix up function ids
  3069. functions.PushLast(0);
  3070. return vf->id;
  3071. }
  3072. asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const asCString &name, const asCDataType &dt, bool isPrivate, bool isProtected, bool isInherited, asCScriptCode *file, asCScriptNode *node)
  3073. {
  3074. if( node )
  3075. {
  3076. asASSERT(!isInherited);
  3077. // Check if the property is allowed
  3078. if( !dt.CanBeInstantiated() )
  3079. {
  3080. if( file && node )
  3081. {
  3082. asCString str;
  3083. if( dt.IsAbstractClass() )
  3084. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->objType->nameSpace).AddressOf());
  3085. else if( dt.IsInterface() )
  3086. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(decl->objType->nameSpace).AddressOf());
  3087. else
  3088. // TODO: Improve error message to explain why
  3089. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(decl->objType->nameSpace).AddressOf());
  3090. WriteError(str, file, node);
  3091. }
  3092. return 0;
  3093. }
  3094. // Register the initialization expression (if any) to be compiled later
  3095. asCScriptNode *declNode = node;
  3096. asCScriptNode *initNode = 0;
  3097. if( node->next && node->next->nodeType != snIdentifier )
  3098. {
  3099. asASSERT( node->next->nodeType == snAssignment );
  3100. initNode = node->next;
  3101. }
  3102. sPropertyInitializer p(name, declNode, initNode, file);
  3103. decl->propInits.PushLast(p);
  3104. }
  3105. else
  3106. {
  3107. // If the declaration node is not given, then
  3108. // this property is inherited from a base class
  3109. asASSERT(isInherited);
  3110. }
  3111. // Add the property to the object type
  3112. return decl->objType->AddPropertyToClass(name, dt, isPrivate, isProtected, isInherited);
  3113. }
  3114. bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex)
  3115. {
  3116. asCScriptFunction *method = GetFunctionDescription(methodId);
  3117. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  3118. {
  3119. asCScriptFunction *m = GetFunctionDescription(objType->methods[n]);
  3120. if( m->name != method->name ) continue;
  3121. if( m->returnType != method->returnType ) continue;
  3122. if( m->isReadOnly != method->isReadOnly ) continue;
  3123. if( m->parameterTypes != method->parameterTypes ) continue;
  3124. if( m->inOutFlags != method->inOutFlags ) continue;
  3125. if( methodIndex )
  3126. *methodIndex = n;
  3127. return true;
  3128. }
  3129. return false;
  3130. }
  3131. void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file)
  3132. {
  3133. int funcId = engine->GetNextScriptFunctionId();
  3134. asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false);
  3135. asCArray<asCDataType> parameterTypes;
  3136. asCArray<asETypeModifiers> inOutFlags;
  3137. asCArray<asCString *> defaultArgs;
  3138. asCArray<asCString> parameterNames;
  3139. // Add the script function
  3140. // TODO: declaredAt should be set to where the class has been declared
  3141. module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false, objType);
  3142. // Set it as default constructor
  3143. if( objType->beh.construct )
  3144. engine->scriptFunctions[objType->beh.construct]->ReleaseInternal();
  3145. objType->beh.construct = funcId;
  3146. objType->beh.constructors[0] = funcId;
  3147. engine->scriptFunctions[funcId]->AddRefInternal();
  3148. // The bytecode for the default constructor will be generated
  3149. // only after the potential inheritance has been established
  3150. sFunctionDescription *func = asNEW(sFunctionDescription);
  3151. if( func == 0 )
  3152. {
  3153. // Out of memory
  3154. return;
  3155. }
  3156. functions.PushLast(func);
  3157. func->script = file;
  3158. func->node = 0;
  3159. func->name = objType->name;
  3160. func->objType = objType;
  3161. func->funcId = funcId;
  3162. func->isExistingShared = false;
  3163. // Add a default factory as well
  3164. funcId = engine->GetNextScriptFunctionId();
  3165. if( objType->beh.factory )
  3166. engine->scriptFunctions[objType->beh.factory]->ReleaseInternal();
  3167. objType->beh.factory = funcId;
  3168. objType->beh.factories[0] = funcId;
  3169. returnType = asCDataType::CreateObjectHandle(objType, false);
  3170. // TODO: should be the same as the constructor
  3171. module->AddScriptFunction(file->idx, 0, funcId, objType->name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, false);
  3172. functions.PushLast(0);
  3173. asCCompiler compiler(engine);
  3174. compiler.CompileFactory(this, file, engine->scriptFunctions[funcId]);
  3175. engine->scriptFunctions[funcId]->AddRefInternal();
  3176. // If the object is shared, then the factory must also be marked as shared
  3177. if( objType->flags & asOBJ_SHARED )
  3178. engine->scriptFunctions[funcId]->isShared = true;
  3179. }
  3180. int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  3181. {
  3182. // Is it a shared enum?
  3183. bool isShared = false;
  3184. asCObjectType *existingSharedType = 0;
  3185. asCScriptNode *tmp = node->firstChild;
  3186. if( tmp->nodeType == snIdentifier && file->TokenEquals(tmp->tokenPos, tmp->tokenLength, SHARED_TOKEN) )
  3187. {
  3188. isShared = true;
  3189. tmp = tmp->next;
  3190. }
  3191. // Grab the name of the enumeration
  3192. asCString name;
  3193. asASSERT(snDataType == tmp->nodeType);
  3194. asASSERT(snIdentifier == tmp->firstChild->nodeType);
  3195. name.Assign(&file->code[tmp->firstChild->tokenPos], tmp->firstChild->tokenLength);
  3196. if( isShared )
  3197. {
  3198. // Look for a pre-existing shared enum with the same signature
  3199. for( asUINT n = 0; n < engine->sharedScriptTypes.GetLength(); n++ )
  3200. {
  3201. asCObjectType *o = engine->sharedScriptTypes[n];
  3202. if( o &&
  3203. o->IsShared() &&
  3204. (o->flags & asOBJ_ENUM) &&
  3205. o->name == name &&
  3206. o->nameSpace == ns )
  3207. {
  3208. existingSharedType = o;
  3209. break;
  3210. }
  3211. }
  3212. }
  3213. // Check the name and add the enum
  3214. int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns);
  3215. if( asSUCCESS == r )
  3216. {
  3217. asCObjectType *st;
  3218. if( existingSharedType )
  3219. {
  3220. st = existingSharedType;
  3221. st->AddRefInternal();
  3222. }
  3223. else
  3224. {
  3225. st = asNEW(asCObjectType)(engine);
  3226. if( st == 0 )
  3227. return asOUT_OF_MEMORY;
  3228. st->flags = asOBJ_ENUM;
  3229. if( isShared )
  3230. st->flags |= asOBJ_SHARED;
  3231. st->size = 4;
  3232. st->name = name;
  3233. st->nameSpace = ns;
  3234. st->module = module;
  3235. }
  3236. module->enumTypes.PushLast(st);
  3237. if( !existingSharedType && isShared )
  3238. {
  3239. engine->sharedScriptTypes.PushLast(st);
  3240. st->AddRefInternal();
  3241. }
  3242. // Store the location of this declaration for reference in name collisions
  3243. sClassDeclaration *decl = asNEW(sClassDeclaration);
  3244. if( decl == 0 )
  3245. return asOUT_OF_MEMORY;
  3246. decl->name = name;
  3247. decl->script = file;
  3248. decl->objType = st;
  3249. namedTypeDeclarations.PushLast(decl);
  3250. asCDataType type = CreateDataTypeFromNode(tmp, file, ns);
  3251. asASSERT(!type.IsReference());
  3252. // Register the enum values
  3253. tmp = tmp->next;
  3254. while( tmp )
  3255. {
  3256. asASSERT(snIdentifier == tmp->nodeType);
  3257. asCString name(&file->code[tmp->tokenPos], tmp->tokenLength);
  3258. if( existingSharedType )
  3259. {
  3260. // If this is a pre-existent shared enum, then just double check
  3261. // that the value is already defined in the original declaration
  3262. bool found = false;
  3263. for( asUINT n = 0; n < st->enumValues.GetLength(); n++ )
  3264. if( st->enumValues[n]->name == name )
  3265. {
  3266. found = true;
  3267. break;
  3268. }
  3269. if( !found )
  3270. {
  3271. asCString str;
  3272. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, st->GetName());
  3273. WriteError(str, file, tmp);
  3274. break;
  3275. }
  3276. tmp = tmp->next;
  3277. if( tmp && tmp->nodeType == snAssignment )
  3278. tmp = tmp->next;
  3279. continue;
  3280. }
  3281. else
  3282. {
  3283. // Check for name conflict errors with other values in the enum
  3284. if( globVariables.GetFirst(ns, name, asCCompGlobVarType(type)) )
  3285. {
  3286. asCString str;
  3287. str.Format(TXT_NAME_CONFLICT_s_ALREADY_USED, name.AddressOf());
  3288. WriteError(str, file, tmp);
  3289. tmp = tmp->next;
  3290. if( tmp && tmp->nodeType == snAssignment )
  3291. tmp = tmp->next;
  3292. continue;
  3293. }
  3294. // Check for assignment
  3295. asCScriptNode *asnNode = tmp->next;
  3296. if( asnNode && snAssignment == asnNode->nodeType )
  3297. asnNode->DisconnectParent();
  3298. else
  3299. asnNode = 0;
  3300. // Create the global variable description so the enum value can be evaluated
  3301. sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
  3302. if( gvar == 0 )
  3303. return asOUT_OF_MEMORY;
  3304. gvar->script = file;
  3305. gvar->declaredAtNode = tmp;
  3306. tmp = tmp->next;
  3307. gvar->declaredAtNode->DisconnectParent();
  3308. gvar->initializationNode = asnNode;
  3309. gvar->name = name;
  3310. gvar->datatype = type;
  3311. gvar->ns = ns;
  3312. // No need to allocate space on the global memory stack since the values are stored in the asCObjectType
  3313. // Set the index to a negative to allow compiler to diferentiate from ordinary global var when compiling the initialization
  3314. gvar->index = -1;
  3315. gvar->isCompiled = false;
  3316. gvar->isPureConstant = true;
  3317. gvar->isEnumValue = true;
  3318. gvar->constantValue = 0xdeadbeef;
  3319. // Allocate dummy property so we can compile the value.
  3320. // This will be removed later on so we don't add it to the engine.
  3321. gvar->property = asNEW(asCGlobalProperty);
  3322. if( gvar->property == 0 )
  3323. return asOUT_OF_MEMORY;
  3324. gvar->property->name = name;
  3325. gvar->property->nameSpace = ns;
  3326. gvar->property->type = gvar->datatype;
  3327. gvar->property->id = 0;
  3328. globVariables.Put(gvar);
  3329. }
  3330. }
  3331. }
  3332. node->Destroy(engine);
  3333. return r;
  3334. }
  3335. int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  3336. {
  3337. // Get the native data type
  3338. asCScriptNode *tmp = node->firstChild;
  3339. asASSERT(NULL != tmp && snDataType == tmp->nodeType);
  3340. asCDataType dataType;
  3341. dataType.CreatePrimitive(tmp->tokenType, false);
  3342. dataType.SetTokenType(tmp->tokenType);
  3343. tmp = tmp->next;
  3344. // Grab the name of the typedef
  3345. asASSERT(NULL != tmp && NULL == tmp->next);
  3346. asCString name;
  3347. name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength);
  3348. // If the name is not already in use add it
  3349. int r = CheckNameConflict(name.AddressOf(), tmp, file, ns);
  3350. asCObjectType *st = 0;
  3351. if( asSUCCESS == r )
  3352. {
  3353. // Create the new type
  3354. st = asNEW(asCObjectType)(engine);
  3355. if( st == 0 )
  3356. r = asOUT_OF_MEMORY;
  3357. }
  3358. if( asSUCCESS == r )
  3359. {
  3360. st->flags = asOBJ_TYPEDEF;
  3361. st->size = dataType.GetSizeInMemoryBytes();
  3362. st->name = name;
  3363. st->nameSpace = ns;
  3364. st->templateSubTypes.PushLast(dataType);
  3365. st->module = module;
  3366. module->typeDefs.PushLast(st);
  3367. // Store the location of this declaration for reference in name collisions
  3368. sClassDeclaration *decl = asNEW(sClassDeclaration);
  3369. if( decl == 0 )
  3370. r = asOUT_OF_MEMORY;
  3371. else
  3372. {
  3373. decl->name = name;
  3374. decl->script = file;
  3375. decl->objType = st;
  3376. namedTypeDeclarations.PushLast(decl);
  3377. }
  3378. }
  3379. node->Destroy(engine);
  3380. return r;
  3381. }
  3382. void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isProtected, bool &isOverride, bool &isFinal, bool &isShared, asSNameSpace *implicitNamespace)
  3383. {
  3384. node = node->firstChild;
  3385. // Is the function a private or protected class method?
  3386. isPrivate = false, isProtected = false;
  3387. if( node->tokenType == ttPrivate )
  3388. {
  3389. isPrivate = true;
  3390. node = node->next;
  3391. }
  3392. else if( node->tokenType == ttProtected )
  3393. {
  3394. isProtected = true;
  3395. node = node->next;
  3396. }
  3397. // Is the function shared?
  3398. isShared = false;
  3399. if( node->tokenType == ttIdentifier && file->TokenEquals(node->tokenPos, node->tokenLength, SHARED_TOKEN) )
  3400. {
  3401. isShared = true;
  3402. node = node->next;
  3403. }
  3404. // Find the name
  3405. isConstructor = false;
  3406. isDestructor = false;
  3407. asCScriptNode *n = 0;
  3408. if( node->nodeType == snDataType )
  3409. n = node->next->next;
  3410. else
  3411. {
  3412. // If the first node is a ~ token, then we know it is a destructor
  3413. if( node->tokenType == ttBitNot )
  3414. {
  3415. n = node->next;
  3416. isDestructor = true;
  3417. }
  3418. else
  3419. {
  3420. n = node;
  3421. isConstructor = true;
  3422. }
  3423. }
  3424. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  3425. // Initialize a script function object for registration
  3426. if( !isConstructor && !isDestructor )
  3427. {
  3428. returnType = CreateDataTypeFromNode(node, file, implicitNamespace);
  3429. returnType = ModifyDataTypeFromNode(returnType, node->next, file, 0, 0);
  3430. if( engine->ep.disallowValueAssignForRefType &&
  3431. returnType.GetObjectType() &&
  3432. (returnType.GetObjectType()->flags & asOBJ_REF) &&
  3433. !(returnType.GetObjectType()->flags & asOBJ_SCOPED) &&
  3434. !returnType.IsReference() &&
  3435. !returnType.IsObjectHandle() )
  3436. {
  3437. WriteError(TXT_REF_TYPE_CANT_BE_RETURNED_BY_VAL, file, node);
  3438. }
  3439. }
  3440. else
  3441. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  3442. isConstMethod = false;
  3443. isFinal = false;
  3444. isOverride = false;
  3445. if( objType && n->next->next )
  3446. {
  3447. asCScriptNode *decorator = n->next->next;
  3448. // Is this a const method?
  3449. if( decorator->tokenType == ttConst )
  3450. {
  3451. isConstMethod = true;
  3452. decorator = decorator->next;
  3453. }
  3454. while( decorator )
  3455. {
  3456. if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, FINAL_TOKEN) )
  3457. isFinal = true;
  3458. else if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, OVERRIDE_TOKEN) )
  3459. isOverride = true;
  3460. decorator = decorator->next;
  3461. }
  3462. }
  3463. // Count the number of parameters
  3464. int count = 0;
  3465. asCScriptNode *c = n->next->firstChild;
  3466. while( c )
  3467. {
  3468. count++;
  3469. c = c->next->next;
  3470. if( c && c->nodeType == snIdentifier )
  3471. c = c->next;
  3472. if( c && c->nodeType == snExpression )
  3473. c = c->next;
  3474. }
  3475. // Get the parameter types
  3476. parameterNames.Allocate(count, false);
  3477. parameterTypes.Allocate(count, false);
  3478. inOutFlags.Allocate(count, false);
  3479. defaultArgs.Allocate(count, false);
  3480. n = n->next->firstChild;
  3481. while( n )
  3482. {
  3483. asETypeModifiers inOutFlag;
  3484. asCDataType type = CreateDataTypeFromNode(n, file, implicitNamespace);
  3485. type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);
  3486. if( engine->ep.disallowValueAssignForRefType &&
  3487. type.GetObjectType() &&
  3488. (type.GetObjectType()->flags & asOBJ_REF) &&
  3489. !(type.GetObjectType()->flags & asOBJ_SCOPED) &&
  3490. !type.IsReference() &&
  3491. !type.IsObjectHandle() )
  3492. {
  3493. WriteError(TXT_REF_TYPE_CANT_BE_PASSED_BY_VAL, file, node);
  3494. }
  3495. // Store the parameter type
  3496. parameterTypes.PushLast(type);
  3497. inOutFlags.PushLast(inOutFlag);
  3498. // Move to next parameter
  3499. n = n->next->next;
  3500. if( n && n->nodeType == snIdentifier )
  3501. {
  3502. asCString name;
  3503. name.Assign(&file->code[n->tokenPos], n->tokenLength);
  3504. parameterNames.PushLast(name);
  3505. n = n->next;
  3506. }
  3507. else
  3508. {
  3509. // No name was given for the parameter
  3510. parameterNames.PushLast(asCString());
  3511. }
  3512. if( n && n->nodeType == snExpression )
  3513. {
  3514. // Strip out white space and comments to better share the string
  3515. asCString *defaultArgStr = asNEW(asCString);
  3516. if( defaultArgStr )
  3517. *defaultArgStr = GetCleanExpressionString(n, file);
  3518. defaultArgs.PushLast(defaultArgStr);
  3519. n = n->next;
  3520. }
  3521. else
  3522. defaultArgs.PushLast(0);
  3523. }
  3524. }
  3525. #endif
  3526. asCString asCBuilder::GetCleanExpressionString(asCScriptNode *node, asCScriptCode *file)
  3527. {
  3528. asASSERT(node && node->nodeType == snExpression);
  3529. asCString str;
  3530. str.Assign(file->code + node->tokenPos, node->tokenLength);
  3531. asCString cleanStr;
  3532. for( asUINT n = 0; n < str.GetLength(); )
  3533. {
  3534. asUINT len = 0;
  3535. asETokenClass tok = engine->ParseToken(str.AddressOf() + n, str.GetLength() - n, &len);
  3536. if( tok != asTC_COMMENT && tok != asTC_WHITESPACE )
  3537. {
  3538. if( cleanStr.GetLength() ) cleanStr += " ";
  3539. cleanStr.Concatenate(str.AddressOf() + n, len);
  3540. }
  3541. n += len;
  3542. }
  3543. return cleanStr;
  3544. }
  3545. #ifndef AS_NO_COMPILER
  3546. int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin)
  3547. {
  3548. asCString name;
  3549. asCDataType returnType;
  3550. asCArray<asCString> parameterNames;
  3551. asCArray<asCDataType> parameterTypes;
  3552. asCArray<asETypeModifiers> inOutFlags;
  3553. asCArray<asCString *> defaultArgs;
  3554. bool isConstMethod;
  3555. bool isOverride;
  3556. bool isFinal;
  3557. bool isConstructor;
  3558. bool isDestructor;
  3559. bool isPrivate;
  3560. bool isProtected;
  3561. bool isShared;
  3562. asASSERT( (objType && ns == 0) || isGlobalFunction || isMixin );
  3563. // Set the default namespace
  3564. if( ns == 0 )
  3565. {
  3566. if( objType )
  3567. ns = objType->nameSpace;
  3568. else
  3569. ns = engine->nameSpaces[0];
  3570. }
  3571. GetParsedFunctionDetails(node, file, objType, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, ns);
  3572. return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared);
  3573. }
  3574. asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns)
  3575. {
  3576. // Get the parameter names from the node
  3577. asCArray<asCString> parameterNames;
  3578. asCArray<asCString*> defaultArgs;
  3579. asCScriptNode *args = node->firstChild;
  3580. while( args && args->nodeType == snIdentifier )
  3581. {
  3582. asCString argName;
  3583. argName.Assign(&file->code[args->tokenPos], args->tokenLength);
  3584. parameterNames.PushLast(argName);
  3585. defaultArgs.PushLast(0);
  3586. args = args->next;
  3587. }
  3588. // The statement block for the function must be disconnected, as the builder is going to be the owner of it
  3589. args->DisconnectParent();
  3590. // Get the return and parameter types from the funcDef
  3591. asCString funcName = name;
  3592. int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, false, false, false, false, false, false, false, false);
  3593. if( r < 0 )
  3594. return 0;
  3595. // Return the function that was just created (but that will be compiled later)
  3596. return engine->scriptFunctions[functions[functions.GetLength()-1]->funcId];
  3597. }
  3598. int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> &parameterNames, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isProtected, bool isOverride, bool isFinal, bool isShared)
  3599. {
  3600. // Determine default namespace if not specified
  3601. if( ns == 0 )
  3602. {
  3603. if( objType )
  3604. ns = objType->nameSpace;
  3605. else
  3606. ns = engine->nameSpaces[0];
  3607. }
  3608. if( isExistingShared )
  3609. {
  3610. asASSERT( objType );
  3611. // Should validate that the function really exists in the class/interface
  3612. bool found = false;
  3613. if( isConstructor || isDestructor )
  3614. {
  3615. // TODO: shared: Should check the existance of these too
  3616. found = true;
  3617. }
  3618. else
  3619. {
  3620. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  3621. {
  3622. asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
  3623. if( func->name == name &&
  3624. func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, isConstMethod) )
  3625. {
  3626. // Add the shared function in this module too
  3627. module->AddScriptFunction(func);
  3628. found = true;
  3629. break;
  3630. }
  3631. }
  3632. }
  3633. if( !found )
  3634. {
  3635. asCString str;
  3636. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, objType->GetName());
  3637. WriteError(str, file, node);
  3638. }
  3639. // Free the default args
  3640. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3641. if( defaultArgs[n] )
  3642. asDELETE(defaultArgs[n], asCString);
  3643. node->Destroy(engine);
  3644. return 0;
  3645. }
  3646. // Check for name conflicts
  3647. if( !isConstructor && !isDestructor )
  3648. {
  3649. if( objType )
  3650. {
  3651. CheckNameConflictMember(objType, name.AddressOf(), node, file, false);
  3652. if( name == objType->name )
  3653. WriteError(TXT_METHOD_CANT_HAVE_NAME_OF_CLASS, file, node);
  3654. }
  3655. else
  3656. CheckNameConflict(name.AddressOf(), node, file, ns);
  3657. }
  3658. else
  3659. {
  3660. if( isMixin )
  3661. {
  3662. // Mixins cannot implement constructors/destructors
  3663. WriteError(TXT_MIXIN_CANNOT_HAVE_CONSTRUCTOR, file, node);
  3664. // Free the default args
  3665. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3666. if( defaultArgs[n] )
  3667. asDELETE(defaultArgs[n], asCString);
  3668. node->Destroy(engine);
  3669. return 0;
  3670. }
  3671. // Verify that the name of the constructor/destructor is the same as the class
  3672. if( name != objType->name )
  3673. {
  3674. asCString str;
  3675. if( isDestructor )
  3676. str.Format(TXT_DESTRUCTOR_s_s_NAME_ERROR, objType->name.AddressOf(), name.AddressOf());
  3677. else
  3678. str.Format(TXT_METHOD_s_s_HAS_NO_RETURN_TYPE, objType->name.AddressOf(), name.AddressOf());
  3679. WriteError(str, file, node);
  3680. }
  3681. if( isDestructor )
  3682. name = "~" + name;
  3683. }
  3684. isExistingShared = false;
  3685. int funcId = engine->GetNextScriptFunctionId();
  3686. if( !isInterface )
  3687. {
  3688. sFunctionDescription *func = asNEW(sFunctionDescription);
  3689. if( func == 0 )
  3690. {
  3691. // Free the default args
  3692. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3693. if( defaultArgs[n] )
  3694. asDELETE(defaultArgs[n], asCString);
  3695. return asOUT_OF_MEMORY;
  3696. }
  3697. functions.PushLast(func);
  3698. func->script = file;
  3699. func->node = node;
  3700. func->name = name;
  3701. func->objType = objType;
  3702. func->funcId = funcId;
  3703. func->isExistingShared = false;
  3704. func->paramNames = parameterNames;
  3705. if( isShared )
  3706. {
  3707. // Look for a pre-existing shared function with the same signature
  3708. for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
  3709. {
  3710. asCScriptFunction *f = engine->scriptFunctions[n];
  3711. if( f &&
  3712. f->isShared &&
  3713. f->name == name &&
  3714. f->nameSpace == ns &&
  3715. f->objectType == objType &&
  3716. f->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, 0, false) )
  3717. {
  3718. funcId = func->funcId = f->id;
  3719. isExistingShared = func->isExistingShared = true;
  3720. break;
  3721. }
  3722. }
  3723. }
  3724. }
  3725. // Destructors may not have any parameters
  3726. if( isDestructor && parameterTypes.GetLength() > 0 )
  3727. WriteError(TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, file, node);
  3728. // If a function, class, or interface is shared then only shared types may be used in the signature
  3729. if( (objType && objType->IsShared()) || isShared )
  3730. {
  3731. asCObjectType *ot = returnType.GetObjectType();
  3732. if( ot && !ot->IsShared() )
  3733. {
  3734. asCString msg;
  3735. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  3736. WriteError(msg, file, node);
  3737. }
  3738. for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
  3739. {
  3740. asCObjectType *ot = parameterTypes[p].GetObjectType();
  3741. if( ot && !ot->IsShared() )
  3742. {
  3743. asCString msg;
  3744. msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
  3745. WriteError(msg, file, node);
  3746. }
  3747. }
  3748. }
  3749. // Check that the same function hasn't been registered already in the namespace
  3750. asCArray<int> funcs;
  3751. if( objType )
  3752. GetObjectMethodDescriptions(name.AddressOf(), objType, funcs, false);
  3753. else
  3754. GetFunctionDescriptions(name.AddressOf(), funcs, ns);
  3755. if( objType && (name == "opConv" || name == "opImplConv" || name == "opCast" || name == "opImplCast") && parameterTypes.GetLength() == 0 )
  3756. {
  3757. // opConv and opCast are special methods used for type casts
  3758. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  3759. {
  3760. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  3761. if( func->IsSignatureExceptNameEqual(returnType, parameterTypes, inOutFlags, objType, isConstMethod) )
  3762. {
  3763. // TODO: clean up: Reuse the same error handling for both opConv and normal methods
  3764. if( isMixin )
  3765. {
  3766. // Clean up the memory, as the function will not be registered
  3767. if( node )
  3768. node->Destroy(engine);
  3769. sFunctionDescription *func = functions.PopLast();
  3770. asDELETE(func, sFunctionDescription);
  3771. // Free the default args
  3772. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3773. if( defaultArgs[n] )
  3774. asDELETE(defaultArgs[n], asCString);
  3775. return 0;
  3776. }
  3777. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  3778. break;
  3779. }
  3780. }
  3781. }
  3782. else
  3783. {
  3784. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  3785. {
  3786. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  3787. if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, objType, isConstMethod) )
  3788. {
  3789. if( isMixin )
  3790. {
  3791. // Clean up the memory, as the function will not be registered
  3792. if( node )
  3793. node->Destroy(engine);
  3794. sFunctionDescription *func = functions.PopLast();
  3795. asDELETE(func, sFunctionDescription);
  3796. // Free the default args
  3797. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3798. if( defaultArgs[n] )
  3799. asDELETE(defaultArgs[n], asCString);
  3800. return 0;
  3801. }
  3802. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  3803. break;
  3804. }
  3805. }
  3806. }
  3807. // Register the function
  3808. if( isExistingShared )
  3809. {
  3810. // Delete the default args as they won't be used anymore
  3811. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3812. if( defaultArgs[n] )
  3813. asDELETE(defaultArgs[n], asCString);
  3814. asCScriptFunction *f = engine->scriptFunctions[funcId];
  3815. module->AddScriptFunction(f);
  3816. // TODO: clean up: This should be done by AddScriptFunction() itself
  3817. module->globalFunctions.Put(f);
  3818. }
  3819. else
  3820. {
  3821. int row = 0, col = 0;
  3822. if( node )
  3823. file->ConvertPosToRowCol(node->tokenPos, &row, &col);
  3824. module->AddScriptFunction(file->idx, (row&0xFFFFF)|((col&0xFFF)<<20), funcId, name, returnType, parameterTypes, parameterNames, inOutFlags, defaultArgs, isInterface, objType, isConstMethod, isGlobalFunction, isPrivate, isProtected, isFinal, isOverride, isShared, ns);
  3825. }
  3826. // Make sure the default args are declared correctly
  3827. ValidateDefaultArgs(file, node, engine->scriptFunctions[funcId]);
  3828. CheckForConflictsDueToDefaultArgs(file, node, engine->scriptFunctions[funcId], objType);
  3829. if( objType )
  3830. {
  3831. asASSERT( !isExistingShared );
  3832. engine->scriptFunctions[funcId]->AddRefInternal();
  3833. if( isConstructor )
  3834. {
  3835. int factoryId = engine->GetNextScriptFunctionId();
  3836. if( parameterTypes.GetLength() == 0 )
  3837. {
  3838. // Overload the default constructor
  3839. engine->scriptFunctions[objType->beh.construct]->ReleaseInternal();
  3840. objType->beh.construct = funcId;
  3841. objType->beh.constructors[0] = funcId;
  3842. // Register the default factory as well
  3843. engine->scriptFunctions[objType->beh.factory]->ReleaseInternal();
  3844. objType->beh.factory = factoryId;
  3845. objType->beh.factories[0] = factoryId;
  3846. }
  3847. else
  3848. {
  3849. objType->beh.constructors.PushLast(funcId);
  3850. // Register the factory as well
  3851. objType->beh.factories.PushLast(factoryId);
  3852. }
  3853. // We must copy the default arg strings to avoid deleting the same object multiple times
  3854. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  3855. if( defaultArgs[n] )
  3856. defaultArgs[n] = asNEW(asCString)(*defaultArgs[n]);
  3857. asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
  3858. module->AddScriptFunction(file->idx, engine->scriptFunctions[funcId]->scriptData->declaredAt, factoryId, name, dt, parameterTypes, parameterNames, inOutFlags, defaultArgs, false);
  3859. // If the object is shared, then the factory must also be marked as shared
  3860. if( objType->flags & asOBJ_SHARED )
  3861. engine->scriptFunctions[factoryId]->isShared = true;
  3862. // Add a dummy function to the builder so that it doesn't mix up the fund Ids
  3863. functions.PushLast(0);
  3864. // Compile the factory immediately
  3865. asCCompiler compiler(engine);
  3866. compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
  3867. engine->scriptFunctions[factoryId]->AddRefInternal();
  3868. }
  3869. else if( isDestructor )
  3870. objType->beh.destruct = funcId;
  3871. else
  3872. {
  3873. // If the method is the assignment operator we need to replace the default implementation
  3874. asCScriptFunction *f = engine->scriptFunctions[funcId];
  3875. if( f->name == "opAssign" && f->parameterTypes.GetLength() == 1 &&
  3876. f->parameterTypes[0].GetObjectType() == f->objectType &&
  3877. (f->inOutFlags[0] & asTM_INREF) )
  3878. {
  3879. engine->scriptFunctions[objType->beh.copy]->ReleaseInternal();
  3880. objType->beh.copy = funcId;
  3881. f->AddRefInternal();
  3882. }
  3883. objType->methods.PushLast(funcId);
  3884. }
  3885. }
  3886. // We need to delete the node already if this is an interface method
  3887. if( isInterface && node )
  3888. node->Destroy(engine);
  3889. return 0;
  3890. }
  3891. int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared)
  3892. {
  3893. if( engine->ep.propertyAccessorMode != 2 )
  3894. {
  3895. WriteError(TXT_PROPERTY_ACCESSOR_DISABLED, file, node);
  3896. node->Destroy(engine);
  3897. return 0;
  3898. }
  3899. asASSERT( (objType && ns == 0) || isGlobalFunction );
  3900. if( ns == 0 )
  3901. {
  3902. if( objType )
  3903. ns = objType->nameSpace;
  3904. else
  3905. ns = engine->nameSpaces[0];
  3906. }
  3907. bool isPrivate = false, isProtected = false;
  3908. asCString emulatedName;
  3909. asCDataType emulatedType;
  3910. asCScriptNode *mainNode = node;
  3911. node = node->firstChild;
  3912. if( !isGlobalFunction && node->tokenType == ttPrivate )
  3913. {
  3914. isPrivate = true;
  3915. node = node->next;
  3916. }
  3917. else if( !isGlobalFunction && node->tokenType == ttProtected )
  3918. {
  3919. isProtected = true;
  3920. node = node->next;
  3921. }
  3922. emulatedType = CreateDataTypeFromNode(node, file, ns);
  3923. emulatedType = ModifyDataTypeFromNode(emulatedType, node->next, file, 0, 0);
  3924. node = node->next->next;
  3925. emulatedName.Assign(&file->code[node->tokenPos], node->tokenLength);
  3926. if( node->next == 0 )
  3927. WriteError(TXT_PROPERTY_WITHOUT_ACCESSOR, file, node);
  3928. node = node->next;
  3929. while( node )
  3930. {
  3931. asCScriptNode *next = node->next;
  3932. asCScriptNode *funcNode = 0;
  3933. bool success = false;
  3934. bool isConst = false;
  3935. bool isFinal = false;
  3936. bool isOverride = false;
  3937. asCDataType returnType;
  3938. asCArray<asCString> paramNames;
  3939. asCArray<asCDataType> paramTypes;
  3940. asCArray<asETypeModifiers> paramModifiers;
  3941. asCArray<asCString*> defaultArgs;
  3942. asCString name;
  3943. // TODO: getset: Allow private for individual property accessors
  3944. // TODO: getset: If the accessor uses its own name, then the property should be automatically declared
  3945. if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN) )
  3946. {
  3947. funcNode = node->firstChild->next;
  3948. if( funcNode && funcNode->tokenType == ttConst )
  3949. {
  3950. isConst = true;
  3951. funcNode = funcNode->next;
  3952. }
  3953. while( funcNode && funcNode->nodeType != snStatementBlock )
  3954. {
  3955. if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
  3956. isFinal = true;
  3957. else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
  3958. isOverride = true;
  3959. funcNode = funcNode->next;
  3960. }
  3961. if( funcNode )
  3962. funcNode->DisconnectParent();
  3963. if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
  3964. {
  3965. // TODO: getset: If no implementation is supplied the builder should provide an automatically generated implementation
  3966. // The compiler needs to be able to handle the different types, primitive, value type, and handle
  3967. // The code is also different for global property accessors
  3968. WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node);
  3969. }
  3970. // Setup the signature for the get accessor method
  3971. returnType = emulatedType;
  3972. name = "get_" + emulatedName;
  3973. success = true;
  3974. }
  3975. else if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN) )
  3976. {
  3977. funcNode = node->firstChild->next;
  3978. if( funcNode && funcNode->tokenType == ttConst )
  3979. {
  3980. isConst = true;
  3981. funcNode = funcNode->next;
  3982. }
  3983. while( funcNode && funcNode->nodeType != snStatementBlock )
  3984. {
  3985. if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
  3986. isFinal = true;
  3987. else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
  3988. isOverride = true;
  3989. funcNode = funcNode->next;
  3990. }
  3991. if( funcNode )
  3992. funcNode->DisconnectParent();
  3993. if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
  3994. WriteError(TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, file, node);
  3995. // Setup the signature for the set accessor method
  3996. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  3997. paramModifiers.PushLast(asTM_NONE);
  3998. paramNames.PushLast("value");
  3999. paramTypes.PushLast(emulatedType);
  4000. defaultArgs.PushLast(0);
  4001. name = "set_" + emulatedName;
  4002. success = true;
  4003. }
  4004. else
  4005. WriteError(TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, file, node);
  4006. if( success )
  4007. {
  4008. if( !isExistingShared )
  4009. RegisterScriptFunction(funcNode, file, objType, isInterface, isGlobalFunction, ns, false, false, name, returnType, paramNames, paramTypes, paramModifiers, defaultArgs, isConst, false, false, isPrivate, isProtected, isOverride, isFinal, false);
  4010. else
  4011. {
  4012. // Free the funcNode as it won't be used
  4013. if( funcNode ) funcNode->Destroy(engine);
  4014. // Should validate that the function really exists in the class/interface
  4015. bool found = false;
  4016. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  4017. {
  4018. asCScriptFunction *func = engine->scriptFunctions[objType->methods[n]];
  4019. if( func->name == name &&
  4020. func->IsSignatureExceptNameEqual(returnType, paramTypes, paramModifiers, objType, isConst) )
  4021. {
  4022. found = true;
  4023. break;
  4024. }
  4025. }
  4026. if( !found )
  4027. {
  4028. asCString str;
  4029. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, objType->GetName());
  4030. WriteError(str, file, node);
  4031. }
  4032. }
  4033. }
  4034. node = next;
  4035. };
  4036. mainNode->Destroy(engine);
  4037. return 0;
  4038. }
  4039. int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
  4040. {
  4041. asCString name;
  4042. asCDataType returnType;
  4043. asCArray<asCString> parameterNames;
  4044. asCArray<asCDataType> parameterTypes;
  4045. asCArray<asETypeModifiers> inOutFlags;
  4046. asCArray<asCString *> defaultArgs;
  4047. bool isConstMethod, isOverride, isFinal, isConstructor, isDestructor, isPrivate, isProtected, isShared;
  4048. if( ns == 0 )
  4049. ns = engine->nameSpaces[0];
  4050. GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, ns);
  4051. CheckNameConflict(name.AddressOf(), node, file, ns);
  4052. // Check that the same function hasn't been registered already in the namespace
  4053. asCArray<int> funcs;
  4054. GetFunctionDescriptions(name.AddressOf(), funcs, ns);
  4055. for( asUINT n = 0; n < funcs.GetLength(); ++n )
  4056. {
  4057. asCScriptFunction *func = GetFunctionDescription(funcs[n]);
  4058. if( func->IsSignatureExceptNameAndReturnTypeEqual(parameterTypes, inOutFlags, 0, false) )
  4059. {
  4060. WriteError(TXT_FUNCTION_ALREADY_EXIST, file, node);
  4061. break;
  4062. }
  4063. }
  4064. // Read the module name as well
  4065. asCScriptNode *nd = node->lastChild;
  4066. asASSERT( nd->nodeType == snConstant && nd->tokenType == ttStringConstant );
  4067. asCString moduleName;
  4068. moduleName.Assign(&file->code[nd->tokenPos+1], nd->tokenLength-2);
  4069. node->Destroy(engine);
  4070. // Register the function
  4071. module->AddImportedFunction(importID, name, returnType, parameterTypes, inOutFlags, defaultArgs, ns, moduleName);
  4072. return 0;
  4073. }
  4074. asCScriptFunction *asCBuilder::GetFunctionDescription(int id)
  4075. {
  4076. // TODO: import: This should be improved when the imported functions are removed
  4077. // Get the description from the engine
  4078. if( (id & FUNC_IMPORTED) == 0 )
  4079. return engine->scriptFunctions[id];
  4080. else
  4081. return engine->importedFunctions[id & ~FUNC_IMPORTED]->importedFunctionSignature;
  4082. }
  4083. void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs, asSNameSpace *ns)
  4084. {
  4085. asUINT n;
  4086. // Get the script declared global functions
  4087. const asCArray<unsigned int> &idxs = module->globalFunctions.GetIndexes(ns, name);
  4088. for( n = 0; n < idxs.GetLength(); n++ )
  4089. {
  4090. const asCScriptFunction *f = module->globalFunctions.Get(idxs[n]);
  4091. asASSERT( f->objectType == 0 );
  4092. funcs.PushLast(f->id);
  4093. }
  4094. // Add the imported functions
  4095. // TODO: optimize: Linear search: This is probably not that critial. Also bindInformation will probably be removed in near future
  4096. for( n = 0; n < module->bindInformations.GetLength(); n++ )
  4097. {
  4098. if( module->bindInformations[n]->importedFunctionSignature->name == name &&
  4099. module->bindInformations[n]->importedFunctionSignature->nameSpace == ns )
  4100. funcs.PushLast(module->bindInformations[n]->importedFunctionSignature->id);
  4101. }
  4102. // Add the registered global functions
  4103. const asCArray<unsigned int> &idxs2 = engine->registeredGlobalFuncs.GetIndexes(ns, name);
  4104. for( n = 0; n < idxs2.GetLength(); n++ )
  4105. {
  4106. asCScriptFunction *f = engine->registeredGlobalFuncs.Get(idxs2[n]);
  4107. // Verify if the module has access to the function
  4108. if( module->accessMask & f->accessMask )
  4109. {
  4110. funcs.PushLast(f->id);
  4111. }
  4112. }
  4113. }
  4114. void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope, asCScriptNode *errNode, asCScriptCode *script)
  4115. {
  4116. if( scope != "" )
  4117. {
  4118. // If searching with a scope informed, then the node and script must also be informed for potential error reporting
  4119. asASSERT( errNode && script );
  4120. // If the scope contains ::identifier, then use the last identifier as the class name and the rest of it as the namespace
  4121. int n = scope.FindLast("::");
  4122. asCString className = n >= 0 ? scope.SubString(n+2) : scope;
  4123. asCString nsName = n >= 0 ? scope.SubString(0, n) : "";
  4124. // Check if the namespace actually exist, if not return silently as this cannot be the referring to a base class
  4125. asSNameSpace *ns = GetNameSpaceByString(nsName, objectType->nameSpace, errNode, script, false);
  4126. if( ns == 0 )
  4127. return;
  4128. // Find the base class with the specified scope
  4129. while( objectType && (objectType->name != className || objectType->nameSpace != ns) )
  4130. objectType = objectType->derivedFrom;
  4131. // If the scope is not any of the base classes, then return no methods
  4132. if( objectType == 0 )
  4133. return;
  4134. }
  4135. // TODO: optimize: Improve linear search
  4136. if( objIsConst )
  4137. {
  4138. // Only add const methods to the list
  4139. for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
  4140. {
  4141. asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]];
  4142. if( func->name == name &&
  4143. func->isReadOnly &&
  4144. (func->accessMask & module->accessMask) )
  4145. {
  4146. // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
  4147. if( scope == "" )
  4148. methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
  4149. else
  4150. {
  4151. asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
  4152. asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
  4153. methods.PushLast(realFunc->id);
  4154. }
  4155. }
  4156. }
  4157. }
  4158. else
  4159. {
  4160. // TODO: Prefer non-const over const
  4161. for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
  4162. {
  4163. asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]];
  4164. if( func->name == name &&
  4165. (func->accessMask & module->accessMask) )
  4166. {
  4167. // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
  4168. if( scope == "" )
  4169. methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
  4170. else
  4171. {
  4172. asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
  4173. asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
  4174. methods.PushLast(realFunc->id);
  4175. }
  4176. }
  4177. }
  4178. }
  4179. }
  4180. #endif
  4181. void asCBuilder::WriteInfo(const asCString &scriptname, const asCString &message, int r, int c, bool pre)
  4182. {
  4183. // Need to store the pre message in a structure
  4184. if( pre )
  4185. {
  4186. engine->preMessage.isSet = true;
  4187. engine->preMessage.c = c;
  4188. engine->preMessage.r = r;
  4189. engine->preMessage.message = message;
  4190. engine->preMessage.scriptname = scriptname;
  4191. }
  4192. else
  4193. {
  4194. engine->preMessage.isSet = false;
  4195. if( !silent )
  4196. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_INFORMATION, message.AddressOf());
  4197. }
  4198. }
  4199. void asCBuilder::WriteInfo(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  4200. {
  4201. int r = 0, c = 0;
  4202. if( node )
  4203. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  4204. WriteInfo(file->name, message, r, c, false);
  4205. }
  4206. void asCBuilder::WriteError(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  4207. {
  4208. int r = 0, c = 0;
  4209. if( node && file )
  4210. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  4211. WriteError(file ? file->name : asCString(""), message, r, c);
  4212. }
  4213. void asCBuilder::WriteError(const asCString &scriptname, const asCString &message, int r, int c)
  4214. {
  4215. numErrors++;
  4216. if( !silent )
  4217. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_ERROR, message.AddressOf());
  4218. }
  4219. void asCBuilder::WriteWarning(const asCString &scriptname, const asCString &message, int r, int c)
  4220. {
  4221. if( engine->ep.compilerWarnings )
  4222. {
  4223. numWarnings++;
  4224. if( !silent )
  4225. engine->WriteMessage(scriptname.AddressOf(), r, c, asMSGTYPE_WARNING, message.AddressOf());
  4226. }
  4227. }
  4228. void asCBuilder::WriteWarning(const asCString &message, asCScriptCode *file, asCScriptNode *node)
  4229. {
  4230. int r = 0, c = 0;
  4231. if( node && file )
  4232. file->ConvertPosToRowCol(node->tokenPos, &r, &c);
  4233. WriteWarning(file ? file->name : asCString(""), message, r, c);
  4234. }
  4235. asCString asCBuilder::GetScopeFromNode(asCScriptNode *node, asCScriptCode *script, asCScriptNode **next)
  4236. {
  4237. asCString scope;
  4238. asCScriptNode *sn = node;
  4239. if( sn->tokenType == ttScope )
  4240. {
  4241. scope = "::";
  4242. sn = sn->next;
  4243. }
  4244. while( sn && sn->next && sn->next->tokenType == ttScope )
  4245. {
  4246. asCString tmp;
  4247. tmp.Assign(&script->code[sn->tokenPos], sn->tokenLength);
  4248. if( scope != "" && scope != "::" )
  4249. scope += "::";
  4250. scope += tmp;
  4251. sn = sn->next->next;
  4252. }
  4253. if( next )
  4254. *next = sn;
  4255. return scope;
  4256. }
  4257. asSNameSpace *asCBuilder::GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next)
  4258. {
  4259. asCString scope = GetScopeFromNode(node, script, next);
  4260. return GetNameSpaceByString(scope, implicitNs, node, script);
  4261. }
  4262. asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, bool isRequired)
  4263. {
  4264. asSNameSpace *ns = implicitNs;
  4265. if( nsName == "::" )
  4266. ns = engine->nameSpaces[0];
  4267. else if( nsName != "" )
  4268. {
  4269. ns = engine->FindNameSpace(nsName.AddressOf());
  4270. if( ns == 0 && isRequired )
  4271. {
  4272. asCString msg;
  4273. msg.Format(TXT_NAMESPACE_s_DOESNT_EXIST, nsName.AddressOf());
  4274. WriteError(msg, script, errNode);
  4275. }
  4276. }
  4277. return ns;
  4278. }
  4279. asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, asSNameSpace *implicitNamespace, bool acceptHandleForScope, asCObjectType *currentType)
  4280. {
  4281. asASSERT(node->nodeType == snDataType);
  4282. asCDataType dt;
  4283. asCScriptNode *n = node->firstChild;
  4284. bool isConst = false;
  4285. bool isImplicitHandle = false;
  4286. if( n->tokenType == ttConst )
  4287. {
  4288. isConst = true;
  4289. n = n->next;
  4290. }
  4291. // Determine namespace
  4292. asSNameSpace *ns = GetNameSpaceFromNode(n, file, implicitNamespace, &n);
  4293. if( ns == 0 )
  4294. {
  4295. // The namespace doesn't exist. Return a dummy type instead.
  4296. dt = asCDataType::CreatePrimitive(ttInt, false);
  4297. return dt;
  4298. }
  4299. if( n->tokenType == ttIdentifier )
  4300. {
  4301. bool found = false;
  4302. asCScriptNode *nameToken = n;
  4303. asCString str;
  4304. str.Assign(&file->code[n->tokenPos], n->tokenLength);
  4305. // Recursively search parent namespaces for matching type
  4306. asSNameSpace *origNs = ns;
  4307. while( ns && !found )
  4308. {
  4309. asCObjectType *ot = 0;
  4310. // If this is for a template type, then we must first determine if the
  4311. // identifier matches any of the template subtypes
  4312. if( currentType && (currentType->flags & asOBJ_TEMPLATE) )
  4313. {
  4314. for( asUINT subtypeIndex = 0; subtypeIndex < currentType->templateSubTypes.GetLength(); subtypeIndex++)
  4315. {
  4316. asCObjectType *type = currentType->templateSubTypes[subtypeIndex].GetObjectType();
  4317. if( type && str == type->name )
  4318. {
  4319. ot = type;
  4320. break;
  4321. }
  4322. }
  4323. }
  4324. if( ot == 0 )
  4325. ot = GetObjectType(str.AddressOf(), ns);
  4326. if( ot == 0 && !module && currentType )
  4327. ot = GetObjectTypeFromTypesKnownByObject(str.AddressOf(), currentType);
  4328. if( ot )
  4329. {
  4330. found = true;
  4331. if( ot->flags & asOBJ_IMPLICIT_HANDLE )
  4332. isImplicitHandle = true;
  4333. // Make sure the module has access to the object type
  4334. if( !module || (module->accessMask & ot->accessMask) )
  4335. {
  4336. if( asOBJ_TYPEDEF == (ot->flags & asOBJ_TYPEDEF) )
  4337. {
  4338. // TODO: typedef: A typedef should be considered different from the original type (though with implicit conversions between the two)
  4339. // Create primitive data type based on object flags
  4340. dt = ot->templateSubTypes[0];
  4341. dt.MakeReadOnly(isConst);
  4342. }
  4343. else
  4344. {
  4345. if( ot->flags & asOBJ_TEMPLATE )
  4346. {
  4347. // Check if the subtype is a type or the template's subtype
  4348. // if it is the template's subtype then this is the actual template type,
  4349. // orderwise it is a template instance.
  4350. // Only do this for application registered interface, as the
  4351. // scripts cannot implement templates.
  4352. asCArray<asCDataType> subTypes;
  4353. asUINT subtypeIndex;
  4354. while( n && n->next && n->next->nodeType == snDataType )
  4355. {
  4356. n = n->next;
  4357. // When parsing function definitions for template registrations (currentType != 0) it is necessary
  4358. // to pass in the current template type to the recursive call since it is this ones sub-template types
  4359. // that should be allowed.
  4360. asCDataType subType = CreateDataTypeFromNode(n, file, implicitNamespace, false, module ? 0 : (currentType ? currentType : ot));
  4361. subTypes.PushLast(subType);
  4362. if( subType.IsReadOnly() )
  4363. {
  4364. asCString msg;
  4365. msg.Format(TXT_TMPL_SUBTYPE_MUST_NOT_BE_READ_ONLY);
  4366. WriteError(msg, file, n);
  4367. // Return a dummy
  4368. return asCDataType::CreatePrimitive(ttInt, false);
  4369. }
  4370. }
  4371. if( subTypes.GetLength() != ot->templateSubTypes.GetLength() )
  4372. {
  4373. asCString msg;
  4374. msg.Format(TXT_TMPL_s_EXPECTS_d_SUBTYPES, ot->name.AddressOf(), int(ot->templateSubTypes.GetLength()));
  4375. WriteError(msg, file, nameToken);
  4376. // Return a dummy
  4377. return asCDataType::CreatePrimitive(ttInt, false);
  4378. }
  4379. // Check if any of the given subtypes are different from the template's declared subtypes
  4380. bool isDifferent = false;
  4381. for( subtypeIndex = 0; subtypeIndex < subTypes.GetLength(); subtypeIndex++ )
  4382. {
  4383. if( subTypes[subtypeIndex].GetObjectType() != ot->templateSubTypes[subtypeIndex].GetObjectType() )
  4384. {
  4385. isDifferent = true;
  4386. break;
  4387. }
  4388. }
  4389. if( isDifferent )
  4390. {
  4391. // This is a template instance
  4392. // Need to find the correct object type
  4393. asCObjectType *otInstance = engine->GetTemplateInstanceType(ot, subTypes, module);
  4394. if( otInstance && otInstance->scriptSectionIdx < 0 )
  4395. {
  4396. // If this is the first time the template instance is used, store where it was declared from
  4397. otInstance->scriptSectionIdx = engine->GetScriptSectionNameIndex(file->name.AddressOf());
  4398. int row, column;
  4399. file->ConvertPosToRowCol(n->tokenPos, &row, &column);
  4400. otInstance->declaredAt = (row&0xFFFFF)|(column<<20);
  4401. }
  4402. if( !otInstance )
  4403. {
  4404. asCString sub = subTypes[0].Format(ot->nameSpace);
  4405. for( asUINT s = 1; s < subTypes.GetLength(); s++ )
  4406. {
  4407. sub += ",";
  4408. sub += subTypes[s].Format(ot->nameSpace);
  4409. }
  4410. asCString str;
  4411. str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, ot->name.AddressOf(), sub.AddressOf());
  4412. WriteError(str, file, n);
  4413. }
  4414. ot = otInstance;
  4415. }
  4416. }
  4417. else if( n && n->next && n->next->nodeType == snDataType )
  4418. {
  4419. asCString str;
  4420. str.Format(TXT_TYPE_s_NOT_TEMPLATE, ot->name.AddressOf());
  4421. WriteError(str, file, n);
  4422. }
  4423. // Create object data type
  4424. if( ot )
  4425. dt = asCDataType::CreateObject(ot, isConst);
  4426. else
  4427. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  4428. }
  4429. }
  4430. else
  4431. {
  4432. asCString msg;
  4433. msg.Format(TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE, (const char *)str.AddressOf());
  4434. WriteError(msg, file, n);
  4435. dt.SetTokenType(ttInt);
  4436. }
  4437. }
  4438. else if( ot == 0 )
  4439. {
  4440. // It can still be a function definition
  4441. asCScriptFunction *funcdef = GetFuncDef(str.AddressOf());
  4442. if( funcdef )
  4443. {
  4444. dt = asCDataType::CreateFuncDef(funcdef);
  4445. found = true;
  4446. }
  4447. }
  4448. if( !found )
  4449. {
  4450. // Try to find it in the parent namespace
  4451. ns = engine->GetParentNameSpace(ns);
  4452. }
  4453. }
  4454. if( !found )
  4455. {
  4456. asCString msg;
  4457. if( origNs->name == "" )
  4458. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_GLOBAL_NS, str.AddressOf());
  4459. else
  4460. msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE_IN_NS_s, str.AddressOf(), origNs->name.AddressOf());
  4461. WriteError(msg, file, n);
  4462. dt = asCDataType::CreatePrimitive(ttInt, isConst);
  4463. return dt;
  4464. }
  4465. }
  4466. else if( n->tokenType == ttAuto )
  4467. {
  4468. dt = asCDataType::CreateAuto(isConst);
  4469. }
  4470. else
  4471. {
  4472. // Create primitive data type
  4473. dt = asCDataType::CreatePrimitive(n->tokenType, isConst);
  4474. }
  4475. // Determine array dimensions and object handles
  4476. n = n->next;
  4477. while( n && (n->tokenType == ttOpenBracket || n->tokenType == ttHandle) )
  4478. {
  4479. if( n->tokenType == ttOpenBracket )
  4480. {
  4481. // Make sure the sub type can be instantiated
  4482. if( !dt.CanBeInstantiated() )
  4483. {
  4484. asCString str;
  4485. if( dt.IsAbstractClass() )
  4486. str.Format(TXT_ABSTRACT_CLASS_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf());
  4487. else if( dt.IsInterface() )
  4488. str.Format(TXT_INTERFACE_s_CANNOT_BE_INSTANTIATED, dt.Format(ns).AddressOf());
  4489. else
  4490. // TODO: Improve error message to explain why
  4491. str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format(ns).AddressOf());
  4492. WriteError(str, file, n);
  4493. }
  4494. // Make the type an array (or multidimensional array)
  4495. if( dt.MakeArray(engine, module) < 0 )
  4496. {
  4497. WriteError(TXT_NO_DEFAULT_ARRAY_TYPE, file, n);
  4498. break;
  4499. }
  4500. }
  4501. else
  4502. {
  4503. // Make the type a handle
  4504. if( dt.IsObjectHandle() )
  4505. {
  4506. WriteError(TXT_HANDLE_OF_HANDLE_IS_NOT_ALLOWED, file, n);
  4507. break;
  4508. }
  4509. else if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
  4510. {
  4511. WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
  4512. break;
  4513. }
  4514. }
  4515. n = n->next;
  4516. }
  4517. if( isImplicitHandle )
  4518. {
  4519. // Make the type a handle
  4520. if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
  4521. WriteError(TXT_OBJECT_HANDLE_NOT_SUPPORTED, file, n);
  4522. }
  4523. return dt;
  4524. }
  4525. asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlags, bool *autoHandle)
  4526. {
  4527. asCDataType dt = type;
  4528. if( inOutFlags ) *inOutFlags = asTM_NONE;
  4529. // Is the argument sent by reference?
  4530. asCScriptNode *n = node->firstChild;
  4531. if( n && n->tokenType == ttAmp )
  4532. {
  4533. dt.MakeReference(true);
  4534. n = n->next;
  4535. if( n )
  4536. {
  4537. if( inOutFlags )
  4538. {
  4539. if( n->tokenType == ttIn )
  4540. *inOutFlags = asTM_INREF;
  4541. else if( n->tokenType == ttOut )
  4542. *inOutFlags = asTM_OUTREF;
  4543. else if( n->tokenType == ttInOut )
  4544. *inOutFlags = asTM_INOUTREF;
  4545. else
  4546. asASSERT(false);
  4547. }
  4548. n = n->next;
  4549. }
  4550. else
  4551. {
  4552. if( inOutFlags )
  4553. *inOutFlags = asTM_INOUTREF; // ttInOut
  4554. }
  4555. if( !engine->ep.allowUnsafeReferences &&
  4556. inOutFlags && *inOutFlags == asTM_INOUTREF )
  4557. {
  4558. // Verify that the base type support &inout parameter types
  4559. if( !dt.IsObject() || dt.IsObjectHandle() || !((dt.GetObjectType()->flags & asOBJ_NOCOUNT) || (dt.GetObjectType()->beh.addref && dt.GetObjectType()->beh.release)) )
  4560. WriteError(TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT, file, node->firstChild);
  4561. }
  4562. }
  4563. if( autoHandle ) *autoHandle = false;
  4564. if( n && n->tokenType == ttPlus )
  4565. {
  4566. // Autohandles are not supported for types with NOCOUNT
  4567. // If the type is not a handle then there was an error with building the type, but
  4568. // this error would already have been reported so no need to report another error here
  4569. if( dt.IsObjectHandle() && (dt.GetObjectType()->flags & asOBJ_NOCOUNT) )
  4570. WriteError(TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT, file, node->firstChild);
  4571. if( autoHandle ) *autoHandle = true;
  4572. }
  4573. return dt;
  4574. }
  4575. asCObjectType *asCBuilder::GetObjectType(const char *type, asSNameSpace *ns)
  4576. {
  4577. asCObjectType *ot = engine->GetRegisteredObjectType(type, ns);
  4578. if( !ot && module )
  4579. ot = module->GetObjectType(type, ns);
  4580. return ot;
  4581. }
  4582. #ifndef AS_NO_COMPILER
  4583. // This function will return true if there are any types in the engine or module
  4584. // with the given name. The namespace is ignored in this verification.
  4585. bool asCBuilder::DoesTypeExist(const asCString &type)
  4586. {
  4587. asUINT n;
  4588. // This function is only used when parsing expressions for building bytecode
  4589. // and this is only done after all types are known. For this reason the types
  4590. // can be safely cached in a map for quick lookup. Once the builder is released
  4591. // the cache will also be destroyed thus avoiding unnecessary memory consumption.
  4592. if( !hasCachedKnownTypes )
  4593. {
  4594. // Only do this once
  4595. hasCachedKnownTypes = true;
  4596. // Add registered object types
  4597. asSMapNode<asSNameSpaceNamePair, asCObjectType*> *cursor;
  4598. engine->allRegisteredTypes.MoveFirst(&cursor);
  4599. while( cursor )
  4600. {
  4601. if( !knownTypes.MoveTo(0, cursor->key.name) )
  4602. knownTypes.Insert(cursor->key.name, true);
  4603. engine->allRegisteredTypes.MoveNext(&cursor, cursor);
  4604. }
  4605. // Add registered funcdefs
  4606. for( n = 0; n < engine->registeredFuncDefs.GetLength(); n++ )
  4607. if( !knownTypes.MoveTo(0, engine->registeredFuncDefs[n]->name) )
  4608. knownTypes.Insert(engine->registeredFuncDefs[n]->name, true);
  4609. if( module )
  4610. {
  4611. // Add script classes and interfaces
  4612. for( n = 0; n < module->classTypes.GetLength(); n++ )
  4613. if( !knownTypes.MoveTo(0, module->classTypes[n]->name) )
  4614. knownTypes.Insert(module->classTypes[n]->name, true);
  4615. // Add script enums
  4616. for( n = 0; n < module->enumTypes.GetLength(); n++ )
  4617. if( !knownTypes.MoveTo(0, module->enumTypes[n]->name) )
  4618. knownTypes.Insert(module->enumTypes[n]->name, true);
  4619. // Add script typedefs
  4620. for( n = 0; n < module->typeDefs.GetLength(); n++ )
  4621. if( !knownTypes.MoveTo(0, module->typeDefs[n]->name) )
  4622. knownTypes.Insert(module->typeDefs[n]->name, true);
  4623. // Add script funcdefs
  4624. for( n = 0; n < module->funcDefs.GetLength(); n++ )
  4625. if( !knownTypes.MoveTo(0, module->funcDefs[n]->name) )
  4626. knownTypes.Insert(module->funcDefs[n]->name, true);
  4627. }
  4628. }
  4629. // Check if the type is known
  4630. return knownTypes.MoveTo(0, type);
  4631. }
  4632. #endif
  4633. asCObjectType *asCBuilder::GetObjectTypeFromTypesKnownByObject(const char *type, asCObjectType *currentType)
  4634. {
  4635. if( currentType->name == type )
  4636. return currentType;
  4637. asUINT n;
  4638. asCObjectType *found = 0;
  4639. for( n = 0; found == 0 && n < currentType->properties.GetLength(); n++ )
  4640. if( currentType->properties[n]->type.GetObjectType() &&
  4641. currentType->properties[n]->type.GetObjectType()->name == type )
  4642. found = currentType->properties[n]->type.GetObjectType();
  4643. for( n = 0; found == 0 && n < currentType->methods.GetLength(); n++ )
  4644. {
  4645. asCScriptFunction *func = engine->scriptFunctions[currentType->methods[n]];
  4646. if( func->returnType.GetObjectType() &&
  4647. func->returnType.GetObjectType()->name == type )
  4648. found = func->returnType.GetObjectType();
  4649. for( asUINT f = 0; found == 0 && f < func->parameterTypes.GetLength(); f++ )
  4650. if( func->parameterTypes[f].GetObjectType() &&
  4651. func->parameterTypes[f].GetObjectType()->name == type )
  4652. found = func->parameterTypes[f].GetObjectType();
  4653. }
  4654. if( found )
  4655. {
  4656. // In case we find a template instance it mustn't be returned
  4657. // because it is not known if the subtype is really matching
  4658. if( found->flags & asOBJ_TEMPLATE )
  4659. return 0;
  4660. }
  4661. return found;
  4662. }
  4663. asCScriptFunction *asCBuilder::GetFuncDef(const char *type)
  4664. {
  4665. for( asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++ )
  4666. // TODO: access: Only return the definitions that the module has access to
  4667. if( engine->registeredFuncDefs[n]->name == type )
  4668. return engine->registeredFuncDefs[n];
  4669. if( module )
  4670. {
  4671. for( asUINT n = 0; n < module->funcDefs.GetLength(); n++ )
  4672. if( module->funcDefs[n]->name == type )
  4673. return module->funcDefs[n];
  4674. }
  4675. return 0;
  4676. }
  4677. #ifndef AS_NO_COMPILER
  4678. int asCBuilder::GetEnumValueFromObjectType(asCObjectType *objType, const char *name, asCDataType &outDt, asDWORD &outValue)
  4679. {
  4680. if( !objType || !(objType->flags & asOBJ_ENUM) )
  4681. return 0;
  4682. for( asUINT n = 0; n < objType->enumValues.GetLength(); ++n )
  4683. {
  4684. if( objType->enumValues[n]->name == name )
  4685. {
  4686. outDt = asCDataType::CreateObject(objType, true);
  4687. outValue = objType->enumValues[n]->value;
  4688. return 1;
  4689. }
  4690. }
  4691. return 0;
  4692. }
  4693. int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outValue, asSNameSpace *ns)
  4694. {
  4695. bool found = false;
  4696. // Search all available enum types
  4697. asUINT t;
  4698. for( t = 0; t < engine->registeredEnums.GetLength(); t++ )
  4699. {
  4700. asCObjectType *ot = engine->registeredEnums[t];
  4701. if( ns != ot->nameSpace ) continue;
  4702. // Don't bother with types the module doesn't have access to
  4703. if( (ot->accessMask & module->accessMask) == 0 )
  4704. continue;
  4705. if( GetEnumValueFromObjectType(ot, name, outDt, outValue) )
  4706. {
  4707. if( !found )
  4708. found = true;
  4709. else
  4710. {
  4711. // Found more than one value in different enum types
  4712. return 2;
  4713. }
  4714. }
  4715. }
  4716. for( t = 0; t < module->enumTypes.GetLength(); t++ )
  4717. {
  4718. asCObjectType *ot = module->enumTypes[t];
  4719. if( ns != ot->nameSpace ) continue;
  4720. if( GetEnumValueFromObjectType(ot, name, outDt, outValue) )
  4721. {
  4722. if( !found )
  4723. found = true;
  4724. else
  4725. {
  4726. // Found more than one value in different enum types
  4727. return 2;
  4728. }
  4729. }
  4730. }
  4731. if( found )
  4732. return 1;
  4733. // Didn't find any value
  4734. return 0;
  4735. }
  4736. #endif // AS_NO_COMPILER
  4737. END_AS_NAMESPACE