parser.bmx 127 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804
  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. ' for negative direction we need to invert the operator
  1769. If TUnaryExpr(stp) And TUnaryExpr(stp).op = "-" Then
  1770. If op="<=" Then
  1771. op=">="
  1772. Else
  1773. op=">"
  1774. End If
  1775. End If
  1776. Local init:TStmt,expr:TExpr,incr:TStmt
  1777. If varlocal
  1778. Local indexVar:TLocalDecl=New TLocalDecl.Create( varid,varty,New TCastExpr.Create( varty,from,CAST_EXPLICIT ),0 )
  1779. init=New TDeclStmt.Create( indexVar )
  1780. ' expr=New TBinaryCompareExpr.Create( op,New TVarExpr.Create( indexVar ),New TCastExpr.Create( varty,term,1 ) )
  1781. ' incr=New TAssignStmt.Create( "=",New TVarExpr.Create( indexVar ),New TBinaryMathExpr.Create( "+",New TVarExpr.Create( indexVar ),New TCastExpr.Create( varty,stp,1 ) ) )
  1782. expr=New TBinaryCompareExpr.Create( op, varExpr,New TCastExpr.Create( varty,term,CAST_EXPLICIT ) )
  1783. If TUnaryExpr(stp) And TUnaryExpr(stp).op = "-" Then
  1784. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "-",varExpr,New TCastExpr.Create( varty,TUnaryExpr(stp).expr,CAST_EXPLICIT ) ) )
  1785. Else
  1786. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "+",varExpr,New TCastExpr.Create( varty,stp,CAST_EXPLICIT ) ) )
  1787. End If
  1788. Else
  1789. ' varty is NULL here for the casts. We will back-populate it later.
  1790. ' init=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),from )
  1791. ' expr=New TBinaryCompareExpr.Create( op,New TIdentExpr.Create( varid ),New TCastExpr.Create( varty,term,1 ) )
  1792. ' incr=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TBinaryMathExpr.Create( "+",New TIdentExpr.Create( varid ),New TCastExpr.Create( varty,stp,1 ) ) )
  1793. init=New TAssignStmt.Create( "=",varExpr,from )
  1794. expr=New TBinaryCompareExpr.Create( op,varExpr,New TCastExpr.Create( varty,term,CAST_EXPLICIT ) )
  1795. If TUnaryExpr(stp) And TUnaryExpr(stp).op = "-" Then
  1796. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "-",varExpr,New TCastExpr.Create( varty,TUnaryExpr(stp).expr,CAST_EXPLICIT ) ) )
  1797. Else
  1798. incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "+",varExpr,New TCastExpr.Create( varty,stp,CAST_EXPLICIT ) ) )
  1799. End If
  1800. EndIf
  1801. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
  1802. PushBlock block
  1803. While Not CParse( "next" )
  1804. ParseStmt
  1805. Wend
  1806. PopBlock
  1807. NextToke
  1808. Local stmt:TForStmt=New TForStmt.Create( init,expr,incr,block,loopLabel )
  1809. _block.AddStmt stmt
  1810. End Method
  1811. Method ParseDefDataStmt(label:TLoopLabelDecl = Null)
  1812. Parse "defdata"
  1813. If AtEos() Then
  1814. Err "Expecting expression but encountered " + DescribeToke(_toke)
  1815. End If
  1816. Local args:TExpr[]
  1817. Local nargs:Int
  1818. Repeat
  1819. Local arg:TExpr
  1820. If _toke And _toke<>"," arg=ParseExpr()
  1821. If args.Length=nargs args=args + New TExpr[10]
  1822. args[nargs]=arg
  1823. nargs:+1
  1824. Until Not CParse(",")
  1825. args=args[..nargs]
  1826. Local dataLabel:TDataLabelDecl
  1827. If label Then
  1828. dataLabel = New TDataLabelDecl.Create(label.ident, label.attrs)
  1829. End If
  1830. Local decl:TDefDataDecl = New TDefDataDecl.Create(args, dataLabel)
  1831. _app.dataDefs.AddLast(decl)
  1832. End Method
  1833. Method ParseReadDataStmt()
  1834. Parse "readdata"
  1835. Local args:TExpr[]
  1836. Local nargs:Int
  1837. If Not AtEos() Then
  1838. Repeat
  1839. Local arg:TExpr
  1840. If _toke And _toke<>"," arg=ParseExpr()
  1841. If args.Length=nargs args=args + New TExpr[10]
  1842. args[nargs]=arg
  1843. nargs:+1
  1844. Until Not CParse(",")
  1845. args=args[..nargs]
  1846. End If
  1847. _block.AddStmt New TReadDataStmt.Create( args )
  1848. End Method
  1849. Method ParseRestoreDataStmt()
  1850. Parse "restoredata"
  1851. Local expr:TExpr = ParseExpr()
  1852. _block.AddStmt New TRestoreDataStmt.Create( expr )
  1853. End Method
  1854. Method ParseReturnStmt()
  1855. Parse "return"
  1856. Local expr:TExpr
  1857. If Not AtEos() expr=ParseExpr()
  1858. _block.AddStmt New TReturnStmt.Create( expr )
  1859. End Method
  1860. Method ParseExitStmt()
  1861. Parse "exit"
  1862. Local expr:TExpr
  1863. If Not AtEos() expr=ParseExpr()
  1864. _block.AddStmt New TBreakStmt.Create(expr)
  1865. End Method
  1866. Method ParseContinueStmt()
  1867. Parse "continue"
  1868. Local expr:TExpr
  1869. If Not AtEos() expr=ParseExpr()
  1870. _block.AddStmt New TContinueStmt.Create(expr)
  1871. End Method
  1872. Method ParseTryStmt()
  1873. Parse "try"
  1874. Local tryStmtDecl:TTryStmtDecl = TTryStmtDecl(New TTryStmtDecl.Create( _block ))
  1875. PushBlock tryStmtDecl
  1876. Local block:TBlockDecl=New TBlockDecl.Create( tryStmtDecl, , BLOCK_TRY )
  1877. Local catches:TList=New TList
  1878. Local finallyStmt:TFinallyStmt = Null
  1879. PushBlock block
  1880. While _toke<>"end" And _toke<>"endtry"
  1881. If CParse( "catch" )
  1882. If finallyStmt Then Err "'Catch' can not appear after 'Finally'."
  1883. Local id:String=ParseIdent()
  1884. Local ty:TType
  1885. If Not CParse(":") Then
  1886. Parse "$"
  1887. ty= TType.stringType
  1888. Else
  1889. ty=ParseType()
  1890. While IsArrayDef()
  1891. ty=ParseArrayType(ty)
  1892. Wend
  1893. End If
  1894. PopBlock
  1895. Local init:TLocalDecl=New TLocalDecl.Create( id,ty,Null,0 )
  1896. Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_CATCH )
  1897. catches.AddLast(New TCatchStmt.Create( init,block ))
  1898. PushBlock block
  1899. Else If CParse("finally") Then
  1900. If finallyStmt Then Err "Try statement cannot have more than one Finally block."
  1901. PopBlock
  1902. Local block:TBlockDecl = New TBlockDecl.Create(_block, , BLOCK_FINALLY)
  1903. finallyStmt = New TFinallyStmt.Create(block)
  1904. PushBlock block
  1905. Else
  1906. ParseStmt
  1907. If _toke = "end" Then
  1908. NextToke
  1909. If _toke = "try" Then
  1910. ' we are done with the try statement
  1911. Exit
  1912. Else
  1913. ParseEndStmt(False)
  1914. End If
  1915. End If
  1916. End If
  1917. Wend
  1918. If catches.Count() = 0 And Not finallyStmt Then Err "Expecting 'Catch' or 'Finally'."
  1919. PopBlock ' try block
  1920. If Not CParse("endtry") Then
  1921. NextToke
  1922. CParse "try"
  1923. End If
  1924. PopBlock ' tryStmtDecl
  1925. Local tryStmt:TTryStmt = New TTryStmt.Create(block,TCatchStmt[](catches.ToArray()), finallyStmt)
  1926. tryStmtDecl.tryStmt = tryStmt
  1927. _block.AddStmt tryStmt
  1928. End Method
  1929. Method ParseThrowStmt()
  1930. Parse "throw"
  1931. Local expr:TExpr = ParseExpr()
  1932. _block.AddStmt New TThrowStmt.Create( expr )
  1933. End Method
  1934. Method ParseReleaseStmt()
  1935. Parse "release"
  1936. Local expr:TExpr = ParseExpr()
  1937. _block.AddStmt New TReleaseStmt.Create( expr )
  1938. End Method
  1939. Method ParseAssertStmt()
  1940. Parse "assert"
  1941. Local expr:TExpr = ParseExpr()
  1942. Local elseExpr:TExpr
  1943. If _toke = "," Or _toke = "else" Then
  1944. NextToke
  1945. elseExpr = ParseExpr()
  1946. End If
  1947. _block.AddStmt New TAssertStmt.Create( expr, elseExpr )
  1948. End Method
  1949. Method ParseEndStmt(eatEnd:Int = True)
  1950. If eatEnd Then
  1951. Parse "end"
  1952. End If
  1953. _block.AddStmt New TEndStmt.Create( )
  1954. End Method
  1955. Method ParseSelectStmt()
  1956. Parse "select"
  1957. Local block:TBlockDecl=_block
  1958. Local tmpVar:TLocalDecl
  1959. Local selectExpr:TExpr = ParseExpr()
  1960. If Not TNullType(selectExpr.exprType)
  1961. tmpVar = New TLocalDecl.Create("", Null, selectExpr, DECL_NO_VAR, True)
  1962. block.AddStmt New TDeclStmt.Create(tmpVar)
  1963. End If
  1964. While _toke<>"end" And _toke<>"default" And _toke<>"endselect"
  1965. SetErr
  1966. Select _toke
  1967. Case "~n"
  1968. NextToke
  1969. Case "case"
  1970. NextToke
  1971. Local comp:TExpr
  1972. Repeat
  1973. Local expr:TExpr
  1974. If TNullType(selectExpr.exprType)
  1975. expr = New TNullExpr.Create(TType.nullObjectType)
  1976. Else
  1977. expr = New TVarExpr.Create(tmpVar)
  1978. End If
  1979. expr=New TBinaryCompareExpr.Create( "=",expr,ParseExpr() )
  1980. If comp
  1981. comp=New TBinaryLogicExpr.Create( "or",comp,expr )
  1982. Else
  1983. comp=expr
  1984. EndIf
  1985. Until Not CParse(",")
  1986. Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_IF )
  1987. Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_ELSE )
  1988. Local ifstmt:TIfStmt=New TIfStmt.Create( comp,thenBlock,elseBlock )
  1989. block.AddStmt ifstmt
  1990. block=ifstmt.thenBlock
  1991. PushBlock block
  1992. Local fin:Int = False
  1993. While _toke<>"case" And _toke<>"default" And _toke<>"end" And _toke<>"endselect"
  1994. ParseStmt
  1995. If _toke = "end" Then
  1996. NextToke
  1997. If _toke = "select" Then
  1998. ' we are done with the select statement, full exit
  1999. fin = True
  2000. Exit
  2001. Else
  2002. ParseEndStmt(False)
  2003. End If
  2004. End If
  2005. Wend
  2006. PopBlock
  2007. block=elseBlock
  2008. If fin Exit
  2009. Default
  2010. Err "Syntax error - expecting 'Case', 'Default' or 'End'."
  2011. End Select
  2012. Wend
  2013. If _toke="default"
  2014. NextToke
  2015. PushBlock block
  2016. While _toke<>"end" And _toke<>"endselect"
  2017. SetErr
  2018. Select _toke
  2019. Case "case"
  2020. Err "Case can not appear after Default."
  2021. Case "default"
  2022. Err "Select statement can have only one Default block."
  2023. End Select
  2024. ParseStmt
  2025. If _toke = "end" Then
  2026. NextToke
  2027. If _toke = "select" Then
  2028. Exit
  2029. Else
  2030. ParseEndStmt(False)
  2031. End If
  2032. End If
  2033. Wend
  2034. PopBlock
  2035. EndIf
  2036. SetErr
  2037. If Not CParse("endselect") Then
  2038. If Not CParse("select")
  2039. Parse "end"
  2040. Parse "select"
  2041. End If
  2042. End If
  2043. End Method
  2044. Method ParseExternBlock(mdecl:TModuleDecl, attrs:Long)
  2045. NextToke
  2046. attrs :| ParseCallConvention()
  2047. attrs = attrs | DECL_EXTERN
  2048. If CParse( "private" ) attrs=attrs|DECL_PRIVATE
  2049. While _toke<>"endextern"
  2050. If CParse( "end" )
  2051. Parse "extern"
  2052. Exit
  2053. EndIf
  2054. SetErr
  2055. Select _toke
  2056. Case "~n"
  2057. NextToke
  2058. Case "const"
  2059. mdecl.InsertDecls ParseDecls( _toke,attrs )
  2060. Case "global"
  2061. ParseDeclStmts(True, attrs, mdecl)
  2062. Case "threadedglobal"
  2063. ParseDeclStmts(True, attrs | DECL_THREADED, mdecl)
  2064. Case "struct"
  2065. mdecl.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
  2066. Case "type"
  2067. mdecl.InsertDecl ParseClassDecl( _toke,attrs )
  2068. Case "function"
  2069. mdecl.InsertDecl ParseFuncDecl( _toke,attrs )
  2070. Case "interface"
  2071. mdecl.InsertDecl ParseClassDecl( _toke,attrs | CLASS_INTERFACE )
  2072. Default
  2073. If _toke <> "end" And _toke <> "endextern" Then
  2074. Err "Expecting expression but encountered '"+_toke+"'"
  2075. End If
  2076. End Select
  2077. Wend
  2078. If _toke="endextern" Then
  2079. NextToke
  2080. End If
  2081. End Method
  2082. Method ParseStmt()
  2083. SetErr
  2084. Select _toke
  2085. Case ";","~n"
  2086. NextToke
  2087. Case "const","local","global","threadedglobal"
  2088. ParseDeclStmts
  2089. ' nested function - needs to get added to the "module"
  2090. Case "function"
  2091. _block.InsertDecl ParseFuncDecl( _toke,FUNC_NESTED)
  2092. Case "type"
  2093. _block.InsertDecl ParseClassDecl( _toke,DECL_NESTED)
  2094. Case "return"
  2095. ParseReturnStmt()
  2096. Case "exit"
  2097. ParseExitStmt()
  2098. Case "continue"
  2099. ParseContinueStmt()
  2100. Case "if"
  2101. ParseIfStmt( "" )
  2102. Case "while"
  2103. ParseWhileStmt()
  2104. Case "repeat"
  2105. ParseRepeatStmt()
  2106. Case "for"
  2107. ParseForStmt()
  2108. Case "select"
  2109. ParseSelectStmt()
  2110. Case "assert"
  2111. ParseAssertStmt()
  2112. Case "try"
  2113. ParseTryStmt()
  2114. Case "throw"
  2115. ParseThrowStmt()
  2116. Case "end"
  2117. ParseEndStmt()
  2118. Case "extern"
  2119. ParseExternBlock(_module, 0)
  2120. Case "#"
  2121. Local decl:TLoopLabelDecl = ParseLoopLabelDecl()
  2122. NextToke
  2123. While _toke
  2124. SetErr
  2125. Select _toke.ToLower()
  2126. Case "~n"
  2127. NextToke
  2128. Case "while"
  2129. ParseWhileStmt(decl)
  2130. Exit
  2131. Case "repeat"
  2132. ParseRepeatStmt(decl)
  2133. Exit
  2134. Case "for"
  2135. ParseForStmt(decl)
  2136. Exit
  2137. Case "defdata"
  2138. ParseDefDataStmt(decl)
  2139. Exit
  2140. Default
  2141. Err "Labels must appear before a loop or DefData statement"
  2142. End Select
  2143. Wend
  2144. Case "release"
  2145. ParseReleaseStmt()
  2146. Case "defdata"
  2147. ParseDefDataStmt()
  2148. Case "readdata"
  2149. ParseReadDataStmt()
  2150. Case "restoredata"
  2151. ParseRestoreDataStmt()
  2152. Default
  2153. If _toke.StartsWith("'!") Then
  2154. If _tokeType = TOKE_NATIVE Then
  2155. ParseNativeStmt()
  2156. End If
  2157. Else
  2158. Local expr:TExpr=ParsePrimaryExpr( True )
  2159. Select _toke.ToLower()
  2160. '"=","*=","/=","+=","-=","&=","|=","~~=","Mod","Shl","Shr"
  2161. Case "=",":*",":/",":+",":-",":&",":|",":~~","mod","shl","shr", ":shl", ":shr", "sar", ":sar", ":mod"
  2162. ' remap symbols...
  2163. 'For Local i:Int = 0 Until TToker._symbols.length
  2164. ' Local sym$= TToker._symbols[i]
  2165. ' If _toke.ToLower() = sym
  2166. ' _toke = TToker._symbols_map[i]
  2167. ' Exit
  2168. ' EndIf
  2169. 'Next
  2170. If TIdentExpr( expr ) Or TIndexExpr( expr )
  2171. Local op$=_toke.ToLower()
  2172. NextToke
  2173. ' If Not op.EndsWith( "=" ) And Not op.StartsWith("=")
  2174. ' Parse "="
  2175. ' op:+"="
  2176. ' EndIf
  2177. _block.AddStmt New TAssignStmt.Create( op,expr,ParseExpr() )
  2178. Else
  2179. Err "Assignment operator '"+_toke+"' cannot be used this way."
  2180. EndIf
  2181. Return
  2182. End Select
  2183. If TIdentExpr( expr )
  2184. expr=New TFuncCallExpr.Create( expr,ParseArgs( True ) )
  2185. Else If TFuncCallExpr( expr) Or TInvokeSuperExpr( expr ) Or TNewObjectExpr( expr ) Or TNewExpr(expr)
  2186. Else If TIndexExpr(expr)
  2187. expr = New TFuncCallExpr.Create( expr, ParseArgs( True ) )
  2188. Else
  2189. Err "Expression cannot be used as a statement."
  2190. EndIf
  2191. _block.AddStmt New TExprStmt.Create( expr )
  2192. End If
  2193. End Select
  2194. End Method
  2195. Method ParseDecl:TDecl( toke$,attrs:Long )
  2196. SetErr
  2197. If CParse("staticarray") Then
  2198. If toke = "const" Then
  2199. Err "Const cannot be used in this way"
  2200. End If
  2201. If attrs & DECL_STATIC Then
  2202. Err "Already declared as a static array"
  2203. End If
  2204. attrs :| DECL_STATIC
  2205. End If
  2206. Local id$=ParseIdent()
  2207. Local ty:TType
  2208. Local init:TExpr
  2209. If attrs & DECL_EXTERN
  2210. ty=ParseDeclType(attrs & (DECL_STATIC | DECL_API_STDCALL))
  2211. If toke = "const" Then
  2212. If CParse("=") Then
  2213. init=ParseExpr()
  2214. End If
  2215. End If
  2216. ' Else If CParse( ":=" )
  2217. ' init=ParseExpr()
  2218. ' ty = init.exprType
  2219. Else
  2220. ty=ParseDeclType(attrs & (DECL_STATIC | DECL_API_STDCALL))
  2221. If CParse( "=" )
  2222. If (attrs & DECL_STATIC) Then
  2223. Err "Static arrays cannot be initialized in this way"
  2224. End If
  2225. init=ParseExpr()
  2226. Else If CParse( "[" ) ' an initialised array?
  2227. If (attrs & DECL_STATIC) Then
  2228. init = ParseExpr()
  2229. Parse "]"
  2230. ty=New TArrayType.Create( ty,1,, attrs & DECL_STATIC > 0 )
  2231. Else
  2232. Local ln:TExpr[]
  2233. Repeat
  2234. If CParse(",") Then
  2235. ln = ln + [New TNullExpr]
  2236. Continue
  2237. End If
  2238. If CParse("]") Exit
  2239. ln = ln + [ParseExpr()]
  2240. If CParse("]") Exit
  2241. Parse(",")
  2242. Forever
  2243. 'Parse "]"
  2244. ty = ParseArrayType(ty)
  2245. 'While CParse( "[]" )
  2246. ' ty=New TArrayType.Create(ty)
  2247. 'Wend
  2248. init=New TNewArrayExpr.Create( ty,ln)
  2249. ty=New TArrayType.Create( ty, ln.length,, attrs & DECL_STATIC > 0 )
  2250. End If
  2251. Else If toke <> "const"
  2252. If toke="global" Or toke="local" Or toke="threadedglobal" Then
  2253. init=New TConstExpr.Create( ty,"" )
  2254. End If
  2255. Else
  2256. Err "Constants must be initialized."
  2257. EndIf
  2258. EndIf
  2259. Local decl:TValDecl
  2260. Select toke
  2261. Case "global"
  2262. decl=New TGlobalDecl.Create( id,ty,init,attrs )
  2263. Case "threadedglobal"
  2264. decl=New TGlobalDecl.Create( id,ty,init,attrs | DECL_THREADED )
  2265. Case "field"
  2266. decl=New TFieldDecl.Create( id,ty,init,attrs )
  2267. If TFunctionPtrType(ty) Then
  2268. TFunctionPtrType(ty).func.attrs :| FUNC_FIELD
  2269. End If
  2270. Case "const" decl=New TConstDecl.Create( id,ty,init,attrs )
  2271. Case "local" decl=New TLocalDecl.Create( id,ty,init,attrs )
  2272. End Select
  2273. If decl.IsExtern()
  2274. Local cdets:TCastDets
  2275. If CParse( "=" )
  2276. Local munged:String = ParseStringLit()
  2277. If munged.Find("(") > 0 Then
  2278. cdets = ParseExternCast(munged, True)
  2279. If cdets Then
  2280. decl.munged = cdets.name
  2281. End If
  2282. Else
  2283. decl.munged = munged
  2284. End If
  2285. Else
  2286. decl.munged=decl.ident
  2287. EndIf
  2288. If TFunctionPtrType(ty) Then
  2289. TFunctionPtrType(ty).func.munged = decl.munged
  2290. If Not cdets Then
  2291. cdets = TCastDets(_externCasts.ValueForKey(TFunctionPtrType(ty).func.munged))
  2292. End If
  2293. If cdets Then
  2294. TFunctionPtrType(ty).func.castTo = cdets.retType
  2295. If cdets.noGen Then
  2296. TFunctionPtrType(ty).func.noCastGen = True
  2297. End If
  2298. For Local i:Int = 0 Until cdets.args.length
  2299. If i < TFunctionPtrType(ty).func.argDecls.length Then
  2300. TFunctionPtrType(ty).func.argDecls[i].castTo = cdets.args[i]
  2301. End If
  2302. Next
  2303. End If
  2304. End If
  2305. EndIf
  2306. ' apply any function ptr metadata to decl
  2307. If TFunctionPtrType(ty) Then
  2308. If TFunctionPtrType(ty).func And TFunctionPtrType(ty).func.metadata Then
  2309. decl.metadata = TFunctionPtrType(ty).func.metadata
  2310. End If
  2311. End If
  2312. 'meta data for variables
  2313. Local meta:TMetaData = ParseMetaData()
  2314. If meta Then
  2315. decl.metadata = meta
  2316. End If
  2317. Return decl
  2318. End Method
  2319. Method ParseDecls:TList( toke$,attrs:Long, isField:Int = False )
  2320. If toke Parse toke
  2321. If isField Then
  2322. Repeat
  2323. If CParse("readonly") Then
  2324. If attrs & DECL_READ_ONLY
  2325. Err "Duplicate modifier 'ReadOnly'."
  2326. End If
  2327. attrs :| DECL_READ_ONLY
  2328. Else If CParse("staticarray") Then
  2329. If attrs & DECL_STATIC
  2330. Err "Duplicate modifier 'Static'."
  2331. End If
  2332. attrs :| DECL_STATIC
  2333. Else
  2334. Exit
  2335. End If
  2336. Forever
  2337. End If
  2338. Local decls:TList=New TList'<Decl>
  2339. Repeat
  2340. Local decl:TDecl=ParseDecl( toke,attrs )
  2341. decls.AddLast decl
  2342. If Not CParse(",") Return decls
  2343. Forever
  2344. End Method
  2345. Method ParseDeclStmts(initOnly:Int = False, attrs:Long = 0, mdecl:TModuleDecl = Null)
  2346. Local toke$=_toke
  2347. NextToke
  2348. Repeat
  2349. Local decl:TDecl=ParseDecl( toke,attrs )
  2350. If Not (attrs & DECL_EXTERN) Then
  2351. _block.AddStmt New TDeclStmt.Create( decl )
  2352. End If
  2353. ' reset the decl scope, adding decl to the block decl list.
  2354. ' this improves scope visibilty - for decls such as embedded functions
  2355. If TConstDecl(decl) Or TGlobalDecl(decl) Then
  2356. If mdecl Then
  2357. mdecl.InsertDecl decl
  2358. End If
  2359. If Not (attrs & DECL_EXTERN) Then
  2360. decl.scope = Null
  2361. _block.InsertDecl(decl)
  2362. End If
  2363. If TGlobalDecl(decl) Then
  2364. If initOnly Then
  2365. decl.attrs :| DECL_INITONLY
  2366. TGlobalDecl(decl).mscope = _module
  2367. Else
  2368. TGlobalDecl(decl).funcGlobal = True
  2369. End If
  2370. End If
  2371. End If
  2372. Until Not CParse(",")
  2373. End Method
  2374. Method ParseLoopLabelDecl:TLoopLabelDecl()
  2375. NextToke
  2376. Local id:String = ParseIdent()
  2377. Return New TLoopLabelDecl.Create(id, 0)
  2378. End Method
  2379. 'handle end-of-line "dot dot return"-line connector
  2380. '-> skips EOL tokens
  2381. Method HandleDotsLineConnector(eatToke:Int = False)
  2382. Local tok:TToker = New TToker.Copy(_toker)
  2383. Local t:String = tok.NextToke()
  2384. Local count:Int = tok.SkipSpace()
  2385. For Local i:Int = 0 Until count
  2386. NextToke
  2387. Next
  2388. t = tok._toke
  2389. If t = "~r" Then
  2390. t = tok.NextToke()
  2391. If t = "~n" Then
  2392. NextToke
  2393. NextToke
  2394. Else
  2395. NextToke
  2396. End If
  2397. Else
  2398. If t = "~n" Then
  2399. NextToke
  2400. End If
  2401. End If
  2402. If eatToke And Not count Then
  2403. NextToke
  2404. End If
  2405. End Method
  2406. 'should return a specific "metadata object" ?
  2407. ' metadata is in the form : {key key=value key="value"}
  2408. Method ParseMetaData:TMetadata()
  2409. If Not CParse( "{" ) Then
  2410. Return Null
  2411. End If
  2412. Local meta:TMetadata = New TMetadata
  2413. SkipEols
  2414. Repeat
  2415. 'reached end of meta data declaration
  2416. If _toke="}" Then Exit
  2417. If meta.metadataString Then
  2418. meta.metadataString :+ " "
  2419. End If
  2420. Select _tokeType
  2421. Case TOKE_INTLIT
  2422. Err "Expecting '}' but encountered integer literal"
  2423. Case TOKE_FLOATLIT
  2424. Err "Expecting '}' but encountered floating point literal"
  2425. Case TOKE_STRINGLIT
  2426. Err "Expecting '}' but encountered string literal"
  2427. Case TOKE_SYMBOL
  2428. Err "Expecting '}' but encountered " + _toke
  2429. End Select
  2430. 'append current token to metaDataString
  2431. Local key:String = _toke
  2432. meta.metadataString :+ key
  2433. 'read next token
  2434. NextToke()
  2435. Local value:String
  2436. ' got a value
  2437. If CParse("=") Then
  2438. If _tokeType = TOKE_IDENT Then
  2439. Err "Meta data must be literal constant"
  2440. End If
  2441. value = _toke
  2442. meta.metadataString :+ "=" + value
  2443. 'read next token
  2444. NextToke()
  2445. Else
  2446. value = "1"
  2447. meta.metadataString :+ "=1"
  2448. End If
  2449. meta.InsertMeta(key.ToLower(), value)
  2450. Forever
  2451. 'continue to next token
  2452. NextToke()
  2453. 'parse this into something
  2454. Return meta
  2455. End Method
  2456. Method ParseFuncDecl:TFuncDecl( toke$, attrs:Long, parent:TScopeDecl = Null )
  2457. SetErr
  2458. If toke Parse toke
  2459. Local id$
  2460. Local ty:TType
  2461. Local meth:Int = attrs & FUNC_METHOD
  2462. Local meta:TMetadata
  2463. Local noMangle:Int
  2464. Local exported:Int
  2465. Local inInterface:Int = attrs & DECL_ABSTRACT
  2466. Local classDecl:TClassDecl = TClassDecl(parent)
  2467. If attrs & FUNC_METHOD
  2468. If _toke="new"
  2469. If attrs & DECL_EXTERN
  2470. Err "Extern classes cannot have constructors"
  2471. EndIf
  2472. id="New"
  2473. NextToke
  2474. attrs:|FUNC_CTOR
  2475. attrs:&~FUNC_METHOD
  2476. ty=ParseDeclType()
  2477. Else If _toke="operator" Then
  2478. attrs:|FUNC_OPERATOR
  2479. NextToke
  2480. Local t:String = _toke.ToLower()
  2481. NextToke
  2482. Select t
  2483. Case "*","/","+","-","&","|","~~","^"
  2484. id = t
  2485. Case ":*",":/",":+",":-",":&",":|",":~~",":^"
  2486. id = t
  2487. Case "<",">"',"="',"<=",">=","=","<>"
  2488. If CParse("=") Then
  2489. t :+ "="
  2490. Else If t = "<" And CParse(">") Then
  2491. t :+ ">"
  2492. End If
  2493. id = t
  2494. Case "="
  2495. id = t
  2496. Case "mod", "shl", "shr"
  2497. id = t
  2498. Case ":mod", ":shl", ":shr"
  2499. id = t
  2500. Case "[]"
  2501. If CParse("=") Then t :+ "="
  2502. id = t
  2503. Default
  2504. DoErr "Operator must be one of: * / + - & | ~~ :* :/ :+ :- :& :| :~~ < > <= >= = <> mod shl shr :mod :shl :shr [] []="
  2505. End Select
  2506. ty=ParseDeclType()
  2507. Else
  2508. id=ParseIdent()
  2509. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2510. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) Then
  2511. DoErr "Illegal function return type"
  2512. End If
  2513. ' Delete() return type should always be Void
  2514. If id.ToLower() = "delete" Then
  2515. attrs:|FUNC_DTOR
  2516. If TIntType(ty) Then
  2517. ty = New TVoidType
  2518. End If
  2519. End If
  2520. ' TODO: make sure Delete cannot be declared with parameters?
  2521. EndIf
  2522. Else
  2523. 'If Not (attrs & FUNC_PTR) Then
  2524. id=ParseIdent()
  2525. ty=ParseDeclType(attrs & DECL_API_STDCALL)
  2526. ' can only return "$z" and "$w" from an extern function.
  2527. If ty._flags & (TType.T_CHAR_PTR | TType.T_SHORT_PTR) And Not (attrs & DECL_EXTERN) Then
  2528. DoErr "Illegal function return type"
  2529. End If
  2530. 'End If
  2531. EndIf
  2532. ' every branch in that nested If block up there contains the line "ty=ParseDeclType()";
  2533. ' this already consumed all sets of parentheses and brackets belonging to this function declaration
  2534. ' so we will now extract our actual return type and args from the result
  2535. Local args:TArgDecl[]
  2536. If Not TFunctionPtrType(ty) Then
  2537. DoErr "Expecting function type"
  2538. Else
  2539. Local fdecl:TFuncDecl = TFunctionPtrType(ty).func
  2540. ty = fdecl.retTypeExpr
  2541. args = fdecl.argDecls
  2542. attrs :| (fdecl.attrs & DECL_API_FLAGS)
  2543. End If
  2544. Local declaredAttrs:Long
  2545. While True
  2546. If CParse( "nodebug" ) Then
  2547. If declaredAttrs & DECL_NODEBUG Then Err "Duplicate modifier 'NoDebug'"
  2548. declaredAttrs :| DECL_NODEBUG
  2549. Continue
  2550. End If
  2551. If CParse( "final" )
  2552. If Not classDecl Then
  2553. Err "Final cannot be used with global functions"
  2554. End If
  2555. If inInterface Then
  2556. If attrs & FUNC_METHOD Then
  2557. Err "Final methods cannot appear in interfaces"
  2558. Else
  2559. Err "Final functions cannot appear in interfaces"
  2560. End If
  2561. End If
  2562. If declaredAttrs & DECL_FINAL Then Err "Duplicate modifier 'Final'"
  2563. declaredAttrs :| DECL_FINAL
  2564. Continue
  2565. End If
  2566. If CParse( "abstract" )
  2567. If Not classDecl Then
  2568. Err "Abstract cannot be used with global functions"
  2569. End If
  2570. If classDecl And classDecl.attrs & DECL_FINAL Then
  2571. Err "Abstract methods cannot appear in final types"
  2572. End If
  2573. If inInterface Then
  2574. If attrs & FUNC_METHOD Then
  2575. Err "Abstract cannot be used in interfaces (interface methods are automatically abstract)"
  2576. Else
  2577. Err "Abstract cannot be used in interfaces (interface functions are automatically abstract)"
  2578. End If
  2579. End If
  2580. If declaredAttrs & DECL_ABSTRACT Then Err "Duplicate modifier 'Abstract'"
  2581. declaredAttrs :| DECL_ABSTRACT
  2582. Continue
  2583. End If
  2584. If CParse("override") Then
  2585. If Not classDecl Then
  2586. Err "Override cannot be used with global functions"
  2587. End If
  2588. If declaredAttrs & DECL_OVERRIDE Then Err "Duplicate modifier 'Override'"
  2589. declaredAttrs :| DECL_OVERRIDE
  2590. Continue
  2591. End If
  2592. If CParse("inline") And Not opt_debug Then
  2593. If classDecl Then
  2594. Err "Inline can only be used with global functions"
  2595. End If
  2596. If declaredAttrs & DECL_INLINE Then Err "Duplicate modifier 'Inline'"
  2597. declaredAttrs :| DECL_INLINE
  2598. Continue
  2599. End If
  2600. Exit
  2601. Wend
  2602. attrs :| declaredAttrs
  2603. 'meta data for functions/methods
  2604. meta = ParseMetaData()
  2605. If meta And meta.HasMeta("nomangle") Then
  2606. If attrs & FUNC_METHOD Then
  2607. Err "Only functions can specify NoMangle"
  2608. Else
  2609. noMangle = True
  2610. End If
  2611. End If
  2612. If CParse("export") Then
  2613. attrs :| DECL_EXPORT
  2614. If attrs & FUNC_METHOD Then
  2615. Err "Only functions can specify Export"
  2616. Else
  2617. exported = True
  2618. End If
  2619. End If
  2620. attrs :| ParseCallConvention(attrs & DECL_API_STDCALL)
  2621. If CParse( "nodebug" ) Then
  2622. attrs :| DECL_NODEBUG
  2623. End If
  2624. Local funcDecl:TFuncDecl
  2625. If attrs & FUNC_CTOR Then
  2626. funcDecl=New TNewDecl.CreateF( id,ty,args,attrs )
  2627. TNewDecl(funcDecl).cdecl = classdecl
  2628. Else
  2629. 'If fdecl Then
  2630. ' funcDecl = fdecl
  2631. ' funcDecl.ident = id
  2632. 'Else
  2633. funcDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
  2634. 'End If
  2635. funcDecl.noMangle = noMangle
  2636. funcDecl.exported = exported
  2637. End If
  2638. If meta Then
  2639. funcDecl.metadata = meta
  2640. End If
  2641. If funcDecl.IsExtern() Or (attrs & FUNC_PTR)
  2642. funcDecl.munged=funcDecl.ident
  2643. ' a normal function pointer definition *probably* can't be defined with a munged name?
  2644. ' If there is an equals here, one can assume it is for an initialisation...
  2645. 'If (Not (attrs & FUNC_PTR)) Or (attrs & FUNC_PTR And Not (attrs & DECL_ARG)) Then
  2646. Local cdets:TCastDets
  2647. If Not (attrs & FUNC_PTR) Then
  2648. If CParse( "=" )
  2649. Local munged:String = ParseStringLit()
  2650. If munged.Find("(") > 0 Then
  2651. cdets = ParseExternCast(munged, True)
  2652. If cdets Then
  2653. funcDecl.munged = cdets.name
  2654. End If
  2655. Else
  2656. funcDecl.munged = munged
  2657. End If
  2658. End If
  2659. 'Array $resize hack!
  2660. 'If funcDecl.munged="$resize"
  2661. ' funcDecl.retTypeExpr=TType.emptyArrayType
  2662. 'EndIf
  2663. EndIf
  2664. If funcDecl.munged Then
  2665. ' look up extern cast list
  2666. If Not cdets Then
  2667. cdets = TCastDets(_externCasts.ValueForKey(funcDecl.munged))
  2668. End If
  2669. If cdets Then
  2670. funcDecl.castTo = cdets.retType
  2671. If cdets.noGen Then
  2672. funcDecl.noCastGen = True
  2673. End If
  2674. For Local i:Int = 0 Until cdets.args.length
  2675. If i < funcDecl.argDecls.length Then
  2676. funcDecl.argDecls[i].castTo = cdets.args[i]
  2677. End If
  2678. Next
  2679. End If
  2680. End If
  2681. Return funcDecl
  2682. EndIf
  2683. If funcDecl.IsAbstract() Return funcDecl
  2684. 'Ok, only first statement of a constructor can call super constructor - not pretty, should be in semant.
  2685. If attrs & FUNC_CTOR
  2686. SkipEols
  2687. If CParse( "super" )
  2688. Parse "."
  2689. If _toke="new"
  2690. Local id$="New"
  2691. NextToke
  2692. 'funcDecl.superCtor=New TInvokeSuperExpr.Create( id,ParseArgs( True ) )
  2693. 'funcDecl.AddStmt New TExprStmt.Create( funcDecl.superCtor )
  2694. funcDecl.AddStmt New TExprStmt.Create( New TNewExpr.Create(ParseArgs(True), True))
  2695. Else
  2696. Local id$=ParseIdent()
  2697. funcDecl.AddStmt New TExprStmt.Create( New TInvokeSuperExpr.Create( id,ParseArgs( True ) ) )
  2698. EndIf
  2699. Else
  2700. 'Invoke super default ctor
  2701. 'funcDecl.superCtor=New InvokeSuperExpr( "new",[] )
  2702. 'funcDecl.AddStmt New TExprStmt( funcDecl.superCtor )
  2703. EndIf
  2704. EndIf
  2705. PushBlock funcDecl
  2706. While (Not meth And _toke.ToLower()<>"endfunction") Or (meth And _toke.ToLower()<>"endmethod")
  2707. If CParse( "end" )
  2708. If (Not meth And CParse("function")) Or (meth And CParse("method"))
  2709. Exit
  2710. End If
  2711. ' handle "end" statement
  2712. ParseEndStmt(False)
  2713. EndIf
  2714. ParseStmt
  2715. Wend
  2716. PopBlock
  2717. NextToke
  2718. 'If toke CParse toke
  2719. Return funcDecl
  2720. End Method
  2721. Method ParseCallConvention:Long(callConvention:Long = DECL_API_DEFAULT)
  2722. If _tokeType <> TOKE_STRINGLIT Then
  2723. Return callConvention
  2724. End If
  2725. Local api:String = ParseStringLit().ToLower()
  2726. If api = "os" Then
  2727. Select opt_platform
  2728. Case "macos", "osx", "ios"
  2729. api = "macos"
  2730. Case "linux", "android", "raspberrypi", "haiku"
  2731. api = "linux"
  2732. Case "win32"
  2733. api = "win32"
  2734. Case "nx"
  2735. api = "nx"
  2736. End Select
  2737. End If
  2738. Select api
  2739. Case "c", "blitz", "macos", "linux", "nx"
  2740. Return DECL_API_CDECL
  2741. Case "win32"
  2742. ' only if we are compiling for win32
  2743. If opt_platform = "win32"
  2744. Return DECL_API_STDCALL
  2745. Else
  2746. Return DECL_API_CDECL
  2747. End If
  2748. End Select
  2749. Err "Unrecognized calling convention '" + api+ "'"
  2750. End Method
  2751. Method ParseFuncParamDecl:TArgDecl[]()
  2752. Local args:TArgDecl[]
  2753. Parse "("
  2754. SkipEols
  2755. If _toke<>")"
  2756. Local nargs:Int
  2757. Repeat
  2758. Local attrs:Long
  2759. If CParse("staticarray") Then
  2760. attrs :| DECL_STATIC
  2761. End If
  2762. Local argId$=ParseIdent()
  2763. Local ty:TType=ParseDeclType(attrs)
  2764. Local init:TExpr
  2765. ' var argument?
  2766. If CParse("var") Then
  2767. If attrs & DECL_STATIC Then
  2768. Err "Unexpected 'Var' for static array argument"
  2769. End If
  2770. ty = TType.MapToVarType(ty)
  2771. Else If CParse( "=" )
  2772. init=ParseExpr()
  2773. Else
  2774. If CParse( "[" ) And (attrs & DECL_STATIC) Then
  2775. init = ParseExpr()
  2776. Parse "]"
  2777. ty=New TArrayType.Create( ty,1,, attrs & DECL_STATIC > 0 )
  2778. End If
  2779. End If
  2780. Local arg:TArgDecl=New TArgDecl.Create( argId,ty,init,attrs )
  2781. If args.Length=nargs args=args + New TArgDecl[10]
  2782. args[nargs]=arg
  2783. nargs:+1
  2784. If _toke=")" Exit
  2785. Parse ","
  2786. Forever
  2787. args=args[..nargs]
  2788. EndIf
  2789. Parse ")"
  2790. Return args
  2791. End Method
  2792. Method ParseEnumDecl:TEnumDecl( toke:String )
  2793. SetErr
  2794. If toke Parse toke
  2795. Local id:String = ParseIdent()
  2796. Local ty:TType = ParseConstNumberType()
  2797. If Not ty Then
  2798. ty = New TIntType
  2799. End If
  2800. Local isFlags:Int = 0
  2801. Local values:TEnumValueDecl[0]
  2802. If CParse("flags")
  2803. isFlags = True
  2804. End If
  2805. Local decl:TEnumDecl = New TEnumDecl.Create(id, ty, isFlags, values)
  2806. Local nValues:Int
  2807. Repeat
  2808. SkipEols
  2809. If CParse("end") Then
  2810. Parse("enum")
  2811. Exit
  2812. End If
  2813. If CParse("endenum") Then
  2814. Exit
  2815. End If
  2816. Local valId:String = ParseIdent()
  2817. Local value:TExpr
  2818. If CParse( "=" ) Then
  2819. value = ParseExpr()
  2820. End If
  2821. Local v:TEnumValueDecl = New TEnumValueDecl.Create(valId, nValues, value)
  2822. If decl.values.Length = nValues Then
  2823. decl.values = decl.values + New TEnumValueDecl[10]
  2824. End If
  2825. decl.values[nValues] = v
  2826. nValues :+ 1
  2827. CParse(",")
  2828. Forever
  2829. decl.values = decl.values[..nValues]
  2830. Return decl
  2831. End Method
  2832. Method ParseClassDecl:TClassDecl( toke$,attrs:Long, templateDets:TTemplateDets = Null )
  2833. SetErr
  2834. Local calculatedStartLine:Int = _toker.Line()
  2835. Local startLine:Int = _toker._line
  2836. If toke Parse toke
  2837. Local id$=ParseIdent()
  2838. Local args:TList = New TList
  2839. Local superTy:TIdentType
  2840. Local imps:TIdentType[]
  2841. Local meta:TMetadata
  2842. 'If (attrs & CLASS_INTERFACE) And (attrs & DECL_EXTERN)
  2843. ' Err "Interfaces cannot be extern."
  2844. 'EndIf
  2845. If CParse( "<" )
  2846. If attrs & DECL_EXTERN
  2847. Err "Extern classes cannot be generic."
  2848. EndIf
  2849. 'If attrs & CLASS_INTERFACE
  2850. ' Err "Interfaces cannot be generic."
  2851. 'EndIf
  2852. 'If attrs & CLASS_TEMPLATEARG
  2853. ' Err "Class parameters cannot be generic."
  2854. 'EndIf
  2855. Local nargs:Int
  2856. Repeat
  2857. 'Local decl:TClassDecl=ParseClassDecl( "",CLASS_TEMPLATEARG )
  2858. 'If args.Length=nargs args=args + New TClassDecl[10]
  2859. 'args[nargs]=decl
  2860. 'nargs:+1
  2861. Local arg:TTemplateArg = New TTemplateArg
  2862. arg.ident = ParseIdent()
  2863. ' If CParse("extends") Then
  2864. ' arg.superTy = ParseIdentType()
  2865. ' End If
  2866. args.AddLast arg
  2867. Until Not CParse(",")
  2868. 'args=args[..nargs]
  2869. Parse ">"
  2870. If CParse( "where" ) Then
  2871. 'DebugStop
  2872. Repeat
  2873. Local argIdent:String = ParseIdent()
  2874. Parse("extends")
  2875. Local found:Int
  2876. For Local arg:TTemplateArg = EachIn args
  2877. If arg.ident = argIdent Then
  2878. Repeat
  2879. arg.ExtendsType(ParseIdentType())
  2880. Until Not CParse("and")
  2881. found = True
  2882. Exit
  2883. EndIf
  2884. Next
  2885. If Not found Then
  2886. Err "Use of undeclared type '" + argIdent + "'."
  2887. End If
  2888. Until Not CParse(",")
  2889. End If
  2890. EndIf
  2891. If CParse( "extends" )
  2892. 'If attrs & CLASS_TEMPLATEARG
  2893. ' Err "Extends cannot be used with class parameters."
  2894. 'EndIf
  2895. ' If CParse( "null" )
  2896. '
  2897. If attrs & CLASS_STRUCT
  2898. Err "Structs cannot be extended"
  2899. EndIf
  2900. '
  2901. ' If Not (attrs & DECL_EXTERN)
  2902. ' Err "Only extern objects can extend null."
  2903. ' EndIf
  2904. '
  2905. ' superTy=Null
  2906. '
  2907. ' Else
  2908. If attrs & CLASS_INTERFACE And Not (attrs & DECL_EXTERN)
  2909. Local nimps:Int
  2910. Repeat
  2911. If imps.Length=nimps imps=imps + New TIdentType[10]
  2912. imps[nimps]=ParseIdentType()
  2913. nimps:+1
  2914. Until Not CParse(",")
  2915. imps=imps[..nimps]
  2916. superTy=New TIdentType.Create( "brl.classes.object" )
  2917. Else
  2918. superTy=ParseIdentType()
  2919. EndIf
  2920. Else
  2921. If Not (attrs & DECL_EXTERN) And Not (attrs & CLASS_STRUCT) Then
  2922. superTy=New TIdentType.Create( "brl.classes.object" )
  2923. End If
  2924. EndIf
  2925. If CParse( "implements" )
  2926. If attrs & CLASS_STRUCT
  2927. Err "Implements cannot be used with Structs"
  2928. EndIf
  2929. 'If attrs & DECL_EXTERN
  2930. ' Err "Implements cannot be used with external classes."
  2931. 'EndIf
  2932. If attrs & CLASS_INTERFACE
  2933. Err "Implements cannot be used with interfaces."
  2934. EndIf
  2935. 'If attrs & CLASS_TEMPLATEARG
  2936. ' Err "Implements cannot be used with class parameters."
  2937. 'EndIf
  2938. Local nimps:Int
  2939. Repeat
  2940. If imps.Length=nimps imps=imps + New TIdentType[10]
  2941. imps[nimps]=ParseIdentType()
  2942. nimps:+1
  2943. Until Not CParse(",")
  2944. imps=imps[..nimps]
  2945. EndIf
  2946. Repeat
  2947. If CParse( "final" )
  2948. If attrs & CLASS_INTERFACE
  2949. Err "Final cannot be used with interfaces."
  2950. End If
  2951. If attrs & CLASS_STRUCT
  2952. Err "Final cannot be used with structs."
  2953. End If
  2954. If attrs & DECL_FINAL
  2955. Err "Duplicate modifier 'Final'."
  2956. End If
  2957. If attrs & DECL_ABSTRACT
  2958. Err "Classes cannot be both final and abstract."
  2959. End If
  2960. attrs:|DECL_FINAL
  2961. Else If CParse( "abstract" )
  2962. If attrs & CLASS_INTERFACE
  2963. Err "Abstract cannot be used with interfaces."
  2964. EndIf
  2965. If attrs & CLASS_STRUCT
  2966. Err "Abstract cannot be used with structs."
  2967. EndIf
  2968. If attrs & DECL_ABSTRACT
  2969. Err "Duplicate modifier 'Abstract'."
  2970. End If
  2971. If attrs & DECL_FINAL
  2972. Err "Types cannot be both final and abstract."
  2973. End If
  2974. attrs:|DECL_ABSTRACT
  2975. Else
  2976. Exit
  2977. EndIf
  2978. Forever
  2979. 'check for metadata
  2980. meta = ParseMetaData()
  2981. Local sargs:TTemplateArg[] = New TTemplateArg[args.Count()]
  2982. Local i:Int = 0
  2983. For Local arg:TTemplateArg = EachIn args
  2984. sargs[i] = arg
  2985. i :+ 1
  2986. Next
  2987. Local classDecl:TClassDecl=New TClassDecl.Create( id,sargs,superTy,imps,attrs )
  2988. If meta Then
  2989. If attrs & CLASS_STRUCT
  2990. Err "Structs cannot store metadata."
  2991. EndIf
  2992. classDecl.metadata = meta
  2993. End If
  2994. If classDecl.IsExtern()
  2995. classDecl.munged=classDecl.ident
  2996. If CParse( "=" ) classDecl.munged=ParseStringLit()
  2997. EndIf
  2998. 'If classDecl.IsTemplateArg() Return classDecl
  2999. Local decl_attrs:Long=(attrs & DECL_EXTERN) | (attrs & DECL_NODEBUG) | (attrs & DECL_API_STDCALL)
  3000. Repeat
  3001. Local method_attrs:Long=decl_attrs|FUNC_METHOD | (attrs & DECL_NODEBUG)
  3002. Local abst_attrs:Long = 0
  3003. If attrs & CLASS_INTERFACE abst_attrs:|DECL_ABSTRACT
  3004. SkipEols
  3005. Select _toke
  3006. Case "end"
  3007. NextToke
  3008. Exit
  3009. Case "endtype"
  3010. If attrs & CLASS_INTERFACE Then
  3011. Err "Syntax error - expecting End Interface, not 'EndType'"
  3012. End If
  3013. If attrs & CLASS_STRUCT Then
  3014. Err "Syntax error - expecting End Struct, not 'EndType'"
  3015. End If
  3016. toke = Null
  3017. NextToke
  3018. Exit
  3019. Case "endstruct"
  3020. If attrs & CLASS_INTERFACE Then
  3021. Err "Syntax error - expecting End Interface, not 'EndStruct'"
  3022. End If
  3023. If Not (attrs & CLASS_STRUCT) Then
  3024. Err "Syntax error - expecting End Type, not 'EndStruct'"
  3025. End If
  3026. toke = Null
  3027. NextToke
  3028. Exit
  3029. Case "endinterface"
  3030. If Not (attrs & CLASS_INTERFACE) And Not (attrs & CLASS_STRUCT) Then
  3031. Err "Syntax error - expecting End Type, not 'EndInterface'"
  3032. End If
  3033. If Not (attrs & CLASS_INTERFACE) And (attrs & CLASS_STRUCT) Then
  3034. Err "Syntax error - expecting End Struct, not 'EndInterface'"
  3035. End If
  3036. toke = Null
  3037. NextToke
  3038. Exit
  3039. Case "private"
  3040. If attrs & CLASS_INTERFACE Then
  3041. Err "Private cannot be used with interfaces."
  3042. End If
  3043. NextToke
  3044. decl_attrs=decl_attrs | DECL_PRIVATE
  3045. decl_attrs:& ~DECL_PROTECTED
  3046. Case "protected"
  3047. If attrs & CLASS_INTERFACE Then
  3048. Err "Protected cannot be used with interfaces."
  3049. End If
  3050. NextToke
  3051. decl_attrs=decl_attrs | DECL_PROTECTED
  3052. decl_attrs:& ~DECL_PRIVATE
  3053. Case "public"
  3054. NextToke
  3055. decl_attrs:& ~DECL_PRIVATE
  3056. decl_attrs:& ~DECL_PROTECTED
  3057. Case "const","global","field","threadedglobal"
  3058. Local extra_attrs:Long
  3059. If _toke = "threadedglobal" Then
  3060. extra_attrs = DECL_THREADED
  3061. End If
  3062. If attrs & DECL_EXTERN Then
  3063. If (attrs & CLASS_INTERFACE) Then
  3064. Err "Extern Interfaces can only contain methods."
  3065. End If
  3066. If Not (attrs & CLASS_STRUCT) Then
  3067. Err "Extern Types can only contain methods."
  3068. End If
  3069. End If
  3070. If (attrs & CLASS_INTERFACE) And _toke<>"const"
  3071. Err "Interfaces can only contain constants and methods."
  3072. EndIf
  3073. If (attrs & CLASS_STRUCT) And _toke<>"field" And _toke<>"global" And _toke<>"threadedglobal"
  3074. Err "Structs can only contain fields."
  3075. EndIf
  3076. classDecl.InsertDecls ParseDecls( _toke,decl_attrs | extra_attrs, _toke = "field")
  3077. Case "method"
  3078. If (attrs & CLASS_STRUCT) And (attrs & DECL_EXTERN) Then
  3079. Err "Structs can only contain fields."
  3080. EndIf
  3081. Local decl:TFuncDecl=ParseFuncDecl( _toke,method_attrs | abst_attrs,classDecl )
  3082. classDecl.InsertDecl decl
  3083. Case "function"
  3084. 'If (attrs & CLASS_INTERFACE)
  3085. ' Err "Interfaces can only contain constants and methods."
  3086. 'EndIf
  3087. If attrs & CLASS_STRUCT Then
  3088. If (attrs & DECL_EXTERN) Then
  3089. Err "Structs can only contain fields."
  3090. End If
  3091. EndIf
  3092. If attrs & DECL_EXTERN Then
  3093. Err "Extern Types can only contain methods."
  3094. End If
  3095. Local decl:TFuncDecl=ParseFuncDecl( _toke,decl_attrs | abst_attrs,classDecl )
  3096. classDecl.InsertDecl decl
  3097. Case "type"
  3098. If templateDets Then
  3099. Local cdecl:TClassDecl = ParseClassDecl( _toke,DECL_NESTED, templateDets)
  3100. cdecl = cdecl.GenClassInstance(templateDets.instArgs, False, Null, templateDets)
  3101. classDecl.InsertDecl cdecl, True
  3102. Else
  3103. classDecl.InsertDecl ParseClassDecl( _toke,DECL_NESTED)
  3104. End If
  3105. Default
  3106. Err "Syntax error - expecting class member declaration, not '" + _toke + "'"
  3107. End Select
  3108. Forever
  3109. If Not args.IsEmpty() Then
  3110. Local endline:Int = _toker._line
  3111. classDecl.templateSource = New TTemplateRecord.Create(calculatedStartLine - 1, _toker._path, _toker.Join(startLine, endLine, "~n"))
  3112. End If
  3113. If toke Parse toke
  3114. Return classDecl
  3115. End Method
  3116. Method ParseNativeStmt()
  3117. If Not _toke.StartsWith("'!") Then
  3118. Err "Syntax error - expecting '!"
  3119. End If
  3120. Local raw:String = _toke[2..]
  3121. _block.AddStmt New TNativeStmt.Create( raw )
  3122. NextToke
  3123. End Method
  3124. Method ParseModuleDecl:String( toke$,attrs:Long )
  3125. NextToke
  3126. ' namespace . module
  3127. Return ParseModPath().ToLower()
  3128. End Method
  3129. Method ParseModPath$()
  3130. Local path$=ParseIdent()
  3131. While CParse( "." )
  3132. path:+"."+ParseIdent()
  3133. Wend
  3134. Return path
  3135. End Method
  3136. Method ExtractModIdent$( modpath$ )
  3137. Local i:Int=modpath.FindLast( "." )
  3138. If i<>-1 Return modpath[i+1..]
  3139. Return modpath
  3140. End Method
  3141. Method ImportFile( filepath$ )
  3142. If filepath.Endswith(".bmx") Then
  3143. filepath = ActualPath(filepath)
  3144. Local origPath:String = RealPath(filepath)
  3145. Local path:String = OutputFilePath(origPath, FileMung(), "i")
  3146. If FileType( origPath )<>FILETYPE_FILE
  3147. Err "File '"+ origPath +"' not found."
  3148. EndIf
  3149. If FileType( path )<>FILETYPE_FILE
  3150. Err "File '"+ path +"' not found."
  3151. EndIf
  3152. If _module.imported.Contains( path ) Return
  3153. Local modpath:String
  3154. If opt_buildtype = BUILDTYPE_MODULE Then
  3155. Local dir:String = ExtractDir(origPath).ToLower()
  3156. dir = dir[dir.findLast("/") + 1..]
  3157. If dir.EndsWith(".mod") Then
  3158. dir = ""
  3159. Else
  3160. dir :+ "_"
  3161. End If
  3162. Local file:String = StripDir(origPath).ToLower()
  3163. modpath = opt_modulename + "_" + dir + StripExt(file)
  3164. Else
  3165. modpath = StripExt(filepath)
  3166. End If
  3167. 'sanitize the path, remove non-allowed chars
  3168. modpath = TStringHelper.Sanitize(modpath.ToLower())
  3169. ' try to import interface
  3170. Local par:TIParser = New TIParser
  3171. If par.ParseModuleImport(_module, modpath, origPath, path, , , filepath, True) Return
  3172. Else If filepath.startswith("-") Then
  3173. If Not _app.fileimports.Contains(filepath) Then
  3174. _app.fileimports.AddLast filepath
  3175. End If
  3176. Else
  3177. If filepath.EndsWith(".h") Or filepath.EndsWith(".hpp") Or filepath.EndsWith(".hxx") Then
  3178. If filepath.Find("*") = -1 Then
  3179. _app.headers.AddLast filepath
  3180. End If
  3181. Else
  3182. Local path:String = ActualPath(RealPath(filepath))
  3183. If FileType( path )<>FILETYPE_FILE
  3184. Err "File '"+ path +"' not found."
  3185. End If
  3186. End If
  3187. End If
  3188. End Method
  3189. Method ImportAllModules(attrs:Long)
  3190. ' get all brl and pub modules
  3191. Local mods:TList = EnumModules("brl")
  3192. mods = EnumModules("pub", mods)
  3193. For Local m:String = EachIn mods
  3194. ImportModule(m, attrs)
  3195. Next
  3196. End Method
  3197. Method ImportModule( modpath$,attrs:Long )
  3198. SetErr
  3199. modpath = modpath.ToLower()
  3200. Local basepath:String = ModulePath(modpath)
  3201. If _module.imported.Contains( basepath ) Return
  3202. ' try to import interface
  3203. Local par:TIParser = New TIParser
  3204. If par.ParseModuleImport(_module, modpath, basepath, , , attrs) Return
  3205. 'DebugStop
  3206. 'Local mdecl:TDecl=_app.imported.ValueForKey( basepath )
  3207. 'If Not mdecl
  3208. ' mdecl=ParseModule( filepath,_app )
  3209. 'EndIf
  3210. '_module.imported.Insert mdecl.filepath,mdecl
  3211. 'If Not (attrs & DECL_PRIVATE) _module.pubImported.Insert mdecl.filepath,mdecl
  3212. '_module.InsertDecl New AliasDecl( mdecl.ident,mdecl,attrs )
  3213. 'End Rem
  3214. End Method
  3215. Method ValidateModIdent( id$ )
  3216. If id.Length
  3217. If IsAlpha( id[0] ) Or id[0]="_"[0]
  3218. Local err:Int
  3219. For Local i:Int=1 Until id.Length
  3220. If IsAlpha( id[i] ) Or IsDigit( id[i] ) Or id[i]="_"[0] Continue
  3221. err=1
  3222. Exit
  3223. Next
  3224. If Not err Return
  3225. EndIf
  3226. EndIf
  3227. Err "Invalid module identifier '"+id+"'."
  3228. End Method
  3229. Method MungAppDecl(app:TAppDecl)
  3230. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain Then
  3231. app.munged = MungModuleName(opt_modulename)
  3232. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3233. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3234. dir = dir[dir.findLast("/") + 1..]
  3235. If dir.EndsWith(".mod") Then
  3236. dir = ""
  3237. Else
  3238. dir :+ "_"
  3239. End If
  3240. app.munged = "_bb_" + opt_modulename + "_" + dir + StripExt(StripDir(opt_filepath).ToLower())
  3241. Else
  3242. ' main application file?
  3243. If opt_apptype Then
  3244. app.munged = "_bb_main"
  3245. Else
  3246. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3247. dir = dir[dir.findLast("/") + 1..]
  3248. If dir.EndsWith(".mod") Then
  3249. dir = dir.Replace(".mod", "")
  3250. End If
  3251. Local file:String = StripDir(opt_filepath).ToLower()
  3252. app.munged = "_bb_" + dir + "_" + StripExt(file)
  3253. End If
  3254. End If
  3255. 'sanitize, remove non-allowed chars
  3256. app.munged = TStringHelper.Sanitize(app.munged)
  3257. End Method
  3258. ' load external cast defs
  3259. Method LoadExternCasts(path:String)
  3260. For Local externs:Int = 0 Until 3
  3261. Local ePath:String
  3262. ' we will iterate through all possibilities as there may be different sets
  3263. ' of explicit casts/no gen funcs for each.
  3264. Select externs
  3265. Case 0
  3266. ' eg. file.win32.x86.x
  3267. ePath = StripExt(path) + "." + opt_platform + "." + opt_arch + ".x"
  3268. Case 1
  3269. ' eg. file.win32.x
  3270. ePath = StripExt(path) + "." + opt_platform + ".x"
  3271. Case 2
  3272. ' eg. file.x
  3273. ePath = StripExt(path) + ".x"
  3274. End Select
  3275. If FileType(ePath) = FILETYPE_FILE Then
  3276. Print "Warning: .x cast definition files are deprecated. You should now place the details in the extern function's alias string. (" + path + ")"
  3277. ParseExternCast(LoadText( ePath ), False, ePath)
  3278. End If
  3279. Next
  3280. End Method
  3281. Method ParseExternCast:TCastDets(txt:String, single:Int = False, path:String = "")
  3282. Local toker:TToker = New TToker.Create(path, txt)
  3283. toker.NextToke
  3284. Local dets:TCastDets
  3285. While True
  3286. SkipEolsToker(toker)
  3287. If toker._tokeType = TOKE_EOF Exit
  3288. dets = New TCastDets
  3289. Local rt$=toker._toke
  3290. If CParseToker(toker, "const") Then
  3291. rt :+ " " + toker._toke
  3292. End If
  3293. If CParseToker(toker, "unsigned") Then
  3294. rt :+ " " + toker._toke
  3295. End If
  3296. NextTokeToker(toker)
  3297. If CParseToker(toker,"*") Then
  3298. rt:+ "*"
  3299. If CParseToker(toker,"*") Then
  3300. rt:+ "*"
  3301. End If
  3302. End If
  3303. If CParseToker(toker, "__stdcall") Then
  3304. dets.api = "__stdcall"
  3305. End If
  3306. ' fname
  3307. Local fn$=toker._toke
  3308. NextTokeToker(toker)
  3309. dets.name = fn
  3310. dets.retType = rt
  3311. ' add to global map (may be referenced by function ptr defs)
  3312. _externCasts.Insert(fn, dets)
  3313. ' args
  3314. ParseToker(toker, "(")
  3315. If CParseToker(toker, ")") Then
  3316. ' don't generate header extern
  3317. If CParseToker(toker, "!") Then
  3318. dets.noGen = True
  3319. End If
  3320. Continue
  3321. End If
  3322. Local i:Int = 0
  3323. Repeat
  3324. Local at$=toker._toke
  3325. If CParseToker(toker, "const") Then
  3326. at :+ " " + toker._toke
  3327. End If
  3328. If CParseToker(toker, "unsigned") Then
  3329. at :+ " " + toker._toke
  3330. End If
  3331. If CParseToker(toker, "struct") Then
  3332. at :+ " " + toker._toke
  3333. End If
  3334. NextTokeToker(toker)
  3335. If CParseToker(toker, "*") Then
  3336. at:+ "*"
  3337. If CParseToker(toker, "const") Then
  3338. at :+ " const"
  3339. End If
  3340. If CParseToker(toker, "*") Then
  3341. at:+ "*"
  3342. End If
  3343. End If
  3344. ' function pointer
  3345. If CParseToker(toker, "(") Then
  3346. ParseToker(toker, "*")
  3347. ParseToker(toker, ")")
  3348. at :+ "(*)"
  3349. ParseToker(toker, "(")
  3350. at :+ "("
  3351. While Not CParseToker(toker, ")")
  3352. NextTokeToker(toker)
  3353. at :+ toker._toke
  3354. Wend
  3355. at :+ ")"
  3356. End If
  3357. dets.args :+ [at]
  3358. If toker._toke=")" Exit
  3359. ParseToker(toker, ",")
  3360. i:+ 1
  3361. Forever
  3362. NextTokeToker(toker)
  3363. ' don't generate header extern
  3364. If CParseToker(toker, "!") Then
  3365. dets.noGen = True
  3366. End If
  3367. If single Then
  3368. Exit
  3369. End If
  3370. Wend
  3371. Return dets
  3372. End Method
  3373. Method ParseCurrentFile:Long(path:String, attrs:Long)
  3374. LoadExternCasts(path)
  3375. While _toke
  3376. SetErr
  3377. Select _toke.toLower()
  3378. Case "~n"
  3379. NextToke
  3380. Case "public"
  3381. NextToke
  3382. attrs=attrs & ~DECL_PRIVATE
  3383. Case "private"
  3384. NextToke
  3385. attrs=attrs | DECL_PRIVATE
  3386. Case "extern"
  3387. ParseExternBlock(_module, attrs)
  3388. Case "const"
  3389. _module.InsertDecls ParseDecls( _toke,attrs )
  3390. Case "global"
  3391. ParseDeclStmts(True, attrs, _module)
  3392. Case "threadedglobal"
  3393. ParseDeclStmts(True, attrs | DECL_THREADED, _module)
  3394. Case "struct"
  3395. _module.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
  3396. Case "type"
  3397. _module.InsertDecl ParseClassDecl( _toke,attrs)
  3398. Case "interface"
  3399. _module.InsertDecl ParseClassDecl( _toke,attrs|CLASS_INTERFACE|DECL_ABSTRACT )
  3400. Case "enum"
  3401. _module.InsertDecl ParseEnumDecl( _toke )
  3402. Case "function"
  3403. _module.InsertDecl ParseFuncDecl( _toke,attrs )
  3404. Case "incbin"
  3405. NextToke
  3406. Local s:String = ParseStringLit()
  3407. _app.mapStringConsts(s)
  3408. Local ib:TIncBin = New TIncbin.Create(s, path)
  3409. If Not ib Then
  3410. DoErr "Incbin file '"+ s +"' not found."
  3411. End If
  3412. _app.incbins.AddLast(ib)
  3413. Case "include"
  3414. 'include command is NOT just a pattern to replace with
  3415. 'content. BlitzMax parses each included file before the
  3416. 'content gets appended to the source (right before
  3417. 'semanting or analyzing content)
  3418. NextToke
  3419. Local includeFile:String = ParseStringLit()
  3420. 'convert the URI of the to include file as it might be
  3421. 'a relative one
  3422. includeFile = RealPath(includeFile)
  3423. 'instead of merging the data of multiple parsers, the
  3424. 'same parser is used for all included files - but each
  3425. 'of them uses an individual toker
  3426. If FileType( includeFile )<>FILETYPE_FILE
  3427. DoErr "File '"+ includeFile +"' not found."
  3428. EndIf
  3429. 'instead of "LoadText" "PreProcess" is used to include
  3430. 'handling of conditionals and comments
  3431. Try
  3432. Local includeSource:String = PreProcess(includeFile)
  3433. Local includeToker:TToker = New TToker.Create(includeFile, includeSource)
  3434. 'backup old vars
  3435. Local oldToker:TToker = Self._toker
  3436. 'assign temporary vars
  3437. Self._toker = includeToker
  3438. 'parse the include file
  3439. parseCurrentFile(includeFile, attrs)
  3440. 'restore backup vars
  3441. Self._toker = oldToker
  3442. Catch e:TStreamException
  3443. DoErr "Failed to include file '" + includeFile + "' : '" + e.ToString() + "'"
  3444. End Try
  3445. 'move on to next toke (after include "xyz.bmx")
  3446. NextToke
  3447. Default
  3448. ParseStmt
  3449. 'Err "Syntax error - expecting declaration."
  3450. End Select
  3451. Wend
  3452. Return attrs
  3453. End Method
  3454. Method ParseGeneric:Object(templateSource:TTemplateRecord, templateDets:TTemplateDets)
  3455. Local toker:TToker = New TToker.Create(templateSource.file, templateSource.source, False, templateSource.start)
  3456. Local parser:TParser = New TParser.Create( toker, _appInstance )
  3457. Local m:TModuleDecl = New TModuleDecl
  3458. parser._module = m
  3459. Local cdecl:TClassDecl = Null
  3460. Select parser._toke
  3461. Case "type"
  3462. cdecl = parser.ParseClassDecl(parser._toke,0, templateDets )
  3463. Case "interface"
  3464. cdecl = parser.ParseClassDecl(parser._toke, CLASS_INTERFACE|DECL_ABSTRACT, templateDets )
  3465. End Select
  3466. Return cdecl
  3467. End Method
  3468. Method ParseMain()
  3469. SkipEols
  3470. Local mattrs:Long
  3471. 'If CParse( "strict" ) mattrs:|MODULE_STRICT
  3472. 'If CParse( "superstrict" ) mattrs:|MODULE_SUPERSTRICT
  3473. Local path$=_toker.Path()
  3474. Local ident$=StripAll( path )
  3475. Local munged$ '="bb_"+ident+"_"
  3476. If opt_buildtype = BUILDTYPE_MODULE And opt_ismain
  3477. ValidateModIdent ident
  3478. Else If opt_buildtype = BUILDTYPE_MODULE Then
  3479. Local dir:String = ExtractDir(opt_filepath).ToLower()
  3480. dir = dir[dir.findLast("/") + 1..]
  3481. If dir.EndsWith(".mod") Then
  3482. dir = ""
  3483. Else
  3484. dir :+ "_"
  3485. End If
  3486. munged = opt_modulename + "_" + dir + ident
  3487. 'sanitize, remove non-allowed chars
  3488. munged = TStringHelper.Sanitize(munged.ToLower())
  3489. End If
  3490. If opt_ismain Then 'And opt_modulename <> "brl.blitz" Then
  3491. ident = opt_modulename
  3492. End If
  3493. If opt_buildtype = BUILDTYPE_APP Then
  3494. ident = "m_" + ident
  3495. End If
  3496. _module=New TModuleDecl.Create( ident,munged,path,mattrs )
  3497. _module.AddImport path,_module
  3498. _app.InsertModule _module
  3499. ' mung the app decl
  3500. MungAppDecl(_app)
  3501. If opt_buildtype = BUILDTYPE_MODULE And opt_modulename = "brl.blitz" Then
  3502. ' import Object and String definitions
  3503. Local par:TIParser = New TIParser
  3504. par.ParseModuleImport(_module, "brl.classes", modulepath("brl.blitz"), modulepath("brl.blitz") + "/blitz_classes.i")
  3505. ' set up built-in keywords
  3506. par = New TIParser
  3507. par.ParseModuleImport(_module, "brl.blitzkeywords", "", "", MakeKeywords())
  3508. End If
  3509. ' don't import ourself
  3510. If opt_modulename <> "brl.blitz" Then
  3511. Local par:TIParser = New TIParser
  3512. par.ParseModuleImport(_module, "brl.blitz", modulepath("brl.blitz"), , , MODULE_ACTUALMOD)
  3513. End If
  3514. Local mainFunc:TFuncDecl = New TFuncDecl.CreateF("__LocalMain", New TIntType,Null,0)
  3515. '_app.InsertDecl mainFunc
  3516. _module.insertDecl(mainFunc)
  3517. 'Local mainBlock:TBlockDecl = New TBlockDecl.Create( _block )
  3518. ' import all brl and pub modules if we haven't specified one
  3519. If opt_buildtype <> BUILDTYPE_MODULE And Not opt_framework Then
  3520. ImportAllModules MODULE_ACTUALMOD
  3521. Else
  3522. If opt_framework Then
  3523. Local par:TIParser = New TIParser
  3524. par.ParseModuleImport(_module, opt_framework, modulepath(opt_framework), , , MODULE_ACTUALMOD)
  3525. End If
  3526. End If
  3527. Local attrs:Long
  3528. While _toke
  3529. SetErr
  3530. Select _toke.ToLower()
  3531. Case "~n"
  3532. NextToke
  3533. Case "strict"
  3534. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3535. Err "Strict or SuperStrict already specified"
  3536. End If
  3537. _module.attrs :| MODULE_STRICT
  3538. nextToke
  3539. Case "superstrict"
  3540. If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
  3541. Err "Strict or SuperStrict already specified"
  3542. End If
  3543. _module.attrs :| MODULE_SUPERSTRICT
  3544. opt_issuperstrict = True
  3545. NextToke
  3546. Default
  3547. Exit
  3548. End Select
  3549. Wend
  3550. If opt_need_strict And Not (_module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT)) Then
  3551. Err "Strict or SuperStrict must be declared at the start of the file."
  3552. End If
  3553. 'Parse header - imports etc.
  3554. While _toke
  3555. SetErr
  3556. Select _toke.ToLower()
  3557. Case "~n"
  3558. NextToke
  3559. Case "public"
  3560. NextToke
  3561. attrs=attrs & ~DECL_PRIVATE
  3562. Case "private"
  3563. NextToke
  3564. attrs=attrs | DECL_PRIVATE
  3565. Case "import"
  3566. NextToke
  3567. If _tokeType=TOKE_STRINGLIT
  3568. ' TODO
  3569. 'ImportFile ReplaceEnvTags( ParseStringLit() )
  3570. ImportFile ParseStringLit()
  3571. Else
  3572. ImportModule ParseModPath(),attrs | MODULE_ACTUALMOD
  3573. EndIf
  3574. Case "framework"
  3575. NextToke
  3576. ImportModule ParseModPath(),attrs
  3577. Case "alias"
  3578. NextToke
  3579. Repeat
  3580. Local ident$=ParseIdent()
  3581. Parse "="
  3582. Local decl:Object
  3583. Local scope:TScopeDecl=_module
  3584. _env=_module 'naughty! Shouldn't be doing GetDecl in parser...
  3585. Repeat
  3586. Local id$=ParseIdent()
  3587. decl=scope.FindDecl( id )
  3588. If Not decl Err "Identifier '"+id+"' not found."
  3589. If Not CParse( "." ) Exit
  3590. scope=TScopeDecl( decl )
  3591. If Not scope Or TFuncDecl( scope ) Err "Invalid scope '"+id+"'."
  3592. Forever
  3593. _env=Null '/naughty
  3594. _module.InsertDecl New TAliasDecl.Create( ident,decl,attrs )
  3595. Until Not CParse(",")
  3596. Case "module"
  3597. Local m:String = ParseModuleDecl(_toke, attrs)
  3598. If m.ToLower() <> opt_modulename Then
  3599. Err "Module does not match commandline module"
  3600. End If
  3601. 'sanitize, remove non-allowed chars
  3602. _module.munged = TStringHelper.Sanitize(m)
  3603. Case "nodebug"
  3604. mainFunc.attrs :| DECL_NODEBUG
  3605. attrs :| DECL_NODEBUG
  3606. NextToke
  3607. Case "moduleinfo"
  3608. NextToke
  3609. Local info:String = ParseStringLit()
  3610. _module.modInfo.AddLast(info)
  3611. Default
  3612. Exit
  3613. End Select
  3614. Wend
  3615. ' app code
  3616. PushBlock(mainFunc)
  3617. 'Parse main app
  3618. attrs = ParseCurrentFile(path, attrs)
  3619. PopBlock
  3620. End Method
  3621. Method ParseModule()
  3622. End Method
  3623. Method Create:TParser( toker:TToker,app:TAppDecl, unknownIdentsEvalFalse:Int = False )
  3624. _toke="~n"
  3625. _toker=toker
  3626. _app=app
  3627. SetErr
  3628. NextToke
  3629. Self.unknownIdentsEvalFalse = unknownIdentsEvalFalse
  3630. Return Self
  3631. End Method
  3632. End Type
  3633. Function Eval$( toker:TToker,_type:TType )
  3634. Local src$
  3635. While toker.Toke() And toker.Toke()<>"'" And toker.Toke()<>"~n" And toker.Toke()<>"~r"
  3636. src:+toker.Toke()
  3637. toker.NextToke()
  3638. Wend
  3639. Local t:String=EvalS( src,_type )
  3640. Return t
  3641. End Function
  3642. Function PreProcessNextToke$(toker:TToker)
  3643. Repeat
  3644. toker.NextToke()
  3645. Until toker.tokeType()<>TOKE_SPACE Or toker.Toke().Endswith("~n")
  3646. Return toker._toke
  3647. End Function
  3648. Function PreProcess$( path$ )
  3649. Local ifnest:Int,con:Int=1,line:Int,source:TStringList=New TStringList
  3650. Local toker:TToker=New TToker.Create( path,LoadText( path ), True )
  3651. PreProcessNextToke(toker)
  3652. Repeat
  3653. If line
  3654. source.AddLast "~n"
  3655. While toker.Toke() And Not toker.Toke().Endswith("~n") And toker.TokeType()<>TOKE_LINECOMMENT
  3656. PreProcessNextToke(toker)
  3657. Wend
  3658. If Not toker.Toke() Exit
  3659. PreProcessNextToke(toker)
  3660. EndIf
  3661. line :+ 1
  3662. ' catch up with any skipped lines
  3663. While line < toker._line - 1
  3664. line:+1
  3665. source.AddLast "~n"
  3666. Wend
  3667. If toker.TokeType()=TOKE_SPACE And Not toker.Toke().Endswith("~n") PreProcessNextToke(toker)
  3668. If toker.Toke()<>"?"
  3669. If con
  3670. Local textline$
  3671. While toker.Toke() And toker.Toke()<>"~n" And toker.TokeType()<>TOKE_LINECOMMENT
  3672. Local toke$=toker.Toke()
  3673. textline:+toke
  3674. toker.NextToke()
  3675. Wend
  3676. If textline Then
  3677. source.AddLast textline
  3678. EndIf
  3679. EndIf
  3680. Continue
  3681. EndIf
  3682. Local stm$= PreProcessNextToke(toker).ToLower()
  3683. 'toker.NextToke()
  3684. Local isNot:Int = False
  3685. If stm = "not" Then
  3686. If toker.TokeType()=TOKE_SPACE PreProcessNextToke(toker)
  3687. stm = toker.Toke().ToLower()
  3688. isNot = True
  3689. End If
  3690. 'If stm="end" Or stm="else"
  3691. ' If toker.TokeType()=TOKE_SPACE toker.NextToke()
  3692. ' If toker.Toke().ToLower()="if"
  3693. ' toker.NextToke()
  3694. ' stm:+"if"
  3695. ' EndIf
  3696. 'EndIf
  3697. Rem
  3698. Debug True if program is being compiled in debug mode.
  3699. Threaded True if program is being compiled in threaded mode.
  3700. Win32 True if program is being compiled for the Windows operating system.
  3701. MacOS True if program is being compiled for the MacOS operating system.
  3702. Linux True if program is being compiled for the Linux operating system.
  3703. X86 True if program is being compiled for the Intel CPU.
  3704. PPC True if program is being compiled for the PowerPC CPU.
  3705. MacOSX86 True if program is being compiled for an Intel Mac.
  3706. MacOSPPC True if program is being compiled for a PowerPC Mac.
  3707. BigEndian True if program is being compiled for a big endian CPU.
  3708. LittleEndian
  3709. End Rem
  3710. Select stm
  3711. Case "~r", "~n"
  3712. 'ifnest = 0
  3713. con = 1
  3714. Default
  3715. ' test for EOF
  3716. If Not toker.Toke() Exit
  3717. con = 0
  3718. Try
  3719. If Eval( toker,New TIntType ) = "1" con = 1
  3720. Catch Error:String
  3721. con = 0
  3722. End Try
  3723. Rem
  3724. Case "macos", "macosx86", "x86", "littleendian", "bigendian"
  3725. con = 1
  3726. ' If con=ifnest
  3727. ' If Eval( toker,TType.intType ) con:+1
  3728. ' EndIf
  3729. '
  3730. ifnest = 1
  3731. ' Case "rem"
  3732. '
  3733. ' ifnest:+1
  3734. Case "threaded", "win32", "linux", "ppc", "win32x86", "linuxx86", "macosppc"
  3735. If isNot Then
  3736. con = 1
  3737. Else
  3738. con = 0
  3739. End If
  3740. ifnest = 1
  3741. Case "else","elseif"
  3742. If Not ifnest Err "#Else without #If"
  3743. If con=ifnest
  3744. con=-con
  3745. Else If con=ifnest-1
  3746. If stm="elseif"
  3747. If Eval( toker,TType.intType ) con:+1
  3748. Else
  3749. con:+1
  3750. EndIf
  3751. EndIf
  3752. Case "end","endif"
  3753. If Not ifnest Err "#End without #If"
  3754. ifnest:-1
  3755. If con<0 con=-con
  3756. If ifnest<con con=ifnest
  3757. ' Case "print"
  3758. ' If con=ifnest
  3759. ' TODO
  3760. 'Print ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3761. ' EndIf
  3762. ' Case "error"
  3763. ' If con=ifnest
  3764. ' TODO
  3765. 'Err ReplaceEnvTags( Eval( toker,TType.stringType ) )
  3766. ' EndIf
  3767. Default
  3768. Err "Unrecognized preprocessor directive '"+stm+"'."
  3769. End Rem
  3770. End Select
  3771. Forever
  3772. Return source.Join( "" )
  3773. End Function
  3774. Function ParseModule:TModuleDecl( path$,app:TAppDecl )
  3775. 'Local source$=PreProcess( path )
  3776. Local source:String = LoadText(path)
  3777. Local toker:TToker=New TToker.Create( path,source )
  3778. Local parser:TParser=New TParser.Create( toker,app )
  3779. parser.ParseMain
  3780. Return parser._module
  3781. End Function
  3782. Function AppendLibInit:String(source:String)
  3783. Local sb:TStringBuffer = TStringBuffer.Create(source)
  3784. sb.Append("~n")
  3785. sb.Append("Extern~n")
  3786. sb.Append("Function bbLibInit()~n")
  3787. sb.Append("End Extern~n")
  3788. sb.Append("Function InitBRL() Export~n")
  3789. sb.Append("bbLibInit()~n")
  3790. sb.Append("End Function~n")
  3791. Return sb.ToString()
  3792. End Function
  3793. '***** PUBLIC API ******
  3794. Function ParseApp:TAppDecl( path$ )
  3795. Local app:TAppDecl=New TAppDecl
  3796. _appInstance = app
  3797. Local source$=PreProcess( path )
  3798. 'Local source:String = LoadString(path)
  3799. If opt_makelib And opt_apptype Then
  3800. source = AppendLibInit(source)
  3801. End If
  3802. Local toker:TToker=New TToker.Create( path,source )
  3803. Local parser:TParser=New TParser.Create( toker,app )
  3804. parser.ParseMain
  3805. Return app
  3806. End Function
  3807. Function MungModuleName:String(ident:Object)
  3808. Local mung:String
  3809. If String(ident) Then
  3810. Local id:String = String(ident)
  3811. mung = "__bb_" + id + "_" + id[id.Find(".") + 1..]
  3812. Else
  3813. Local mdecl:TModuleDecl = TModuleDecl(ident)
  3814. If mdecl Then
  3815. Local id:String = mdecl.ident
  3816. Local dir:String = ExtractDir(mdecl.filepath).ToLower()
  3817. dir = dir[dir.findLast("/") + 1..]
  3818. If dir.EndsWith(".mod") Then
  3819. dir = ""
  3820. Else
  3821. dir :+ "_"
  3822. End If
  3823. mung = "__bb_" + id + "_" + dir + id[id.Find(".") + 1..]
  3824. End If
  3825. End If
  3826. 'return sanitized, remove non-allowed chars
  3827. Return TStringHelper.Sanitize(mung)
  3828. End Function
  3829. Function EvalS$( source$,ty:TType )
  3830. Local env:TScopeDecl=New TScopeDecl
  3831. ' debug/release
  3832. env.InsertDecl New TConstDecl.Create( "debug",New TIntType,New TConstExpr.Create( New TIntType,opt_debug ),0 )
  3833. env.InsertDecl New TConstDecl.Create( "gdbdebug",New TIntType,New TConstExpr.Create( New TIntType,opt_gdbdebug ),0 )
  3834. ' threaded
  3835. env.InsertDecl New TConstDecl.Create( "threaded",New TIntType,New TConstExpr.Create( New TIntType,opt_threaded ),0 )
  3836. ' macos
  3837. 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 )
  3838. 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 )
  3839. 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 )
  3840. 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 )
  3841. 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 )
  3842. ' osx
  3843. env.InsertDecl New TConstDecl.Create( "osx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="macos" Or opt_platform="osx" ),0 )
  3844. 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 )
  3845. 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 )
  3846. 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 )
  3847. 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 )
  3848. ' ios
  3849. env.InsertDecl New TConstDecl.Create( "ios",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" ),0 )
  3850. env.InsertDecl New TConstDecl.Create( "iosx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x86"),0 )
  3851. env.InsertDecl New TConstDecl.Create( "iosx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="x64"),0 )
  3852. env.InsertDecl New TConstDecl.Create( "iosarmv7",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="armv7"),0 )
  3853. env.InsertDecl New TConstDecl.Create( "iosarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="ios" And opt_arch="arm64"),0 )
  3854. ' windows
  3855. env.InsertDecl New TConstDecl.Create( "win32",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" ),0 )
  3856. env.InsertDecl New TConstDecl.Create( "win32x86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="x86"),0 )
  3857. 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 )
  3858. 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 )
  3859. env.InsertDecl New TConstDecl.Create( "win32armv7",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="armv7"),0 )
  3860. env.InsertDecl New TConstDecl.Create( "win32arm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="win32" And opt_arch="arm64"),0 )
  3861. ' linux
  3862. 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 )
  3863. 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 )
  3864. 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 )
  3865. 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 )
  3866. 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 )
  3867. env.InsertDecl New TConstDecl.Create( "linuxriscv32",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="linux" And opt_arch="riscv32")),0 )
  3868. env.InsertDecl New TConstDecl.Create( "linuxriscv64",New TIntType,New TConstExpr.Create( New TIntType, (opt_platform="linux" And opt_arch="riscv64")),0 )
  3869. ' android
  3870. env.InsertDecl New TConstDecl.Create( "android",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" ),0 )
  3871. env.InsertDecl New TConstDecl.Create( "androidx86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x86"),0 )
  3872. env.InsertDecl New TConstDecl.Create( "androidx64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="x64"),0 )
  3873. 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 )
  3874. env.InsertDecl New TConstDecl.Create( "androidarmeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabi"),0 )
  3875. env.InsertDecl New TConstDecl.Create( "androidarmeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="armeabiv7a"),0 )
  3876. env.InsertDecl New TConstDecl.Create( "androidarm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="android" And opt_arch="arm64v8a"),0 )
  3877. ' raspberrypi - ARM only
  3878. 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 )
  3879. env.InsertDecl New TConstDecl.Create( "raspberrypiarm",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm"),0 )
  3880. env.InsertDecl New TConstDecl.Create( "raspberrypiarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="raspberrypi" And opt_arch="arm64"),0 )
  3881. ' haiku
  3882. 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 )
  3883. env.InsertDecl New TConstDecl.Create( "haikux86",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="haiku" And opt_arch="x86"),0 )
  3884. env.InsertDecl New TConstDecl.Create( "haikux64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="haiku" And opt_arch="x64"),0 )
  3885. ' emscripten
  3886. env.InsertDecl New TConstDecl.Create( "emscripten",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" ),0 )
  3887. env.InsertDecl New TConstDecl.Create( "emscriptenjs",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="emscripten" And opt_arch="js"),0 )
  3888. ' arch
  3889. env.InsertDecl New TConstDecl.Create( "ppc",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3890. env.InsertDecl New TConstDecl.Create( "x86",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x86" ),0 )
  3891. env.InsertDecl New TConstDecl.Create( "x64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="x64" ),0 )
  3892. 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 )
  3893. env.InsertDecl New TConstDecl.Create( "armeabi",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabi" ),0 )
  3894. env.InsertDecl New TConstDecl.Create( "armeabiv7a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armeabiv7a" ),0 )
  3895. env.InsertDecl New TConstDecl.Create( "arm64v8a",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64v8a" ),0 )
  3896. env.InsertDecl New TConstDecl.Create( "js",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="js" ),0 )
  3897. env.InsertDecl New TConstDecl.Create( "armv7",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="armv7" ),0 )
  3898. env.InsertDecl New TConstDecl.Create( "arm64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="arm64" ),0 )
  3899. env.InsertDecl New TConstDecl.Create( "riscv32",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="riscv32" ),0 )
  3900. env.InsertDecl New TConstDecl.Create( "riscv64",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="riscv64" ),0 )
  3901. 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 )
  3902. 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 )
  3903. ' endian
  3904. env.InsertDecl New TConstDecl.Create( "bigendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch="ppc" ),0 )
  3905. env.InsertDecl New TConstDecl.Create( "littleendian",New TIntType,New TConstExpr.Create( New TIntType,opt_arch<>"ppc" ),0 )
  3906. ' opengles target platform
  3907. 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 )
  3908. ' musl - linux only
  3909. 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 )
  3910. ' nx / switch
  3911. env.InsertDecl New TConstDecl.Create( "nx",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" ),0 )
  3912. env.InsertDecl New TConstDecl.Create( "nxarm64",New TIntType,New TConstExpr.Create( New TIntType,opt_platform="nx" And opt_arch="arm64"),0 )
  3913. ' new compiler
  3914. env.InsertDecl New TConstDecl.Create( "bmxng",New TIntType,New TConstExpr.Create( New TIntType, True ),0 )
  3915. ' coverage
  3916. env.InsertDecl New TConstDecl.Create( "coverage",New TIntType,New TConstExpr.Create( New TIntType, opt_coverage ),0 )
  3917. ' console or gui build?
  3918. env.InsertDecl New TConstDecl.Create( "console",New TIntType,New TConstExpr.Create( New TIntType, opt_apptype = APPTYPE_CONSOLE ),0 )
  3919. env.InsertDecl New TConstDecl.Create( "gui",New TIntType,New TConstExpr.Create( New TIntType, opt_apptype = APPTYPE_GUI ),0 )
  3920. ' user defines
  3921. If opt_userdefs Then
  3922. Local defs:String[] = opt_userdefs.ToLower().Split(",")
  3923. For Local def:String = EachIn defs
  3924. def = def.Trim()
  3925. If def Then
  3926. Local name:String = def
  3927. Local value:Int = 1
  3928. Local dp:String[] = def.Split("=")
  3929. If dp.length = 2 Then
  3930. name = dp[0].Trim()
  3931. value = Int(dp[1])
  3932. End If
  3933. env.InsertDecl New TConstDecl.Create( name,New TIntType,New TConstExpr.Create( New TIntType, value ),0 )
  3934. End If
  3935. Next
  3936. End If
  3937. PushEnv env
  3938. Local toker:TToker=New TToker.Create( "",source )
  3939. Local parser:TParser=New TParser.Create( toker,Null,True )
  3940. Local val:String
  3941. Try
  3942. Local expr:TExpr=parser.ParseExpr()
  3943. expr=expr.Semant()
  3944. If ty expr=expr.Cast( ty )
  3945. val=expr.Eval()
  3946. Catch error:String
  3947. val = "0"
  3948. End Try
  3949. PopEnv
  3950. Return val
  3951. End Function
  3952. Type TCastDets
  3953. Field name:String
  3954. Field retType:String
  3955. Field noGen:Int
  3956. Field args:String[0]
  3957. Field api:String
  3958. End Type