parser.bmx 127 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786
  1. ' Copyright (c) 2013-2023 Bruce A Henderson
  2. '
  3. ' Based on the public domain Monkey "trans" by Mark Sibly
  4. '
  5. ' This software is provided 'as-is', without any express or implied
  6. ' warranty. In no event will the authors be held liable for any damages
  7. ' arising from the use of this software.
  8. '
  9. ' Permission is granted to anyone to use this software for any purpose,
  10. ' including commercial applications, and to alter it and redistribute it
  11. ' freely, subject to the following restrictions:
  12. '
  13. ' 1. The origin of this software must not be misrepresented; you must not
  14. ' claim that you wrote the original software. If you use this software
  15. ' in a product, an acknowledgment in the product documentation would be
  16. ' appreciated but is not required.
  17. '
  18. ' 2. Altered source versions must be plainly marked as such, and must not be
  19. ' misrepresented as being the original software.
  20. '
  21. ' 3. This notice may not be removed or altered from any source
  22. ' distribution.
  23. '
  24. SuperStrict
  25. Import BRL.MaxUtil
  26. Import "toker.bmx"
  27. Include "iparser.bmx"
  28. Global FILE_EXT$="bmx"
  29. Type TForEachinStmt Extends TLoopStmt
  30. Field varid$
  31. Field varty:TType
  32. Field varlocal:Int
  33. Field expr:TExpr
  34. Field varExpr:TExpr
  35. Method Create:TForEachinStmt( varid$,varty:TType,varlocal:Int,expr:TExpr,block:TBlockDecl,loopLabel:TLoopLabelDecl,varExpr:TExpr )
  36. Self.varid=varid
  37. Self.varty=varty
  38. Self.varlocal=varlocal
  39. Self.expr=expr
  40. Self.block=block
  41. block.extra = Self
  42. Self.loopLabel=loopLabel
  43. Self.varExpr = varExpr
  44. Return Self
  45. End Method
  46. Method OnCopy:TStmt( scope:TScopeDecl )
  47. If loopLabel Then
  48. If varExpr Then
  49. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),TLoopLabelDecl(loopLabel.Copy()), varExpr.Copy() )
  50. Else
  51. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),TLoopLabelDecl(loopLabel.Copy()), Null )
  52. End If
  53. Else
  54. If varExpr Then
  55. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),Null, varExpr.Copy() )
  56. Else
  57. Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ),Null, Null )
  58. End If
  59. End If
  60. End Method
  61. Method OnSemant()
  62. Const NotIterableError:String = "EachIn requires a type that implements IIterable or has a suitable ObjectEnumerator method."
  63. expr=expr.Semant()
  64. If TArrayType( expr.exprType ) Or TStringType( expr.exprType )
  65. Local exprTmp:TLocalDecl
  66. Local exprVar:TExpr
  67. If TArrayType( expr.exprType ).isStatic And (TVarExpr(expr) Or TMemberVarExpr(expr)) Then ' TODO TSliceExpr
  68. exprVar = expr
  69. Else
  70. exprTmp = New TLocalDecl.Create( "",Null,expr,,True )
  71. exprVar = New TVarExpr.Create( exprTmp )
  72. End If
  73. Local indexTmp:TLocalDecl=New TLocalDecl.Create( "",Null,New TConstExpr.Create( New TUIntType,"0" ),,True )
  74. Local lenExpr:TExpr=New TIdentExpr.Create( "Length",exprVar )
  75. Local cmpExpr:TExpr=New TBinaryCompareExpr.Create( "<",New TVarExpr.Create( indexTmp ),lenExpr )
  76. Local indexExpr:TExpr=New TIndexExpr.Create( exprVar,[New TVarExpr.Create( indexTmp )] )
  77. Local addExpr:TExpr=New TBinaryMathExpr.Create( "+",New TVarExpr.Create( indexTmp ),New TConstExpr.Create( New TIntType,"1" ) )
  78. Local cont:TContinueStmt
  79. If varlocal
  80. ' array of object ?
  81. If TArrayType( expr.exprType ) And TObjectType(TArrayType( expr.exprType ).elemType) And (Not TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsExtern() ..
  82. Or (TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsExtern() ..
  83. And IsPointerType(TArrayType( expr.exprType ).elemType))) Then
  84. Local isStruct:Int = TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsStruct()
  85. Local cExpr:TExpr
  86. Local varObjTmp:TLocalDecl
  87. Local varObjStmt:TStmt
  88. If exprTmp Then
  89. exprTmp.Semant()
  90. End If
  91. indexTmp.Semant()
  92. If TIdentType(varty) And TIdentType(varty).ident = "Object" Then
  93. cExpr = indexExpr
  94. Else
  95. If TStringType(varty) Then
  96. varObjTmp = New TLocalDecl.Create( "",TType.objectType,indexExpr,,True)
  97. varObjTmp.Semant()
  98. Local varObjExpr:TExpr=New TVarExpr.Create( varObjTmp )
  99. Local expr:TExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectIsString"), [varObjExpr])
  100. expr=New TBinaryCompareExpr.Create( "=",expr, New TConstExpr.Create( New TIntType,"0" ))
  101. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  102. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  103. cont = New TContinueStmt.Create(Null, True)
  104. thenBlock.AddStmt cont
  105. varObjStmt = New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  106. 'block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  107. cExpr = New TCastExpr.Create( varty, varObjExpr,CAST_EXPLICIT )
  108. Else
  109. cExpr = New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT )
  110. End If
  111. 'cExpr = New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT )
  112. End If
  113. ' local variable
  114. Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,cExpr )
  115. ' local var as expression
  116. Local expr:TExpr=New TVarExpr.Create( varTmp )
  117. If Not isStruct And Not varObjTmp Then
  118. ' var = Null
  119. expr=New TBinaryCompareExpr.Create( "=",expr, New TNullExpr.Create(TType.nullObjectType))
  120. ' then continue
  121. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_IF )
  122. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_ELSE )
  123. cont = New TContinueStmt
  124. thenBlock.AddStmt cont
  125. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock )
  126. End If
  127. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr )
  128. block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  129. If varObjTmp Then
  130. block.stmts.AddFirst varObjStmt
  131. block.stmts.AddFirst New TDeclStmt.Create( varObjTmp, True )
  132. End If
  133. Else
  134. Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,indexExpr )
  135. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr, True )
  136. block.stmts.AddFirst New TDeclStmt.Create( varTmp, True )
  137. End If
  138. Else
  139. If TArrayType( expr.exprType ) And TObjectType(TArrayType( expr.exprType ).elemType) Then
  140. ' var = Null
  141. If Not varty Then
  142. varExpr = varExpr.Semant()
  143. varty = varExpr.exprType
  144. 'Local decl:TValDecl = block.scope.FindValDecl(varid.ToLower())
  145. 'If decl Then
  146. ' decl.Semant()
  147. '
  148. ' varty = decl.ty.Copy()
  149. 'End If
  150. End If
  151. Local isStruct:Int = TObjectType(TArrayType( expr.exprType ).elemType).classdecl.IsStruct()
  152. ' expr=New TBinaryCompareExpr.Create( "=",New TIdentExpr.Create( varid ), New TNullExpr.Create(TType.nullObjectType))
  153. If Not isStruct Then
  154. expr=New TBinaryCompareExpr.Create( "=",varExpr, New TNullExpr.Create(TType.nullObjectType))
  155. ' then continue
  156. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_IF )
  157. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_ELSE )
  158. cont = New TContinueStmt
  159. thenBlock.AddStmt cont
  160. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock )
  161. End If
  162. 'block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  163. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr, True )
  164. ' block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT ), True )
  165. block.stmts.AddFirst New TAssignStmt.Create( "=",varExpr,New TCastExpr.Create( varty, indexExpr,CAST_EXPLICIT ), True )
  166. Else
  167. block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr, True )
  168. ' block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),indexExpr, True )
  169. block.stmts.AddFirst New TAssignStmt.Create( "=",varExpr,indexExpr, True )
  170. End If
  171. EndIf
  172. Local whileStmt:TWhileStmt=New TWhileStmt.Create( cmpExpr,block,loopLabel, True )
  173. block=New TBlockDecl.Create( block.scope, True, BLOCK_LOOP )
  174. If exprTmp Then
  175. block.AddStmt New TDeclStmt.Create( exprTmp, True )
  176. End If
  177. block.AddStmt New TDeclStmt.Create( indexTmp, True )
  178. block.AddStmt whileStmt
  179. If cont Then
  180. cont.loop = whileStmt
  181. End If
  182. Else If TObjectType( expr.exprType )
  183. Local tmpDecl:TDeclStmt
  184. Local iterable:Int
  185. ' ensure semanted
  186. TObjectType(expr.exprType).classDecl.Semant()
  187. If TObjectType(expr.exprType).classDecl.ImplementsInterface("iiterable") Or (TObjectType(expr.exprType).classDecl.ident="IIterable" And TObjectType(expr.exprType).classDecl.IsInterface()) Then
  188. iterable = True
  189. Else
  190. Local declList:TFuncDeclList = TFuncDeclList(TObjectType(expr.exprType).classDecl.GetDecl("objectenumerator"))
  191. If Not declList Then
  192. Err NotIterableError
  193. End If
  194. End If
  195. If TInvokeExpr(expr) Or TInvokeMemberExpr(expr) Then
  196. Local tmpVar:TLocalDecl=New TLocalDecl.Create( "",expr.exprType,expr,,True )
  197. tmpVar.Semant()
  198. tmpDecl = New TDeclStmt.Create( tmpVar, True )
  199. expr = New TVarExpr.Create( tmpVar )
  200. End If
  201. Local enumerInit:TExpr
  202. If iterable Then
  203. enumerInit = New TFuncCallExpr.Create( New TIdentExpr.Create( "GetIterator",expr ) )
  204. Else
  205. enumerInit = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectEnumerator",expr ) )
  206. End If
  207. Local enumerTmp:TLocalDecl=New TLocalDecl.Create( "",Null,enumerInit,,True )
  208. enumerTmp.Semant()
  209. Local hasNextExpr:TExpr
  210. If iterable Then
  211. hasNextExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "MoveNext",New TVarExpr.Create( enumerTmp ) ) )
  212. Else
  213. hasNextExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "HasNext",New TVarExpr.Create( enumerTmp ) ) )
  214. End If
  215. Local nextObjExpr:TExpr
  216. If iterable Then
  217. nextObjExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "Current",New TVarExpr.Create( enumerTmp ) ) )
  218. Else
  219. nextObjExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "NextObject",New TVarExpr.Create( enumerTmp ) ) )
  220. End If
  221. Local cont:TContinueStmt
  222. If varlocal
  223. ' Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,nextObjExpr )
  224. ' block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  225. Local cExpr:TExpr
  226. Local varObjTmp:TLocalDecl
  227. Local varObjStmt:TStmt
  228. If iterable Or (TIdentType(varty) And TIdentType(varty).ident = "Object") Then
  229. cExpr = nextObjExpr
  230. Else
  231. If TStringType(varty) Then
  232. varObjTmp = New TLocalDecl.Create( "",TType.objectType,nextObjExpr,,True)
  233. varObjTmp.Semant()
  234. Local varObjExpr:TExpr=New TVarExpr.Create( varObjTmp )
  235. Local expr:TExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectIsString"), [varObjExpr])
  236. expr=New TBinaryCompareExpr.Create( "=",expr, New TConstExpr.Create( New TIntType,"0" ))
  237. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  238. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  239. cont = New TContinueStmt.Create(Null, True)
  240. thenBlock.AddStmt cont
  241. varObjStmt = New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  242. 'block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  243. cExpr = New TCastExpr.Create( varty, varObjExpr,CAST_EXPLICIT )
  244. Else
  245. cExpr = New TCastExpr.Create( varty, nextObjExpr,CAST_EXPLICIT )
  246. End If
  247. End If
  248. ' local variable
  249. Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,cExpr)
  250. If Not TNumericType(varty) And Not varObjTmp Then
  251. If iterable Then
  252. '
  253. Else
  254. ' local var as expression
  255. Local expr:TExpr=New TVarExpr.Create( varTmp )
  256. ' var = Null
  257. expr=New TBinaryCompareExpr.Create( "=",expr, New TNullExpr.Create(TType.nullObjectType))
  258. ' then continue
  259. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  260. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  261. cont = New TContinueStmt.Create(Null, True)
  262. thenBlock.AddStmt cont
  263. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  264. End If
  265. End If
  266. block.stmts.AddFirst New TDeclStmt.Create( varTmp, True )
  267. If varObjTmp Then
  268. block.stmts.AddFirst varObjStmt
  269. block.stmts.AddFirst New TDeclStmt.Create( varObjTmp, True )
  270. End If
  271. Else
  272. If Not varty Then
  273. varExpr = varExpr.Semant()
  274. varty = varExpr.exprType
  275. End If
  276. Local varObjTmp:TLocalDecl
  277. Local varObjStmt:TStmt
  278. Local cExpr:TExpr
  279. If TStringType(varty) Then
  280. varObjTmp = New TLocalDecl.Create( "",TType.objectType,nextObjExpr,,True)
  281. varObjTmp.Semant()
  282. Local varObjExpr:TExpr=New TVarExpr.Create( varObjTmp )
  283. Local expr:TExpr = New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectIsString"), [varObjExpr])
  284. expr=New TBinaryCompareExpr.Create( "=",expr, New TConstExpr.Create( New TIntType,"0" ))
  285. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
  286. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
  287. cont = New TContinueStmt.Create(Null, True)
  288. thenBlock.AddStmt cont
  289. varObjStmt = New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  290. 'block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock, True )
  291. cExpr = New TCastExpr.Create( varty, varObjExpr,CAST_EXPLICIT )
  292. Else
  293. cExpr = New TCastExpr.Create( varty, nextObjExpr,CAST_EXPLICIT )
  294. End If
  295. ' If Not varty Then
  296. ' Local decl:TValDecl = block.scope.FindValDecl(varid.ToLower())
  297. '
  298. ' If decl Then
  299. ' decl.Semant()
  300. '
  301. ' varty = decl.ty.Copy()
  302. ' End If
  303. ' End If
  304. ' var = Null
  305. ' Local expr:TExpr=New TBinaryCompareExpr.Create( "=",New TIdentExpr.Create( varid ), New TNullExpr.Create(TType.nullObjectType))
  306. If Not TNumericType(varty) And Not varObjTmp Then
  307. If iterable Then
  308. '
  309. Else
  310. Local expr:TExpr=New TBinaryCompareExpr.Create( "=",varExpr, New TNullExpr.Create(TType.nullObjectType))
  311. ' then continue
  312. Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, ,BLOCK_IF )
  313. Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, ,BLOCK_ELSE )
  314. cont = New TContinueStmt
  315. thenBlock.AddStmt cont
  316. block.stmts.AddFirst New TIfStmt.Create( expr,thenBlock,elseBlock )
  317. 'block.stmts.AddFirst New TDeclStmt.Create( varTmp )
  318. End If
  319. End If
  320. ' block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TCastExpr.Create( varty, nextObjExpr,CAST_EXPLICIT ))
  321. block.stmts.AddFirst New TAssignStmt.Create( "=",varExpr,cExpr)
  322. If varObjTmp Then
  323. block.stmts.AddFirst varObjStmt
  324. block.stmts.AddFirst New TDeclStmt.Create( varObjTmp, True )
  325. End If
  326. EndIf
  327. Local whileStmt:TWhileStmt=New TWhileStmt.Create( hasNextExpr,block, loopLabel, True )
  328. block=New TBlockDecl.Create( block.scope, True, BLOCK_LOOP )
  329. If tmpDecl Then
  330. block.AddStmt tmpDecl
  331. End If
  332. block.AddStmt New TDeclStmt.Create( enumerTmp, True )
  333. block.AddStmt whileStmt
  334. If cont Then
  335. cont.loop = whileStmt
  336. End If
  337. Else
  338. Err NotIterableError
  339. EndIf
  340. block.Semant
  341. End Method
  342. Method Trans$()
  343. _trans.EmitBlock block
  344. End Method
  345. End Type
  346. Type TIncbin
  347. Field file:String
  348. Field path:String
  349. Field id:Int
  350. Field length:Int
  351. Global count:Int
  352. Method Create:TIncbin(file:String, source:String)
  353. count :+ 1
  354. Self.file = file
  355. ' find the file
  356. If Not FileType(file) Then
  357. ' maybe relative to source
  358. Local dir:String = ExtractDir(source) + "/" + file
  359. If FileType(dir) = FILETYPE_FILE Then
  360. path = RealPath(dir)
  361. Else
  362. Return Null
  363. End If
  364. Else
  365. path = RealPath(file)
  366. End If
  367. id = count
  368. Return Self
  369. End Method
  370. Method GeneratedDataName:String(app:TAppDecl)
  371. Return "_ib" + app.munged + "_" + id + "_data"
  372. End Method
  373. Method GeneratedSizeName:String(app:TAppDecl)
  374. Return "_ib" + app.munged + "_" + id + "_size"
  375. End Method
  376. End Type
  377. '***** Parser *****
  378. Type TParser Extends TGenProcessor
  379. Field _toker:TToker
  380. Field _toke:String
  381. Field _tokeType:Int
  382. Field _block:TBlockDecl
  383. Field _blockStack:TList=New TList'<TBlockDecl>
  384. Field _errStack:TStringList=New TStringList
  385. Field _app:TAppDecl
  386. Field _module:TModuleDecl
  387. Field _externCasts:TMap = New TMap
  388. Field unknownIdentsEvalFalse:Int
  389. Method SetErr(toker:TToker = Null)
  390. Local t:TToker = _toker
  391. If toker Then
  392. t = toker
  393. End If
  394. If t.Path()
  395. _errInfo=FormatError(t.Path(),t.Line(),0)
  396. EndIf
  397. End Method
  398. Method DoErr(error:String, toker:TToker = Null)
  399. SetErr(toker)
  400. Err error
  401. End Method
  402. Method PushBlock( block:TBlockDecl )
  403. If _block <> Null Then
  404. _blockStack.AddLast _block
  405. End If
  406. _errStack.AddLast _errInfo
  407. _block=block
  408. End Method
  409. Method PopBlock()
  410. _block=TBlockDecl(_blockStack.RemoveLast())
  411. _errInfo=String(_errStack.RemoveLast())
  412. End Method
  413. Method RealPath$( path$ )
  414. Local popDir$=CurrentDir()
  415. ChangeDir ExtractDir( _toker.Path() )
  416. path=BRL.FileSystem.RealPath( path )
  417. ChangeDir popDir
  418. Return path
  419. End Method
  420. Method ActualPath:String(path:String)
  421. Local dir:String = ExtractDir(path)
  422. Local origFile:String = StripDir(path)
  423. Local lowerFile:String = origFile.ToLower()
  424. Local actualDir:String = ExtractDir(RealPath(path))
  425. Local files:String[] = LoadDir(actualDir)
  426. For Local file:String = EachIn files
  427. If file.ToLower() = lowerFile Then
  428. If file <> origFile Then
  429. ' we could raise as a warning instead, but an error encourages the user to fix their code ;-)
  430. Err "Actual file '" + file + "' differs in case with import '" + origFile + "'"
  431. ' what we might do were we to warn instead...
  432. If dir Then
  433. Return dir + "/" + file
  434. Else
  435. Return file
  436. End If
  437. End If
  438. Exit
  439. End If
  440. Next
  441. Return path
  442. End Method
  443. Method NextToke$()
  444. Local toke$=_toke
  445. Repeat
  446. _toke=_toker.NextToke()
  447. _tokeType=_toker.TokeType()
  448. Until _tokeType<>TOKE_SPACE
  449. If _tokeType=TOKE_KEYWORD _toke=_toker._tokeLower
  450. If toke="," SkipEols
  451. Return _toke
  452. End Method
  453. Method NextTokeToker$(toker:TToker)
  454. ' Local toke$=toker._toke
  455. Repeat
  456. toker.NextToke()
  457. Until toker.tokeType()<>TOKE_SPACE
  458. Return toker._toke
  459. End Method
  460. Method DescribeToke:String( toke:String )
  461. Select toke
  462. Case "~n"
  463. Return "end-of-line"
  464. End Select
  465. Local uni:String
  466. If toke.length > 0 And toke[0] > 255 Then
  467. uni = " (unicode : " + _toker._lastTCHR + ")"
  468. End If
  469. Return "'" + toke + "'" + uni
  470. End Method
  471. Method CParse:Int( toke$ )
  472. If _toke.ToLower()<>toke
  473. Return False
  474. EndIf
  475. NextToke
  476. Return True
  477. End Method
  478. Method CParseToker:Int( toker:TToker, toke$ )
  479. If toker._toke.ToLower()<>toke
  480. Return False
  481. EndIf
  482. NextTokeToker(toker)
  483. Return True
  484. End Method
  485. Method Parse( toke$ )
  486. If Not CParse( toke )
  487. DoErr "Syntax error - expecting '"+toke+"' but found " + DescribeToke(_toke)
  488. EndIf
  489. End Method
  490. Method ParseToker( toker:TToker, toke$ )
  491. If Not CParseToker( toker, toke )
  492. DoErr "Syntax error - expecting '"+toke+"'.", toker
  493. EndIf
  494. End Method
  495. Method AtEos:Int()
  496. Return _toke="" Or _toke=";" Or _toke="~n" Or _toke="else"
  497. End Method
  498. Method SkipEols()
  499. While CParse( "~n" ) Or CParse(";")
  500. Wend
  501. SetErr
  502. End Method
  503. Method SkipEolsToker(toker:TToker)
  504. While CParseToker( toker, "~n" )
  505. Wend
  506. SetErr
  507. End Method
  508. Method ParseStringLit$()
  509. If _tokeType<>TOKE_STRINGLIT Err "Expecting string literal."
  510. Local str$=BmxUnquote( _toke )
  511. NextToke
  512. Return str
  513. End Method
  514. Method ParseIdent$()
  515. Select _toke
  516. Case "@" NextToke
  517. Case "string","object", "self"
  518. Default
  519. If _tokeType<>TOKE_IDENT Then
  520. Local kw:String
  521. If _tokeType = TOKE_KEYWORD Then
  522. kw = " keyword"
  523. End If
  524. Err "Syntax error - expecting identifier, but found" + kw + " '" + EscapeLines(_toke) + "'"
  525. End If
  526. End Select
  527. Local id$=_toke
  528. NextToke
  529. Return id
  530. End Method
  531. Method ParseIdentType:TIdentType()
  532. Local id$=ParseIdent()
  533. If CParse( "." ) id:+"."+ParseIdent()
  534. If CParse( "." ) id:+"."+ParseIdent()
  535. Local args:TType[]
  536. If CParse( "<" )
  537. Local nargs:Int
  538. Repeat
  539. Local arg:TType = ParseType()
  540. Repeat
  541. If (_toke = "[" Or _toke = "[]") And IsArrayDef()
  542. arg = ParseArrayType(arg)
  543. Else If _toke = "(" Then
  544. Local argDecls:TArgDecl[] = ParseFuncParamDecl()
  545. arg = New TFunctionPtrType.Create(New TFuncDecl.CreateF("", arg, argDecls, FUNC_PTR))
  546. Else
  547. Exit
  548. End If
  549. Forever
  550. If args.Length=nargs args=args+ New TType[10]
  551. args[nargs]=arg
  552. nargs:+1
  553. Until Not CParse(",")
  554. args=args[..nargs]
  555. Parse ">"
  556. EndIf
  557. Return New TIdentType.Create( id,args )
  558. End Method
  559. Method CParseIdentType:TIdentType( inner:Int=False )
  560. If _tokeType<>TOKE_IDENT Return Null
  561. Local id$=ParseIdent()
  562. While CParse( "." )
  563. If _tokeType<>TOKE_IDENT Return Null
  564. id:+"."+ParseIdent()
  565. Wend
  566. If Not CParse( "<" )
  567. If inner Return New TIdentType.Create( id,Null )
  568. Return Null
  569. EndIf
  570. Local args:TType[]
  571. Local nargs:Int
  572. Repeat
  573. Local arg:TType=CParsePrimitiveType()
  574. If Not arg
  575. arg=CParseIdentType( True )
  576. If Not arg Return Null
  577. EndIf
  578. While IsArrayDef()
  579. arg = ParseArrayType(arg)
  580. Wend
  581. ' While CParse( "[]" )
  582. ' arg=arg.ArrayOf()
  583. ' Wend
  584. args = args + [arg]
  585. nargs :+ 1
  586. Until Not CParse(",")
  587. If Not CParse( ">" ) Return Null
  588. Return New TIdentType.Create( id,args )
  589. End Method
  590. Method CParsePrimitiveType:TType()
  591. If CParse( "string" ) Return TType.stringType
  592. If CParse( "object" ) Return New TIdentType.Create( "brl.classes.object" )
  593. Local ty:TType
  594. If CParse( "short" )
  595. ty = New TShortType
  596. Else If CParse( "byte" )
  597. ty = New TByteType
  598. Else If CParse( "int" )
  599. ty = New TIntType
  600. Else If CParse( "uint" )
  601. ty = New TUIntType
  602. Else If CParse( "float" )
  603. ty = New TFloatType
  604. Else If CParse( "long" )
  605. ty = New TLongType
  606. Else If CParse( "ulong" )
  607. ty = New TULongType
  608. Else If CParse( "longint" )
  609. ty = New TLongIntType
  610. Else If CParse( "ulongint" )
  611. ty = New TULongIntType
  612. Else If CParse( "double" )
  613. ty = New TDoubleType
  614. Else If CParse( "size_t" )
  615. ty = New TSizeTType
  616. Else If CParse( "int128" ) Then
  617. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  618. ty = New TInt128Type
  619. Else If CParse( "float128" ) Then
  620. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  621. ty = New TFloat128Type
  622. Else If CParse( "double128" ) Then
  623. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  624. ty = New TDouble128Type
  625. Else If CParse( "float64" ) Then
  626. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  627. ty = New TFloat64Type
  628. Else If CParse( "wparam" ) Then
  629. If opt_platform <> "win32" Err "WParam types only available on Win32"
  630. ty = New TWParamType
  631. Else If CParse( "lparam" ) Then
  632. If opt_platform <> "win32" Err "LParam types only available on Win32"
  633. ty = New TLParamType
  634. End If
  635. While CParse("ptr")
  636. ty = TType.MapToPointerType(ty)
  637. Wend
  638. Return ty
  639. End Method
  640. Method CParsePrimitiveNumberType:TType()
  641. If CParse( "short" ) Return New TShortType
  642. If CParse( "byte" ) Return New TByteType
  643. If CParse( "int" ) Return New TIntType
  644. If CParse( "uint" ) Return New TUIntType
  645. If CParse( "float" ) Return New TFloatType
  646. If CParse( "long" ) Return New TLongType
  647. If CParse( "ulong" ) Return New TULongType
  648. If CParse( "longint" ) Return New TLongIntType
  649. If CParse( "ulongint" ) Return New TULongIntType
  650. If CParse( "double" ) Return New TDoubleType
  651. If CParse( "size_t" ) Return New TSizeTType
  652. If CParse( "int128" ) Then
  653. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  654. Return New TInt128Type
  655. End If
  656. If CParse( "float128" ) Then
  657. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  658. Return New TFloat128Type
  659. End If
  660. If CParse( "double128" ) Then
  661. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  662. Return New TDouble128Type
  663. End If
  664. If CParse( "float64" ) Then
  665. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  666. Return New TFloat64Type
  667. End If
  668. If CParse( "wparam" ) Then
  669. If opt_platform <> "win32" Err "WParam types only available on Win32"
  670. Return New TWParamType
  671. End If
  672. If CParse( "lparam" ) Then
  673. If opt_platform <> "win32" Err "LParam types only available on Win32"
  674. Return New TLParamType
  675. End If
  676. End Method
  677. Method ParseNewType:TType()
  678. If CParse( "void" ) Return New TVoidType
  679. If CParse( "short" ) Return New TShortType
  680. If CParse( "byte" ) Return New TByteType
  681. If CParse( "int" ) Return New TIntType
  682. If CParse( "uint" ) Return New TUIntType
  683. If CParse( "float" ) Return New TFloatType
  684. If CParse( "string" ) Return TType.stringType
  685. If CParse( "object" ) Return New TIdentType.Create( "brl.classes.object" )
  686. If CParse( "long" ) Return New TLongType
  687. If CParse( "ulong" ) Return New TULongType
  688. If CParse( "longint" ) Return New TLongIntType
  689. If CParse( "ulongint" ) Return New TULongIntType
  690. If CParse( "double" ) Return New TDoubleType
  691. If CParse( "size_t" ) Return New TSizeTType
  692. If CParse( "int128" ) Then
  693. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  694. Return New TInt128Type
  695. End If
  696. If CParse( "float128" ) Then
  697. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  698. Return New TFloat128Type
  699. End If
  700. If CParse( "double128" ) Then
  701. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  702. Return New TDouble128Type
  703. End If
  704. If CParse( "float64" ) Then
  705. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  706. Return New TFloat64Type
  707. End If
  708. If CParse( "wparam" ) Then
  709. If opt_platform <> "win32" Err "WParam types only available on Win32"
  710. Return New TWParamType
  711. End If
  712. If CParse( "lparam" ) Then
  713. If opt_platform <> "win32" Err "LParam types only available on Win32"
  714. Return New TLParamType
  715. End If
  716. Return ParseIdentType()
  717. End Method
  718. Method ParseType:TType()
  719. Local ty:TType=CParsePrimitiveType()
  720. If ty Return ty
  721. Return ParseIdentType()
  722. End Method
  723. Method ParseConstNumberType:TType()
  724. Local ty:TType
  725. Select _toke
  726. Case "@"
  727. NextToke
  728. ty=New TByteType
  729. While CParse("ptr")
  730. ty = TType.MapToPointerType(ty)
  731. Wend
  732. Case "@@"
  733. NextToke
  734. ty=New TShortType
  735. While CParse("ptr")
  736. ty = TType.MapToPointerType(ty)
  737. Wend
  738. Case "%"
  739. NextToke
  740. ty=New TIntType
  741. While CParse("ptr")
  742. ty = TType.MapToPointerType(ty)
  743. Wend
  744. Case "#"
  745. NextToke
  746. ty=New TFloatType
  747. While CParse("ptr")
  748. ty = TType.MapToPointerType(ty)
  749. Wend
  750. Case "$"
  751. NextToke
  752. ty=New TStringType
  753. Case "!"
  754. NextToke
  755. ty=New TDoubleType
  756. While CParse("ptr")
  757. ty = TType.MapToPointerType(ty)
  758. Wend
  759. Case "%%"
  760. NextToke
  761. ty=New TLongType
  762. While CParse("ptr")
  763. ty = TType.MapToPointerType(ty)
  764. Wend
  765. Case ":"
  766. NextToke
  767. ty=CParsePrimitiveNumberType()
  768. If Not ty Then
  769. If CParse("string") Then
  770. ty=New TStringType
  771. Else
  772. ty = ParseIdentType()
  773. End If
  774. Else
  775. While CParse("ptr")
  776. ty = TType.MapToPointerType(ty)
  777. Wend
  778. End If
  779. End Select
  780. While IsArrayDef()
  781. ty = ParseArrayType(ty)
  782. Wend
  783. 'While CParse( "[]" )
  784. ' ty=New TArrayType.Create( ty )
  785. 'Wend
  786. Return ty
  787. End Method
  788. Method ParseDeclType:TType(attr:Long = 0)
  789. Local ty:TType
  790. Select _toke
  791. Case "@"
  792. NextToke
  793. ty=New TByteType
  794. While CParse("ptr")
  795. ty = TType.MapToPointerType(ty)
  796. Wend
  797. Case "@@"
  798. NextToke
  799. ty=New TShortType
  800. While CParse("ptr")
  801. ty = TType.MapToPointerType(ty)
  802. Wend
  803. Case "%"
  804. NextToke
  805. ty=New TIntType
  806. While CParse("ptr")
  807. ty = TType.MapToPointerType(ty)
  808. Wend
  809. Case "%%"
  810. NextToke
  811. ty=New TLongType
  812. While CParse("ptr")
  813. ty = TType.MapToPointerType(ty)
  814. Wend
  815. Case "#"
  816. NextToke
  817. ty=New TFloatType
  818. If CParse("ptr") Then
  819. ty = TType.MapToPointerType(ty)
  820. End If
  821. Case "$"
  822. NextToke
  823. ty=New TStringType
  824. If CParse("z") Then
  825. ty._flags :| TType.T_CHAR_PTR
  826. Else If CParse("w") Then
  827. ty._flags :| TType.T_SHORT_PTR
  828. End If
  829. Case "!"
  830. NextToke
  831. ty=New TDoubleType
  832. While CParse("ptr")
  833. ty = TType.MapToPointerType(ty)
  834. Wend
  835. Case ":"
  836. NextToke
  837. ty=ParseType()
  838. If CParse("ptr") Then
  839. ' FIXME #200
  840. 'If TStringType(ty) = Null And (TObjectType(ty) = Null Or (TObjectType(ty) <> Null And TObjectType(ty).classDecl.IsExtern())) And TArrayType(ty) = Null Then
  841. ty = TType.MapToPointerType(ty)
  842. While CParse("ptr")
  843. ty = TType.MapToPointerType(ty)
  844. Wend
  845. 'Else
  846. ' ty = Null
  847. 'End If
  848. If Not ty DoErr "Invalid Pointer type."
  849. End If
  850. Case "("
  851. ' for Strict code, void will be converted to Int during semanting.
  852. ty=New TVoidType
  853. Default
  854. If _module.IsSuperStrict() Err "Missing type specifier."
  855. ty=New TIntType
  856. While CParse("ptr")
  857. ty = TType.MapToPointerType(ty)
  858. Wend
  859. End Select
  860. ' array or function pointer?
  861. Repeat
  862. If (_toke = "[" Or _toke = "[]") And (IsArrayDef() Or IsArrayDef(attr & DECL_STATIC > 0)) Then
  863. If Not IsArrayDef(attr & DECL_STATIC > 0) Then
  864. Err "Invalid static array initialization."
  865. Else
  866. If attr & DECL_STATIC > 0 Then
  867. Exit
  868. End If
  869. ty = ParseArrayType(ty)
  870. End If
  871. Else If _toke = "(" Then
  872. Local args:TArgDecl[] = ParseFuncParamDecl()
  873. attr :| ParseCallConvention(attr & DECL_API_STDCALL)
  874. ty = New TFunctionPtrType.Create(New TFuncDecl.CreateF("", ty, args, FUNC_PTR | (attr & DECL_API_STDCALL)))
  875. Else
  876. Exit
  877. End If
  878. Forever
  879. Return ty
  880. End Method
  881. Method ParseArrayExpr:TArrayExpr()
  882. Parse "["
  883. Local args:TExpr[],nargs:Int
  884. Repeat
  885. Local arg:TExpr=ParseExpr()
  886. If args.Length=nargs args=args + New TExpr[10]
  887. args[nargs]=arg
  888. nargs:+1
  889. Until Not CParse(",")
  890. args=args[..nargs]
  891. Parse "]"
  892. Return New TArrayExpr.Create( args )
  893. End Method
  894. ' replaces While CParse( "[]" ) sections, with support for multi-dimension arrays
  895. Method ParseArrayType:TType(ty:TType, isStatic:Int = False)
  896. If isStatic Then
  897. Parse("[")
  898. Local expr:TExpr = ParseUnaryExpr()
  899. ty = New TArrayType.Create( ty )
  900. TArrayType(ty).isStatic = True
  901. Parse("]")
  902. Return ty
  903. End If
  904. While True
  905. Local dims:Int = 1
  906. If CParse("[]") Then
  907. ty=New TArrayType.Create( ty )
  908. ' test for array of arrays
  909. If IsArrayTypeNext(_toker) Continue
  910. Exit
  911. End If
  912. If Not CParse("[") Then
  913. Exit
  914. End If
  915. While CParse( ",")
  916. dims :+ 1
  917. Wend
  918. Parse "]"
  919. ty=New TArrayType.Create( ty, dims )
  920. ' test for array of arrays
  921. If IsArrayTypeNext(_toker) Continue
  922. Exit
  923. Wend
  924. Return ty
  925. End Method
  926. Method IsArrayTypeNext:Int(tok:TToker)
  927. Local toker:TToker=New TToker.Copy(tok)
  928. If CParseToker(toker, "[]") Return True
  929. If CParseToker(toker, "[") Then
  930. ' look ahead to see if this is an array decl, or something else..
  931. If CParseToker(toker, "]") Or CParseToker(toker, ",") Then
  932. Return True
  933. End If
  934. End If
  935. Return False
  936. End Method
  937. Method IsArrayDef:Int(isStatic:Int = False)
  938. Local isDef:Int = True
  939. Local toker:TToker=New TToker.Copy(_toker)
  940. If isStatic Then
  941. If Not CParseToker(toker, "[") Then
  942. Return False
  943. End If
  944. NextTokeToker(toker)
  945. If Not CParseToker(toker, "]") Then
  946. Return False
  947. End If
  948. Return True
  949. End If
  950. While True
  951. 'Local dims:Int = 1
  952. If CParseToker(toker, "[]") Then
  953. Exit
  954. End If
  955. If Not CParseToker(toker, "[") Then
  956. isDef = False
  957. Exit
  958. End If
  959. While CParseToker(toker, ",")
  960. 'dims :+ 1
  961. Wend
  962. If Not CParseToker(toker, "]") Then
  963. isDef = False
  964. Exit
  965. End If
  966. Exit
  967. Wend
  968. Return isDef
  969. End Method
  970. Method ParseArgs:TExpr[]( stmt:Int )
  971. Local args:TExpr[]
  972. If stmt
  973. If AtEos() Return args
  974. Else
  975. If _toke<>"(" Return args
  976. EndIf
  977. Local nargs:Int,eat:Int
  978. If _toke="("
  979. If stmt
  980. Local toker:TToker=New TToker.Copy(_toker),bra:Int=1
  981. Repeat
  982. toker.NextToke
  983. toker.SkipSpace
  984. Select toker.Toke().ToLower()
  985. Case "","else"
  986. Err "Parenthesis mismatch error."
  987. Case "(","["
  988. bra:+1
  989. Case "]",")"
  990. bra:-1
  991. If bra Continue
  992. toker.NextToke
  993. toker.SkipSpace
  994. Select toker.Toke().ToLower()
  995. Case ".","(","[","",";","~n","else"
  996. eat=True
  997. End Select
  998. Exit
  999. Case ","
  1000. If bra<>1 Continue
  1001. eat=True
  1002. Exit
  1003. End Select
  1004. Forever
  1005. Else
  1006. eat=True
  1007. EndIf
  1008. If eat And NextToke()=")"
  1009. NextToke
  1010. Return args
  1011. EndIf
  1012. EndIf
  1013. Repeat
  1014. Local arg:TExpr
  1015. If _toke And _toke<>"," arg=ParseExpr()
  1016. If args.Length=nargs args=args + New TExpr[10]
  1017. args[nargs]=arg
  1018. nargs:+1
  1019. Until Not CParse(",")
  1020. args=args[..nargs]
  1021. If eat Parse ")"
  1022. Return args
  1023. End Method
  1024. Method ParsePrimaryExpr:TExpr( stmt:Int )
  1025. Local expr:TExpr
  1026. Select _toke.ToLower()
  1027. Case "("
  1028. NextToke
  1029. expr=ParseExpr()
  1030. Parse ")"
  1031. Case "["
  1032. expr=ParseArrayExpr()
  1033. Case "[]"
  1034. NextToke
  1035. expr=New TConstExpr.Create( TType.emptyArrayType,"" )
  1036. Case "."
  1037. expr=New TScopeExpr.Create( _module )
  1038. Case "new"
  1039. NextToke
  1040. If _toke = "(" Then
  1041. ' call constructor
  1042. expr=New TNewExpr.Create( ParseArgs(stmt) )
  1043. Else
  1044. Local ty:TType=ParseType()
  1045. While CParse("ptr")
  1046. ty = TType.MapToPointerType(ty)
  1047. Wend
  1048. If _toke = "[" Or _toke = "[]" Then
  1049. Local depth:Int = 0
  1050. Local ln:TExpr[]
  1051. Local tmpTy:TType = ty.Copy()
  1052. Repeat
  1053. Local dims:Int = 1
  1054. If CParse("[]") Then
  1055. tmpTy=New TArrayType.Create( tmpTy )
  1056. depth :+ 1
  1057. Continue
  1058. End If
  1059. ' looking for an array with expression
  1060. If Not ln Then
  1061. Parse "["
  1062. Else
  1063. If Not CParse("[") Then
  1064. Exit
  1065. Else
  1066. Err "Unexpected '[' after array size declaration"
  1067. End If
  1068. End If
  1069. Repeat
  1070. If CParse(",") Then
  1071. dims :+ 1
  1072. Continue
  1073. End If
  1074. If CParse("]") Exit
  1075. ln = ln + [ParseExpr()]
  1076. If CParse("]") Exit
  1077. Parse(",")
  1078. dims :+ 1
  1079. Forever
  1080. If Not ln Then
  1081. tmpTy=New TArrayType.Create( tmpTy, dims )
  1082. End If
  1083. Forever
  1084. If ln Then
  1085. ty = tmpTy
  1086. End If
  1087. ' Repeat
  1088. 'If CParse( "[" )
  1089. ' Repeat
  1090. ' ln = ln + [ParseExpr()]
  1091. ' If CParse("]") Exit
  1092. ' Parse ","
  1093. ' Forever
  1094. 'Parse "]"
  1095. ' ty = ParseArrayType(ty)
  1096. ' Forever
  1097. 'While CParse( "[]" )
  1098. ' ty=New TArrayType.Create( ty)
  1099. 'Wend
  1100. expr=New TNewArrayExpr.Create( ty,ln )
  1101. Else
  1102. expr=New TNewObjectExpr.Create( ty,ParseArgs( stmt ) )
  1103. EndIf
  1104. End If
  1105. Case "null"
  1106. NextToke
  1107. expr = New TNullExpr.Create(TType.nullObjectType)
  1108. 'expr=New TConstExpr.Create( TType.nullObjectType,"" )
  1109. Case "true"
  1110. NextToke
  1111. expr=New TConstExpr.Create( New TIntType,"1" )
  1112. Case "false"
  1113. NextToke
  1114. expr=New TConstExpr.Create( New TIntType,"" )
  1115. Case "int","long","float","double","object","short","byte","size_t","uint","ulong","longint","ulongint","int128","float64","float128","double128","lparam","wparam","string"
  1116. Local id$=_toke
  1117. Local ty:TType=ParseType()
  1118. If TIntType(ty) And id.ToLower() <> "int" Then
  1119. Select id.ToLower()
  1120. Case "byte"
  1121. ty = New TByteType
  1122. Case "short"
  1123. ty = New TShortType
  1124. Case "uint"
  1125. ty = New TUIntType
  1126. Case "long"
  1127. ty = New TLongType
  1128. Case "ulong"
  1129. ty = New TULongType
  1130. Case "longint"
  1131. ty = New TLongIntType
  1132. Case "ulongint"
  1133. ty = New TULongIntType
  1134. Case "float"
  1135. ty = New TFloatType
  1136. Case "double"
  1137. ty = New TDoubleType
  1138. Case "size_t"
  1139. ty = New TSizeTType
  1140. Case "int128"
  1141. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1142. ty = New TInt128Type
  1143. Case "float128"
  1144. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1145. ty = New TFloat128Type
  1146. Case "double128"
  1147. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1148. ty = New TDouble128Type
  1149. Case "float64"
  1150. If opt_arch <> "x64" Err "Intrinsic types only available on x64"
  1151. ty = New TFloat64Type
  1152. Case "wparam"
  1153. If opt_platform <> "win32" Err "WParam types only available on Win32"
  1154. ty = New TWParamType
  1155. Case "lparam"
  1156. If opt_platform <> "win32" Err "LParam types only available on Win32"
  1157. ty = New TLParamType
  1158. End Select
  1159. End If
  1160. While CParse("ptr")
  1161. ty = TType.MapToPointerType(ty)
  1162. Wend
  1163. ' array
  1164. ty = ParseArrayType(ty)
  1165. ' optional brackets
  1166. If CParse( "(" )
  1167. expr=ParseExpr()
  1168. Parse ")"
  1169. expr=New TCastExpr.Create( ty,expr,CAST_EXPLICIT )
  1170. Else
  1171. Local tok:TToker=New TToker.Copy( _toker )
  1172. If id="string" And CParseToker(tok, ".") Then
  1173. expr=New TIdentExpr.Create( id )
  1174. Else
  1175. expr=ParseExpr()
  1176. If TBinaryExpr(expr) Then
  1177. ' cast lhs and apply to rhs
  1178. Local cexpr:TCastExpr=New TCastExpr.Create( ty,TBinaryExpr(expr).lhs,CAST_EXPLICIT )
  1179. TBinaryExpr(expr).lhs = cexpr
  1180. Else
  1181. expr=New TCastExpr.Create( ty,expr,CAST_EXPLICIT )
  1182. End If
  1183. End If
  1184. EndIf
  1185. Case "sizeof"
  1186. NextToke
  1187. Local ty:TType = ParseConstNumberType()
  1188. If ty Then
  1189. If Not TIntType(ty) Then
  1190. Err "Return type for 'SizeOf' must be Int"
  1191. End If
  1192. End If
  1193. ' optional brackets
  1194. If CParse( "(" )
  1195. expr=ParseExpr()
  1196. Parse ")"
  1197. expr=New TSizeOfExpr.Create( expr )
  1198. Else
  1199. expr=ParseExpr()
  1200. expr=New TSizeOfExpr.Create( expr )
  1201. EndIf
  1202. Case "len"
  1203. NextToke
  1204. Local ty:TType = ParseConstNumberType()
  1205. If ty Then
  1206. If Not TIntType(ty) Then
  1207. Err "Return type for 'Len' must be Int"
  1208. End If
  1209. End If
  1210. ' optional brackets
  1211. If CParse( "(" )
  1212. expr=ParseExpr()
  1213. Parse ")"
  1214. expr=New TLenExpr.Create( expr )
  1215. Else
  1216. expr=ParseExpr()
  1217. expr=New TLenExpr.Create( expr )
  1218. EndIf
  1219. Case "asc"
  1220. NextToke
  1221. Local ty:TType = ParseConstNumberType()
  1222. If ty Then
  1223. If Not TIntType(ty) Then
  1224. Err "Return type for 'Asc' must be Int"
  1225. End If
  1226. End If
  1227. ' optional brackets
  1228. If CParse( "(" )
  1229. expr=ParseExpr()
  1230. Parse ")"
  1231. expr=New TAscExpr.Create( expr )
  1232. Else
  1233. expr=ParseExpr()
  1234. expr=New TAscExpr.Create( expr )
  1235. EndIf
  1236. Case "chr"
  1237. NextToke
  1238. Local ty:TType = ParseConstNumberType()
  1239. If ty Then
  1240. If Not TStringType(ty) Then
  1241. Err "Return type for 'Chr' must be String"
  1242. End If
  1243. End If
  1244. ' optional brackets
  1245. If CParse( "(" )
  1246. expr=ParseExpr()
  1247. Parse ")"
  1248. expr=New TChrExpr.Create( expr )
  1249. Else
  1250. expr=ParseExpr()
  1251. expr=New TChrExpr.Create( expr )
  1252. EndIf
  1253. Case "varptr"
  1254. NextToke
  1255. expr=ParseExpr()
  1256. expr=New TCastExpr.Create( New TVarPtrType, expr, CAST_EXPLICIT )
  1257. Case "pi"
  1258. NextToke
  1259. expr=New TConstExpr.Create( New TDoubleType, Pi )
  1260. Case "self"
  1261. NextToke
  1262. expr=New TSelfExpr
  1263. Case "super"
  1264. NextToke
  1265. Parse "."
  1266. If _toke="new"
  1267. Err "Call to super class constructor must be first statement in a constructor."
  1268. EndIf
  1269. Local id$=ParseIdent()
  1270. ' eat any type stuff
  1271. ParseConstNumberType()
  1272. expr=New TInvokeSuperExpr.Create( id,ParseArgs( stmt ) )
  1273. Case "stackalloc"
  1274. NextToke
  1275. ' optional brackets
  1276. If CParse( "(" )
  1277. expr=ParseExpr()
  1278. Parse ")"
  1279. expr=New TStackAllocExpr.Create( expr )
  1280. Else
  1281. expr=ParseExpr()
  1282. expr=New TStackAllocExpr.Create( expr )
  1283. EndIf
  1284. Case "fieldoffset"
  1285. NextToke
  1286. Local withBrackets:Int
  1287. If CParse("(")
  1288. withBrackets = True
  1289. End If
  1290. Local typeExpr:TExpr = ParseExpr()
  1291. Parse ","
  1292. Local fieldExpr:TExpr = ParseExpr()
  1293. If withBrackets Then
  1294. Parse(")")
  1295. End If
  1296. expr=New TFieldOffsetExpr.Create( typeExpr, fieldExpr )
  1297. Default
  1298. Select _tokeType
  1299. Case TOKE_IDENT
  1300. Local tok:TToker=New TToker.Copy( _toker )
  1301. Local ty:TType=CParseIdentType()
  1302. If ty
  1303. expr=New TIdentTypeExpr.Create( ty )
  1304. Else
  1305. _toker=tok
  1306. _toke=_toker.Toke()
  1307. _tokeType=_toker.TokeType()
  1308. expr=New TIdentExpr.Create( ParseIdent(),,,unknownIdentsEvalFalse )
  1309. ty = ParseConstNumberType()
  1310. If TArrayType(ty) Then
  1311. If Not TArrayType(ty).elemType Then
  1312. TArrayType(ty).elemType = New TIdentType.Create(TIdentExpr(expr).ident)
  1313. expr=New TIdentTypeExpr.Create( ty )
  1314. End If
  1315. End If
  1316. EndIf
  1317. 'expr=New TIdentExpr.Create( ParseIdent() )
  1318. Case TOKE_INTLIT
  1319. expr=New TConstExpr.Create( New TIntType,_toke )
  1320. NextToke
  1321. Local ty:TType = ParseConstNumberType()
  1322. If ty Then
  1323. TConstExpr(expr).UpdateType(ty)
  1324. End If
  1325. Case TOKE_LONGLIT
  1326. expr=New TConstExpr.Create( New TLongType,_toke )
  1327. NextToke
  1328. Local ty:TType = ParseConstNumberType()
  1329. If ty Then
  1330. TConstExpr(expr).UpdateType(ty)
  1331. End If
  1332. Case TOKE_FLOATLIT
  1333. expr=New TConstExpr.Create( New TFloatType,_toke )
  1334. NextToke
  1335. Local ty:TType = ParseConstNumberType()
  1336. If ty Then
  1337. TConstExpr(expr).ty = ty
  1338. End If
  1339. Case TOKE_STRINGLIT
  1340. Local s:String = BmxUnquote( _toke )
  1341. expr=New TConstExpr.Create( TType.stringType,s )
  1342. _app.mapStringConsts(s)
  1343. NextToke
  1344. Case TOKE_STRINGMULTI
  1345. Local s:String = BmxProcessMultiString( _toke )
  1346. expr=New TConstExpr.Create( TType.stringType,s )
  1347. _app.mapStringConsts(s)
  1348. NextToke
  1349. Default
  1350. Err "Expecting expression but encountered "+DescribeToke(_toke)
  1351. End Select
  1352. End Select
  1353. Repeat
  1354. Select _toke
  1355. Case "."
  1356. NextToke
  1357. expr=New TIdentExpr.Create( ParseIdent(),expr )
  1358. ParseConstNumberType()
  1359. 'DebugLog expr.ToString()
  1360. Case "("
  1361. If expr = Null Then
  1362. NextToke
  1363. expr=ParseExpr()
  1364. Parse ")"
  1365. Else
  1366. expr=New TFuncCallExpr.Create( expr,ParseArgs( stmt ) )
  1367. End If
  1368. Case "["
  1369. NextToke
  1370. If CParse( ".." )
  1371. If _toke="]"
  1372. expr=New TSliceExpr.Create( expr,Null,Null )
  1373. Else
  1374. expr=New TSliceExpr.Create( expr,Null,ParseExpr() )
  1375. EndIf
  1376. Parse "]"
  1377. Else
  1378. Local from:TExpr=ParseExpr()
  1379. If CParse( ".." )
  1380. If _toke="]"
  1381. expr=New TSliceExpr.Create( expr,from,Null )
  1382. Else
  1383. expr=New TSliceExpr.Create( expr,from,ParseExpr() )
  1384. EndIf
  1385. Parse "]"
  1386. Else
  1387. Local ind:TExpr[] = [from]
  1388. Repeat
  1389. If CParse("]") Then
  1390. Exit
  1391. End If
  1392. Parse ","
  1393. ind = ind + [ParseExpr()]
  1394. Forever
  1395. expr=New TIndexExpr.Create( expr,ind )
  1396. EndIf
  1397. EndIf
  1398. Default
  1399. Return expr
  1400. End Select
  1401. Forever
  1402. End Method
  1403. Method ParseUnaryExpr:TExpr()
  1404. Local op$=_toke
  1405. Select op
  1406. Case "+","-","~~","not"
  1407. NextToke
  1408. Local expr:TExpr=ParseUnaryExpr()
  1409. Return New TUnaryExpr.Create( op,expr )
  1410. End Select
  1411. Return ParsePrimaryExpr( False )
  1412. End Method
  1413. Method ParsePowExpr:TExpr()
  1414. Local expr:TExpr=ParseUnaryExpr()
  1415. Repeat
  1416. Local op$=_toke
  1417. Select op
  1418. Case "^"
  1419. NextToke
  1420. Local rhs:TExpr=ParseUnaryExpr()
  1421. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1422. Default
  1423. Return expr
  1424. End Select
  1425. Forever
  1426. End Method
  1427. Method ParseMulDivExpr:TExpr()
  1428. Local expr:TExpr=ParsePowExpr()
  1429. Repeat
  1430. Local op$=_toke
  1431. Select op
  1432. Case "*","/","mod","shl","shr", "sar"
  1433. NextToke
  1434. Local rhs:TExpr=ParsePowExpr()
  1435. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1436. Default
  1437. Return expr
  1438. End Select
  1439. Forever
  1440. End Method
  1441. Method ParseAddSubExpr:TExpr()
  1442. Local expr:TExpr=ParseMulDivExpr()
  1443. Repeat
  1444. Local op$=_toke
  1445. Select op
  1446. Case "+","-"
  1447. NextToke
  1448. Local rhs:TExpr=ParseMulDivExpr()
  1449. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1450. Default
  1451. Return expr
  1452. End Select
  1453. Forever
  1454. End Method
  1455. Method ParseBitandExpr:TExpr()
  1456. Local expr:TExpr=ParseAddSubExpr()
  1457. Repeat
  1458. Local op$=_toke
  1459. Select op
  1460. Case "&","~~"
  1461. NextToke
  1462. Local rhs:TExpr=ParseAddSubExpr()
  1463. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1464. Default
  1465. Return expr
  1466. End Select
  1467. Forever
  1468. End Method
  1469. Method ParseBitorExpr:TExpr()
  1470. Local expr:TExpr=ParseBitandExpr()
  1471. Repeat
  1472. Local op$=_toke
  1473. Select op
  1474. Case "|"
  1475. NextToke
  1476. Local rhs:TExpr=ParseBitandExpr()
  1477. expr=New TBinaryMathExpr.Create( op,expr,rhs )
  1478. Default
  1479. Return expr
  1480. End Select
  1481. Forever
  1482. End Method
  1483. Method ParseCompareExpr:TExpr()
  1484. Local expr:TExpr=ParseBitorExpr()
  1485. Repeat
  1486. Local op$=_toke
  1487. Select op
  1488. Case "=","<",">","<=","=<",">=","=>","<>"
  1489. NextToke
  1490. ' <= or =>
  1491. If (op=">" And (_toke="=")) Or (op="=" And (_toke=">"))
  1492. op:+_toke
  1493. NextToke
  1494. ' <> or <= or =<
  1495. Else If (op="<" And _toke=">") Or (op="<" And _toke="=") Or (op="=" And _toke="<")
  1496. op:+_toke
  1497. NextToke
  1498. EndIf
  1499. Local rhs:TExpr=ParseBitorExpr()
  1500. expr=New TBinaryCompareExpr.Create( op,expr,rhs )
  1501. Default
  1502. Return expr
  1503. End Select
  1504. Forever
  1505. End Method
  1506. Method ParseAndExpr:TExpr()
  1507. Local expr:TExpr=ParseCompareExpr()
  1508. Repeat
  1509. Local op$=_toke
  1510. If op="and"
  1511. NextToke
  1512. Local rhs:TExpr=ParseCompareExpr()
  1513. expr=New TBinaryLogicExpr.Create( op,expr,rhs )
  1514. Else
  1515. Return expr
  1516. EndIf
  1517. Forever
  1518. End Method
  1519. Method ParseOrExpr:TExpr()
  1520. Local expr:TExpr=ParseAndExpr()
  1521. Repeat
  1522. Local op$=_toke
  1523. If op="or"
  1524. NextToke
  1525. Local rhs:TExpr=ParseAndExpr()
  1526. expr=New TBinaryLogicExpr.Create( op,expr,rhs )
  1527. Else
  1528. Return expr
  1529. EndIf
  1530. Forever
  1531. End Method
  1532. Method ParseExpr:TExpr()
  1533. Return ParseOrExpr()
  1534. End Method
  1535. Rem
  1536. unused atm
  1537. Method ReadTillNextToken:string(amount:int=1)
  1538. 'copy current toker and move one token forward
  1539. local tok:TToker = New TToker.Copy(_toker)
  1540. local result:string = _toker._toke
  1541. for local i:int = 0 until amount
  1542. NextTokeToker(tok)
  1543. result :+ " "+ tok._toke
  1544. Next
  1545. return _toker._toke+" "+tok._toke
  1546. End Method
  1547. End Rem
  1548. Method ParseIfStmt( term$, elseIfEndIfReadAheadCheck:Int = False )
  1549. Local tok:TToker
  1550. 'rules:
  1551. '- the command "end" cannot be used as condition
  1552. '- "endif" or "end if" is not allowed in singleline-ifs
  1553. 'if current toke is "if", move on to the next toke
  1554. CParse "if"
  1555. 'read in the expression/condition following after "if"
  1556. Local expr:TExpr=ParseExpr()
  1557. 'if current toke is "then", move to next, else stay at this
  1558. 'position -> makes "then" usage voluntary
  1559. CParse "then"
  1560. 'create empty blocks for then/else
  1561. Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block, ,BLOCK_IF )
  1562. Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block, ,BLOCK_ELSE )
  1563. 'define if the current if is a "singleline if"
  1564. '"singleline ifs" are not allowed to contain "endif" "end if"
  1565. Local singleLineIf:Int = True
  1566. 'to know if it is a multiline or singleline if we have to check
  1567. 'for certain situations
  1568. Select _toke
  1569. Case "~n"
  1570. 'if a <- newline
  1571. ' print "a"
  1572. 'endif
  1573. singleLineIf = False
  1574. Case "if"
  1575. 'another "if" means the outer one is a singleline if!
  1576. singleLineIf = True
  1577. Case "else"
  1578. 'if ReadTillNextToken().toLower() = "else if"
  1579. ' print "IF: found if X then Y else if ..."
  1580. 'else
  1581. ' print "IF: found if X then Y else ..."
  1582. 'endif
  1583. 'also read "else if"
  1584. singleLineIf = True
  1585. Case "elseif"
  1586. singleLineIf = True
  1587. End Select
  1588. 'set thenBlock as the active block
  1589. PushBlock( thenBlock )
  1590. 'now check each toke until we reach our desired term
  1591. 'for singleline-if this is "~n", for multiline-if this is
  1592. '"endif" or "end if"
  1593. If singleLineIf
  1594. term = "~n"
  1595. Else
  1596. term = "end" 'endif, end if
  1597. EndIf
  1598. 'only read until reaching the limit - or no valid toke was returned
  1599. While _toke <> term
  1600. Local currentToke:String = _toke
  1601. Select currentToke
  1602. 'file end before endif/end/elseif
  1603. Case ""
  1604. Err("Expecting expression but encountered end-of-file")
  1605. '"endif" / "end if"
  1606. Case "endif", "end"
  1607. NextToke()
  1608. If singleLineIf Then
  1609. 'check for "end"-command ("if a=1 end")
  1610. If currentToke = "end" And (currentToke + _toke) <> "endif" Then
  1611. ParseEndStmt(False)
  1612. 'found "end if"
  1613. Else
  1614. Err "'End If' without matching 'If'"
  1615. Exit
  1616. EndIf
  1617. EndIf
  1618. 'If currentToke = "endif" or (currentToke + _toke)="endif"
  1619. ' 'do something if "endif/end if" happens ?
  1620. 'Endif
  1621. 'finish this if-statement
  1622. Exit
  1623. '"else" and "elseif" / "else if"
  1624. Case "else","elseif"
  1625. ' print "parsing "+currentToke
  1626. If _block = elseBlock
  1627. Err("If statement can only have one 'else' block.")
  1628. EndIf
  1629. 'switch from thenBlock to elseBlock
  1630. PopBlock()
  1631. PushBlock(elseBlock)
  1632. 'move to next token, might contain "if" for "else if"
  1633. 'doing it this way avoids to parse "elseif if" as
  1634. 'else-statement
  1635. NextToke()
  1636. If currentToke = "elseif" Or (currentToke + _toke)="elseif"
  1637. 'create a new if-statement and exit current handling
  1638. SetErr
  1639. ParseIfStmt(term, True)
  1640. Exit
  1641. EndIf
  1642. Default
  1643. 'parse the current and next tokens
  1644. ParseStmt()
  1645. currentToke = _toke
  1646. 'handle the end-function and "end if"
  1647. Select currentToke
  1648. Case "end"
  1649. 'check next toke too
  1650. NextToke()
  1651. 'found end-function
  1652. If currentToke = "end" And (currentToke + _toke)<>"endif"
  1653. ' print " parsing end .... handling"
  1654. ParseEndStmt(False)
  1655. 'found "end if"
  1656. Else
  1657. If CParse("if") Then
  1658. If singleLineIf Then
  1659. Err "'End If' without matching 'If'"
  1660. End If
  1661. Exit
  1662. End If
  1663. 'NextToke()
  1664. EndIf
  1665. End Select
  1666. End Select
  1667. Wend
  1668. 'change block
  1669. PopBlock()
  1670. 'create a if-then[-else]-statement
  1671. Local stmt:TIfStmt=New TIfStmt.Create( expr,thenBlock,elseBlock )
  1672. _block.AddStmt stmt
  1673. End Method
  1674. Method ParseWhileStmt(loopLabel:TLoopLabelDecl = Null)
  1675. Parse "while"
  1676. Local expr:TExpr=ParseExpr()
  1677. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1678. PushBlock block
  1679. While Not CParse( "wend" ) And Not CParse( "endwhile" )
  1680. ' If CParse( "end" )
  1681. ' CParse "while"
  1682. ' Exit
  1683. ' EndIf
  1684. ParseStmt
  1685. ' to handle "end" statement
  1686. If _toke = "end" Then
  1687. NextToke
  1688. If _toke = "while" Then
  1689. NextToke
  1690. Exit
  1691. Else
  1692. ParseEndStmt(False)
  1693. End If
  1694. End If
  1695. Wend
  1696. PopBlock
  1697. Local stmt:TWhileStmt=New TWhileStmt.Create( expr,block,loopLabel )
  1698. _block.AddStmt stmt
  1699. End Method
  1700. Method ParseRepeatStmt(loopLabel:TLoopLabelDecl = Null)
  1701. Parse "repeat"
  1702. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1703. PushBlock block
  1704. While _toke<>"until" And _toke<>"forever"
  1705. ParseStmt
  1706. Wend
  1707. PopBlock
  1708. SetErr
  1709. Local expr:TExpr
  1710. If CParse( "until" )
  1711. expr=ParseExpr()
  1712. Else
  1713. Parse "forever"
  1714. expr=New TConstExpr.Create( New TBoolType,"" )
  1715. EndIf
  1716. Local stmt:TRepeatStmt=New TRepeatStmt.Create( block,expr,loopLabel )
  1717. _block.AddStmt stmt
  1718. End Method
  1719. Method ParseForStmt(loopLabel:TLoopLabelDecl = Null)
  1720. Parse "for"
  1721. Local varid$,varty:TType,varlocal:Int
  1722. Local varExpr:TExpr
  1723. If CParse( "local" )
  1724. varlocal=True
  1725. varid=ParseIdent()
  1726. varty=ParseDeclType()
  1727. If varty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) Then
  1728. DoErr "Illegal variable type"
  1729. End If
  1730. Parse( "=" )
  1731. ' use an ident expr to pass the variable to different parts of the statement.
  1732. ' the original implementation passed decl references, which cause problems if we wanted to
  1733. ' copy the statement later.
  1734. varExpr = New TIdentExpr.Create(varid)
  1735. Else
  1736. varlocal=False
  1737. varExpr=ParsePrimaryExpr( False )
  1738. Parse "="
  1739. EndIf
  1740. If CParse( "eachin" )
  1741. Local expr:TExpr=ParseExpr()
  1742. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1743. PushBlock block
  1744. While Not CParse( "next" )
  1745. ParseStmt
  1746. Wend
  1747. PopBlock
  1748. Local stmt:TForEachinStmt=New TForEachinStmt.Create( varid,varty,varlocal,expr,block,loopLabel, varExpr )
  1749. _block.AddStmt stmt
  1750. Return
  1751. EndIf
  1752. Local from:TExpr=ParseExpr()
  1753. Local op$
  1754. If CParse( "to" )
  1755. op="<="
  1756. Else If CParse( "until" )
  1757. op="<"
  1758. Else
  1759. Err "Expecting 'To' or 'Until'."
  1760. EndIf
  1761. Local term:TExpr=ParseExpr()
  1762. Local stp:TExpr
  1763. If CParse( "step" )
  1764. stp=ParseExpr()
  1765. Else
  1766. stp=New TConstExpr.Create( New TIntType,"1" )
  1767. EndIf
  1768. Local init:TStmt,expr:TExpr,incr:TStmt
  1769. If varlocal
  1770. Local indexVar:TLocalDecl=New TLocalDecl.Create( varid,varty,New TCastExpr.Create( varty,from,CAST_EXPLICIT ),0 )
  1771. init=New TDeclStmt.Create( indexVar )
  1772. ' expr=New TBinaryCompareExpr.Create( op,New TVarExpr.Create( indexVar ),New TCastExpr.Create( varty,term,1 ) )
  1773. ' incr=New TAssignStmt.Create( "=",New TVarExpr.Create( indexVar ),New TBinaryMathExpr.Create( "+",New TVarExpr.Create( indexVar ),New TCastExpr.Create( varty,stp,1 ) ) )
  1774. expr=New TBinaryCompareExpr.Create( op, varExpr,New TCastExpr.Create( varty,term,CAST_EXPLICIT ) )
  1775. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "+",varExpr,New TCastExpr.Create( varty,stp,CAST_EXPLICIT ) ) )
  1776. Else
  1777. ' varty is NULL here for the casts. We will back-populate it later.
  1778. ' init=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),from )
  1779. ' expr=New TBinaryCompareExpr.Create( op,New TIdentExpr.Create( varid ),New TCastExpr.Create( varty,term,1 ) )
  1780. ' incr=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TBinaryMathExpr.Create( "+",New TIdentExpr.Create( varid ),New TCastExpr.Create( varty,stp,1 ) ) )
  1781. init=New TAssignStmt.Create( "=",varExpr,from )
  1782. expr=New TBinaryCompareExpr.Create( op,varExpr,New TCastExpr.Create( varty,term,CAST_EXPLICIT ) )
  1783. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "+",varExpr,New TCastExpr.Create( varty,stp,CAST_EXPLICIT ) ) )
  1784. EndIf
  1785. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1786. PushBlock block
  1787. While Not CParse( "next" )
  1788. ParseStmt
  1789. Wend
  1790. PopBlock
  1791. NextToke
  1792. Local stmt:TForStmt=New TForStmt.Create( init,expr,incr,block,loopLabel )
  1793. _block.AddStmt stmt
  1794. End Method
  1795. Method ParseDefDataStmt(label:TLoopLabelDecl = Null)
  1796. Parse "defdata"
  1797. If AtEos() Then
  1798. Err "Expecting expression but encountered " + DescribeToke(_toke)
  1799. End If
  1800. Local args:TExpr[]
  1801. Local nargs:Int
  1802. Repeat
  1803. Local arg:TExpr
  1804. If _toke And _toke<>"," arg=ParseExpr()
  1805. If args.Length=nargs args=args + New TExpr[10]
  1806. args[nargs]=arg
  1807. nargs:+1
  1808. Until Not CParse(",")
  1809. args=args[..nargs]
  1810. Local dataLabel:TDataLabelDecl
  1811. If label Then
  1812. dataLabel = New TDataLabelDecl.Create(label.ident, label.attrs)
  1813. End If
  1814. Local decl:TDefDataDecl = New TDefDataDecl.Create(args, dataLabel)
  1815. _app.dataDefs.AddLast(decl)
  1816. End Method
  1817. Method ParseReadDataStmt()
  1818. Parse "readdata"
  1819. Local args:TExpr[]
  1820. Local nargs:Int
  1821. If Not AtEos() Then
  1822. Repeat
  1823. Local arg:TExpr
  1824. If _toke And _toke<>"," arg=ParseExpr()
  1825. If args.Length=nargs args=args + New TExpr[10]
  1826. args[nargs]=arg
  1827. nargs:+1
  1828. Until Not CParse(",")
  1829. args=args[..nargs]
  1830. End If
  1831. _block.AddStmt New TReadDataStmt.Create( args )
  1832. End Method
  1833. Method ParseRestoreDataStmt()
  1834. Parse "restoredata"
  1835. Local expr:TExpr = ParseExpr()
  1836. _block.AddStmt New TRestoreDataStmt.Create( expr )
  1837. End Method
  1838. Method ParseReturnStmt()
  1839. Parse "return"
  1840. Local expr:TExpr
  1841. If Not AtEos() expr=ParseExpr()
  1842. _block.AddStmt New TReturnStmt.Create( expr )
  1843. End Method
  1844. Method ParseExitStmt()
  1845. Parse "exit"
  1846. Local expr:TExpr
  1847. If Not AtEos() expr=ParseExpr()
  1848. _block.AddStmt New TBreakStmt.Create(expr)
  1849. End Method
  1850. Method ParseContinueStmt()
  1851. Parse "continue"
  1852. Local expr:TExpr
  1853. If Not AtEos() expr=ParseExpr()
  1854. _block.AddStmt New TContinueStmt.Create(expr)
  1855. End Method
  1856. Method ParseTryStmt()
  1857. Parse "try"
  1858. Local tryStmtDecl:TTryStmtDecl = TTryStmtDecl(New TTryStmtDecl.Create( _block ))
  1859. PushBlock tryStmtDecl
  1860. Local block:TBlockDecl=New TBlockDecl.Create( tryStmtDecl, , BLOCK_TRY )
  1861. Local catches:TList=New TList
  1862. Local finallyStmt:TFinallyStmt = Null
  1863. PushBlock block
  1864. While _toke<>"end" And _toke<>"endtry"
  1865. If CParse( "catch" )
  1866. If finallyStmt Then Err "'Catch' can not appear after 'Finally'."
  1867. Local id:String=ParseIdent()
  1868. Local ty:TType
  1869. If Not CParse(":") Then
  1870. Parse "$"
  1871. ty= TType.stringType
  1872. Else
  1873. ty=ParseType()
  1874. While IsArrayDef()
  1875. ty=ParseArrayType(ty)
  1876. Wend
  1877. End If
  1878. PopBlock
  1879. Local init:TLocalDecl=New TLocalDecl.Create( id,ty,Null,0 )
  1880. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_CATCH )
  1881. catches.AddLast(New TCatchStmt.Create( init,block ))
  1882. PushBlock block
  1883. Else If CParse("finally") Then
  1884. If finallyStmt Then Err "Try statement cannot have more than one Finally block."
  1885. PopBlock
  1886. Local block:TBlockDecl = New TBlockDecl.Create(_block, , BLOCK_FINALLY)
  1887. finallyStmt = New TFinallyStmt.Create(block)
  1888. PushBlock block
  1889. Else
  1890. ParseStmt
  1891. If _toke = "end" Then
  1892. NextToke
  1893. If _toke = "try" Then
  1894. ' we are done with the try statement
  1895. Exit
  1896. Else
  1897. ParseEndStmt(False)
  1898. End If
  1899. End If
  1900. End If
  1901. Wend
  1902. If catches.Count() = 0 And Not finallyStmt Then Err "Expecting 'Catch' or 'Finally'."
  1903. PopBlock ' try block
  1904. If Not CParse("endtry") Then
  1905. NextToke
  1906. CParse "try"
  1907. End If
  1908. PopBlock ' tryStmtDecl
  1909. Local tryStmt:TTryStmt = New TTryStmt.Create(block,TCatchStmt[](catches.ToArray()), finallyStmt)
  1910. tryStmtDecl.tryStmt = tryStmt
  1911. _block.AddStmt tryStmt
  1912. End Method
  1913. Method ParseThrowStmt()
  1914. Parse "throw"
  1915. Local expr:TExpr = ParseExpr()
  1916. _block.AddStmt New TThrowStmt.Create( expr )
  1917. End Method
  1918. Method ParseReleaseStmt()
  1919. Parse "release"
  1920. Local expr:TExpr = ParseExpr()
  1921. _block.AddStmt New TReleaseStmt.Create( expr )
  1922. End Method
  1923. Method ParseAssertStmt()
  1924. Parse "assert"
  1925. Local expr:TExpr = ParseExpr()
  1926. Local elseExpr:TExpr
  1927. If _toke = "," Or _toke = "else" Then
  1928. NextToke
  1929. elseExpr = ParseExpr()
  1930. End If
  1931. _block.AddStmt New TAssertStmt.Create( expr, elseExpr )
  1932. End Method
  1933. Method ParseEndStmt(eatEnd:Int = True)
  1934. If eatEnd Then
  1935. Parse "end"
  1936. End If
  1937. _block.AddStmt New TEndStmt.Create( )
  1938. End Method
  1939. Method ParseSelectStmt()
  1940. Parse "select"
  1941. Local block:TBlockDecl=_block
  1942. Local tmpVar:TLocalDecl
  1943. Local selectExpr:TExpr = ParseExpr()
  1944. If Not TNullType(selectExpr.exprType)
  1945. tmpVar = New TLocalDecl.Create("", Null, selectExpr, DECL_NO_VAR, True)
  1946. block.AddStmt New TDeclStmt.Create(tmpVar)
  1947. End If
  1948. While _toke<>"end" And _toke<>"default" And _toke<>"endselect"
  1949. SetErr
  1950. Select _toke
  1951. Case "~n"
  1952. NextToke
  1953. Case "case"
  1954. NextToke
  1955. Local comp:TExpr
  1956. Repeat
  1957. Local expr:TExpr
  1958. If TNullType(selectExpr.exprType)
  1959. expr = New TNullExpr.Create(TType.nullObjectType)
  1960. Else
  1961. expr = New TVarExpr.Create(tmpVar)
  1962. End If
  1963. expr=New TBinaryCompareExpr.Create( "=",expr,ParseExpr() )
  1964. If comp
  1965. comp=New TBinaryLogicExpr.Create( "or",comp,expr )
  1966. Else
  1967. comp=expr
  1968. EndIf
  1969. Until Not CParse(",")
  1970. Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_IF )
  1971. Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_ELSE )
  1972. Local ifstmt:TIfStmt=New TIfStmt.Create( comp,thenBlock,elseBlock )
  1973. block.AddStmt ifstmt
  1974. block=ifstmt.thenBlock
  1975. PushBlock block
  1976. Local fin:Int = False
  1977. While _toke<>"case" And _toke<>"default" And _toke<>"end" And _toke<>"endselect"
  1978. ParseStmt
  1979. If _toke = "end" Then
  1980. NextToke
  1981. If _toke = "select" Then
  1982. ' we are done with the select statement, full exit
  1983. fin = True
  1984. Exit
  1985. Else
  1986. ParseEndStmt(False)
  1987. End If
  1988. End If
  1989. Wend
  1990. PopBlock
  1991. block=elseBlock
  1992. If fin Exit
  1993. Default
  1994. Err "Syntax error - expecting 'Case', 'Default' or 'End'."
  1995. End Select
  1996. Wend
  1997. If _toke="default"
  1998. NextToke
  1999. PushBlock block
  2000. While _toke<>"end" And _toke<>"endselect"
  2001. SetErr
  2002. Select _toke
  2003. Case "case"
  2004. Err "Case can not appear after Default."
  2005. Case "default"
  2006. Err "Select statement can have only one Default block."
  2007. End Select
  2008. ParseStmt
  2009. If _toke = "end" Then
  2010. NextToke
  2011. If _toke = "select" Then
  2012. Exit
  2013. Else
  2014. ParseEndStmt(False)
  2015. End If
  2016. End If
  2017. Wend
  2018. PopBlock
  2019. EndIf
  2020. SetErr
  2021. If Not CParse("endselect") Then
  2022. If Not CParse("select")
  2023. Parse "end"
  2024. Parse "select"
  2025. End If
  2026. End If
  2027. End Method
  2028. Method ParseExternBlock(mdecl:TModuleDecl, attrs:Long)
  2029. NextToke
  2030. attrs :| ParseCallConvention()
  2031. attrs = attrs | DECL_EXTERN
  2032. If CParse( "private" ) attrs=attrs|DECL_PRIVATE
  2033. While _toke<>"endextern"
  2034. If CParse( "end" )
  2035. Parse "extern"
  2036. Exit
  2037. EndIf
  2038. SetErr
  2039. Select _toke
  2040. Case "~n"
  2041. NextToke
  2042. Case "const"
  2043. mdecl.InsertDecls ParseDecls( _toke,attrs )
  2044. Case "global"
  2045. ParseDeclStmts(True, attrs, mdecl)
  2046. Case "threadedglobal"
  2047. ParseDeclStmts(True, attrs | DECL_THREADED, mdecl)
  2048. Case "struct"
  2049. mdecl.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
  2050. Case "type"
  2051. mdecl.InsertDecl ParseClassDecl( _toke,attrs )
  2052. Case "function"
  2053. mdecl.InsertDecl ParseFuncDecl( _toke,attrs )
  2054. Case "interface"
  2055. mdecl.InsertDecl ParseClassDecl( _toke,attrs | CLASS_INTERFACE )
  2056. Default
  2057. If _toke <> "end" And _toke <> "endextern" Then
  2058. Err "Expecting expression but encountered '"+_toke+"'"
  2059. End If
  2060. End Select
  2061. Wend
  2062. If _toke="endextern" Then
  2063. NextToke
  2064. End If
  2065. End Method
  2066. Method ParseStmt()
  2067. SetErr
  2068. Select _toke
  2069. Case ";","~n"
  2070. NextToke
  2071. Case "const","local","global","threadedglobal"
  2072. ParseDeclStmts
  2073. ' nested function - needs to get added to the "module"
  2074. Case "function"
  2075. _block.InsertDecl ParseFuncDecl( _toke,FUNC_NESTED)
  2076. Case "type"
  2077. _block.InsertDecl ParseClassDecl( _toke,DECL_NESTED)
  2078. Case "return"
  2079. ParseReturnStmt()
  2080. Case "exit"
  2081. ParseExitStmt()
  2082. Case "continue"
  2083. ParseContinueStmt()
  2084. Case "if"
  2085. ParseIfStmt( "" )
  2086. Case "while"
  2087. ParseWhileStmt()
  2088. Case "repeat"
  2089. ParseRepeatStmt()
  2090. Case "for"
  2091. ParseForStmt()
  2092. Case "select"
  2093. ParseSelectStmt()
  2094. Case "assert"
  2095. ParseAssertStmt()
  2096. Case "try"
  2097. ParseTryStmt()
  2098. Case "throw"
  2099. ParseThrowStmt()
  2100. Case "end"
  2101. ParseEndStmt()
  2102. Case "extern"
  2103. ParseExternBlock(_module, 0)
  2104. Case "#"
  2105. Local decl:TLoopLabelDecl = ParseLoopLabelDecl()
  2106. NextToke
  2107. While _toke
  2108. SetErr
  2109. Select _toke.ToLower()
  2110. Case "~n"
  2111. NextToke
  2112. Case "while"
  2113. ParseWhileStmt(decl)
  2114. Exit
  2115. Case "repeat"
  2116. ParseRepeatStmt(decl)
  2117. Exit
  2118. Case "for"
  2119. ParseForStmt(decl)
  2120. Exit
  2121. Case "defdata"
  2122. ParseDefDataStmt(decl)
  2123. Exit
  2124. Default
  2125. Err "Labels must appear before a loop or DefData statement"
  2126. End Select
  2127. Wend
  2128. Case "release"
  2129. ParseReleaseStmt()
  2130. Case "defdata"
  2131. ParseDefDataStmt()
  2132. Case "readdata"
  2133. ParseReadDataStmt()
  2134. Case "restoredata"
  2135. ParseRestoreDataStmt()
  2136. Default
  2137. If _toke.StartsWith("'!") Then
  2138. If _tokeType = TOKE_NATIVE Then
  2139. ParseNativeStmt()
  2140. End If
  2141. Else
  2142. Local expr:TExpr=ParsePrimaryExpr( True )
  2143. Select _toke.ToLower()
  2144. '"=","*=","/=","+=","-=","&=","|=","~~=","Mod","Shl","Shr"
  2145. Case "=",":*",":/",":+",":-",":&",":|",":~~","mod","shl","shr", ":shl", ":shr", "sar", ":sar", ":mod"
  2146. ' remap symbols...
  2147. 'For Local i:Int = 0 Until TToker._symbols.length
  2148. ' Local sym$= TToker._symbols[i]
  2149. ' If _toke.ToLower() = sym
  2150. ' _toke = TToker._symbols_map[i]
  2151. ' Exit
  2152. ' EndIf
  2153. 'Next
  2154. If TIdentExpr( expr ) Or TIndexExpr( expr )
  2155. Local op$=_toke.ToLower()
  2156. NextToke
  2157. ' If Not op.EndsWith( "=" ) And Not op.StartsWith("=")
  2158. ' Parse "="
  2159. ' op:+"="
  2160. ' EndIf
  2161. _block.AddStmt New TAssignStmt.Create( op,expr,ParseExpr() )
  2162. Else
  2163. Err "Assignment operator '"+_toke+"' cannot be used this way."
  2164. EndIf
  2165. Return
  2166. End Select
  2167. If TIdentExpr( expr )
  2168. expr=New TFuncCallExpr.Create( expr,ParseArgs( True ) )
  2169. Else If TFuncCallExpr( expr) Or TInvokeSuperExpr( expr ) Or TNewObjectExpr( expr ) Or TNewExpr(expr)
  2170. Else If TIndexExpr(expr)
  2171. expr = New TFuncCallExpr.Create( expr, ParseArgs( True ) )
  2172. Else
  2173. Err "Expression cannot be used as a statement."
  2174. EndIf
  2175. _block.AddStmt New TExprStmt.Create( expr )
  2176. End If
  2177. End Select
  2178. End Method
  2179. Method ParseDecl:TDecl( toke$,attrs:Long )
  2180. SetErr
  2181. If CParse("staticarray") Then
  2182. If toke = "const" Then
  2183. Err "Const cannot be used in this way"
  2184. End If
  2185. If attrs & DECL_STATIC Then
  2186. Err "Already declared as a static array"
  2187. End If
  2188. attrs :| DECL_STATIC
  2189. End If
  2190. Local id$=ParseIdent()
  2191. Local ty:TType
  2192. Local init:TExpr
  2193. If attrs & DECL_EXTERN
  2194. ty=ParseDeclType(attrs & (DECL_STATIC | DECL_API_STDCALL))
  2195. If toke = "const" Then
  2196. If CParse("=") Then
  2197. init=ParseExpr()
  2198. End If
  2199. End If
  2200. ' Else If CParse( ":=" )
  2201. ' init=ParseExpr()
  2202. ' ty = init.exprType
  2203. Else
  2204. ty=ParseDeclType(attrs & (DECL_STATIC | DECL_API_STDCALL))
  2205. If CParse( "=" )
  2206. If (attrs & DECL_STATIC) Then
  2207. Err "Static arrays cannot be initialized in this way"
  2208. End If
  2209. init=ParseExpr()
  2210. Else If CParse( "[" ) ' an initialised array?
  2211. If (attrs & DECL_STATIC) Then
  2212. init = ParseExpr()
  2213. Parse "]"
  2214. ty=New TArrayType.Create( ty,1,, attrs & DECL_STATIC > 0 )
  2215. Else
  2216. Local ln:TExpr[]
  2217. Repeat
  2218. If CParse(",") Then
  2219. ln = ln + [New TNullExpr]
  2220. Continue
  2221. End If
  2222. If CParse("]") Exit
  2223. ln = ln + [ParseExpr()]
  2224. If CParse("]") Exit
  2225. Parse(",")
  2226. Forever
  2227. 'Parse "]"
  2228. ty = ParseArrayType(ty)
  2229. 'While CParse( "[]" )
  2230. ' ty=New TArrayType.Create(ty)
  2231. 'Wend
  2232. init=New TNewArrayExpr.Create( ty,ln)
  2233. ty=New TArrayType.Create( ty, ln.length,, attrs & DECL_STATIC > 0 )
  2234. End If
  2235. Else If toke <> "const"
  2236. If toke="global" Or toke="local" Or toke="threadedglobal" Then
  2237. init=New TConstExpr.Create( ty,"" )
  2238. End If
  2239. Else
  2240. Err "Constants must be initialized."
  2241. EndIf
  2242. EndIf
  2243. Local decl:TValDecl
  2244. Select toke
  2245. Case "global"
  2246. decl=New TGlobalDecl.Create( id,ty,init,attrs )
  2247. Case "threadedglobal"
  2248. decl=New TGlobalDecl.Create( id,ty,init,attrs | DECL_THREADED )
  2249. Case "field"
  2250. decl=New TFieldDecl.Create( id,ty,init,attrs )
  2251. If TFunctionPtrType(ty) Then
  2252. TFunctionPtrType(ty).func.attrs :| FUNC_FIELD
  2253. End If
  2254. Case "const" decl=New TConstDecl.Create( id,ty,init,attrs )
  2255. Case "local" decl=New TLocalDecl.Create( id,ty,init,attrs )
  2256. End Select
  2257. If decl.IsExtern()
  2258. Local cdets:TCastDets
  2259. If CParse( "=" )
  2260. Local munged:String = ParseStringLit()
  2261. If munged.Find("(") > 0 Then
  2262. cdets = ParseExternCast(munged, True)
  2263. If cdets Then
  2264. decl.munged = cdets.name
  2265. End If
  2266. Else
  2267. decl.munged = munged
  2268. End If
  2269. Else
  2270. decl.munged=decl.ident
  2271. EndIf
  2272. If TFunctionPtrType(ty) Then
  2273. TFunctionPtrType(ty).func.munged = decl.munged
  2274. If Not cdets Then
  2275. cdets = TCastDets(_externCasts.ValueForKey(TFunctionPtrType(ty).func.munged))
  2276. End If
  2277. If cdets Then
  2278. TFunctionPtrType(ty).func.castTo = cdets.retType
  2279. If cdets.noGen Then
  2280. TFunctionPtrType(ty).func.noCastGen = True
  2281. End If
  2282. For Local i:Int = 0 Until cdets.args.length
  2283. If i < TFunctionPtrType(ty).func.argDecls.length Then
  2284. TFunctionPtrType(ty).func.argDecls[i].castTo = cdets.args[i]
  2285. End If
  2286. Next
  2287. End If
  2288. End If
  2289. EndIf
  2290. ' apply any function ptr metadata to decl
  2291. If TFunctionPtrType(ty) Then
  2292. If TFunctionPtrType(ty).func And TFunctionPtrType(ty).func.metadata Then
  2293. decl.metadata = TFunctionPtrType(ty).func.metadata
  2294. End If
  2295. End If
  2296. 'meta data for variables
  2297. Local meta:TMetaData = ParseMetaData()
  2298. If meta Then
  2299. decl.metadata = meta
  2300. End If
  2301. Return decl
  2302. End Method
  2303. Method ParseDecls:TList( toke$,attrs:Long, isField:Int = False )
  2304. If toke Parse toke
  2305. If isField Then
  2306. Repeat
  2307. If CParse("readonly") Then
  2308. If attrs & DECL_READ_ONLY
  2309. Err "Duplicate modifier 'ReadOnly'."
  2310. End If
  2311. attrs :| DECL_READ_ONLY
  2312. Else If CParse("staticarray") Then
  2313. If attrs & DECL_STATIC
  2314. Err "Duplicate modifier 'Static'."
  2315. End If
  2316. attrs :| DECL_STATIC
  2317. Else
  2318. Exit
  2319. End If
  2320. Forever
  2321. End If
  2322. Local decls:TList=New TList'<Decl>
  2323. Repeat
  2324. Local decl:TDecl=ParseDecl( toke,attrs )
  2325. decls.AddLast decl
  2326. If Not CParse(",") Return decls
  2327. Forever
  2328. End Method
  2329. Method ParseDeclStmts(initOnly:Int = False, attrs:Long = 0, mdecl:TModuleDecl = Null)
  2330. Local toke$=_toke
  2331. NextToke
  2332. Repeat
  2333. Local decl:TDecl=ParseDecl( toke,attrs )
  2334. If Not (attrs & DECL_EXTERN) Then
  2335. _block.AddStmt New TDeclStmt.Create( decl )
  2336. End If
  2337. ' reset the decl scope, adding decl to the block decl list.
  2338. ' this improves scope visibilty - for decls such as embedded functions
  2339. If TConstDecl(decl) Or TGlobalDecl(decl) Then
  2340. If mdecl Then
  2341. mdecl.InsertDecl decl
  2342. End If
  2343. If Not (attrs & DECL_EXTERN) Then
  2344. decl.scope = Null
  2345. _block.InsertDecl(decl)
  2346. End If
  2347. If TGlobalDecl(decl) Then
  2348. If initOnly Then
  2349. decl.attrs :| DECL_INITONLY
  2350. TGlobalDecl(decl).mscope = _module
  2351. Else
  2352. TGlobalDecl(decl).funcGlobal = True
  2353. End If
  2354. End If
  2355. End If
  2356. Until Not CParse(",")
  2357. End Method
  2358. Method ParseLoopLabelDecl:TLoopLabelDecl()
  2359. NextToke
  2360. Local id:String = ParseIdent()
  2361. Return New TLoopLabelDecl.Create(id, 0)
  2362. End Method
  2363. 'handle end-of-line "dot dot return"-line connector
  2364. '-> skips EOL tokens
  2365. Method HandleDotsLineConnector(eatToke:Int = False)
  2366. Local tok:TToker = New TToker.Copy(_toker)
  2367. Local t:String = tok.NextToke()
  2368. Local count:Int = tok.SkipSpace()
  2369. For Local i:Int = 0 Until count
  2370. NextToke
  2371. Next
  2372. t = tok._toke
  2373. If t = "~r" Then
  2374. t = tok.NextToke()
  2375. If t = "~n" Then
  2376. NextToke
  2377. NextToke
  2378. Else
  2379. NextToke
  2380. End If
  2381. Else
  2382. If t = "~n" Then
  2383. NextToke
  2384. End If
  2385. End If
  2386. If eatToke And Not count Then
  2387. NextToke
  2388. End If
  2389. End Method
  2390. 'should return a specific "metadata object" ?
  2391. ' metadata is in the form : {key key=value key="value"}
  2392. Method ParseMetaData:TMetadata()
  2393. If Not CParse( "{" ) Then
  2394. Return Null
  2395. End If
  2396. Local meta:TMetadata = New TMetadata
  2397. SkipEols
  2398. Repeat
  2399. 'reached end of meta data declaration
  2400. If _toke="}" Then Exit
  2401. If meta.metadataString Then
  2402. meta.metadataString :+ " "
  2403. End If
  2404. Select _tokeType
  2405. Case TOKE_INTLIT
  2406. Err "Expecting '}' but encountered integer literal"
  2407. Case TOKE_FLOATLIT
  2408. Err "Expecting '}' but encountered floating point literal"
  2409. Case TOKE_STRINGLIT
  2410. Err "Expecting '}' but encountered string literal"
  2411. Case TOKE_SYMBOL
  2412. Err "Expecting '}' but encountered " + _toke
  2413. End Select
  2414. 'append current token to metaDataString
  2415. Local key:String = _toke
  2416. meta.metadataString :+ key
  2417. 'read next token
  2418. NextToke()
  2419. Local value:String
  2420. ' got a value
  2421. If CParse("=") Then
  2422. If _tokeType = TOKE_IDENT Then
  2423. Err "Meta data must be literal constant"
  2424. End If
  2425. value = _toke
  2426. meta.metadataString :+ "=" + value
  2427. 'read next token
  2428. NextToke()
  2429. Else
  2430. value = "1"
  2431. meta.metadataString :+ "=1"
  2432. End If
  2433. meta.InsertMeta(key.ToLower(), value)
  2434. Forever
  2435. 'continue to next token
  2436. NextToke()
  2437. 'parse this into something
  2438. Return meta
  2439. End Method
  2440. Method ParseFuncDecl:TFuncDecl( toke$, attrs:Long, parent:TScopeDecl = Null )
  2441. SetErr
  2442. If toke Parse toke
  2443. Local id$
  2444. Local ty:TType
  2445. Local meth:Int = attrs & FUNC_METHOD
  2446. Local meta:TMetadata
  2447. Local noMangle:Int
  2448. Local exported:Int
  2449. Local inInterface:Int = attrs & DECL_ABSTRACT
  2450. Local classDecl:TClassDecl = TClassDecl(parent)
  2451. If attrs & FUNC_METHOD
  2452. If _toke="new"
  2453. If attrs & DECL_EXTERN
  2454. Err "Extern classes cannot have constructors"
  2455. EndIf
  2456. id="New"
  2457. NextToke
  2458. attrs:|FUNC_CTOR
  2459. attrs:&~FUNC_METHOD
  2460. ty=ParseDeclType()
  2461. Else If _toke="operator" Then
  2462. attrs:|FUNC_OPERATOR
  2463. NextToke
  2464. Local t:String = _toke.ToLower()
  2465. NextToke
  2466. Select t
  2467. Case "*","/","+","-","&","|","~~","^"
  2468. id = t
  2469. Case ":*",":/",":+",":-",":&",":|",":~~",":^"
  2470. id = t
  2471. Case "<",">"',"="',"<=",">=","=","<>"
  2472. If CParse("=") Then
  2473. t :+ "="
  2474. Else If t = "<" And CParse(">") Then
  2475. t :+ ">"
  2476. End If
  2477. id = t
  2478. Case "="
  2479. id = t
  2480. Case "mod", "shl", "shr"
  2481. id = t
  2482. Case ":mod", ":shl", ":shr"
  2483. id = t
  2484. Case "[]"
  2485. If CParse("=") Then t :+ "="
  2486. id = t
  2487. Default
  2488. DoErr "Operator must be one of: * / + - & | ~~ :* :/ :+ :- :& :| :~~ < > <= >= = <> mod shl shr :mod :shl :shr [] []="
  2489. End Select
  2490. ty=ParseDeclType()
  2491. Else
  2492. id=ParseIdent()
  2493. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2494. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) Then
  2495. DoErr "Illegal function return type"
  2496. End If
  2497. ' Delete() return type should always be Void
  2498. If id.ToLower() = "delete" Then
  2499. attrs:|FUNC_DTOR
  2500. If TIntType(ty) Then
  2501. ty = New TVoidType
  2502. End If
  2503. End If
  2504. ' TODO: make sure Delete cannot be declared with parameters?
  2505. EndIf
  2506. Else
  2507. 'If Not (attrs & FUNC_PTR) Then
  2508. id=ParseIdent()
  2509. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2510. ' can only return "$z" and "$w" from an extern function.
  2511. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) And Not (attrs & DECL_EXTERN) Then
  2512. DoErr "Illegal function return type"
  2513. End If
  2514. 'End If
  2515. EndIf
  2516. ' every branch in that nested If block up there contains the line "ty=ParseDeclType()";
  2517. ' this already consumed all sets of parentheses and brackets belonging to this function declaration
  2518. ' so we will now extract our actual return type and args from the result
  2519. Local args:TArgDecl[]
  2520. If Not TFunctionPtrType(ty) Then
  2521. DoErr "Expecting function type"
  2522. Else
  2523. Local fdecl:TFuncDecl = TFunctionPtrType(ty).func
  2524. ty = fdecl.retTypeExpr
  2525. args = fdecl.argDecls
  2526. attrs :| (fdecl.attrs & DECL_API_FLAGS)
  2527. End If
  2528. Local declaredAttrs:Long
  2529. While True
  2530. If CParse( "nodebug" ) Then
  2531. If declaredAttrs & DECL_NODEBUG Then Err "Duplicate modifier 'NoDebug'"
  2532. declaredAttrs :| DECL_NODEBUG
  2533. Continue
  2534. End If
  2535. If CParse( "final" )
  2536. If Not classDecl Then
  2537. Err "Final cannot be used with global functions"
  2538. End If
  2539. If inInterface Then
  2540. If attrs & FUNC_METHOD Then
  2541. Err "Final methods cannot appear in interfaces"
  2542. Else
  2543. Err "Final functions cannot appear in interfaces"
  2544. End If
  2545. End If
  2546. If declaredAttrs & DECL_FINAL Then Err "Duplicate modifier 'Final'"
  2547. declaredAttrs :| DECL_FINAL
  2548. Continue
  2549. End If
  2550. If CParse( "abstract" )
  2551. If Not classDecl Then
  2552. Err "Abstract cannot be used with global functions"
  2553. End If
  2554. If classDecl And classDecl.attrs & DECL_FINAL Then
  2555. Err "Abstract methods cannot appear in final types"
  2556. End If
  2557. If inInterface Then
  2558. If attrs & FUNC_METHOD Then
  2559. Err "Abstract cannot be used in interfaces (interface methods are automatically abstract)"
  2560. Else
  2561. Err "Abstract cannot be used in interfaces (interface functions are automatically abstract)"
  2562. End If
  2563. End If
  2564. If declaredAttrs & DECL_ABSTRACT Then Err "Duplicate modifier 'Abstract'"
  2565. declaredAttrs :| DECL_ABSTRACT
  2566. Continue
  2567. End If
  2568. If CParse("override") Then
  2569. If Not classDecl Then
  2570. Err "Override cannot be used with global functions"
  2571. End If
  2572. If declaredAttrs & DECL_OVERRIDE Then Err "Duplicate modifier 'Override'"
  2573. declaredAttrs :| DECL_OVERRIDE
  2574. Continue
  2575. End If
  2576. If CParse("inline") And Not opt_debug Then
  2577. If classDecl Then
  2578. Err "Inline can only be used with global functions"
  2579. End If
  2580. If declaredAttrs & DECL_INLINE Then Err "Duplicate modifier 'Inline'"
  2581. declaredAttrs :| DECL_INLINE
  2582. Continue
  2583. End If
  2584. Exit
  2585. Wend
  2586. attrs :| declaredAttrs
  2587. 'meta data for functions/methods
  2588. meta = ParseMetaData()
  2589. If meta And meta.HasMeta("nomangle") Then
  2590. If attrs & FUNC_METHOD Then
  2591. Err "Only functions can specify NoMangle"
  2592. Else
  2593. noMangle = True
  2594. End If
  2595. End If
  2596. If CParse("export") Then
  2597. attrs :| DECL_EXPORT
  2598. If attrs & FUNC_METHOD Then
  2599. Err "Only functions can specify Export"
  2600. Else
  2601. exported = True
  2602. End If
  2603. End If
  2604. attrs :| ParseCallConvention(attrs & DECL_API_STDCALL)
  2605. If CParse( "nodebug" ) Then
  2606. attrs :| DECL_NODEBUG
  2607. End If
  2608. Local funcDecl:TFuncDecl
  2609. If attrs & FUNC_CTOR Then
  2610. funcDecl=New TNewDecl.CreateF( id,ty,args,attrs )
  2611. TNewDecl(funcDecl).cdecl = classdecl
  2612. Else
  2613. 'If fdecl Then
  2614. ' funcDecl = fdecl
  2615. ' funcDecl.ident = id
  2616. 'Else
  2617. funcDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
  2618. 'End If
  2619. funcDecl.noMangle = noMangle
  2620. funcDecl.exported = exported
  2621. End If
  2622. If meta Then
  2623. funcDecl.metadata = meta
  2624. End If
  2625. If funcDecl.IsExtern() Or (attrs & FUNC_PTR)
  2626. funcDecl.munged=funcDecl.ident
  2627. ' a normal function pointer definition *probably* can't be defined with a munged name?
  2628. ' If there is an equals here, one can assume it is for an initialisation...
  2629. 'If (Not (attrs & FUNC_PTR)) Or (attrs & FUNC_PTR And Not (attrs & DECL_ARG)) Then
  2630. Local cdets:TCastDets
  2631. If Not (attrs & FUNC_PTR) Then
  2632. If CParse( "=" )
  2633. Local munged:String = ParseStringLit()
  2634. If munged.Find("(") > 0 Then
  2635. cdets = ParseExternCast(munged, True)
  2636. If cdets Then
  2637. funcDecl.munged = cdets.name
  2638. End If
  2639. Else
  2640. funcDecl.munged = munged
  2641. End If
  2642. End If
  2643. 'Array $resize hack!
  2644. 'If funcDecl.munged="$resize"
  2645. ' funcDecl.retTypeExpr=TType.emptyArrayType
  2646. 'EndIf
  2647. EndIf
  2648. If funcDecl.munged Then
  2649. ' look up extern cast list
  2650. If Not cdets Then
  2651. cdets = TCastDets(_externCasts.ValueForKey(funcDecl.munged))
  2652. End If
  2653. If cdets Then
  2654. funcDecl.castTo = cdets.retType
  2655. If cdets.noGen Then
  2656. funcDecl.noCastGen = True
  2657. End If
  2658. For Local i:Int = 0 Until cdets.args.length
  2659. If i < funcDecl.argDecls.length Then
  2660. funcDecl.argDecls[i].castTo = cdets.args[i]
  2661. End If
  2662. Next
  2663. End If
  2664. End If
  2665. Return funcDecl
  2666. EndIf
  2667. If funcDecl.IsAbstract() Return funcDecl
  2668. 'Ok, only first statement of a constructor can call super constructor - not pretty, should be in semant.
  2669. If attrs & FUNC_CTOR
  2670. SkipEols
  2671. If CParse( "super" )
  2672. Parse "."
  2673. If _toke="new"
  2674. Local id$="New"
  2675. NextToke
  2676. 'funcDecl.superCtor=New TInvokeSuperExpr.Create( id,ParseArgs( True ) )
  2677. 'funcDecl.AddStmt New TExprStmt.Create( funcDecl.superCtor )
  2678. funcDecl.AddStmt New TExprStmt.Create( New TNewExpr.Create(ParseArgs(True), True))
  2679. Else
  2680. Local id$=ParseIdent()
  2681. funcDecl.AddStmt New TExprStmt.Create( New TInvokeSuperExpr.Create( id,ParseArgs( True ) ) )
  2682. EndIf
  2683. Else
  2684. 'Invoke super default ctor
  2685. 'funcDecl.superCtor=New InvokeSuperExpr( "new",[] )
  2686. 'funcDecl.AddStmt New TExprStmt( funcDecl.superCtor )
  2687. EndIf
  2688. EndIf
  2689. PushBlock funcDecl
  2690. While (Not meth And _toke.ToLower()<>"endfunction") Or (meth And _toke.ToLower()<>"endmethod")
  2691. If CParse( "end" )
  2692. If (Not meth And CParse("function")) Or (meth And CParse("method"))
  2693. Exit
  2694. End If
  2695. ' handle "end" statement
  2696. ParseEndStmt(False)
  2697. EndIf
  2698. ParseStmt
  2699. Wend
  2700. PopBlock
  2701. NextToke
  2702. 'If toke CParse toke
  2703. Return funcDecl
  2704. End Method
  2705. Method ParseCallConvention:Long(callConvention:Long = DECL_API_DEFAULT)
  2706. If _tokeType <> TOKE_STRINGLIT Then
  2707. Return callConvention
  2708. End If
  2709. Local api:String = ParseStringLit().ToLower()
  2710. If api = "os" Then
  2711. Select opt_platform
  2712. Case "macos", "osx", "ios"
  2713. api = "macos"
  2714. Case "linux", "android", "raspberrypi", "haiku"
  2715. api = "linux"
  2716. Case "win32"
  2717. api = "win32"
  2718. Case "nx"
  2719. api = "nx"
  2720. End Select
  2721. End If
  2722. Select api
  2723. Case "c", "blitz", "macos", "linux", "nx"
  2724. Return DECL_API_CDECL
  2725. Case "win32"
  2726. ' only if we are compiling for win32
  2727. If opt_platform = "win32"
  2728. Return DECL_API_STDCALL
  2729. Else
  2730. Return DECL_API_CDECL
  2731. End If
  2732. End Select
  2733. Err "Unrecognized calling convention '" + api+ "'"
  2734. End Method
  2735. Method ParseFuncParamDecl:TArgDecl[]()
  2736. Local args:TArgDecl[]
  2737. Parse "("
  2738. SkipEols
  2739. If _toke<>")"
  2740. Local nargs:Int
  2741. Repeat
  2742. Local attrs:Long
  2743. If CParse("staticarray") Then
  2744. attrs :| DECL_STATIC
  2745. End If
  2746. Local argId$=ParseIdent()
  2747. Local ty:TType=ParseDeclType(attrs)
  2748. Local init:TExpr
  2749. ' var argument?
  2750. If CParse("var") Then
  2751. If attrs & DECL_STATIC Then
  2752. Err "Unexpected 'Var' for static array argument"
  2753. End If
  2754. ty = TType.MapToVarType(ty)
  2755. Else If CParse( "=" )
  2756. init=ParseExpr()
  2757. Else
  2758. If CParse( "[" ) And (attrs & DECL_STATIC) Then
  2759. init = ParseExpr()
  2760. Parse "]"
  2761. ty=New TArrayType.Create( ty,1,, attrs & DECL_STATIC > 0 )
  2762. End If
  2763. End If
  2764. Local arg:TArgDecl=New TArgDecl.Create( argId,ty,init,attrs )
  2765. If args.Length=nargs args=args + New TArgDecl[10]
  2766. args[nargs]=arg
  2767. nargs:+1
  2768. If _toke=")" Exit
  2769. Parse ","
  2770. Forever
  2771. args=args[..nargs]
  2772. EndIf
  2773. Parse ")"
  2774. Return args
  2775. End Method
  2776. Method ParseEnumDecl:TEnumDecl( toke:String )
  2777. SetErr
  2778. If toke Parse toke
  2779. Local id:String = ParseIdent()
  2780. Local ty:TType = ParseConstNumberType()
  2781. If Not ty Then
  2782. ty = New TIntType
  2783. End If
  2784. Local isFlags:Int = 0
  2785. Local values:TEnumValueDecl[0]
  2786. If CParse("flags")
  2787. isFlags = True
  2788. End If
  2789. Local decl:TEnumDecl = New TEnumDecl.Create(id, ty, isFlags, values)
  2790. Local nValues:Int
  2791. Repeat
  2792. SkipEols
  2793. If CParse("end") Then
  2794. Parse("enum")
  2795. Exit
  2796. End If
  2797. If CParse("endenum") Then
  2798. Exit
  2799. End If
  2800. Local valId:String = ParseIdent()
  2801. Local value:TExpr
  2802. If CParse( "=" ) Then
  2803. value = ParseExpr()
  2804. End If
  2805. Local v:TEnumValueDecl = New TEnumValueDecl.Create(valId, nValues, value)
  2806. If decl.values.Length = nValues Then
  2807. decl.values = decl.values + New TEnumValueDecl[10]
  2808. End If
  2809. decl.values[nValues] = v
  2810. nValues :+ 1
  2811. CParse(",")
  2812. Forever
  2813. decl.values = decl.values[..nValues]
  2814. Return decl
  2815. End Method
  2816. Method ParseClassDecl:TClassDecl( toke$,attrs:Long, templateDets:TTemplateDets = Null )
  2817. SetErr
  2818. Local calculatedStartLine:Int = _toker.Line()
  2819. Local startLine:Int = _toker._line
  2820. If toke Parse toke
  2821. Local id$=ParseIdent()
  2822. Local args:TList = New TList
  2823. Local superTy:TIdentType
  2824. Local imps:TIdentType[]
  2825. Local meta:TMetadata
  2826. 'If (attrs & CLASS_INTERFACE) And (attrs & DECL_EXTERN)
  2827. ' Err "Interfaces cannot be extern."
  2828. 'EndIf
  2829. If CParse( "<" )
  2830. If attrs & DECL_EXTERN
  2831. Err "Extern classes cannot be generic."
  2832. EndIf
  2833. 'If attrs & CLASS_INTERFACE
  2834. ' Err "Interfaces cannot be generic."
  2835. 'EndIf
  2836. 'If attrs & CLASS_TEMPLATEARG
  2837. ' Err "Class parameters cannot be generic."
  2838. 'EndIf
  2839. Local nargs:Int
  2840. Repeat
  2841. 'Local decl:TClassDecl=ParseClassDecl( "",CLASS_TEMPLATEARG )
  2842. 'If args.Length=nargs args=args + New TClassDecl[10]
  2843. 'args[nargs]=decl
  2844. 'nargs:+1
  2845. Local arg:TTemplateArg = New TTemplateArg
  2846. arg.ident = ParseIdent()
  2847. ' If CParse("extends") Then
  2848. ' arg.superTy = ParseIdentType()
  2849. ' End If
  2850. args.AddLast arg
  2851. Until Not CParse(",")
  2852. 'args=args[..nargs]
  2853. Parse ">"
  2854. If CParse( "where" ) Then
  2855. 'DebugStop
  2856. Repeat
  2857. Local argIdent:String = ParseIdent()
  2858. Parse("extends")
  2859. Local found:Int
  2860. For Local arg:TTemplateArg = EachIn args
  2861. If arg.ident = argIdent Then
  2862. Repeat
  2863. arg.ExtendsType(ParseIdentType())
  2864. Until Not CParse("and")
  2865. found = True
  2866. Exit
  2867. EndIf
  2868. Next
  2869. If Not found Then
  2870. Err "Use of undeclared type '" + argIdent + "'."
  2871. End If
  2872. Until Not CParse(",")
  2873. End If
  2874. EndIf
  2875. If CParse( "extends" )
  2876. 'If attrs & CLASS_TEMPLATEARG
  2877. ' Err "Extends cannot be used with class parameters."
  2878. 'EndIf
  2879. ' If CParse( "null" )
  2880. '
  2881. If attrs & CLASS_STRUCT
  2882. Err "Structs cannot be extended"
  2883. EndIf
  2884. '
  2885. ' If Not (attrs & DECL_EXTERN)
  2886. ' Err "Only extern objects can extend null."
  2887. ' EndIf
  2888. '
  2889. ' superTy=Null
  2890. '
  2891. ' Else
  2892. If attrs & CLASS_INTERFACE And Not (attrs & DECL_EXTERN)
  2893. Local nimps:Int
  2894. Repeat
  2895. If imps.Length=nimps imps=imps + New TIdentType[10]
  2896. imps[nimps]=ParseIdentType()
  2897. nimps:+1
  2898. Until Not CParse(",")
  2899. imps=imps[..nimps]
  2900. superTy=New TIdentType.Create( "brl.classes.object" )
  2901. Else
  2902. superTy=ParseIdentType()
  2903. EndIf
  2904. Else
  2905. If Not (attrs & DECL_EXTERN) And Not (attrs & CLASS_STRUCT) Then
  2906. superTy=New TIdentType.Create( "brl.classes.object" )
  2907. End If
  2908. EndIf
  2909. If CParse( "implements" )
  2910. If attrs & CLASS_STRUCT
  2911. Err "Implements cannot be used with Structs"
  2912. EndIf
  2913. 'If attrs & DECL_EXTERN
  2914. ' Err "Implements cannot be used with external classes."
  2915. 'EndIf
  2916. If attrs & CLASS_INTERFACE
  2917. Err "Implements cannot be used with interfaces."
  2918. EndIf
  2919. 'If attrs & CLASS_TEMPLATEARG
  2920. ' Err "Implements cannot be used with class parameters."
  2921. 'EndIf
  2922. Local nimps:Int
  2923. Repeat
  2924. If imps.Length=nimps imps=imps + New TIdentType[10]
  2925. imps[nimps]=ParseIdentType()
  2926. nimps:+1
  2927. Until Not CParse(",")
  2928. imps=imps[..nimps]
  2929. EndIf
  2930. Repeat
  2931. If CParse( "final" )
  2932. If attrs & CLASS_INTERFACE
  2933. Err "Final cannot be used with interfaces."
  2934. End If
  2935. If attrs & CLASS_STRUCT
  2936. Err "Final cannot be used with structs."
  2937. End If
  2938. If attrs & DECL_FINAL
  2939. Err "Duplicate modifier 'Final'."
  2940. End If
  2941. If attrs & DECL_ABSTRACT
  2942. Err "Classes cannot be both final and abstract."
  2943. End If
  2944. attrs:|DECL_FINAL
  2945. Else If CParse( "abstract" )
  2946. If attrs & CLASS_INTERFACE
  2947. Err "Abstract cannot be used with interfaces."
  2948. EndIf
  2949. If attrs & CLASS_STRUCT
  2950. Err "Abstract cannot be used with structs."
  2951. EndIf
  2952. If attrs & DECL_ABSTRACT
  2953. Err "Duplicate modifier 'Abstract'."
  2954. End If
  2955. If attrs & DECL_FINAL
  2956. Err "Types cannot be both final and abstract."
  2957. End If
  2958. attrs:|DECL_ABSTRACT
  2959. Else
  2960. Exit
  2961. EndIf
  2962. Forever
  2963. 'check for metadata
  2964. meta = ParseMetaData()
  2965. Local sargs:TTemplateArg[] = New TTemplateArg[args.Count()]
  2966. Local i:Int = 0
  2967. For Local arg:TTemplateArg = EachIn args
  2968. sargs[i] = arg
  2969. i :+ 1
  2970. Next
  2971. Local classDecl:TClassDecl=New TClassDecl.Create( id,sargs,superTy,imps,attrs )
  2972. If meta Then
  2973. If attrs & CLASS_STRUCT
  2974. Err "Structs cannot store metadata."
  2975. EndIf
  2976. classDecl.metadata = meta
  2977. End If
  2978. If classDecl.IsExtern()
  2979. classDecl.munged=classDecl.ident
  2980. If CParse( "=" ) classDecl.munged=ParseStringLit()
  2981. EndIf
  2982. 'If classDecl.IsTemplateArg() Return classDecl
  2983. Local decl_attrs:Long=(attrs & DECL_EXTERN) | (attrs & DECL_NODEBUG) | (attrs & DECL_API_STDCALL)
  2984. Repeat
  2985. Local method_attrs:Long=decl_attrs|FUNC_METHOD | (attrs & DECL_NODEBUG)
  2986. Local abst_attrs:Long = 0
  2987. If attrs & CLASS_INTERFACE abst_attrs:|DECL_ABSTRACT
  2988. SkipEols
  2989. Select _toke
  2990. Case "end"
  2991. NextToke
  2992. Exit
  2993. Case "endtype"
  2994. If attrs & CLASS_INTERFACE Then
  2995. Err "Syntax error - expecting End Interface, not 'EndType'"
  2996. End If
  2997. If attrs & CLASS_STRUCT Then
  2998. Err "Syntax error - expecting End Struct, not 'EndType'"
  2999. End If
  3000. toke = Null
  3001. NextToke
  3002. Exit
  3003. Case "endstruct"
  3004. If attrs & CLASS_INTERFACE Then
  3005. Err "Syntax error - expecting End Interface, not 'EndStruct'"
  3006. End If
  3007. If Not (attrs & CLASS_STRUCT) Then
  3008. Err "Syntax error - expecting End Type, not 'EndStruct'"
  3009. End If
  3010. toke = Null
  3011. NextToke
  3012. Exit
  3013. Case "endinterface"
  3014. If Not (attrs & CLASS_INTERFACE) And Not (attrs & CLASS_STRUCT) Then
  3015. Err "Syntax error - expecting End Type, not 'EndInterface'"
  3016. End If
  3017. If Not (attrs & CLASS_INTERFACE) And (attrs & CLASS_STRUCT) Then
  3018. Err "Syntax error - expecting End Struct, not 'EndInterface'"
  3019. End If
  3020. toke = Null
  3021. NextToke
  3022. Exit
  3023. Case "private"
  3024. If attrs & CLASS_INTERFACE Then
  3025. Err "Private cannot be used with interfaces."
  3026. End If
  3027. NextToke
  3028. decl_attrs=decl_attrs | DECL_PRIVATE
  3029. decl_attrs:& ~DECL_PROTECTED
  3030. Case "protected"
  3031. If attrs & CLASS_INTERFACE Then
  3032. Err "Protected cannot be used with interfaces."
  3033. End If
  3034. NextToke
  3035. decl_attrs=decl_attrs | DECL_PROTECTED
  3036. decl_attrs:& ~DECL_PRIVATE
  3037. Case "public"
  3038. NextToke
  3039. decl_attrs:& ~DECL_PRIVATE
  3040. decl_attrs:& ~DECL_PROTECTED
  3041. Case "const","global","field","threadedglobal"
  3042. Local extra_attrs:Long
  3043. If _toke = "threadedglobal" Then
  3044. extra_attrs = DECL_THREADED
  3045. End If
  3046. If attrs & DECL_EXTERN Then
  3047. If (attrs & CLASS_INTERFACE) Then
  3048. Err "Extern Interfaces can only contain methods."
  3049. End If
  3050. If Not (attrs & CLASS_STRUCT) Then
  3051. Err "Extern Types can only contain methods."
  3052. End If
  3053. End If
  3054. If (attrs & CLASS_INTERFACE) And _toke<>"const"
  3055. Err "Interfaces can only contain constants and methods."
  3056. EndIf
  3057. If (attrs & CLASS_STRUCT) And _toke<>"field" And _toke<>"global" And _toke<>"threadedglobal"
  3058. Err "Structs can only contain fields."
  3059. EndIf
  3060. classDecl.InsertDecls ParseDecls( _toke,decl_attrs | extra_attrs, _toke = "field")
  3061. Case "method"
  3062. If (attrs & CLASS_STRUCT) And (attrs & DECL_EXTERN) Then
  3063. Err "Structs can only contain fields."
  3064. EndIf
  3065. Local decl:TFuncDecl=ParseFuncDecl( _toke,method_attrs | abst_attrs,classDecl )
  3066. classDecl.InsertDecl decl
  3067. Case "function"
  3068. 'If (attrs & CLASS_INTERFACE)
  3069. ' Err "Interfaces can only contain constants and methods."
  3070. 'EndIf
  3071. If attrs & CLASS_STRUCT Then
  3072. If (attrs & DECL_EXTERN) Then
  3073. Err "Structs can only contain fields."
  3074. End If
  3075. EndIf
  3076. If attrs & DECL_EXTERN Then
  3077. Err "Extern Types can only contain methods."
  3078. End If
  3079. Local decl:TFuncDecl=ParseFuncDecl( _toke,decl_attrs | abst_attrs,classDecl )
  3080. classDecl.InsertDecl decl
  3081. Case "type"
  3082. If templateDets Then
  3083. Local cdecl:TClassDecl = ParseClassDecl( _toke,DECL_NESTED, templateDets)
  3084. cdecl = cdecl.GenClassInstance(templateDets.instArgs, False, Null, templateDets)
  3085. classDecl.InsertDecl cdecl, True
  3086. Else
  3087. classDecl.InsertDecl ParseClassDecl( _toke,DECL_NESTED)
  3088. End If
  3089. Default
  3090. Err "Syntax error - expecting class member declaration, not '" + _toke + "'"
  3091. End Select
  3092. Forever
  3093. If Not args.IsEmpty() Then
  3094. Local endline:Int = _toker._line
  3095. classDecl.templateSource = New TTemplateRecord.Create(calculatedStartLine - 1, _toker._path, _toker.Join(startLine, endLine, "~n"))
  3096. End If
  3097. If toke Parse toke
  3098. Return classDecl
  3099. End Method
  3100. Method ParseNativeStmt()
  3101. If Not _toke.StartsWith("'!") Then
  3102. Err "Syntax error - expecting '!"
  3103. End If
  3104. Local raw:String = _toke[2..]
  3105. _block.AddStmt New TNativeStmt.Create( raw )
  3106. NextToke
  3107. End Method
  3108. Method ParseModuleDecl:String( toke$,attrs:Long )
  3109. NextToke
  3110. ' namespace . module
  3111. Return ParseModPath().ToLower()
  3112. End Method
  3113. Method ParseModPath$()
  3114. Local path$=ParseIdent()
  3115. While CParse( "." )
  3116. path:+"."+ParseIdent()
  3117. Wend
  3118. Return path
  3119. End Method
  3120. Method ExtractModIdent$( modpath$ )
  3121. Local i:Int=modpath.FindLast( "." )
  3122. If i<>-1 Return modpath[i+1..]
  3123. Return modpath
  3124. End Method
  3125. Method ImportFile( filepath$ )
  3126. If filepath.Endswith(".bmx") Then
  3127. filepath = ActualPath(filepath)
  3128. Local origPath:String = RealPath(filepath)
  3129. Local path:String = OutputFilePath(origPath, FileMung(), "i")
  3130. If FileType( origPath )<>FILETYPE_FILE
  3131. Err "File '"+ origPath +"' not found."
  3132. EndIf
  3133. If FileType( path )<>FILETYPE_FILE
  3134. Err "File '"+ path +"' not found."
  3135. EndIf
  3136. If _module.imported.Contains( path ) Return
  3137. Local modpath:String
  3138. If opt_buildtype = BUILDTYPE_MODULE Then
  3139. Local dir:String = ExtractDir(origPath).ToLower()
  3140. dir = dir[dir.findLast("/") + 1..]
  3141. If dir.EndsWith(".mod") Then
  3142. dir = ""
  3143. Else
  3144. dir :+ "_"
  3145. End If
  3146. Local file:String = StripDir(origPath).ToLower()
  3147. modpath = opt_modulename + "_" + dir + StripExt(file)
  3148. Else
  3149. modpath = StripExt(filepath)
  3150. End If
  3151. 'sanitize the path, remove non-allowed chars
  3152. modpath = TStringHelper.Sanitize(modpath.ToLower())
  3153. ' try to import interface
  3154. Local par:TIParser = New TIParser
  3155. If par.ParseModuleImport(_module, modpath, origPath, path, , , filepath, True) Return
  3156. Else If filepath.startswith("-") Then
  3157. If Not _app.fileimports.Contains(filepath) Then
  3158. _app.fileimports.AddLast filepath
  3159. End If
  3160. Else
  3161. If filepath.EndsWith(".h") Or filepath.EndsWith(".hpp") Or filepath.EndsWith(".hxx") Then
  3162. If filepath.Find("*") = -1 Then
  3163. _app.headers.AddLast filepath
  3164. End If
  3165. Else
  3166. Local path:String = ActualPath(RealPath(filepath))
  3167. If FileType( path )<>FILETYPE_FILE
  3168. Err "File '"+ path +"' not found."
  3169. End If
  3170. End If
  3171. End If
  3172. End Method
  3173. Method ImportAllModules(attrs:Long)
  3174. ' get all brl and pub modules
  3175. Local mods:TList = EnumModules("brl")
  3176. mods = EnumModules("pub", mods)
  3177. For Local m:String = EachIn mods
  3178. ImportModule(m, attrs)
  3179. Next
  3180. End Method
  3181. Method ImportModule( modpath$,attrs:Long )
  3182. SetErr
  3183. modpath = modpath.ToLower()
  3184. Local basepath:String = ModulePath(modpath)
  3185. If _module.imported.Contains( basepath ) Return
  3186. ' try to import interface
  3187. Local par:TIParser = New TIParser
  3188. If par.ParseModuleImport(_module, modpath, basepath, , , attrs) Return
  3189. 'DebugStop
  3190. 'Local mdecl:TDecl=_app.imported.ValueForKey( basepath )
  3191. 'If Not mdecl
  3192. ' mdecl=ParseModule( filepath,_app )
  3193. 'EndIf
  3194. '_module.imported.Insert mdecl.filepath,mdecl
  3195. 'If Not (attrs & DECL_PRIVATE) _module.pubImported.Insert mdecl.filepath,mdecl
  3196. '_module.InsertDecl New AliasDecl( mdecl.ident,mdecl,attrs )
  3197. 'End Rem
  3198. End Method
  3199. Method ValidateModIdent( id$ )
  3200. If id.Length
  3201. If IsAlpha( id[0] ) Or id[0]="_"[0]
  3202. Local err:Int
  3203. For Local i:Int=1 Until id.Length
  3204. If IsAlpha( id[i] ) Or IsDigit( id[i] ) Or id[i]="_"[0] Continue
  3205. err=1
  3206. Exit
  3207. Next
  3208. If Not err Return
  3209. EndIf
  3210. EndIf
  3211. Err "Invalid module identifier '"+id+"'."
  3212. End Method
  3213. Method MungAppDecl(app:TAppDecl)
  3214. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain Then
  3215. app.munged = MungModuleName(opt_modulename)
  3216. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3217. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3218. dir = dir[dir.findLast("/") + 1..]
  3219. If dir.EndsWith(".mod") Then
  3220. dir = ""
  3221. Else
  3222. dir :+ "_"
  3223. End If
  3224. app.munged = "_bb_" + opt_modulename + "_" + dir + StripExt(StripDir(opt_filepath).ToLower())
  3225. Else
  3226. ' main application file?
  3227. If opt_apptype Then
  3228. app.munged = "_bb_main"
  3229. Else
  3230. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3231. dir = dir[dir.findLast("/") + 1..]
  3232. If dir.EndsWith(".mod") Then
  3233. dir = dir.Replace(".mod", "")
  3234. End If
  3235. Local file:String = StripDir(opt_filepath).ToLower()
  3236. app.munged = "_bb_" + dir + "_" + StripExt(file)
  3237. End If
  3238. End If
  3239. 'sanitize, remove non-allowed chars
  3240. app.munged = TStringHelper.Sanitize(app.munged)
  3241. End Method
  3242. ' load external cast defs
  3243. Method LoadExternCasts(path:String)
  3244. For Local externs:Int = 0 Until 3
  3245. Local ePath:String
  3246. ' we will iterate through all possibilities as there may be different sets
  3247. ' of explicit casts/no gen funcs for each.
  3248. Select externs
  3249. Case 0
  3250. ' eg. file.win32.x86.x
  3251. ePath = StripExt(path) + "." + opt_platform + "." + opt_arch + ".x"
  3252. Case 1
  3253. ' eg. file.win32.x
  3254. ePath = StripExt(path) + "." + opt_platform + ".x"
  3255. Case 2
  3256. ' eg. file.x
  3257. ePath = StripExt(path) + ".x"
  3258. End Select
  3259. If FileType(ePath) = FILETYPE_FILE Then
  3260. Print "Warning: .x cast definition files are deprecated. You should now place the details in the extern function's alias string. (" + path + ")"
  3261. ParseExternCast(LoadText( ePath ), False, ePath)
  3262. End If
  3263. Next
  3264. End Method
  3265. Method ParseExternCast:TCastDets(txt:String, single:Int = False, path:String = "")
  3266. Local toker:TToker = New TToker.Create(path, txt)
  3267. toker.NextToke
  3268. Local dets:TCastDets
  3269. While True
  3270. SkipEolsToker(toker)
  3271. If toker._tokeType = TOKE_EOF Exit
  3272. dets = New TCastDets
  3273. Local rt$=toker._toke
  3274. If CParseToker(toker, "const") Then
  3275. rt :+ " " + toker._toke
  3276. End If
  3277. If CParseToker(toker, "unsigned") Then
  3278. rt :+ " " + toker._toke
  3279. End If
  3280. NextTokeToker(toker)
  3281. If CParseToker(toker,"*") Then
  3282. rt:+ "*"
  3283. If CParseToker(toker,"*") Then
  3284. rt:+ "*"
  3285. End If
  3286. End If
  3287. If CParseToker(toker, "__stdcall") Then
  3288. dets.api = "__stdcall"
  3289. End If
  3290. ' fname
  3291. Local fn$=toker._toke
  3292. NextTokeToker(toker)
  3293. dets.name = fn
  3294. dets.retType = rt
  3295. ' add to global map (may be referenced by function ptr defs)
  3296. _externCasts.Insert(fn, dets)
  3297. ' args
  3298. ParseToker(toker, "(")
  3299. If CParseToker(toker, ")") Then
  3300. ' don't generate header extern
  3301. If CParseToker(toker, "!") Then
  3302. dets.noGen = True
  3303. End If
  3304. Continue
  3305. End If
  3306. Local i:Int = 0
  3307. Repeat
  3308. Local at$=toker._toke
  3309. If CParseToker(toker, "const") Then
  3310. at :+ " " + toker._toke
  3311. End If
  3312. If CParseToker(toker, "unsigned") Then
  3313. at :+ " " + toker._toke
  3314. End If
  3315. If CParseToker(toker, "struct") Then
  3316. at :+ " " + toker._toke
  3317. End If
  3318. NextTokeToker(toker)
  3319. If CParseToker(toker, "*") Then
  3320. at:+ "*"
  3321. If CParseToker(toker, "const") Then
  3322. at :+ " const"
  3323. End If
  3324. If CParseToker(toker, "*") Then
  3325. at:+ "*"
  3326. End If
  3327. End If
  3328. ' function pointer
  3329. If CParseToker(toker, "(") Then
  3330. ParseToker(toker, "*")
  3331. ParseToker(toker, ")")
  3332. at :+ "(*)"
  3333. ParseToker(toker, "(")
  3334. at :+ "("
  3335. While Not CParseToker(toker, ")")
  3336. NextTokeToker(toker)
  3337. at :+ toker._toke
  3338. Wend
  3339. at :+ ")"
  3340. End If
  3341. dets.args :+ [at]
  3342. If toker._toke=")" Exit
  3343. ParseToker(toker, ",")
  3344. i:+ 1
  3345. Forever
  3346. NextTokeToker(toker)
  3347. ' don't generate header extern
  3348. If CParseToker(toker, "!") Then
  3349. dets.noGen = True
  3350. End If
  3351. If single Then
  3352. Exit
  3353. End If
  3354. Wend
  3355. Return dets
  3356. End Method
  3357. Method ParseCurrentFile:Long(path:String, attrs:Long)
  3358. LoadExternCasts(path)
  3359. While _toke
  3360. SetErr
  3361. Select _toke.toLower()
  3362. Case "~n"
  3363. NextToke
  3364. Case "public"
  3365. NextToke
  3366. attrs=attrs & ~DECL_PRIVATE
  3367. Case "private"
  3368. NextToke
  3369. attrs=attrs | DECL_PRIVATE
  3370. Case "extern"
  3371. ParseExternBlock(_module, attrs)
  3372. Case "const"
  3373. _module.InsertDecls ParseDecls( _toke,attrs )
  3374. Case "global"
  3375. ParseDeclStmts(True, attrs, _module)
  3376. Case "threadedglobal"
  3377. ParseDeclStmts(True, attrs | DECL_THREADED, _module)
  3378. Case "struct"
  3379. _module.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
  3380. Case "type"
  3381. _module.InsertDecl ParseClassDecl( _toke,attrs)
  3382. Case "interface"
  3383. _module.InsertDecl ParseClassDecl( _toke,attrs|CLASS_INTERFACE|DECL_ABSTRACT )
  3384. Case "enum"
  3385. _module.InsertDecl ParseEnumDecl( _toke )
  3386. Case "function"
  3387. _module.InsertDecl ParseFuncDecl( _toke,attrs )
  3388. Case "incbin"
  3389. NextToke
  3390. Local s:String = ParseStringLit()
  3391. _app.mapStringConsts(s)
  3392. Local ib:TIncBin = New TIncbin.Create(s, path)
  3393. If Not ib Then
  3394. DoErr "Incbin file '"+ s +"' not found."
  3395. End If
  3396. _app.incbins.AddLast(ib)
  3397. Case "include"
  3398. 'include command is NOT just a pattern to replace with
  3399. 'content. BlitzMax parses each included file before the
  3400. 'content gets appended to the source (right before
  3401. 'semanting or analyzing content)
  3402. NextToke
  3403. Local includeFile:String = ParseStringLit()
  3404. 'convert the URI of the to include file as it might be
  3405. 'a relative one
  3406. includeFile = RealPath(includeFile)
  3407. 'instead of merging the data of multiple parsers, the
  3408. 'same parser is used for all included files - but each
  3409. 'of them uses an individual toker
  3410. If FileType( includeFile )<>FILETYPE_FILE
  3411. DoErr "File '"+ includeFile +"' not found."
  3412. EndIf
  3413. 'instead of "LoadText" "PreProcess" is used to include
  3414. 'handling of conditionals and comments
  3415. Try
  3416. Local includeSource:String = PreProcess(includeFile)
  3417. Local includeToker:TToker = New TToker.Create(includeFile, includeSource)
  3418. 'backup old vars
  3419. Local oldToker:TToker = Self._toker
  3420. 'assign temporary vars
  3421. Self._toker = includeToker
  3422. 'parse the include file
  3423. parseCurrentFile(includeFile, attrs)
  3424. 'restore backup vars
  3425. Self._toker = oldToker
  3426. Catch e:TStreamException
  3427. DoErr "Failed to include file '" + includeFile + "' : '" + e.ToString() + "'"
  3428. End Try
  3429. 'move on to next toke (after include "xyz.bmx")
  3430. NextToke
  3431. Default
  3432. ParseStmt
  3433. 'Err "Syntax error - expecting declaration."
  3434. End Select
  3435. Wend
  3436. Return attrs
  3437. End Method
  3438. Method ParseGeneric:Object(templateSource:TTemplateRecord, templateDets:TTemplateDets)
  3439. Local toker:TToker = New TToker.Create(templateSource.file, templateSource.source, False, templateSource.start)
  3440. Local parser:TParser = New TParser.Create( toker, _appInstance )
  3441. Local m:TModuleDecl = New TModuleDecl
  3442. parser._module = m
  3443. Local cdecl:TClassDecl = Null
  3444. Select parser._toke
  3445. Case "type"
  3446. cdecl = parser.ParseClassDecl(parser._toke,0, templateDets )
  3447. Case "interface"
  3448. cdecl = parser.ParseClassDecl(parser._toke, CLASS_INTERFACE|DECL_ABSTRACT, templateDets )
  3449. End Select
  3450. Return cdecl
  3451. End Method
  3452. Method ParseMain()
  3453. SkipEols
  3454. Local mattrs:Long
  3455. 'If CParse( "strict" ) mattrs:|MODULE_STRICT
  3456. 'If CParse( "superstrict" ) mattrs:|MODULE_SUPERSTRICT
  3457. Local path$=_toker.Path()
  3458. Local ident$=StripAll( path )
  3459. Local munged$ '="bb_"+ident+"_"
  3460. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain
  3461. ValidateModIdent ident
  3462. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3463. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3464. dir = dir[dir.findLast("/") + 1..]
  3465. If dir.EndsWith(".mod") Then
  3466. dir = ""
  3467. Else
  3468. dir :+ "_"
  3469. End If
  3470. munged = opt_modulename + "_" + dir + ident
  3471. 'sanitize, remove non-allowed chars
  3472. munged = TStringHelper.Sanitize(munged.ToLower())
  3473. End If
  3474. If opt_ismain Then 'And opt_modulename <> "brl.blitz" Then
  3475. ident = opt_modulename
  3476. End If
  3477. If opt_buildtype = BUILDTYPE_APP Then
  3478. ident = "m_" + ident
  3479. End If
  3480. _module=New TModuleDecl.Create( ident,munged,path,mattrs )
  3481. _module.AddImport path,_module
  3482. _app.InsertModule _module
  3483. ' mung the app decl
  3484. MungAppDecl(_app)
  3485. If opt_buildtype = BUILDTYPE_MODULE And opt_modulename = "brl.blitz" Then
  3486. ' import Object and String definitions
  3487. Local par:TIParser = New TIParser
  3488. par.ParseModuleImport(_module, "brl.classes", modulepath("brl.blitz"), modulepath("brl.blitz") + "/blitz_classes.i")
  3489. ' set up built-in keywords
  3490. par = New TIParser
  3491. par.ParseModuleImport(_module, "brl.blitzkeywords", "", "", MakeKeywords())
  3492. End If
  3493. ' don't import ourself
  3494. If opt_modulename <> "brl.blitz" Then
  3495. Local par:TIParser = New TIParser
  3496. par.ParseModuleImport(_module, "brl.blitz", modulepath("brl.blitz"), , , MODULE_ACTUALMOD)
  3497. End If
  3498. Local mainFunc:TFuncDecl = New TFuncDecl.CreateF("__LocalMain", New TIntType,Null,0)
  3499. '_app.InsertDecl mainFunc
  3500. _module.insertDecl(mainFunc)
  3501. 'Local mainBlock:TBlockDecl = New TBlockDecl.Create( _block )
  3502. ' import all brl and pub modules if we haven't specified one
  3503. If opt_buildtype <> BUILDTYPE_MODULE And Not opt_framework Then
  3504. ImportAllModules MODULE_ACTUALMOD
  3505. Else
  3506. If opt_framework Then
  3507. Local par:TIParser = New TIParser
  3508. par.ParseModuleImport(_module, opt_framework, modulepath(opt_framework), , , MODULE_ACTUALMOD)
  3509. End If
  3510. End If
  3511. Local attrs:Long
  3512. While _toke
  3513. SetErr
  3514. Select _toke.ToLower()
  3515. Case "~n"
  3516. NextToke
  3517. Case "strict"
  3518. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3519. Err "Strict or SuperStrict already specified"
  3520. End If
  3521. _module.attrs :| MODULE_STRICT
  3522. nextToke
  3523. Case "superstrict"
  3524. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3525. Err "Strict or SuperStrict already specified"
  3526. End If
  3527. _module.attrs :| MODULE_SUPERSTRICT
  3528. opt_issuperstrict = True
  3529. NextToke
  3530. Default
  3531. Exit
  3532. End Select
  3533. Wend
  3534. If opt_need_strict And Not (_module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT)) Then
  3535. Err "Strict or SuperStrict must be declared at the start of the file."
  3536. End If
  3537. 'Parse header - imports etc.
  3538. While _toke
  3539. SetErr
  3540. Select _toke.ToLower()
  3541. Case "~n"
  3542. NextToke
  3543. Case "public"
  3544. NextToke
  3545. attrs=attrs & ~DECL_PRIVATE
  3546. Case "private"
  3547. NextToke
  3548. attrs=attrs | DECL_PRIVATE
  3549. Case "import"
  3550. NextToke
  3551. If _tokeType=TOKE_STRINGLIT
  3552. ' TODO
  3553. 'ImportFile ReplaceEnvTags( ParseStringLit() )
  3554. ImportFile ParseStringLit()
  3555. Else
  3556. ImportModule ParseModPath(),attrs | MODULE_ACTUALMOD
  3557. EndIf
  3558. Case "framework"
  3559. NextToke
  3560. ImportModule ParseModPath(),attrs
  3561. Case "alias"
  3562. NextToke
  3563. Repeat
  3564. Local ident$=ParseIdent()
  3565. Parse "="
  3566. Local decl:Object
  3567. Local scope:TScopeDecl=_module
  3568. _env=_module 'naughty! Shouldn't be doing GetDecl in parser...
  3569. Repeat
  3570. Local id$=ParseIdent()
  3571. decl=scope.FindDecl( id )
  3572. If Not decl Err "Identifier '"+id+"' not found."
  3573. If Not CParse( "." ) Exit
  3574. scope=TScopeDecl( decl )
  3575. If Not scope Or TFuncDecl( scope ) Err "Invalid scope '"+id+"'."
  3576. Forever
  3577. _env=Null '/naughty
  3578. _module.InsertDecl New TAliasDecl.Create( ident,decl,attrs )
  3579. Until Not CParse(",")
  3580. Case "module"
  3581. Local m:String = ParseModuleDecl(_toke, attrs)
  3582. If m.ToLower() <> opt_modulename Then
  3583. Err "Module does not match commandline module"
  3584. End If
  3585. 'sanitize, remove non-allowed chars
  3586. _module.munged = TStringHelper.Sanitize(m)
  3587. Case "nodebug"
  3588. mainFunc.attrs :| DECL_NODEBUG
  3589. attrs :| DECL_NODEBUG
  3590. NextToke
  3591. Case "moduleinfo"
  3592. NextToke
  3593. Local info:String = ParseStringLit()
  3594. _module.modInfo.AddLast(info)
  3595. Default
  3596. Exit
  3597. End Select
  3598. Wend
  3599. ' app code
  3600. PushBlock(mainFunc)
  3601. 'Parse main app
  3602. attrs = ParseCurrentFile(path, attrs)
  3603. PopBlock
  3604. End Method
  3605. Method ParseModule()
  3606. End Method
  3607. Method Create:TParser( toker:TToker,app:TAppDecl, unknownIdentsEvalFalse:Int = False )
  3608. _toke="~n"
  3609. _toker=toker
  3610. _app=app
  3611. SetErr
  3612. NextToke
  3613. Self.unknownIdentsEvalFalse = unknownIdentsEvalFalse
  3614. Return Self
  3615. End Method
  3616. End Type
  3617. Function Eval$( toker:TToker,_type:TType )
  3618. Local src$
  3619. While toker.Toke() And toker.Toke()<>"'" And toker.Toke()<>"~n" And toker.Toke()<>"~r"
  3620. src:+toker.Toke()
  3621. toker.NextToke()
  3622. Wend
  3623. Local t:String=EvalS( src,_type )
  3624. Return t
  3625. End Function
  3626. Function PreProcessNextToke$(toker:TToker)
  3627. Repeat
  3628. toker.NextToke()
  3629. Until toker.tokeType()<>TOKE_SPACE Or toker.Toke().Endswith("~n")
  3630. Return toker._toke
  3631. End Function
  3632. Function PreProcess$( path$ )
  3633. Local ifnest:Int,con:Int=1,line:Int,source:TStringList=New TStringList
  3634. Local toker:TToker=New TToker.Create( path,LoadText( path ), True )
  3635. PreProcessNextToke(toker)
  3636. Repeat
  3637. If line
  3638. source.AddLast "~n"
  3639. While toker.Toke() And Not toker.Toke().Endswith("~n") And toker.TokeType()<>TOKE_LINECOMMENT
  3640. PreProcessNextToke(toker)
  3641. Wend
  3642. If Not toker.Toke() Exit
  3643. PreProcessNextToke(toker)
  3644. EndIf
  3645. line :+ 1
  3646. ' catch up with any skipped lines
  3647. While line < toker._line - 1
  3648. line:+1
  3649. source.AddLast "~n"
  3650. Wend
  3651. If toker.TokeType()=TOKE_SPACE And Not toker.Toke().Endswith("~n") PreProcessNextToke(toker)
  3652. If toker.Toke()<>"?"
  3653. If con
  3654. Local textline$
  3655. While toker.Toke() And toker.Toke()<>"~n" And toker.TokeType()<>TOKE_LINECOMMENT
  3656. Local toke$=toker.Toke()
  3657. textline:+toke
  3658. toker.NextToke()
  3659. Wend
  3660. If textline Then
  3661. source.AddLast textline
  3662. EndIf
  3663. EndIf
  3664. Continue
  3665. EndIf
  3666. Local stm$= PreProcessNextToke(toker).ToLower()
  3667. 'toker.NextToke()
  3668. Local isNot:Int = False
  3669. If stm = "not" Then
  3670. If toker.TokeType()=TOKE_SPACE PreProcessNextToke(toker)
  3671. stm = toker.Toke().ToLower()
  3672. isNot = True
  3673. End If
  3674. 'If stm="end" Or stm="else"
  3675. ' If toker.TokeType()=TOKE_SPACE toker.NextToke()
  3676. ' If toker.Toke().ToLower()="if"
  3677. ' toker.NextToke()
  3678. ' stm:+"if"
  3679. ' EndIf
  3680. 'EndIf
  3681. Rem
  3682. Debug True if program is being compiled in debug mode.
  3683. Threaded True if program is being compiled in threaded mode.
  3684. Win32 True if program is being compiled for the Windows operating system.
  3685. MacOS True if program is being compiled for the MacOS operating system.
  3686. Linux True if program is being compiled for the Linux operating system.
  3687. X86 True if program is being compiled for the Intel CPU.
  3688. PPC True if program is being compiled for the PowerPC CPU.
  3689. MacOSX86 True if program is being compiled for an Intel Mac.
  3690. MacOSPPC True if program is being compiled for a PowerPC Mac.
  3691. BigEndian True if program is being compiled for a big endian CPU.
  3692. LittleEndian
  3693. End Rem
  3694. Select stm
  3695. Case "~r", "~n"
  3696. 'ifnest = 0
  3697. con = 1
  3698. Default
  3699. ' test for EOF
  3700. If Not toker.Toke() Exit
  3701. con = 0
  3702. Try
  3703. If Eval( toker,New TIntType ) = "1" con = 1
  3704. Catch Error:String
  3705. con = 0
  3706. End Try
  3707. Rem
  3708. Case "macos", "macosx86", "x86", "littleendian", "bigendian"
  3709. con = 1
  3710. ' If con=ifnest
  3711. ' If Eval( toker,TType.intType ) con:+1
  3712. ' EndIf
  3713. '
  3714. ifnest = 1
  3715. ' Case "rem"
  3716. '
  3717. ' ifnest:+1
  3718. Case "threaded", "win32", "linux", "ppc", "win32x86", "linuxx86", "macosppc"
  3719. If isNot Then
  3720. con = 1
  3721. Else
  3722. con = 0
  3723. End If
  3724. ifnest = 1
  3725. Case "else","elseif"
  3726. If Not ifnest Err "#Else without #If"
  3727. If con=ifnest
  3728. con=-con
  3729. Else If con=ifnest-1
  3730. If stm="elseif"
  3731. If Eval( toker,TType.intType ) con:+1
  3732. Else
  3733. con:+1
  3734. EndIf
  3735. EndIf
  3736. Case "end","endif"
  3737. If Not ifnest Err "#End without #If"
  3738. ifnest:-1
  3739. If con<0 con=-con
  3740. If ifnest<con con=ifnest
  3741. ' Case "print"
  3742. ' If con=ifnest
  3743. ' TODO
  3744. 'Print ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3745. ' EndIf
  3746. ' Case "error"
  3747. ' If con=ifnest
  3748. ' TODO
  3749. 'Err ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3750. ' EndIf
  3751. Default
  3752. Err "Unrecognized preprocessor directive '"+stm+"'."
  3753. End Rem
  3754. End Select
  3755. Forever
  3756. Return source.Join( "" )
  3757. End Function
  3758. Function ParseModule:TModuleDecl( path$,app:TAppDecl )
  3759. 'Local source$=PreProcess( path )
  3760. Local source:String = LoadText(path)
  3761. Local toker:TToker=New TToker.Create( path,source )
  3762. Local parser:TParser=New TParser.Create( toker,app )
  3763. parser.ParseMain
  3764. Return parser._module
  3765. End Function
  3766. Function AppendLibInit:String(source:String)
  3767. Local sb:TStringBuffer = TStringBuffer.Create(source)
  3768. sb.Append("~n")
  3769. sb.Append("Extern~n")
  3770. sb.Append("Function bbLibInit()~n")
  3771. sb.Append("End Extern~n")
  3772. sb.Append("Function InitBRL() Export~n")
  3773. sb.Append("bbLibInit()~n")
  3774. sb.Append("End Function~n")
  3775. Return sb.ToString()
  3776. End Function
  3777. '***** PUBLIC API ******
  3778. Function ParseApp:TAppDecl( path$ )
  3779. Local app:TAppDecl=New TAppDecl
  3780. _appInstance = app
  3781. Local source$=PreProcess( path )
  3782. 'Local source:String = LoadString(path)
  3783. If opt_makelib And opt_apptype Then
  3784. source = AppendLibInit(source)
  3785. End If
  3786. Local toker:TToker=New TToker.Create( path,source )
  3787. Local parser:TParser=New TParser.Create( toker,app )
  3788. parser.ParseMain
  3789. Return app
  3790. End Function
  3791. Function MungModuleName:String(ident:Object)
  3792. Local mung:String
  3793. If String(ident) Then
  3794. Local id:String = String(ident)
  3795. mung = "__bb_" + id + "_" + id[id.Find(".") + 1..]
  3796. Else
  3797. Local mdecl:TModuleDecl = TModuleDecl(ident)
  3798. If mdecl Then
  3799. Local id:String = mdecl.ident
  3800. Local dir:String = ExtractDir(mdecl.filepath).ToLower()
  3801. dir = dir[dir.findLast("/") + 1..]
  3802. If dir.EndsWith(".mod") Then
  3803. dir = ""
  3804. Else
  3805. dir :+ "_"
  3806. End If
  3807. mung = "__bb_" + id + "_" + dir + id[id.Find(".") + 1..]
  3808. End If
  3809. End If
  3810. 'return sanitized, remove non-allowed chars
  3811. Return TStringHelper.Sanitize(mung)
  3812. End Function
  3813. Function EvalS$( source$,ty:TType )
  3814. Local env:TScopeDecl=New TScopeDecl
  3815. ' debug/release
  3816. env.InsertDecl New TConstDecl.Create( "debug",New TIntType,New TConstExpr.Create( New TIntType,opt_debug ),0 )
  3817. env.InsertDecl New TConstDecl.Create( "gdbdebug",New TIntType,New TConstExpr.Create( New TIntType,opt_gdbdebug ),0 )
  3818. ' threaded
  3819. env.InsertDecl New TConstDecl.Create( "threaded",New TIntType,New TConstExpr.Create( New TIntType,opt_threaded ),0 )
  3820. ' macos
  3821. env.InsertDecl New TConstDecl.Create( "macos",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="macos" Or opt_platform="osx" Or opt_platform="ios"),0 )
  3822. env.InsertDecl New TConstDecl.Create( "macosx86",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx" Or opt_platform="ios") And opt_arch="x86"),0 )
  3823. env.InsertDecl New TConstDecl.Create( "macosppc",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="ppc"),0 )
  3824. env.InsertDecl New TConstDecl.Create( "macosx64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx" Or opt_platform="ios") And opt_arch="x64"),0 )
  3825. env.InsertDecl New TConstDecl.Create( "macosarm64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx" Or opt_platform="ios") And opt_arch="arm64"),0 )
  3826. ' osx
  3827. env.InsertDecl New TConstDecl.Create( "osx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="macos" Or opt_platform="osx" ),0 )
  3828. env.InsertDecl New TConstDecl.Create( "osxx86",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="x86"),0 )
  3829. env.InsertDecl New TConstDecl.Create( "osxppc",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="ppc"),0 )
  3830. env.InsertDecl New TConstDecl.Create( "osxx64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="x64"),0 )
  3831. env.InsertDecl New TConstDecl.Create( "osxarm64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="macos" Or opt_platform="osx") And opt_arch="arm64"),0 )
  3832. ' ios
  3833. env.InsertDecl New TConstDecl.Create( "ios",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" ),0 )
  3834. env.InsertDecl New TConstDecl.Create( "iosx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x86"),0 )
  3835. env.InsertDecl New TConstDecl.Create( "iosx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x64"),0 )
  3836. env.InsertDecl New TConstDecl.Create( "iosarmv7",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="armv7"),0 )
  3837. env.InsertDecl New TConstDecl.Create( "iosarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="arm64"),0 )
  3838. ' windows
  3839. env.InsertDecl New TConstDecl.Create( "win32",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" ),0 )
  3840. env.InsertDecl New TConstDecl.Create( "win32x86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="x86"),0 )
  3841. env.InsertDecl New TConstDecl.Create( "win32x64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="win64" And opt_arch="x64") Or (opt_platform="win32" And opt_arch="x64")),0 )
  3842. env.InsertDecl New TConstDecl.Create( "win64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="win64" And opt_arch="x64") Or (opt_platform="win32" And opt_arch="x64") Or (opt_platform="win32" And opt_arch="arm64")),0 )
  3843. env.InsertDecl New TConstDecl.Create( "win32armv7",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="armv7"),0 )
  3844. env.InsertDecl New TConstDecl.Create( "win32arm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="arm64"),0 )
  3845. ' linux
  3846. env.InsertDecl New TConstDecl.Create( "linux",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="linux" Or opt_platform="android" Or opt_platform="raspberrypi")),0 )
  3847. env.InsertDecl New TConstDecl.Create( "linuxx86",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="linux" Or opt_platform="android") And opt_arch="x86"),0 )
  3848. env.InsertDecl New TConstDecl.Create( "linuxx64",New TIntType,New TConstExpr.Create( New TIntType,(opt_platform="linux" Or opt_platform="android") And opt_arch="x64"),0 )
  3849. env.InsertDecl New TConstDecl.Create( "linuxarm",New TIntType,New TConstExpr.Create( New TIntType, ((opt_platform="android" Or opt_platform="linux") And (opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" Or opt_arch="arm64v8a")) Or (opt_platform="raspberrypi" And opt_arch="arm")),0 )
  3850. env.InsertDecl New TConstDecl.Create( "linuxarm64",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="android" And opt_arch="arm64v8a") Or ((opt_platform="linux" Or opt_platform="raspberrypi") And opt_arch="arm64")),0 )
  3851. env.InsertDecl New TConstDecl.Create( "linuxriscv32",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="linux" And opt_arch="riscv32")),0 )
  3852. env.InsertDecl New TConstDecl.Create( "linuxriscv64",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="linux" And opt_arch="riscv64")),0 )
  3853. ' android
  3854. env.InsertDecl New TConstDecl.Create( "android",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" ),0 )
  3855. env.InsertDecl New TConstDecl.Create( "androidx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x86"),0 )
  3856. env.InsertDecl New TConstDecl.Create( "androidx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x64"),0 )
  3857. env.InsertDecl New TConstDecl.Create( "androidarm",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And (opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" Or opt_arch="arm64v8a") ),0 )
  3858. env.InsertDecl New TConstDecl.Create( "androidarmeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabi"),0 )
  3859. env.InsertDecl New TConstDecl.Create( "androidarmeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabiv7a"),0 )
  3860. env.InsertDecl New TConstDecl.Create( "androidarm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="arm64v8a"),0 )
  3861. ' raspberrypi - ARM only
  3862. env.InsertDecl New TConstDecl.Create( "raspberrypi",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And (opt_arch="arm" Or opt_arch="arm64")),0 )
  3863. env.InsertDecl New TConstDecl.Create( "raspberrypiarm",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm"),0 )
  3864. env.InsertDecl New TConstDecl.Create( "raspberrypiarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm64"),0 )
  3865. ' haiku
  3866. env.InsertDecl New TConstDecl.Create( "haiku",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="haiku" And (opt_arch="x86" Or opt_arch="x64")),0 )
  3867. env.InsertDecl New TConstDecl.Create( "haikux86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="haiku" And opt_arch="x86"),0 )
  3868. env.InsertDecl New TConstDecl.Create( "haikux64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="haiku" And opt_arch="x64"),0 )
  3869. ' emscripten
  3870. env.InsertDecl New TConstDecl.Create( "emscripten",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" ),0 )
  3871. env.InsertDecl New TConstDecl.Create( "emscriptenjs",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" And opt_arch="js"),0 )
  3872. ' arch
  3873. env.InsertDecl New TConstDecl.Create( "ppc",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3874. env.InsertDecl New TConstDecl.Create( "x86",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x86" ),0 )
  3875. env.InsertDecl New TConstDecl.Create( "x64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x64" ),0 )
  3876. env.InsertDecl New TConstDecl.Create( "arm",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" Or opt_arch="arm64v8a" ),0 )
  3877. env.InsertDecl New TConstDecl.Create( "armeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabi" ),0 )
  3878. env.InsertDecl New TConstDecl.Create( "armeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabiv7a" ),0 )
  3879. env.InsertDecl New TConstDecl.Create( "arm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64v8a" ),0 )
  3880. env.InsertDecl New TConstDecl.Create( "js",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="js" ),0 )
  3881. env.InsertDecl New TConstDecl.Create( "armv7",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armv7" ),0 )
  3882. env.InsertDecl New TConstDecl.Create( "arm64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64" ),0 )
  3883. env.InsertDecl New TConstDecl.Create( "riscv32",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="riscv32" ),0 )
  3884. env.InsertDecl New TConstDecl.Create( "riscv64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="riscv64" ),0 )
  3885. env.InsertDecl New TConstDecl.Create( "ptr32",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x86" Or opt_arch="ppc" Or opt_arch="armv7" Or opt_arch="arm" Or opt_arch="armeabi" Or opt_arch="armeabiv7a" Or opt_arch="riscv32" ),0 )
  3886. env.InsertDecl New TConstDecl.Create( "ptr64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x64" Or opt_arch="arm64" Or opt_arch="arm64v8a" Or opt_arch="riscv64" ),0 )
  3887. ' endian
  3888. env.InsertDecl New TConstDecl.Create( "bigendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3889. env.InsertDecl New TConstDecl.Create( "littleendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch<>"ppc" ),0 )
  3890. ' opengles target platform
  3891. env.InsertDecl New TConstDecl.Create( "opengles",New TIntType,New TConstExpr.Create( New TIntType, opt_platform="android" Or opt_platform="raspberrypi" Or opt_platform="emscripten" Or opt_platform="ios"),0 )
  3892. ' musl - linux only
  3893. env.InsertDecl New TConstDecl.Create( "musl",New TIntType,New TConstExpr.Create( New TIntType,(opt_musl And (opt_platform="linux" Or opt_platform="android" Or opt_platform="raspberrypi"))),0 )
  3894. ' nx / switch
  3895. env.InsertDecl New TConstDecl.Create( "nx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" ),0 )
  3896. env.InsertDecl New TConstDecl.Create( "nxarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" And opt_arch="arm64"),0 )
  3897. ' new compiler
  3898. env.InsertDecl New TConstDecl.Create( "bmxng",New TIntType,New TConstExpr.Create( New TIntType, True ),0 )
  3899. ' coverage
  3900. env.InsertDecl New TConstDecl.Create( "coverage",New TIntType,New TConstExpr.Create( New TIntType, opt_coverage ),0 )
  3901. ' console or gui build?
  3902. env.InsertDecl New TConstDecl.Create( "console",New TIntType,New TConstExpr.Create( New TIntType, opt_apptype = APPTYPE_CONSOLE ),0 )
  3903. env.InsertDecl New TConstDecl.Create( "gui",New TIntType,New TConstExpr.Create( New TIntType, opt_apptype = APPTYPE_GUI ),0 )
  3904. ' user defines
  3905. If opt_userdefs Then
  3906. Local defs:String[] = opt_userdefs.ToLower().Split(",")
  3907. For Local def:String = EachIn defs
  3908. def = def.Trim()
  3909. If def Then
  3910. Local name:String = def
  3911. Local value:Int = 1
  3912. Local dp:String[] = def.Split("=")
  3913. If dp.length = 2 Then
  3914. name = dp[0].Trim()
  3915. value = Int(dp[1])
  3916. End If
  3917. env.InsertDecl New TConstDecl.Create( name,New TIntType,New TConstExpr.Create( New TIntType, value ),0 )
  3918. End If
  3919. Next
  3920. End If
  3921. PushEnv env
  3922. Local toker:TToker=New TToker.Create( "",source )
  3923. Local parser:TParser=New TParser.Create( toker,Null,True )
  3924. Local val:String
  3925. Try
  3926. Local expr:TExpr=parser.ParseExpr()
  3927. expr=expr.Semant()
  3928. If ty expr=expr.Cast( ty )
  3929. val=expr.Eval()
  3930. Catch error:String
  3931. val = "0"
  3932. End Try
  3933. PopEnv
  3934. Return val
  3935. End Function
  3936. Type TCastDets
  3937. Field name:String
  3938. Field retType:String
  3939. Field noGen:Int
  3940. Field args:String[0]
  3941. Field api:String
  3942. End Type