as_builder.cpp 134 KB

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