M2.atg 199 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451
  1. COMPILER M2
  2. (* Step 1 — minimal integer pipeline (m2compiler-V3).
  3. Subset: program MODULE + CONST (literal) + VAR INTEGER +
  4. assignment + integer expressions (+ - * DIV MOD, leading sign,
  5. parens). Fresh QBE backend (QbeGen) to gen_ssa/<Module>.ssa;
  6. assemble with qbe, link with cc.
  7. Test convention: a global VAR ExitCode : INTEGER makes generated
  8. $main return its value as the process exit code, else return 0.
  9. Semantic errors reuse the V1/V2/Test2 family: 200 duplicate,
  10. 201 undeclared, 202 module name mismatch, 210 bad assignment,
  11. 211 bad arithmetic, 221 not a type, 230 not supported yet,
  12. 231 opaque type outside definition.
  13. Scalar-phase TYPEs (named, integer subrange, enum) check fully;
  14. composite forms wait for step 3. Procedure headings (formals,
  15. result, FORWARD) enter scopes now; bodies parse + check with one
  16. 230 at END (lowering = step 4).
  17. Statements: assignment, IF/ELSIF/ELSE, WHILE, REPEAT/UNTIL,
  18. LOOP/EXIT (230 outside LOOP), FOR/TO/static-sign-BY, full CASE
  19. (labels, ranges, ELSE; compare-chain), RETURN with 232 checks
  20. (outside proc / value mismatch / missing value). WITH waits for
  21. records (step 3). Boolean connectives are eager (or/and/xor);
  22. relations yield 0/1 via cXXw.
  23. Clarion-form classes (docs/OOP.txt): CLASS decl + single
  24. inheritance + CLASS IMPLEMENTATION blocks, methods with ";"
  25. (per the Table example, not the sketch's ","), VIRTUAL flagged.
  26. Scopes and member checks now; lowering later (one 230 per
  27. class/impl block). Classic identifiers: no underscores, so the
  28. Table example's _names stay lexically out of reach.
  29. Step 3.1 arrays: "ARRAY [lo..hi, ...] OF T" (folded literal
  30. bounds, int/char) and open "ARRAY OF T" formals; index suffixes
  31. with per-level checks (217/218, trap on breach via $abort);
  32. whole-array ":=" with runtime count check + blit; string
  33. literals lower as descriptors (1-char stays CHAR, empty works);
  34. array/string "=" is 213 (no built-in whole comparison).
  35. Step 3.3 sets: multi-word masks (no header, static words) over
  36. bases ≤ 256 values; literals are SET OF [0..255] (222 on
  37. out-of-span); + - * / as or/and/xor-not, IN with span trap,
  38. =/# word-wise (lenient cross-base); CASE labels reject sets.
  39. Step 3.4 records: flat blobs; array fields are pointers to static
  40. descriptors (locked amendment — one layout per type); nested
  41. records inline; static declaration-order offsets; field chains
  42. mix with indexes; WITH pushes fields + bases (215/216);
  43. whole-record deep copy; record/set/class "=" is 213.
  44. Step 3.6 pointers: vars (l), NIL as a real type (FNil — assignment
  45. and =/# work, everything else 210-214/222), ^ deref with sfx
  46. discipline (address flows, load at use; chains compose),
  47. pointer =/# via ceql/cnel (< > etc. are 213), NEW/DISPOSE as
  48. builtin statements via extern malloc/free (recursive skeleton
  49. init; DISPOSE shallow and nils, deviating from Wirth-undefined);
  50. nil-deref is raw (no check). *)
  51. IMPORT SymTab, QbeGen, AST, Lower, Check;
  52. VAR
  53. (* Two-phase frontend (docs/plan-two-phase.md). When TRUE the
  54. productions ALSO build AST nodes alongside the legacy emit path.
  55. Slice 1: the nodes are inert scaffolding — nothing reads them, so
  56. the emitted output is unchanged. *)
  57. twoPhase: BOOLEAN;
  58. (* Result slot for the expression-AST builder (slice 2). Every
  59. Expr/SimExpr/Term/Fact leaves its node here; the combination
  60. productions save it into locals before parsing the next operand.
  61. `astIsLit` in Fact is per-invocation, so a nested Fact cannot make
  62. an outer non-literal Fact look literal. *)
  63. astCur: AST.Node;
  64. (* Actual-argument nodes collected by ActParam for the call being
  65. parsed by ArgList (slice 4). Fact resets the count before the
  66. optional ArgList and then folds the nodes into an NkCall. *)
  67. astNArgs: CARDINAL;
  68. astArgs: ARRAY [0 .. 31] OF AST.Node;
  69. (* Statement-AST result slot (slice 5): the most recently parsed
  70. statement. StatSeq folds these into an NkBlock. *)
  71. astStmt: AST.Node;
  72. (* Declaration-AST result slot (slice 6): the most recently built
  73. declaration; DeclSeq folds these into an NkDeclSeq. *)
  74. astDecl: AST.Node;
  75. (* The local declarations of the most recent Block (a procedure body);
  76. ProcDecl stores them as the proc node's child 2. *)
  77. astBlkDecls: AST.Node;
  78. (* Unit-AST root (slice 7): NkUnit(name, decls, body). *)
  79. astUnit: AST.Node;
  80. (* Import accumulator (slice 11): `{ Import }` appends NkImport
  81. nodes here; each unit stores them as NkUnit child[3]. *)
  82. astImp, astImpTail: AST.Node;
  83. (* Class-AST accumulators (slice 13): the class node currently being
  84. parsed and its parent/field/method lists. Classes are not nested
  85. inside one another, so module-level state is safe. *)
  86. astCls, astClsP, astClsPTail, astClsF, astClsFTail,
  87. astClsM, astClsMTail, astMethod: AST.Node;
  88. (* Class of the method named by the last `obj.Method` designator
  89. (InvalidType when the callee is an ordinary procedure). Set by
  90. Design, consumed by the following ArgList. *)
  91. methCls: SymTab.TypeIndex;
  92. (* Class of the type of the innermost `TypeName{...}` brace
  93. constructor (ClSet or ClArray); dispatches BraceElem. *)
  94. braceCls: INTEGER;
  95. (* Module-level VAR declarations whose type was still an unresolved
  96. forward alias at declaration time; emitted once the TYPE block
  97. completes (module scope only). *)
  98. nPendVar: CARDINAL;
  99. pendVarName: ARRAY [0 .. 255] OF SymTab.Name;
  100. pendVarT: ARRAY [0 .. 255] OF SymTab.TypeIndex;
  101. (* Forward module-level variables referenced from a procedure body. *)
  102. (* GOTO/labels: the label and goto names of the procedure being parsed,
  103. reset per procedure and checked at its END. *)
  104. nLab, nGot: CARDINAL;
  105. labNm, gotNm: ARRAY [0 .. 255] OF SymTab.Name;
  106. (* Generics (Increment 1): the last refining module seen — instance
  107. name, generic name, and the actual type parameters. *)
  108. refInst, refGen: SymTab.Name;
  109. refN: CARDINAL;
  110. refActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
  111. isGen: BOOLEAN;
  112. (* Generics (Increment 2): instantiation re-parse context. When the
  113. driver re-parses a generic's source to instantiate it as `instName`,
  114. instActive is TRUE, the module is renamed, and each type formal is
  115. bound to the corresponding instActual entry. *)
  116. instActive: BOOLEAN;
  117. instName: SymTab.Name;
  118. instActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
  119. instN: CARDINAL;
  120. instFk: CARDINAL; (* formal cursor while binding during re-parse *)
  121. (* Identity of the last-parsed unit and refinement, for the driver's
  122. generic registry and its re-parse decision. *)
  123. unitName: SymTab.Name;
  124. unitWasGen: BOOLEAN;
  125. unitWasDef: BOOLEAN;
  126. refSeen: BOOLEAN;
  127. refIsDef: BOOLEAN;
  128. PROCEDURE CopyNm (src: ARRAY OF CHAR; VAR dst: SymTab.Name);
  129. VAR i: CARDINAL;
  130. BEGIN
  131. i := 0;
  132. WHILE (i <= HIGH(dst)) AND (i <= HIGH(src)) AND (src[i] # CHR(0)) DO
  133. dst[i] := src[i]; INC(i)
  134. END;
  135. IF i <= HIGH(dst) THEN dst[i] := CHR(0) END
  136. END CopyNm;
  137. PROCEDURE InInst () : BOOLEAN;
  138. BEGIN RETURN instActive END InInst;
  139. PROCEDURE InstNameGet (VAR nm: SymTab.Name);
  140. BEGIN CopyNm(instName, nm) END InstNameGet;
  141. PROCEDURE InstActualGet (i: CARDINAL) : SymTab.TypeIndex;
  142. BEGIN
  143. IF i >= instN THEN RETURN SymTab.InvalidType END;
  144. RETURN instActual[i]
  145. END InstActualGet;
  146. PROCEDURE InstBegin (name: ARRAY OF CHAR);
  147. BEGIN instActive := TRUE; CopyNm(name, instName); instN := 0;
  148. instFk := 0 END InstBegin;
  149. PROCEDURE InstAddActual (t: SymTab.TypeIndex);
  150. BEGIN
  151. IF instN <= HIGH(instActual) THEN instActual[instN] := t; INC(instN) END
  152. END InstAddActual;
  153. PROCEDURE InstEnd;
  154. BEGIN instActive := FALSE; instN := 0 END InstEnd;
  155. PROCEDURE UnitNameGet (VAR nm: SymTab.Name);
  156. BEGIN CopyNm(unitName, nm) END UnitNameGet;
  157. PROCEDURE UnitIsGeneric () : BOOLEAN;
  158. BEGIN RETURN unitWasGen END UnitIsGeneric;
  159. PROCEDURE UnitIsDefModule () : BOOLEAN;
  160. BEGIN RETURN unitWasDef END UnitIsDefModule;
  161. PROCEDURE RefineSeen () : BOOLEAN;
  162. BEGIN RETURN refSeen END RefineSeen;
  163. PROCEDURE RefineIsDef () : BOOLEAN;
  164. BEGIN RETURN refIsDef END RefineIsDef;
  165. PROCEDURE RefineInst (VAR nm: SymTab.Name);
  166. BEGIN CopyNm(refInst, nm) END RefineInst;
  167. PROCEDURE RefineGen (VAR nm: SymTab.Name);
  168. BEGIN CopyNm(refGen, nm) END RefineGen;
  169. PROCEDURE RefineActualCount () : CARDINAL;
  170. BEGIN RETURN refN END RefineActualCount;
  171. PROCEDURE RefineActualGet (i: CARDINAL) : SymTab.TypeIndex;
  172. BEGIN
  173. IF i >= refN THEN RETURN SymTab.InvalidType END;
  174. RETURN refActual[i]
  175. END RefineActualGet;
  176. PROCEDURE NoteLabel (nm: ARRAY OF CHAR);
  177. (* Record a statement label; duplicate is 200. *)
  178. VAR i: CARDINAL;
  179. BEGIN
  180. i := 0;
  181. WHILE i < nLab DO
  182. IF SymTab.Equal(labNm[i], nm) THEN SemError(200); RETURN END;
  183. INC(i)
  184. END;
  185. IF nLab <= HIGH(labNm) THEN
  186. CopyNm(nm, labNm[nLab]); INC(nLab)
  187. END
  188. END NoteLabel;
  189. PROCEDURE NoteGoto (nm: ARRAY OF CHAR);
  190. VAR i: CARDINAL;
  191. BEGIN
  192. i := 0;
  193. WHILE i < nGot DO
  194. IF SymTab.Equal(gotNm[i], nm) THEN RETURN END;
  195. INC(i)
  196. END;
  197. IF nGot <= HIGH(gotNm) THEN
  198. CopyNm(nm, gotNm[nGot]); INC(nGot)
  199. END
  200. END NoteGoto;
  201. PROCEDURE CheckGotos;
  202. (* At a procedure's END: every GOTO must name a label in that procedure. *)
  203. VAR i, j: CARDINAL; found: BOOLEAN;
  204. BEGIN
  205. i := 0;
  206. WHILE i < nGot DO
  207. found := FALSE; j := 0;
  208. WHILE (j < nLab) AND NOT found DO
  209. IF SymTab.Equal(labNm[j], gotNm[i]) THEN found := TRUE END;
  210. INC(j)
  211. END;
  212. IF NOT found THEN SemError(201) END;
  213. INC(i)
  214. END
  215. END CheckGotos;
  216. PROCEDURE FlushPend;
  217. (* Emit module-level globals whose forward type is now resolved. *)
  218. VAR k: CARDINAL;
  219. BEGIN
  220. k := 0;
  221. WHILE k < nPendVar DO
  222. INC(k)
  223. END;
  224. nPendVar := 0
  225. END FlushPend;
  226. PROCEDURE AstAppend (kind: INTEGER; VAR head, tail: AST.Node;
  227. item: AST.Node);
  228. (* Appends `item` to a chunked sequence: each node holds up to
  229. AST.MaxChild-1 items; child[MaxChild-1] continues into the next
  230. chunk. Unbounded, so blocks/decl sequences are not capped at 8. *)
  231. VAR n: AST.Node;
  232. BEGIN
  233. IF item = AST.NoNode THEN RETURN END;
  234. IF head = AST.NoNode THEN
  235. head := AST.MakeNode(kind); tail := head
  236. END;
  237. IF AST.NChild(tail) >= AST.MaxChild - 1 THEN
  238. n := AST.MakeNode(kind);
  239. AST.SetChild(tail, AST.MaxChild - 1, n);
  240. tail := n
  241. END;
  242. AST.SetChild(tail, AST.NChild(tail), item)
  243. END AstAppend;
  244. PROCEDURE AstCallNode (callee: AST.Node) : AST.Node;
  245. (* Builds NkCall(callee, actuals...) from astArgs/astNArgs. The actuals
  246. are a chunked sequence (AstAppend): a call can have more than
  247. MaxChild-1 arguments (the generic ArgList has 9), and SetChild would
  248. silently drop the tail. NkBlock marks the continuation chunks. *)
  249. VAR n, tail: AST.Node; j: CARDINAL;
  250. BEGIN
  251. n := AST.MakeNode(AST.NkCall);
  252. AST.SetChild(n, 0, callee);
  253. tail := n;
  254. j := 0;
  255. WHILE j < astNArgs DO
  256. AstAppend(AST.NkBlock, n, tail, astArgs[j]);
  257. INC(j)
  258. END;
  259. RETURN n
  260. END AstCallNode;
  261. PROCEDURE GetUnit (): AST.Node;
  262. (* The most recently parsed unit's AST root (for the Lower comparison). *)
  263. BEGIN
  264. RETURN astUnit
  265. END GetUnit;
  266. CHARACTERS
  267. eol = CHR(13) .
  268. lf = CHR(10) .
  269. letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
  270. digit = "0123456789" .
  271. hexDigit = digit + "ABCDEFabcdef" .
  272. noQuote1 = ANY - "'" - eol .
  273. noQuote2 = ANY - '"' - eol .
  274. IGNORE CHR(9) .. CHR(13)
  275. COMMENTS FROM "(*" TO "*)" NESTED
  276. COMMENTS FROM "//" TO lf
  277. TOKENS
  278. ident = letter { letter | digit | "_" } .
  279. integer = digit { digit }
  280. | digit { digit } CONTEXT("..")
  281. | "0x" hexDigit { hexDigit }
  282. | "0X" hexDigit { hexDigit } .
  283. real = digit { digit } "." { digit }
  284. [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
  285. string = "'" { noQuote1 } "'"
  286. | '"' { noQuote2 } '"' .
  287. charConst = digit { digit } ( "C" | "c" ) .
  288. ustring = ( "U" | "u" ) ( "'" { noQuote1 } "'" | '"' { noQuote2 } '"' ) .
  289. PRODUCTIONS
  290. M2
  291. = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
  292. astImp := AST.NoNode;
  293. astImpTail := AST.NoNode; .)
  294. Unit "." .
  295. (* Units: program modules compile fully; DEFINITION and
  296. IMPLEMENTATION modules parse + check now but lower in step 4
  297. (each ends with one 230); same for nested local modules. *)
  298. (* Generics (Increment 1): formal and actual parameters. Formals are
  299. TYPE parameters only; actuals are type identifiers. *)
  300. GenericFormals
  301. = "(" GenericFormal { ";" GenericFormal } ")" .
  302. GenericFormal (. VAR nm: SymTab.Name; .)
  303. = GetIdent<nm> (. IF instActive THEN
  304. IF NOT SymTab.EnterTypeParamBound(nm,
  305. InstActualGet(instFk)) THEN
  306. SemError(200) END
  307. ELSIF NOT SymTab.EnterTypeParam(nm) THEN
  308. SemError(200) END;
  309. INC(instFk); .)
  310. { "," GetIdent<nm> (. IF instActive THEN
  311. IF NOT SymTab.EnterTypeParamBound(nm,
  312. InstActualGet(instFk)) THEN
  313. SemError(200) END
  314. ELSIF NOT SymTab.EnterTypeParam(nm) THEN
  315. SemError(200) END;
  316. INC(instFk); .) }
  317. ":" "TYPE" .
  318. Actuals
  319. = Actual { "," Actual } .
  320. Actual (. VAR at: SymTab.TypeIndex; .)
  321. = TypeIdent<at> (. IF refN <= HIGH(refActual) THEN
  322. refActual[refN] := at; INC(refN)
  323. END; .) .
  324. Unit
  325. = (. isGen := FALSE; .)
  326. [ "GENERIC" (. isGen := TRUE; .) ]
  327. ( DefUnit | ImplUnit | ProgModule ) .
  328. (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
  329. and one program (last) into one image. Units share the symbol
  330. table; imports materialize exported names. *)
  331. DefUnit (. VAR m1, m2, pn: SymTab.Name;
  332. g: SymTab.Name;
  333. astSeq, astTail, astProc: AST.Node; .)
  334. = (. refN := 0; refSeen := FALSE; .)
  335. "DEFINITION" "MODULE"
  336. GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
  337. IF instActive THEN
  338. IF NOT SymTab.Reenter(m1,
  339. SymTab.UnitDef) THEN
  340. SemError(200) END
  341. ELSIF NOT SymTab.BeginDef(m1) THEN
  342. SemError(200) END;
  343. QbeGen.SetModule(m1);
  344. CopyNm(m1, unitName);
  345. unitWasGen := isGen
  346. AND NOT instActive;
  347. unitWasDef := TRUE; .)
  348. [ GenericFormals ]
  349. ( ";"
  350. { Import (. AstAppend(AST.NkDeclSeq,
  351. astImp, astImpTail, astDecl); .) }
  352. [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
  353. list: parsed, and the
  354. names are already exported
  355. by the module scope *) .)
  356. GetIdent<pn> { "," GetIdent<pn> } ";" ]
  357. (. astSeq := AST.NoNode;
  358. astTail := AST.NoNode; .)
  359. { ConstBlock (. AstAppend(AST.NkDeclSeq,
  360. astSeq, astTail, astDecl); .)
  361. | TypeBlock<TRUE> (. AstAppend(AST.NkDeclSeq,
  362. astSeq, astTail, astDecl); .)
  363. | VarBlock (. AstAppend(AST.NkDeclSeq,
  364. astSeq, astTail, astDecl); .)
  365. | ProcHeading<pn, SymTab.InvalidType> ";"
  366. (. (* a heading only: record it so
  367. Lower can replay it *)
  368. astProc := AST.MakeNode(AST.NkProcDecl);
  369. AST.SetOp(astProc, 0);
  370. AST.SetChild(astProc, 0,
  371. AST.MakeLeaf(AST.NkIdent, pn));
  372. AstAppend(AST.NkDeclSeq,
  373. astSeq, astTail, astProc);
  374. Lower.NoteProcNode(astProc);
  375. Lower.ScopeLeave;
  376. SymTab.CloseProc;
  377. QbeGen.AbortFunc; .) }
  378. (. astUnit := AST.MakeNode(AST.NkUnit);
  379. AST.SetChild(astUnit, 0,
  380. AST.MakeLeaf(AST.NkIdent, m1));
  381. AST.SetChild(astUnit, 1, astSeq);
  382. AST.SetChild(astUnit, 3, astImp);
  383. astDecl := AST.NoNode;
  384. astStmt := AST.NoNode; .)
  385. "END"
  386. GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
  387. IF NOT SymTab.Equal(m1, m2) THEN
  388. SemError(202) END;
  389. SymTab.EndUnit; .)
  390. | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
  391. (. CopyNm(m1, refInst);
  392. CopyNm(g, refGen);
  393. refSeen := TRUE; refIsDef := TRUE;
  394. astUnit := AST.MakeNode(AST.NkUnit);
  395. AST.SetChild(astUnit, 0,
  396. AST.MakeLeaf(AST.NkIdent, m1));
  397. astDecl := AST.NoNode;
  398. astStmt := AST.NoNode; .)
  399. "END"
  400. GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
  401. SemError(202) END;
  402. SymTab.EndUnit; .) ) .
  403. ImplUnit (. VAR m1, m2: SymTab.Name;
  404. g: SymTab.Name;
  405. k: CARDINAL;
  406. fname: SymTab.Name;
  407. unres: BOOLEAN;
  408. astNode: AST.Node; .)
  409. = (. refN := 0; refSeen := FALSE; .)
  410. "IMPLEMENTATION" "MODULE"
  411. GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
  412. IF instActive THEN
  413. IF NOT SymTab.Reenter(m1,
  414. SymTab.UnitImpl) THEN
  415. SemError(201) END
  416. ELSIF NOT SymTab.BeginImpl(m1) THEN
  417. SemError(201) END;
  418. astStmt := AST.NoNode;
  419. astDecl := AST.NoNode;
  420. astImp := AST.NoNode;
  421. astImpTail := AST.NoNode;
  422. nPendVar := 0;
  423. CopyNm(m1, unitName);
  424. unitWasGen := isGen AND NOT instActive;
  425. unitWasDef := FALSE;
  426. QbeGen.SetModule(m1); .)
  427. [ GenericFormals ]
  428. ( ";"
  429. { Import (. AstAppend(AST.NkDeclSeq,
  430. astImp, astImpTail, astDecl); .) }
  431. DeclSeq (. astStmt := AST.NoNode; .)
  432. [ "BEGIN" (. FlushPend;
  433. k := 0;
  434. WHILE k < SymTab.FwdPending() DO
  435. SymTab.FwdInfo(k, fname, unres);
  436. IF unres THEN SemError(201) END;
  437. INC(k)
  438. END;
  439. SymTab.FwdClear;
  440. nLab := 0; nGot := 0; .)
  441. [ StatSeq ] ]
  442. "END"
  443. GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
  444. FlushPend;
  445. k := 0;
  446. WHILE k < SymTab.FwdPending() DO
  447. SymTab.FwdInfo(k, fname, unres);
  448. IF unres THEN SemError(201) END;
  449. INC(k)
  450. END;
  451. SymTab.FwdClear;
  452. astNode := AST.MakeNode(AST.NkUnit);
  453. AST.SetChild(astNode, 0,
  454. AST.MakeLeaf(AST.NkIdent, m1));
  455. AST.SetChild(astNode, 1, astDecl);
  456. AST.SetChild(astNode, 2, astStmt);
  457. AST.SetChild(astNode, 3, astImp);
  458. astUnit := astNode;
  459. IF NOT SymTab.Equal(m1, m2) THEN
  460. SemError(202) END;
  461. CheckGotos;
  462. SymTab.EndUnit; .)
  463. | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
  464. (. CopyNm(m1, refInst);
  465. CopyNm(g, refGen);
  466. refSeen := TRUE; refIsDef := FALSE;
  467. astNode := AST.MakeNode(AST.NkUnit);
  468. AST.SetChild(astNode, 0,
  469. AST.MakeLeaf(AST.NkIdent, m1));
  470. astDecl := AST.NoNode;
  471. astStmt := AST.NoNode; .)
  472. "END"
  473. GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
  474. SemError(202) END;
  475. SymTab.EndUnit; .) ) .
  476. ProgModule (. VAR m1, m2: SymTab.Name;
  477. k: CARDINAL;
  478. fname: SymTab.Name;
  479. unres: BOOLEAN;
  480. astNode: AST.Node; .)
  481. = "MODULE"
  482. GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
  483. SemError(200) END;
  484. astStmt := AST.NoNode;
  485. astDecl := AST.NoNode;
  486. astImp := AST.NoNode;
  487. astImpTail := AST.NoNode;
  488. nPendVar := 0;
  489. QbeGen.SetModule(m1); .)
  490. [ Priority ]
  491. ";"
  492. { Import (. AstAppend(AST.NkDeclSeq,
  493. astImp, astImpTail, astDecl); .) }
  494. DeclSeq (. astStmt := AST.NoNode; .)
  495. [ "BEGIN" (. FlushPend;
  496. k := 0;
  497. WHILE k < SymTab.FwdPending() DO
  498. SymTab.FwdInfo(k, fname, unres);
  499. IF unres THEN SemError(201) END;
  500. INC(k)
  501. END;
  502. SymTab.FwdClear;
  503. nLab := 0; nGot := 0; .)
  504. [ StatSeq ] ]
  505. "END"
  506. GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
  507. FlushPend;
  508. k := 0;
  509. WHILE k < SymTab.FwdPending() DO
  510. SymTab.FwdInfo(k, fname, unres);
  511. IF unres THEN SemError(201) END;
  512. INC(k)
  513. END;
  514. SymTab.FwdClear;
  515. IF NOT SymTab.Equal(m1, m2) THEN
  516. SemError(202) END;
  517. astNode := AST.MakeNode(AST.NkUnit);
  518. AST.SetChild(astNode, 0,
  519. AST.MakeLeaf(AST.NkIdent, m1));
  520. AST.SetChild(astNode, 1, astDecl);
  521. AST.SetChild(astNode, 2, astStmt);
  522. AST.SetChild(astNode, 3, astImp);
  523. astUnit := astNode;
  524. CheckGotos;
  525. SymTab.EndUnit; .) .
  526. DeclSeq (. VAR astSeq, astTail: AST.Node; .)
  527. = (. astSeq := AST.NoNode;
  528. astTail := AST.NoNode; .)
  529. { (. astDecl := AST.NoNode; .)
  530. ( ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
  531. | NestedModule ";" | ClassItem ";" )
  532. (. AstAppend(AST.NkDeclSeq,
  533. astSeq, astTail, astDecl); .) }
  534. (. astDecl := astSeq; .) .
  535. (* Local module, Wirth form. Declarations lower like top-level ones
  536. (same QBE module prefix); a BEGIN body becomes an init function
  537. that main calls; the EXPORT list is hoisted into the enclosing
  538. scope at END. *)
  539. NestedModule (. VAR m1, m2: SymTab.Name;
  540. expNames: ARRAY [0 .. 63] OF SymTab.Name;
  541. expCount, k: CARDINAL;
  542. astNode, nImp, nImpTail:
  543. AST.Node; .)
  544. = "MODULE"
  545. GetIdent<m1> (. IF NOT SymTab.Enter(m1,
  546. SymTab.KindModule) THEN
  547. SemError(200) END;
  548. SymTab.PushScope;
  549. expCount := 0;
  550. astNode := AST.MakeNode(AST.NkUnit);
  551. AST.SetChild(astNode, 0,
  552. AST.MakeLeaf(AST.NkIdent, m1));
  553. astStmt := AST.NoNode;
  554. astDecl := AST.NoNode;
  555. nImp := AST.NoNode;
  556. nImpTail := AST.NoNode; .)
  557. [ Priority ]
  558. ";"
  559. { Import (. AstAppend(AST.NkDeclSeq,
  560. nImp, nImpTail, astDecl); .) }
  561. [ "EXPORT" [ "QUALIFIED" ]
  562. GetIdent<expNames[expCount]> (. INC(expCount); .)
  563. { "," GetIdent<expNames[expCount]>
  564. (. INC(expCount); .) }
  565. ";" ]
  566. DeclSeq (. astStmt := AST.NoNode; .)
  567. [ "BEGIN" (. astStmt := AST.NoNode;
  568. .)
  569. [ StatSeq ] ]
  570. "END"
  571. GetIdent<m2> (. AST.SetChild(astNode, 1, astDecl);
  572. AST.SetChild(astNode, 2, astStmt);
  573. AST.SetChild(astNode, 3, nImp);
  574. astDecl := astNode;
  575. IF NOT SymTab.Equal(m1, m2) THEN
  576. SemError(202) END;
  577. k := 0;
  578. WHILE k < expCount DO
  579. SymTab.ExportUp(expNames[k]);
  580. INC(k)
  581. END;
  582. SymTab.PopScope; .) .
  583. Priority
  584. = "[" integer "]" (. SemError(230); .) .
  585. (* Imports (4.3): FROM materializes the names (unqualified use);
  586. plain IMPORT only demands the module exists — qualified `L.x`
  587. materializes on first use (Design). *)
  588. (* Unknown modules stay unchecked stubs (legacy, so hand-written
  589. import lines don't fail); a known module's missing export is
  590. 201. *)
  591. Import (. VAR n: SymTab.Name;
  592. astImport: AST.Node; .)
  593. = "FROM"
  594. GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
  595. AST.SetChild(astImport, 0,
  596. AST.MakeLeaf(AST.NkIdent, n)); .)
  597. "IMPORT"
  598. ImpList<n, astImport> ";" (. astDecl := astImport; .)
  599. | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
  600. ImpModList<astImport> ";" (. astDecl := astImport; .) .
  601. ImpList<mod: SymTab.Name; node: AST.Node>
  602. (. VAR n: SymTab.Name; .)
  603. = ImpName<mod, node>
  604. { "," ImpName<mod, node> } .
  605. (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
  606. accepted and ignored: the built-in applies regardless. *)
  607. ImpName<mod: SymTab.Name; node: AST.Node>
  608. (. VAR n: SymTab.Name; .)
  609. = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
  610. AST.MakeLeaf(AST.NkIdent, n));
  611. IF SymTab.Equal(mod, "libc") THEN
  612. (* intrinsic C library:
  613. permissive external *)
  614. IF NOT SymTab.DeclareCProc(n) THEN
  615. SemError(201) END;
  616. Lower.NoteCProc(n)
  617. ELSIF SymTab.ModKnown(mod) THEN
  618. IF NOT SymTab.ImportFrom(mod, n) THEN
  619. SemError(201)
  620. ELSE Lower.NoteImportedProc(n)
  621. END
  622. END; .)
  623. | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
  624. | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
  625. | "UCHR" | "CHR8" | "UORD"
  626. | "INC" | "DEC" ) .
  627. ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
  628. = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
  629. AST.MakeLeaf(AST.NkIdent, n)); .)
  630. { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
  631. AST.MakeLeaf(AST.NkIdent, n)); .) } .
  632. (* Opaque TYPE declarations (definition modules). The targetless
  633. alias resolves to InvalidType until step 4 completes it. *)
  634. (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
  635. Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
  636. Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
  637. TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
  638. = "TYPE" (. SymTab.BeginTypeBlock;
  639. astSeq := AST.NoNode;
  640. astTail := AST.NoNode; .)
  641. { (. astDecl := AST.NoNode; .)
  642. ( TypeItem<isDef> ";" | ClassItem ";" )
  643. (. AstAppend(AST.NkDeclSeq,
  644. astSeq, astTail, astDecl); .) }
  645. (. SymTab.EndTypeBlock;
  646. astDecl := astSeq; .) .
  647. TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
  648. t, op: SymTab.TypeIndex;
  649. astNode: AST.Node; .)
  650. = GetIdent<n> (. op := SymTab.OpaqueBase(n);
  651. IF op = SymTab.InvalidType THEN
  652. IF NOT SymTab.Enter(n,
  653. SymTab.KindType) THEN
  654. SemError(200) END
  655. END; .)
  656. ( "=" Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkTypeDecl);
  657. AST.SetChild(astNode, 0,
  658. AST.MakeLeaf(AST.NkIdent, n));
  659. AST.SetTy(astNode, t);
  660. astDecl := astNode;
  661. IF op # SymTab.InvalidType THEN
  662. SymTab.SetTarget(op, t)
  663. ELSE SymTab.SetSymType(n, t)
  664. END; .)
  665. | (. IF op # SymTab.InvalidType THEN
  666. (* stays opaque *)
  667. ELSIF NOT isDef THEN
  668. SemError(231)
  669. ELSE SymTab.SetSymType(n,
  670. SymTab.NewAlias()) END; .) ) .
  671. Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
  672. = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
  673. | Subrange<t>
  674. | Enum<t>
  675. | ArrayType<t, allowOpen>
  676. | SetType<t>
  677. | RecordType<t>
  678. | PointerType<t>
  679. | ProcType<t> .
  680. PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
  681. = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
  682. (* Procedure types (step 8.5): PROCEDURE (params): result. Values
  683. are code pointers; params are collected into the descriptor. *)
  684. ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
  685. isV: BOOLEAN; .)
  686. = "PROCEDURE" (. res := SymTab.InvalidType;
  687. t := SymTab.NewProcType(res); .)
  688. [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
  689. [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
  690. ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
  691. isV: BOOLEAN;
  692. cnt, k: CARDINAL;
  693. names: ARRAY [0 .. 15] OF SymTab.Name; .)
  694. = (. isV := FALSE; cnt := 0; .)
  695. [ "VAR" (. isV := TRUE; .) ]
  696. ( GetIdent<names[cnt]> (. INC(cnt); .)
  697. { "," GetIdent<names[cnt]> (. INC(cnt); .) }
  698. ( ":" Type<pt, TRUE> (. k := 0;
  699. WHILE k < cnt DO
  700. SymTab.ProcTypeAdd(t, isV, pt);
  701. INC(k)
  702. END; .)
  703. | (. (* type-only parameter list:
  704. each name is a type (GNU
  705. shorthand used by the
  706. Coco/R scanner frame) *)
  707. k := 0;
  708. WHILE k < cnt DO
  709. IF SymTab.Lookup(names[k])
  710. AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
  711. OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
  712. pt := SymTab.SymType(names[k])
  713. ELSE SemError(201);
  714. pt := SymTab.InvalidType
  715. END;
  716. SymTab.ProcTypeAdd(t, isV, pt);
  717. INC(k)
  718. END; .) )
  719. | Type<pt, TRUE> (. (* unnamed parameter (PIM):
  720. e.g. PROCEDURE (VAR ARRAY OF REAL) *)
  721. SymTab.ProcTypeAdd(t, isV, pt); .) ) .
  722. (* Arrays: "OF" without bounds is an open formal (allowed only
  723. where allowOpen); "[lo..hi, ...]" nests bounded levels inside
  724. out. Bounds are folded literals (int/char); anything else 230.
  725. Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
  726. ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
  727. (. VAR elem: SymTab.TypeIndex;
  728. ok: BOOLEAN;
  729. bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
  730. nb, k: CARDINAL;
  731. idx: SymTab.TypeIndex;
  732. ilo, ihi: INTEGER; .)
  733. = "ARRAY"
  734. ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
  735. SemError(230) END;
  736. t := SymTab.NewOpenArray(elem); .)
  737. | TypeIdent<idx> [ Subrange<idx> ]
  738. "OF" Type<elem, FALSE> (. (* index-type array: the index
  739. type's ordinal bounds give the
  740. [lo..hi] pair *)
  741. IF SymTab.TypeBounds(idx, ilo,
  742. ihi)
  743. THEN t := SymTab.NewArrayB(elem,
  744. ilo, ihi)
  745. ELSE SemError(230);
  746. t := SymTab.InvalidType
  747. END; .)
  748. | "[" (. SymTab.BoundBegin; ok := TRUE; .)
  749. BoundPair<ok>
  750. { "," BoundPair<ok> }
  751. "]" (. (* snapshot before the element
  752. type, which reuses the bound
  753. buffer for a nested ARRAY *)
  754. nb := SymTab.BoundCount();
  755. k := 0;
  756. WHILE k < nb DO
  757. bnds[k] := SymTab.BoundLo(k);
  758. bndh[k] := SymTab.BoundHi(k);
  759. INC(k)
  760. END; .)
  761. "OF" Type<elem, FALSE>
  762. (. IF ok THEN
  763. k := nb;
  764. WHILE k > 0 DO
  765. DEC(k);
  766. elem := SymTab.NewArrayB(
  767. elem, bnds[k], bndh[k])
  768. END;
  769. t := elem
  770. ELSE t := SymTab.InvalidType
  771. END; .) ) .
  772. BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
  773. qlo, qhi: QbeGen.QVal;
  774. lo, hi: INTEGER;
  775. cl, cl2: INTEGER; .)
  776. = Expr<tlo, qlo> ".." Expr<thi, qhi>
  777. (. IF (tlo = SymTab.InvalidType)
  778. OR (thi = SymTab.InvalidType) THEN
  779. ok := FALSE
  780. ELSE cl := SymTab.ClassOf(tlo);
  781. cl2 := SymTab.ClassOf(thi);
  782. IF ((cl # SymTab.ClInt)
  783. AND (cl # SymTab.ClChar))
  784. OR ((cl2 # SymTab.ClInt)
  785. AND (cl2 # SymTab.ClChar)) THEN
  786. SemError(230); ok := FALSE
  787. ELSIF NOT SymTab.ConstInt(qlo, lo)
  788. OR NOT SymTab.ConstInt(qhi, hi)
  789. OR (lo > hi) THEN
  790. SemError(230); ok := FALSE
  791. ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
  792. SemError(230); ok := FALSE
  793. END;
  794. END; .) .
  795. (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
  796. bounded subranges; enums wait for ordinals, INTEGER is
  797. unbounded). Literals are SET OF [0..255]; assignment and
  798. comparison across suitable bases are lenient (masks over min
  799. words + zero-check extras), out-of-span literals are 222. *)
  800. SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
  801. blo, bhi, bspan: INTEGER;
  802. bcls: INTEGER; .)
  803. = "SET" "OF" Type<base, FALSE>
  804. (. IF base = SymTab.InvalidType THEN
  805. t := SymTab.InvalidType
  806. ELSE bcls :=
  807. SymTab.ClassOf(base);
  808. IF bcls = SymTab.ClBool THEN
  809. blo := 0; bspan := 2
  810. ELSIF bcls = SymTab.ClChar THEN
  811. blo := 0; bspan := 256
  812. ELSIF bcls = SymTab.ClEnum THEN
  813. blo := 0;
  814. bspan := VAL(INTEGER,
  815. SymTab.EnumCount(base))
  816. ELSIF SymTab.SubBounds(base,
  817. blo, bhi) THEN
  818. bspan := bhi - blo + 1
  819. ELSE bspan := 0 END;
  820. IF (bspan <= 0)
  821. OR (bspan > 65536) THEN
  822. SemError(230);
  823. t := SymTab.InvalidType
  824. ELSE t := SymTab.NewSet(base)
  825. END
  826. END; .) .
  827. (* Records: flat blobs; array fields are pointers to static
  828. descriptors (locked amendment), nested records inline. Field
  829. offsets static and declaration-ordered. *)
  830. (* Field list: plain fields and (optionally) one variant part. The
  831. variant part is a `CASE ... END` item; because it starts with the
  832. CASE keyword it is unambiguously distinguishable from a field
  833. (which starts with an identifier). *)
  834. RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
  835. tagOk: BOOLEAN; .)
  836. = "RECORD" (. t := SymTab.NewRecord(); .)
  837. [ RecItem<t> { ";" [ RecItem<t> ] } ]
  838. "END" (. SymTab.LayoutRecord(t); .) .
  839. RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
  840. = RecField<rec>
  841. | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
  842. (* A variant part: CASE tag : Type OF variants. The layout overlays
  843. every branch from the tag slot (see SymTab.ComputeOffsets). *)
  844. CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
  845. tagN: SymTab.Name; .)
  846. = "CASE" (. SymTab.ResetFields(rec); .)
  847. GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
  848. tagN) THEN
  849. SemError(200) END; .)
  850. ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
  851. AND NOT SymTab.IsOrdinal(tagT) THEN
  852. SemError(224)
  853. END;
  854. SymTab.FixPendingF(rec, tagT);
  855. SymTab.SetVariantTag(rec, tagN); .)
  856. "OF"
  857. RecFieldList<rec>
  858. { "|" (. SymTab.ResetFields(rec); .)
  859. RecFieldList<rec> }
  860. "END" .
  861. RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
  862. lv1, lv2: QbeGen.QVal; .)
  863. = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
  864. RecField<rec> { ";" [ RecField<rec> ] } .
  865. (* Variant case label: a constant (or a constant range). Values are
  866. not interpreted (the layout overlays regardless). *)
  867. VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  868. (. VAR lname: SymTab.Name; .)
  869. = ( ident (. LexName(lname);
  870. QbeGen.CopyOp("0", q);
  871. t := SymTab.IntType(); .)
  872. | integer (. LexString(lname);
  873. QbeGen.CopyOp("0", q);
  874. t := SymTab.IntType(); .)
  875. | charConst (. LexString(lname);
  876. QbeGen.CopyOp("0", q);
  877. t := SymTab.CharType(); .) ) .
  878. RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
  879. t2: SymTab.TypeIndex; .)
  880. = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
  881. RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
  882. = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
  883. n) THEN
  884. SemError(200) END; .)
  885. { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
  886. n) THEN
  887. SemError(200) END; .) } .
  888. TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
  889. k: INTEGER;
  890. dotted: BOOLEAN; .)
  891. = GetIdent<n> (. dotted := FALSE;
  892. IF NOT SymTab.Lookup(n) THEN
  893. k := -1;
  894. t := SymTab.ForwardType(n);
  895. IF t = SymTab.InvalidType THEN
  896. SemError(201)
  897. END
  898. ELSE k := SymTab.SymKind(n);
  899. IF (k = SymTab.KindType)
  900. OR (k = SymTab.KindPredef) THEN
  901. t := SymTab.SymType(n)
  902. ELSE t := SymTab.InvalidType
  903. END
  904. END; .)
  905. [ "." GetIdent<qid> (. dotted := TRUE;
  906. IF k = SymTab.KindModule THEN
  907. t := SymTab.QualType(n, qid);
  908. IF t = SymTab.InvalidType THEN
  909. SemError(201)
  910. END
  911. ELSE SemError(221);
  912. t := SymTab.InvalidType
  913. END; .) ]
  914. (. IF NOT dotted THEN
  915. IF (k = SymTab.KindModule)
  916. OR ((k # SymTab.KindType)
  917. AND (k # SymTab.KindPredef)
  918. AND (k # SymTab.KindImport)
  919. AND (k # -1)) THEN
  920. SemError(221)
  921. END
  922. END; .) .
  923. Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
  924. qlo, qhi: QbeGen.QVal;
  925. lo, hi: INTEGER; .)
  926. = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
  927. (. IF (tlo = SymTab.InvalidType)
  928. OR (thi = SymTab.InvalidType) THEN
  929. t := SymTab.InvalidType
  930. ELSIF NOT SymTab.IsOrdinal(tlo)
  931. OR NOT SymTab.IsOrdinal(thi) THEN
  932. SemError(230);
  933. t := SymTab.InvalidType
  934. ELSIF NOT SymTab.ConstInt(qlo, lo)
  935. OR NOT SymTab.ConstInt(qhi, hi)
  936. OR (lo > hi) THEN
  937. SemError(230);
  938. t := SymTab.InvalidType
  939. ELSE t := SymTab.NewSubR(lo, hi)
  940. END; .)
  941. "]" .
  942. Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
  943. ord: INTEGER;
  944. qv: QbeGen.QVal; .)
  945. = "(" (. t := SymTab.NewEnum();
  946. ord := 0; .)
  947. GetIdent<n> (. IF NOT SymTab.Enter(n,
  948. SymTab.KindConst) THEN
  949. SemError(200) END;
  950. SymTab.SetSymType(n, t);
  951. QbeGen.IntStr(ord, qv);
  952. SymTab.SetSymVal(n, qv);
  953. Lower.NoteVar(n,
  954. SymTab.KindConst, t);
  955. Lower.NoteConstVal(qv);
  956. INC(ord); .)
  957. { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
  958. SymTab.KindConst) THEN
  959. SemError(200) END;
  960. SymTab.SetSymType(n, t);
  961. QbeGen.IntStr(ord, qv);
  962. SymTab.SetSymVal(n, qv);
  963. Lower.NoteVar(n,
  964. SymTab.KindConst, t);
  965. Lower.NoteConstVal(qv);
  966. INC(ord); .) }
  967. ")" (. SymTab.SetEnumCount(t,
  968. VAL(CARDINAL, ord)); .) .
  969. (* Clarion-form classes (docs/OOP.txt): declaration + single
  970. inheritance + IMPLEMENTATION blocks. Scopes and member checks
  971. now; lowering (vtable, dispatch, THIS) later — one 230 per
  972. class/impl block. Methods end with ";" per the Table example
  973. (not "," as in the sketch). No underscores in identifiers. *)
  974. (* Single CLASS item in both loops: separating declaration from
  975. IMPLEMENTATION at the loop level needs 2-token lookahead
  976. (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
  977. The second token decides after CLASS is consumed. A misplaced
  978. CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
  979. whole unit ends 230 until lowering). *)
  980. ClassItem
  981. = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
  982. ClassRest (. VAR cn, m2, pn: SymTab.Name;
  983. ct: SymTab.TypeIndex; .)
  984. = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
  985. SymTab.KindType) THEN
  986. SemError(200) END;
  987. ct := SymTab.NewClass();
  988. SymTab.SetSymType(cn, ct);
  989. SymTab.PushClassScope(ct);
  990. astCls := AST.MakeNode(AST.NkClassDecl);
  991. AST.SetChild(astCls, 0,
  992. AST.MakeLeaf(AST.NkIdent, cn));
  993. astClsP := AST.NoNode;
  994. astClsPTail := AST.NoNode;
  995. astClsF := AST.NoNode;
  996. astClsFTail := AST.NoNode;
  997. astClsM := AST.NoNode;
  998. astClsMTail := AST.NoNode; .)
  999. [ Parents<ct> ]
  1000. ";"
  1001. { ClassField<ct> ";" }
  1002. { MethodHeading<pn, SymTab.InvalidType> ";"
  1003. (. Lower.ScopeLeave;
  1004. SymTab.CloseProc;
  1005. QbeGen.AbortFunc; .) }
  1006. "END"
  1007. GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
  1008. SemError(202) END;
  1009. SymTab.LayoutClass(ct);
  1010. SymTab.PopScope;
  1011. AST.SetChild(astCls, 1, astClsP);
  1012. AST.SetChild(astCls, 2, astClsF);
  1013. AST.SetChild(astCls, 3, astClsM);
  1014. astDecl := astCls; .) .
  1015. Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
  1016. = "(" Parent1<ct>
  1017. { "," GetIdent<p> (. SemError(230); .) }
  1018. ")" .
  1019. Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
  1020. pt: SymTab.TypeIndex; .)
  1021. = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
  1022. SemError(201)
  1023. ELSE pt := SymTab.SymType(p);
  1024. IF SymTab.ClassOf(pt) #
  1025. SymTab.ClClass THEN
  1026. SemError(230)
  1027. ELSE SymTab.SetParent(ct, pt)
  1028. END
  1029. END;
  1030. AstAppend(AST.NkFieldDecl,
  1031. astClsP, astClsPTail,
  1032. AST.MakeLeaf(AST.NkIdent, p)); .) .
  1033. ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
  1034. t: SymTab.TypeIndex;
  1035. astNode: AST.Node; .)
  1036. = GetIdent<n>
  1037. ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
  1038. SymTab.KindConst) THEN
  1039. SemError(200) END;
  1040. astNode := AST.MakeNode(AST.NkConstDecl);
  1041. AST.SetChild(astNode, 0,
  1042. AST.MakeLeaf(AST.NkIdent, n));
  1043. AST.SetChild(astNode, 1,
  1044. AST.MakeLeaf(AST.NkIdent, rhs));
  1045. AstAppend(AST.NkFieldDecl,
  1046. astClsF, astClsFTail, astNode);
  1047. IF SymTab.Lookup(rhs) THEN
  1048. SymTab.SetSymType(n,
  1049. SymTab.SymType(rhs))
  1050. END; .)
  1051. | (. IF NOT SymTab.FieldPending(ct,
  1052. n) THEN
  1053. SemError(200) END;
  1054. astNode := AST.MakeNode(AST.NkVarDecl);
  1055. AST.SetChild(astNode, 0,
  1056. AST.MakeLeaf(AST.NkIdent, n)); .)
  1057. { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
  1058. n) THEN
  1059. SemError(200) END;
  1060. AST.SetChild(astNode,
  1061. AST.NChild(astNode),
  1062. AST.MakeLeaf(AST.NkIdent, n)); .) }
  1063. ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
  1064. AST.SetTy(astNode, t);
  1065. AstAppend(AST.NkFieldDecl,
  1066. astClsF, astClsFTail, astNode); .) ) .
  1067. MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
  1068. (. VAR wantVirt: BOOLEAN; .)
  1069. = (. wantVirt := FALSE; .)
  1070. [ "VIRTUAL" (. wantVirt := TRUE; .) ]
  1071. ProcHeading<pn, ct> (. IF wantVirt THEN
  1072. SymTab.MarkVirtual END;
  1073. astMethod := AST.MakeNode(AST.NkProcDecl);
  1074. AST.SetChild(astMethod, 0,
  1075. AST.MakeLeaf(AST.NkIdent, pn));
  1076. IF wantVirt THEN
  1077. AST.SetOp(astMethod, 3)
  1078. ELSE AST.SetOp(astMethod, 0)
  1079. END;
  1080. AstAppend(AST.NkFieldDecl,
  1081. astClsM, astClsMTail, astMethod); .) .
  1082. ClassImplRest (. VAR cn, m2: SymTab.Name;
  1083. ct: SymTab.TypeIndex; .)
  1084. = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
  1085. SemError(201);
  1086. ct := SymTab.InvalidType
  1087. ELSE ct := SymTab.SymType(cn);
  1088. IF SymTab.ClassOf(ct) #
  1089. SymTab.ClClass THEN
  1090. SemError(230);
  1091. ct := SymTab.InvalidType
  1092. END
  1093. END;
  1094. astCls := AST.MakeNode(AST.NkClassDecl);
  1095. AST.SetOp(astCls, 1);
  1096. AST.SetChild(astCls, 0,
  1097. AST.MakeLeaf(AST.NkIdent, cn));
  1098. astClsM := AST.NoNode;
  1099. astClsMTail := AST.NoNode;
  1100. astStmt := AST.NoNode;
  1101. IF ct #
  1102. SymTab.InvalidType THEN
  1103. IF NOT SymTab.PushClassMembers(
  1104. ct) THEN
  1105. SemError(230) END;
  1106. SymTab.PushImplClass(ct)
  1107. END; .)
  1108. ";" { MethodImpl<ct> ";" }
  1109. (. astStmt := AST.NoNode; .)
  1110. [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
  1111. .)
  1112. [ StatSeq ] ]
  1113. "END"
  1114. GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
  1115. SemError(202) END;
  1116. SymTab.PopImplClass;
  1117. SymTab.PopScope;
  1118. AST.SetChild(astCls, 1, AST.NoNode);
  1119. AST.SetChild(astCls, 2, astStmt);
  1120. AST.SetChild(astCls, 3, astClsM);
  1121. astDecl := astCls; .) .
  1122. MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
  1123. thisQ: QbeGen.QVal;
  1124. methRes: SymTab.TypeIndex; .)
  1125. = MethodHeading<pn, ct> ";"
  1126. (. IF (ct #
  1127. SymTab.InvalidType)
  1128. AND NOT SymTab.MethodExists(ct,
  1129. pn) THEN
  1130. SemError(201) END; .)
  1131. ( "FORWARD" (. AST.SetOp(astMethod, 1);
  1132. SymTab.MarkFwd;
  1133. QbeGen.AbortFunc;
  1134. Lower.ScopeLeave;
  1135. SymTab.CloseProc; .)
  1136. | (.
  1137. (* bind the receiver: bare
  1138. field names resolve
  1139. against THIS *)
  1140. QbeGen.CopyOp("@", thisQ);
  1141. QbeGen.PushWith(thisQ); .)
  1142. Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
  1143. AST.SetChild(astMethod, 2, astBlkDecls);
  1144. QbeGen.PopWith;
  1145. methRes := SymTab.CurRes();
  1146. Lower.ScopeLeave;
  1147. SymTab.CloseProc;
  1148. QbeGen.EndFunc(methRes); .) ) .
  1149. ConstBlock (. VAR astSeq, astTail: AST.Node; .)
  1150. = "CONST" (. astSeq := AST.NoNode;
  1151. astTail := AST.NoNode; .)
  1152. { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
  1153. astSeq, astTail, astDecl); .) }
  1154. (. astDecl := astSeq; .) .
  1155. ConstDecl (. VAR n: SymTab.Name;
  1156. t: SymTab.TypeIndex;
  1157. qv: QbeGen.QVal;
  1158. cls: INTEGER;
  1159. astNode: AST.Node; .)
  1160. = GetIdent<n> (. IF NOT SymTab.Enter(n,
  1161. SymTab.KindConst) THEN
  1162. SemError(200) END; .)
  1163. "="
  1164. Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
  1165. AST.SetChild(astNode, 0,
  1166. AST.MakeLeaf(AST.NkIdent, n));
  1167. AST.SetChild(astNode, 1, astCur);
  1168. AST.SetTy(astNode, t);
  1169. astDecl := astNode;
  1170. Lower.NoteVar(n, SymTab.KindConst, t);
  1171. Lower.NoteConstVal(qv);
  1172. SymTab.SetSymType(n, t);
  1173. cls := SymTab.ClassOf(t);
  1174. IF (cls = SymTab.ClArray)
  1175. OR (cls = SymTab.ClRecord)
  1176. OR (cls = SymTab.ClClass)
  1177. OR (cls = SymTab.ClStr)
  1178. OR (cls = SymTab.ClUStr) THEN
  1179. (* an aggregate/string
  1180. constant: qv is its
  1181. descriptor address; no
  1182. scalar data *)
  1183. SymTab.SetSymVal(n, qv)
  1184. ELSIF NOT QbeGen.IsImm(qv) THEN
  1185. SemError(230)
  1186. ELSE
  1187. SymTab.SetSymVal(n, qv);
  1188. END; .) .
  1189. VarBlock (. VAR astSeq, astTail: AST.Node; .)
  1190. = "VAR" (. astSeq := AST.NoNode;
  1191. astTail := AST.NoNode; .)
  1192. { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
  1193. astSeq, astTail, astDecl); .) }
  1194. (. astDecl := astSeq; .) .
  1195. VarDecl (. VAR nm: SymTab.Name;
  1196. t: SymTab.TypeIndex;
  1197. i: CARDINAL;
  1198. cls: INTEGER;
  1199. astNode, astTail: AST.Node; .)
  1200. = VarIdents ":"
  1201. Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
  1202. astTail := astNode;
  1203. i := 0;
  1204. WHILE i < SymTab.PendCount() DO
  1205. SymTab.PendName(i, nm);
  1206. Lower.NoteVar(nm, SymTab.KindVar, t);
  1207. (* chunked: a VAR list can
  1208. exceed AST.MaxChild *)
  1209. AstAppend(AST.NkBlock,
  1210. astNode, astTail,
  1211. AST.MakeLeaf(AST.NkIdent, nm));
  1212. INC(i)
  1213. END;
  1214. AST.SetTy(astNode, t);
  1215. astDecl := astNode;
  1216. cls := SymTab.ClassOf(t);
  1217. IF (t # SymTab.InvalidType)
  1218. AND NOT SymTab.IsUnresolved(t)
  1219. AND (cls # SymTab.ClInt)
  1220. AND (cls # SymTab.ClBool)
  1221. AND (cls # SymTab.ClChar)
  1222. AND (cls # SymTab.ClReal)
  1223. AND (cls # SymTab.ClArray)
  1224. AND (cls # SymTab.ClSet)
  1225. AND (cls # SymTab.ClRecord)
  1226. AND (cls # SymTab.ClPtr)
  1227. AND (cls # SymTab.ClLong)
  1228. AND (cls # SymTab.ClProc)
  1229. AND (cls # SymTab.ClUChar)
  1230. AND (cls # SymTab.ClUStr)
  1231. AND (cls # SymTab.ClEnum)
  1232. AND (cls # SymTab.ClClass) THEN
  1233. SemError(230) END;
  1234. IF QbeGen.LocFull() THEN
  1235. SemError(233) END;
  1236. i := 0;
  1237. IF SymTab.IsUnresolved(t)
  1238. AND NOT SymTab.InProc() THEN
  1239. (* a forward-typed global:
  1240. defer emission until the
  1241. TYPE block completes *)
  1242. AST.SetOp(astNode, 1);
  1243. WHILE i < SymTab.PendCount() DO
  1244. SymTab.PendName(i, nm);
  1245. IF nPendVar <=
  1246. HIGH(pendVarName) THEN
  1247. pendVarName[nPendVar] := nm;
  1248. pendVarT[nPendVar] := t;
  1249. INC(nPendVar)
  1250. END;
  1251. INC(i)
  1252. END
  1253. ELSE
  1254. WHILE i < SymTab.PendCount() DO
  1255. SymTab.PendName(i, nm);
  1256. INC(i)
  1257. END
  1258. END;
  1259. (* a plain VAR list, not a
  1260. heading: the signature
  1261. result is discarded *)
  1262. IF NOT SymTab.FixPending(t) THEN
  1263. END; .) .
  1264. VarIdents (. VAR n: SymTab.Name; .)
  1265. = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
  1266. SymTab.KindVar) THEN
  1267. SemError(200) END; .)
  1268. { ","
  1269. GetIdent<n> (. IF NOT SymTab.EnterPending(n,
  1270. SymTab.KindVar) THEN
  1271. SemError(200) END; .) } .
  1272. ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
  1273. = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
  1274. SemError(200) END; .)
  1275. { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
  1276. SemError(200) END; .) } .
  1277. (* Procedure headings enter scopes/params/result and buffer the
  1278. QBE header; bodies lower to functions (4.1, module level only).
  1279. FORWARD marks; the body heading re-enters (signature compare
  1280. deferred). Nested procedures parse + check, lowering = 4.2. *)
  1281. ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
  1282. (. VAR t: SymTab.TypeIndex;
  1283. mg: QbeGen.QVal; .)
  1284. = "PROCEDURE"
  1285. GetIdent<pn> (. IF methCls #
  1286. SymTab.InvalidType THEN
  1287. (* a method: resume the
  1288. declared symbol (reuse
  1289. its uid) *)
  1290. IF NOT SymTab.ResumeMethod(
  1291. methCls, pn) THEN
  1292. SemError(200) END
  1293. ELSIF NOT SymTab.EnterProc(pn) THEN
  1294. IF NOT SymTab.ReenterProc(pn) THEN
  1295. IF NOT SymTab.ResumeProc(pn) THEN
  1296. SemError(200) END
  1297. END
  1298. END;
  1299. Lower.ScopeEnter;
  1300. Lower.NoteProc(pn,
  1301. SymTab.ProcUid(pn),
  1302. SymTab.InvalidType,
  1303. SymTab.ProcDepthOf(pn),
  1304. FALSE);
  1305. QbeGen.BeginFunc("");
  1306. IF methCls #
  1307. SymTab.InvalidType THEN
  1308. (* hidden THIS receiver:
  1309. a VAR param of the
  1310. class type, pushed as
  1311. the WITH base *)
  1312. IF NOT SymTab.EnterThisParam(
  1313. methCls) THEN
  1314. SemError(200) END;
  1315. IF NOT QbeGen.FuncParam(
  1316. "THIS", TRUE,
  1317. methCls) THEN
  1318. SemError(233) END
  1319. END; .)
  1320. [ FormalParams ]
  1321. [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
  1322. SemError(235) END;
  1323. Lower.SetProcRes(t); .) ] .
  1324. FormalParams
  1325. = "(" [ ParamSection { ";" ParamSection } ] ")" .
  1326. ParamSection (. VAR t: SymTab.TypeIndex;
  1327. nm: SymTab.Name;
  1328. i: CARDINAL;
  1329. isV: BOOLEAN; .)
  1330. = (. isV := FALSE; .)
  1331. [ "VAR" (. isV := TRUE; .) ]
  1332. ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
  1333. WHILE i < SymTab.PendCount() DO
  1334. SymTab.PendName(i, nm);
  1335. Lower.NoteParam(nm, t, isV);
  1336. Lower.NoteVar(nm, SymTab.KindParam, t);
  1337. (* value open arrays are
  1338. passed as descriptor
  1339. addresses (no copy):
  1340. same representation as
  1341. VAR formals *)
  1342. IF NOT QbeGen.FuncParam(nm,
  1343. isV
  1344. OR SymTab.IsOpenArray(t),
  1345. t) THEN
  1346. SemError(233) END;
  1347. INC(i)
  1348. END;
  1349. IF NOT SymTab.FixPending(t) THEN
  1350. SemError(235) END; .) .
  1351. (* Nested procedures lower like top-level ones (4.2): the
  1352. static link gives them their parent's frame. Methods keep
  1353. parse-now/230-later. *)
  1354. ProcDecl (. VAR pn: SymTab.Name;
  1355. astNode: AST.Node; .)
  1356. = ProcHeading<pn, SymTab.InvalidType> ";"
  1357. (. astNode := AST.MakeNode(AST.NkProcDecl);
  1358. AST.SetOp(astNode, 0);
  1359. AST.SetChild(astNode, 0,
  1360. AST.MakeLeaf(AST.NkIdent, pn));
  1361. Lower.NoteProcNode(astNode); .)
  1362. ( "FORWARD" (. AST.SetOp(astNode, 1);
  1363. astDecl := astNode;
  1364. Lower.ScopeLeave;
  1365. SymTab.MarkFwd;
  1366. SymTab.CloseProc;
  1367. QbeGen.AbortFunc; .)
  1368. | "EXTERNAL" (. AST.SetOp(astNode, 2);
  1369. astDecl := astNode;
  1370. Lower.MarkProcExternal;
  1371. Lower.ScopeLeave;
  1372. SymTab.MarkExternal("");
  1373. SymTab.CloseProc;
  1374. QbeGen.AbortFunc; .)
  1375. |
  1376. Block<pn> (. AST.SetChild(astNode, 1, astStmt);
  1377. AST.SetChild(astNode, 2, astBlkDecls);
  1378. astDecl := astNode;
  1379. Lower.ScopeLeave;
  1380. SymTab.CloseProc;
  1381. QbeGen.EndFunc(
  1382. SymTab.ProcRes(pn)); .) ) .
  1383. Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
  1384. = DeclSeq (. astBlkDecls := astDecl;
  1385. astStmt := AST.NoNode;
  1386. nLab := 0; nGot := 0; .)
  1387. [ "BEGIN" (. (* an empty body is still a
  1388. body: mark it so Lower
  1389. does not read it as a
  1390. definition heading *)
  1391. IF astStmt = AST.NoNode THEN
  1392. astStmt :=
  1393. AST.MakeNode(AST.NkBlock)
  1394. END; .)
  1395. [ StatSeq ] ]
  1396. "END"
  1397. GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
  1398. SemError(202) END;
  1399. CheckGotos; .) .
  1400. StatSeq (. VAR astSeq, astTail: AST.Node; .)
  1401. = (. astSeq := AST.NoNode;
  1402. astTail := AST.NoNode; .)
  1403. Statement (. AstAppend(AST.NkBlock,
  1404. astSeq, astTail, astStmt); .)
  1405. { ";" [ Statement (. AstAppend(AST.NkBlock,
  1406. astSeq, astTail, astStmt); .) ] }
  1407. (. astStmt := astSeq; .) .
  1408. (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
  1409. are accepted: the statement after ';' is optional. *)
  1410. Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
  1411. = (. astStmt := AST.NoNode; .)
  1412. ( AssOrCall
  1413. | IfStat
  1414. | WhileStat
  1415. | RepeatStat
  1416. | LoopStat
  1417. | ForStat
  1418. | CaseStat
  1419. | WithStat
  1420. | ReturnStat
  1421. | HaltStat
  1422. | NewStat
  1423. | DisposeStat
  1424. | IncDecStat
  1425. | InclExclStat
  1426. | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
  1427. SemError(230) END;
  1428. astStmt := AST.MakeNode(AST.NkExit); .)
  1429. | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
  1430. astStmt := AST.MakeNode(AST.NkGoto);
  1431. AST.SetChild(astStmt, 0,
  1432. AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
  1433. (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
  1434. InclExclStat (. VAR at, et2: SymTab.TypeIndex;
  1435. dk: INTEGER;
  1436. qd, qe: QbeGen.QVal;
  1437. qn: SymTab.Name;
  1438. sfx, isInc: BOOLEAN;
  1439. astNode, astD: AST.Node; .)
  1440. = ( "INCL" (. isInc := TRUE; .)
  1441. | "EXCL" (. isInc := FALSE; .) )
  1442. "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
  1443. Expr<et2, qe> ")"
  1444. (. astNode := AST.MakeNode(AST.NkCall);
  1445. IF isInc THEN
  1446. AST.SetChild(astNode, 0,
  1447. AST.MakeLeaf(AST.NkIdent, "INCL"))
  1448. ELSE AST.SetChild(astNode, 0,
  1449. AST.MakeLeaf(AST.NkIdent, "EXCL"))
  1450. END;
  1451. IF astD # AST.NoNode THEN
  1452. AST.SetChild(astNode, 1, astD) END;
  1453. IF astCur # AST.NoNode THEN
  1454. AST.SetChild(astNode, 2, astCur) END;
  1455. astStmt := astNode; .)
  1456. (. IF (at # SymTab.InvalidType)
  1457. AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
  1458. SemError(222)
  1459. END; .) .
  1460. (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
  1461. integer designator. *)
  1462. IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
  1463. dk: INTEGER;
  1464. qd, qv, qn2, qstep:
  1465. QbeGen.QVal;
  1466. qn: SymTab.Name;
  1467. sfx, isInc: BOOLEAN;
  1468. astNode, astD, astStep:
  1469. AST.Node; .)
  1470. = (. isInc := TRUE; .)
  1471. ( "INC" (. isInc := TRUE; .)
  1472. | "DEC" (. isInc := FALSE; .) )
  1473. "(" (. astStep := AST.NoNode; .)
  1474. Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
  1475. [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
  1476. ")" (. astNode := AST.MakeNode(AST.NkCall);
  1477. IF isInc THEN
  1478. AST.SetChild(astNode, 0,
  1479. AST.MakeLeaf(AST.NkIdent, "INC"))
  1480. ELSE AST.SetChild(astNode, 0,
  1481. AST.MakeLeaf(AST.NkIdent, "DEC"))
  1482. END;
  1483. IF astD # AST.NoNode THEN
  1484. AST.SetChild(astNode, 1, astD) END;
  1485. IF astStep # AST.NoNode THEN
  1486. AST.SetChild(astNode, 2, astStep) END;
  1487. astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
  1488. ELSIF (dk # SymTab.KindVar)
  1489. AND (dk # SymTab.KindParam)
  1490. AND (dk # SymTab.KindField) THEN
  1491. SemError(210)
  1492. ELSIF NOT SymTab.IsIntFamily(dt) THEN
  1493. SemError(211)
  1494. END; .) .
  1495. (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
  1496. Targets are pointer designators; DISPOSE nils afterwards (safer
  1497. than Wirth-undefined; documented). DISPOSE is shallow. *)
  1498. NewStat (. VAR dt: SymTab.TypeIndex;
  1499. dk: INTEGER;
  1500. qd, qm: QbeGen.QVal;
  1501. qn: SymTab.Name;
  1502. sfx: BOOLEAN;
  1503. bt: SymTab.TypeIndex;
  1504. astNode, astD: AST.Node; .)
  1505. = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
  1506. (. astNode := AST.MakeNode(AST.NkCall);
  1507. AST.SetChild(astNode, 0,
  1508. AST.MakeLeaf(AST.NkIdent, "NEW"));
  1509. IF astD # AST.NoNode THEN
  1510. AST.SetChild(astNode, 1, astD) END;
  1511. astStmt := astNode; .)
  1512. (. IF dt = SymTab.InvalidType THEN
  1513. ELSIF (dk # SymTab.KindVar)
  1514. AND (dk # SymTab.KindParam)
  1515. AND (dk # SymTab.KindField) THEN
  1516. SemError(210)
  1517. ELSIF SymTab.ClassOf(dt) #
  1518. SymTab.ClPtr THEN
  1519. SemError(219)
  1520. END; .) .
  1521. DisposeStat (. VAR dt: SymTab.TypeIndex;
  1522. dk: INTEGER;
  1523. qd, qv: QbeGen.QVal;
  1524. qn: SymTab.Name;
  1525. sfx: BOOLEAN;
  1526. astNode, astD: AST.Node; .)
  1527. = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
  1528. (. astNode := AST.MakeNode(AST.NkCall);
  1529. AST.SetChild(astNode, 0,
  1530. AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
  1531. IF astD # AST.NoNode THEN
  1532. AST.SetChild(astNode, 1, astD) END;
  1533. astStmt := astNode; .)
  1534. (. IF dt = SymTab.InvalidType THEN
  1535. ELSIF (dk # SymTab.KindVar)
  1536. AND (dk # SymTab.KindParam)
  1537. AND (dk # SymTab.KindField) THEN
  1538. SemError(210)
  1539. ELSIF SymTab.ClassOf(dt) #
  1540. SymTab.ClPtr THEN
  1541. SemError(219)
  1542. END; .) .
  1543. (* WITH pushes each record's fields (inner wins) plus its base
  1544. address; field designators resolve through both stacks. *)
  1545. WithStat (. VAR nW: CARDINAL;
  1546. astNode: AST.Node; .)
  1547. = "WITH" (. nW := 0;
  1548. astNode := AST.MakeNode(AST.NkWith); .)
  1549. WithItem<nW, astNode> { "," WithItem<nW, astNode> }
  1550. "DO" (. astStmt := AST.NoNode; .)
  1551. [ StatSeq ] "END" (. AST.SetChild(astNode,
  1552. AST.NChild(astNode), astStmt);
  1553. astStmt := astNode;
  1554. WHILE nW > 0 DO
  1555. SymTab.PopScope;
  1556. QbeGen.PopWith;
  1557. DEC(nW)
  1558. END; .) .
  1559. WithItem<VAR nW: CARDINAL; wnode: AST.Node>
  1560. (. VAR dt: SymTab.TypeIndex;
  1561. dk: INTEGER;
  1562. qd, qe: QbeGen.QVal;
  1563. qn: SymTab.Name;
  1564. sfx: BOOLEAN; .)
  1565. = Design<dt, dk, qd, qn, sfx>
  1566. (. IF astCur # AST.NoNode THEN
  1567. AST.SetChild(wnode,
  1568. AST.NChild(wnode), astCur) END;
  1569. IF dt = SymTab.InvalidType THEN
  1570. ELSIF (SymTab.ClassOf(dt) #
  1571. SymTab.ClRecord)
  1572. AND (SymTab.ClassOf(dt) #
  1573. SymTab.ClClass) THEN
  1574. SemError(215)
  1575. ELSIF SymTab.PushRecord(dt) THEN
  1576. QbeGen.PushWith(qd);
  1577. INC(nW)
  1578. END; .) .
  1579. (* Assignment or procedure-statement call (4.1, module level).
  1580. Bare `P;` is a syntax error; function-as-statement is 233. *)
  1581. AssOrCall (. VAR dt, et: SymTab.TypeIndex;
  1582. dk: INTEGER;
  1583. qd, qe, qt, ql: QbeGen.QVal;
  1584. qn: SymTab.Name;
  1585. ct2, res0: SymTab.TypeIndex;
  1586. q2, mg0: QbeGen.QVal;
  1587. isR, conv, wconv: BOOLEAN;
  1588. called, sfx: BOOLEAN;
  1589. astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
  1590. n: SymTab.Name; astLab, astNode: AST.Node; .)
  1591. = GetIdent<n>
  1592. ( ":" (. NoteLabel(n);
  1593. astNode := AST.MakeNode(AST.NkLabel);
  1594. AST.SetChild(astNode, 0,
  1595. AST.MakeLeaf(AST.NkIdent, n));
  1596. astLab := AST.MakeNode(AST.NkBlock);
  1597. AST.SetChild(astLab, 0, astNode); .)
  1598. Statement (. IF astStmt # AST.NoNode THEN
  1599. AST.SetChild(astLab, 1, astStmt) END;
  1600. astStmt := astLab; .)
  1601. | DesignTail<n, dt, dk, qd, qn, sfx>
  1602. (. astLhs := astCur; astNArgs := 0; .)
  1603. ( ":="
  1604. Expr<et, qe> (. astStmt := AST.MakeBin(
  1605. AST.NkAssign, 0, astLhs, astCur);
  1606. IF (dt # SymTab.InvalidType)
  1607. AND (dk # SymTab.KindVar)
  1608. AND (dk # SymTab.KindParam)
  1609. AND (dk # SymTab.KindField) THEN
  1610. SemError(210)
  1611. ELSIF NOT SymTab.Assignable(et,
  1612. dt) THEN
  1613. SemError(210)
  1614. ELSIF (dt # SymTab.InvalidType)
  1615. AND (SymTab.ClassOf(dt) =
  1616. SymTab.ClClass) THEN
  1617. SemError(230) END;
  1618. isR := (dt #
  1619. SymTab.InvalidType)
  1620. AND (SymTab.ClassOf(dt)
  1621. = SymTab.ClReal);
  1622. conv := isR
  1623. AND SymTab.IsIntFamily(et);
  1624. wconv := (dt #
  1625. SymTab.InvalidType)
  1626. AND SymTab.IsLongFamily(dt)
  1627. AND SymTab.IsIntFamily(et);
  1628. IF ((dk = SymTab.KindVar)
  1629. OR (dk = SymTab.KindParam)
  1630. OR (dk = SymTab.KindField))
  1631. AND (dt # SymTab.InvalidType)
  1632. AND (et # SymTab.InvalidType)
  1633. AND (SymTab.ClassOf(dt) #
  1634. SymTab.ClClass) THEN
  1635. END; .)
  1636. | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
  1637. (. astRes := AstCallNode(astLhs);
  1638. sfx := FALSE; .)
  1639. ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
  1640. ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
  1641. AST.NkAssign, 0, astRes, astCur);
  1642. IF NOT sfx THEN
  1643. SemError(233)
  1644. ELSIF (ct2 # SymTab.InvalidType)
  1645. AND NOT SymTab.Assignable(et, ct2) THEN
  1646. SemError(210)
  1647. END; .)
  1648. | (. IF ct2 #
  1649. SymTab.InvalidType THEN
  1650. SemError(233) END;
  1651. astStmt := astRes; .) )
  1652. | (* bare `P;`: proper parameterless
  1653. procedure call; anything else
  1654. here is 233 (was a bare syntax
  1655. error before 4.2) *)
  1656. (. astStmt := AstCallNode(astLhs);
  1657. IF (dk = SymTab.KindProc)
  1658. AND NOT sfx THEN
  1659. res0 := SymTab.ProcRes(qn);
  1660. IF res0 #
  1661. SymTab.InvalidType THEN
  1662. SemError(233)
  1663. ELSIF SymTab.ProcNPar(qn) #
  1664. 0 THEN
  1665. SemError(233)
  1666. END
  1667. ELSE SemError(233)
  1668. END; .) ) ) .
  1669. (* Actual-parameter list shared by statement and expression calls.
  1670. want selects CallEnd's result handling; t/q carry the call
  1671. value (statement calls discard). Arity/type failures are 233;
  1672. evaluation code still emits so the .ssa stays assembleable. *)
  1673. ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
  1674. want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
  1675. VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
  1676. VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
  1677. vs: INTEGER;
  1678. res: SymTab.TypeIndex;
  1679. mg: QbeGen.QVal;
  1680. ok, ind, isMeth, va: BOOLEAN; .)
  1681. = "(" (. called := TRUE;
  1682. ok := TRUE;
  1683. ind := FALSE;
  1684. isMeth := methCls #
  1685. SymTab.InvalidType;
  1686. IF isMeth THEN
  1687. res := SymTab.ClassMethodRes(methCls, pn)
  1688. ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
  1689. res := SymTab.ProcRes(pn)
  1690. ELSIF (pt # SymTab.InvalidType)
  1691. AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
  1692. ind := TRUE;
  1693. res := SymTab.ProcTypeRes(pt)
  1694. ELSE SemError(233);
  1695. ok := FALSE;
  1696. res := SymTab.InvalidType
  1697. END;
  1698. i := 0; .)
  1699. [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
  1700. { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
  1701. ")" (. IF ok THEN
  1702. IF isMeth THEN
  1703. np := SymTab.ClassMethodNPar(
  1704. methCls, pn)
  1705. ELSIF ind THEN
  1706. np := SymTab.ProcTypeNPar(pt)
  1707. ELSE np := SymTab.ProcNPar(pn)
  1708. END;
  1709. va := (NOT isMeth) AND (NOT ind)
  1710. AND (SymTab.SymKind(pn) =
  1711. SymTab.KindProc)
  1712. AND SymTab.Varargs(pn);
  1713. IF (i # np) AND NOT va THEN
  1714. SemError(233); ok := FALSE
  1715. END
  1716. END;
  1717. IF NOT ok THEN
  1718. t := SymTab.InvalidType;
  1719. QbeGen.CopyOp("0", q)
  1720. ELSIF want THEN
  1721. IF res =
  1722. SymTab.InvalidType THEN
  1723. IF NOT soft THEN SemError(233) END;
  1724. t := SymTab.InvalidType;
  1725. QbeGen.CopyOp("0", q)
  1726. ELSE t := res;
  1727. QbeGen.CopyOp("@", q)
  1728. END
  1729. ELSE
  1730. IF res #
  1731. SymTab.InvalidType THEN
  1732. SemError(233)
  1733. END;
  1734. t := SymTab.InvalidType;
  1735. QbeGen.CopyOp("0", q);
  1736. END; .) .
  1737. (* One actual: VAR formals take recorded designator addresses
  1738. (233 otherwise); value formals take converted expressions. *)
  1739. ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
  1740. methCls: SymTab.TypeIndex; i: CARDINAL>
  1741. (. VAR at, ft: SymTab.TypeIndex;
  1742. qe, qa, qt: QbeGen.QVal;
  1743. isV, conv, va: BOOLEAN;
  1744. cl: CHAR;
  1745. savedN, aj: CARDINAL;
  1746. savedArgs: ARRAY [0 .. 31]
  1747. OF AST.Node;
  1748. astActual: AST.Node; .)
  1749. = (. (* Parsing the actual can clobber
  1750. the enclosing call's argument
  1751. list (Factor resets astNArgs),
  1752. so save/restore it. *)
  1753. savedN := astNArgs; aj := 0;
  1754. WHILE aj <= HIGH(astArgs) DO
  1755. savedArgs[aj] := astArgs[aj];
  1756. INC(aj)
  1757. END; .)
  1758. Expr<at, qe> (. astActual := astCur;
  1759. astNArgs := savedN; aj := 0;
  1760. WHILE aj <= HIGH(astArgs) DO
  1761. astArgs[aj] := savedArgs[aj];
  1762. INC(aj)
  1763. END;
  1764. IF astNArgs <= HIGH(astArgs) THEN
  1765. astArgs[astNArgs] := astCur;
  1766. INC(astNArgs)
  1767. END;
  1768. va := (NOT ind)
  1769. AND (methCls =
  1770. SymTab.InvalidType)
  1771. AND (SymTab.SymKind(pn) =
  1772. SymTab.KindProc)
  1773. AND SymTab.Varargs(pn);
  1774. IF ind THEN
  1775. ft :=
  1776. SymTab.ProcTypeParamType(pt,
  1777. i);
  1778. isV :=
  1779. SymTab.ProcTypeParamIsVar(pt,
  1780. i)
  1781. ELSIF methCls #
  1782. SymTab.InvalidType THEN
  1783. ft :=
  1784. SymTab.ClassMethodParamType(
  1785. methCls, pn, i);
  1786. isV :=
  1787. SymTab.ClassMethodParamIsVar(
  1788. methCls, pn, i)
  1789. ELSE
  1790. ft := SymTab.ParamType(pn, i);
  1791. isV := SymTab.ParamIsVar(pn, i)
  1792. END;
  1793. IF (at = SymTab.InvalidType) THEN
  1794. ELSIF ft = SymTab.InvalidType THEN
  1795. ELSIF isV THEN
  1796. IF (SymTab.ClassOf(at) = SymTab.ClChar)
  1797. AND (SymTab.ClassOf(ft) = SymTab.ClArray)
  1798. AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
  1799. AND QbeGen.IsImm(qe) THEN
  1800. ELSIF (AST.Kind(astActual) #
  1801. AST.NkDesignator)
  1802. AND (AST.Kind(astActual) # AST.NkStrLit) THEN
  1803. SemError(233)
  1804. ELSIF NOT SymTab.VarParamOk(at, ft) THEN
  1805. SemError(233)
  1806. END
  1807. ELSE
  1808. IF (SymTab.ClassOf(at) = SymTab.ClChar)
  1809. AND (SymTab.ClassOf(ft) = SymTab.ClArray)
  1810. AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
  1811. AND QbeGen.IsImm(qe) THEN
  1812. ELSIF NOT SymTab.Assignable(at, ft) THEN
  1813. SemError(233)
  1814. END
  1815. END; .) .
  1816. IfStat (. VAR t: SymTab.TypeIndex;
  1817. q: QbeGen.QVal;
  1818. hasElse: BOOLEAN;
  1819. astCond, astIf, astLast,
  1820. astNode: AST.Node; .)
  1821. = "IF" (. hasElse := FALSE; .)
  1822. Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
  1823. IF NOT SymTab.BoolCheck(t) THEN
  1824. SemError(214) END; .)
  1825. "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
  1826. AST.SetChild(astNode, 0, astCond);
  1827. AST.SetChild(astNode, 1, astStmt);
  1828. astIf := astNode;
  1829. astLast := astNode; .)
  1830. { "ELSIF"
  1831. Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
  1832. IF NOT SymTab.BoolCheck(t) THEN
  1833. SemError(214) END; .)
  1834. "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
  1835. AST.SetChild(astNode, 0, astCond);
  1836. AST.SetChild(astNode, 1, astStmt);
  1837. AST.SetChild(astLast, 2, astNode);
  1838. astLast := astNode; .) }
  1839. [ "ELSE" (. hasElse := TRUE;
  1840. astStmt := AST.NoNode; .)
  1841. [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
  1842. "END" (. astStmt := astIf; .) .
  1843. WhileStat (. VAR t: SymTab.TypeIndex;
  1844. q: QbeGen.QVal;
  1845. astCond, astNode: AST.Node; .)
  1846. = "WHILE" (. astStmt := AST.NoNode; .)
  1847. Expr<t, q> (. astCond := astCur;
  1848. IF NOT SymTab.BoolCheck(t) THEN
  1849. SemError(214) END; .)
  1850. "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
  1851. AST.SetChild(astNode, 0, astCond);
  1852. AST.SetChild(astNode, 1, astStmt);
  1853. astStmt := astNode; .)
  1854. "END" .
  1855. RepeatStat (. VAR t: SymTab.TypeIndex;
  1856. q: QbeGen.QVal;
  1857. astCond, astBody, astNode:
  1858. AST.Node; .)
  1859. = "REPEAT" (. astStmt := AST.NoNode; .)
  1860. [ StatSeq ] (. astBody := astStmt; .)
  1861. "UNTIL" Expr<t, q> (. astCond := astCur;
  1862. astNode := AST.MakeNode(AST.NkRepeat);
  1863. AST.SetChild(astNode, 0, astBody);
  1864. AST.SetChild(astNode, 1, astCond);
  1865. astStmt := astNode;
  1866. IF NOT SymTab.BoolCheck(t) THEN
  1867. SemError(214) END; .) .
  1868. LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
  1869. = "LOOP" (. astStmt := AST.NoNode;
  1870. QbeGen.NewLabel(lEnd);
  1871. QbeGen.PushLoop(lEnd); .)
  1872. [ StatSeq ]
  1873. "END" (. astNode := AST.MakeNode(AST.NkLoop);
  1874. AST.SetChild(astNode, 0, astStmt);
  1875. astStmt := astNode;
  1876. QbeGen.PopLoop; .) .
  1877. (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
  1878. Runtime direction would need a compare-select; the literal
  1879. sign picks cslew/csegew at "DO" time. *)
  1880. ForStat (. VAR lv: SymTab.Name;
  1881. tlo, thi, tby:
  1882. SymTab.TypeIndex;
  1883. qlo, qhi, qby, qt, qk, qb:
  1884. QbeGen.QVal;
  1885. lTop, lBody, lEnd:
  1886. QbeGen.QVal;
  1887. by: INTEGER;
  1888. ok: BOOLEAN;
  1889. astVar, astLo, astHi, astBy,
  1890. astNode: AST.Node; .)
  1891. = "FOR" (. by := 1; .)
  1892. GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
  1893. astStmt := AST.NoNode;
  1894. astBy := AST.NoNode;
  1895. ok := SymTab.Lookup(lv);
  1896. IF NOT ok THEN
  1897. SemError(201)
  1898. ELSIF (SymTab.SymKind(lv) #
  1899. SymTab.KindVar)
  1900. AND (SymTab.SymKind(lv) #
  1901. SymTab.KindParam) THEN
  1902. SemError(220); ok := FALSE
  1903. ELSIF NOT SymTab.IsIntFamily(
  1904. SymTab.SymType(lv)) THEN
  1905. SemError(220); ok := FALSE
  1906. END; .)
  1907. ":=" Expr<tlo, qlo> (. astLo := astCur;
  1908. IF NOT SymTab.IsIntFamily(tlo) THEN
  1909. SemError(220); ok := FALSE
  1910. END; .)
  1911. "TO" Expr<thi, qhi> (. astHi := astCur;
  1912. IF NOT SymTab.IsIntFamily(thi) THEN
  1913. SemError(220); ok := FALSE
  1914. END; .)
  1915. [ "BY" Expr<tby, qby> (. astBy := astCur;
  1916. IF (tby #
  1917. SymTab.InvalidType)
  1918. AND NOT SymTab.IsIntFamily(tby) THEN
  1919. SemError(220); ok := FALSE
  1920. END;
  1921. IF NOT SymTab.ConstInt(qby, by) THEN
  1922. SemError(230); by := 1
  1923. ELSIF by = 0 THEN
  1924. SemError(220); by := 1
  1925. END; .) ]
  1926. "DO"
  1927. [ StatSeq ]
  1928. "END" (. astNode := AST.MakeNode(AST.NkFor);
  1929. AST.SetChild(astNode, 0, astVar);
  1930. AST.SetChild(astNode, 1, astLo);
  1931. AST.SetChild(astNode, 2, astHi);
  1932. AST.SetChild(astNode, 3, astBy);
  1933. AST.SetChild(astNode, 4, astStmt);
  1934. astStmt := astNode;
  1935. .) .
  1936. CaseStat (. VAR tsel: SymTab.TypeIndex;
  1937. qsel, lEnd: QbeGen.QVal;
  1938. arm, astNode, astArms,
  1939. astArmsTail: AST.Node; .)
  1940. = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
  1941. AST.SetChild(astNode, 0, astCur);
  1942. astArms := AST.NoNode;
  1943. astArmsTail := AST.NoNode;
  1944. .)
  1945. "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
  1946. { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
  1947. [ "ELSE" (. astStmt := AST.NoNode; .)
  1948. [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
  1949. AST.SetOp(arm, 1);
  1950. AST.SetChild(arm, 0, astStmt);
  1951. AstAppend(AST.NkBlock,
  1952. astArms, astArmsTail, arm); .) ]
  1953. "END" (. AST.SetChild(astNode, 1, astArms);
  1954. astStmt := astNode;
  1955. .) .
  1956. (* Compare-chain lowering: each alternative ends its match-tests
  1957. with "jmp lAfter", so the no-match fallthrough skips the body:
  1958. "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
  1959. lAfter:". Falls into the next alternative, ELSE, or END. *)
  1960. CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
  1961. lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
  1962. (. VAR arm: AST.Node; .)
  1963. = (. arm := AST.MakeNode(AST.NkCaseArm); .)
  1964. CaseLabel<tsel, qsel, arm>
  1965. { "," CaseLabel<tsel, qsel, arm> }
  1966. ":" (. astStmt := AST.NoNode; .)
  1967. [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
  1968. astStmt);
  1969. AstAppend(AST.NkBlock,
  1970. arms, armsTail, arm);
  1971. .) .
  1972. CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
  1973. arm: AST.Node>
  1974. (. VAR t2, t3: SymTab.TypeIndex;
  1975. q2, q3, qc, qd, qe:
  1976. QbeGen.QVal;
  1977. astLab: AST.Node;
  1978. lNext: QbeGen.QVal; .)
  1979. = Expr<t2, q2> (. astLab := astCur;
  1980. IF (t2 #
  1981. SymTab.InvalidType)
  1982. AND (tsel #
  1983. SymTab.InvalidType)
  1984. AND ((SymTab.ClassOf(t2) =
  1985. SymTab.ClSet)
  1986. OR (SymTab.ClassOf(tsel) =
  1987. SymTab.ClSet)) THEN
  1988. SemError(230)
  1989. ELSIF (t2 #
  1990. SymTab.InvalidType)
  1991. AND (tsel #
  1992. SymTab.InvalidType)
  1993. AND NOT SymTab.EqCheck(t2,
  1994. tsel) THEN
  1995. SemError(213) END;
  1996. IF NOT QbeGen.IsImm(q2) THEN
  1997. SemError(230)
  1998. END; .)
  1999. [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
  2000. AST.NkSubrange, 0, astLab, astCur);
  2001. IF (t3 #
  2002. SymTab.InvalidType)
  2003. AND (tsel #
  2004. SymTab.InvalidType)
  2005. AND NOT SymTab.EqCheck(t3,
  2006. tsel) THEN
  2007. SemError(213) END;
  2008. IF NOT QbeGen.IsImm(q3) THEN
  2009. SemError(230)
  2010. END; .) ]
  2011. (. AST.SetChild(arm,
  2012. AST.NChild(arm), astLab); .) .
  2013. ReturnStat (. VAR t: SymTab.TypeIndex;
  2014. q, qt: QbeGen.QVal;
  2015. res: SymTab.TypeIndex;
  2016. hadE, conv: BOOLEAN;
  2017. astVal, astNode: AST.Node; .)
  2018. = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
  2019. [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
  2020. (. astNode := AST.MakeNode(AST.NkReturn);
  2021. IF hadE THEN
  2022. AST.SetChild(astNode, 0, astVal)
  2023. END;
  2024. astStmt := astNode;
  2025. conv := FALSE;
  2026. IF NOT SymTab.InProc() THEN
  2027. SemError(232)
  2028. ELSE res := SymTab.CurRes();
  2029. IF NOT hadE THEN
  2030. IF res #
  2031. SymTab.InvalidType THEN
  2032. SemError(232)
  2033. END
  2034. ELSIF (res =
  2035. SymTab.InvalidType)
  2036. OR (t #
  2037. SymTab.InvalidType)
  2038. AND NOT SymTab.Assignable(t,
  2039. res) THEN
  2040. SemError(232)
  2041. END
  2042. END; .) .
  2043. HaltStat (. VAR t: SymTab.TypeIndex;
  2044. q: QbeGen.QVal;
  2045. astVal, astNode: AST.Node; .)
  2046. = "HALT" (. astVal := AST.NoNode; .)
  2047. [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
  2048. (. astNode := AST.MakeNode(AST.NkHalt);
  2049. IF astVal # AST.NoNode THEN
  2050. AST.SetChild(astNode, 0, astVal)
  2051. END;
  2052. astStmt := astNode;
  2053. .) .
  2054. (* Designator: scalar loads, array addresses, and index suffixes.
  2055. Each index descends one level (bounds-checked, trap on breach);
  2056. nested levels reload the inner descriptor address. q ends as the
  2057. value (scalars), the descriptor address (plain arrays), or the
  2058. element address (indexed); sfx marks the indexed form. *)
  2059. Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  2060. VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
  2061. (. VAR n: SymTab.Name; .)
  2062. = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
  2063. (* The part of Design after the identifier: resolve it and walk the
  2064. selectors. Split out so a statement can decide between a label
  2065. (`ident :`) and a designator (`ident := ...`) with one token. *)
  2066. DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  2067. VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
  2068. (. VAR fn, mal: SymTab.Name;
  2069. cls: INTEGER;
  2070. ic: SymTab.TypeIndex;
  2071. curT, it, eT, bt:
  2072. SymTab.TypeIndex;
  2073. iq, ql, qlo, qhi, qe:
  2074. QbeGen.QVal;
  2075. lo, hi: INTEGER;
  2076. fo: INTEGER;
  2077. isOpen: BOOLEAN;
  2078. qb, cv: QbeGen.QVal;
  2079. fid, fref: INTEGER;
  2080. r: BOOLEAN;
  2081. astDes, astSel: AST.Node;
  2082. fwd: BOOLEAN; .)
  2083. = (. methCls := SymTab.InvalidType;
  2084. QbeGen.CopyOp(n, qn);
  2085. sfx := FALSE; fwd := FALSE;
  2086. fid := 0; fref := 0;
  2087. IF NOT SymTab.Lookup(n) THEN
  2088. (* a bare method name inside
  2089. a CLASS IMPLEMENTATION
  2090. is a sibling call on
  2091. THIS *)
  2092. ic := SymTab.CurImplClass();
  2093. IF (ic #
  2094. SymTab.InvalidType)
  2095. AND SymTab.MethodExists(ic, n) THEN
  2096. sfx := FALSE;
  2097. QbeGen.CopyOp("@", q);
  2098. methCls := ic;
  2099. k := SymTab.KindProc;
  2100. t := SymTab.InvalidType
  2101. ELSIF SymTab.InProc() THEN
  2102. (* not declared yet: a
  2103. forward reference to a
  2104. module-level variable
  2105. declared further down. *)
  2106. k := SymTab.KindVar;
  2107. r := SymTab.FwdVarRef(n, k,
  2108. fref, t);
  2109. Check.NoteForward(fref);
  2110. QbeGen.CopyOp("@", q);
  2111. sfx := TRUE; fwd := TRUE
  2112. ELSE
  2113. SemError(201);
  2114. t :=
  2115. SymTab.InvalidType;
  2116. k := -1;
  2117. QbeGen.CopyOp("0", q)
  2118. END
  2119. ELSE
  2120. t := SymTab.SymType(n);
  2121. k := SymTab.SymKind(n);
  2122. IF k = SymTab.KindConst THEN
  2123. IF SymTab.Equal(n,
  2124. "TRUE") THEN
  2125. t := SymTab.BoolType();
  2126. QbeGen.CopyOp("1", q)
  2127. ELSIF SymTab.Equal(n,
  2128. "FALSE") THEN
  2129. t := SymTab.BoolType();
  2130. QbeGen.CopyOp("0", q)
  2131. ELSIF SymTab.Equal(n,
  2132. "NIL") THEN
  2133. QbeGen.CopyOp("0", q)
  2134. ELSE
  2135. cls :=
  2136. SymTab.ClassOf(t);
  2137. IF (t #
  2138. SymTab.InvalidType)
  2139. AND ((cls = SymTab.ClInt)
  2140. OR (cls
  2141. = SymTab.ClChar)
  2142. OR (cls
  2143. = SymTab.ClEnum)
  2144. OR (cls
  2145. = SymTab.ClReal)
  2146. OR (cls
  2147. = SymTab.ClLong)
  2148. OR (cls
  2149. = SymTab.ClNil)) THEN
  2150. IF cls = SymTab.ClNil THEN
  2151. QbeGen.CopyOp("0", q)
  2152. ELSIF ((cls
  2153. = SymTab.ClInt)
  2154. OR (cls
  2155. = SymTab.ClChar)
  2156. OR (cls
  2157. = SymTab.ClEnum)
  2158. OR (cls
  2159. = SymTab.ClLong))
  2160. AND SymTab.GetSymVal(n, cv)
  2161. AND QbeGen.IsImm(cv) THEN
  2162. QbeGen.CopyOp(cv, q)
  2163. ELSE
  2164. QbeGen.LoadVar(n,
  2165. cls = SymTab.ClReal,
  2166. q)
  2167. END
  2168. ELSIF (cls = SymTab.ClArray)
  2169. OR (cls = SymTab.ClRecord)
  2170. OR (cls = SymTab.ClClass)
  2171. OR (cls = SymTab.ClStr)
  2172. OR (cls = SymTab.ClUStr) THEN
  2173. (* aggregate constant:
  2174. its value IS the
  2175. descriptor address *)
  2176. IF SymTab.GetSymVal(n, cv) THEN
  2177. QbeGen.CopyOp(cv, q)
  2178. ELSE
  2179. QbeGen.CopyOp("0", q)
  2180. END
  2181. ELSE
  2182. IF t #
  2183. SymTab.InvalidType THEN
  2184. SemError(230)
  2185. END;
  2186. QbeGen.CopyOp("0", q)
  2187. END
  2188. END
  2189. ELSIF (k = SymTab.KindVar)
  2190. OR (k = SymTab.KindParam) THEN
  2191. cls := SymTab.ClassOf(t);
  2192. IF (cls # SymTab.ClInt)
  2193. AND (cls # SymTab.ClBool)
  2194. AND (cls # SymTab.ClChar)
  2195. AND (cls # SymTab.ClUChar)
  2196. AND (cls # SymTab.ClEnum)
  2197. AND (cls # SymTab.ClReal)
  2198. AND (cls # SymTab.ClPtr)
  2199. AND (cls # SymTab.ClProc)
  2200. AND (cls # SymTab.ClLong)
  2201. AND (cls # SymTab.ClArray)
  2202. AND (cls # SymTab.ClSet)
  2203. AND (cls # SymTab.ClRecord)
  2204. AND (cls # SymTab.ClUStr)
  2205. AND (cls # SymTab.ClClass) THEN
  2206. SemError(230);
  2207. QbeGen.CopyOp("0", q)
  2208. ELSE QbeGen.CopyOp("@", q)
  2209. END
  2210. ELSE QbeGen.CopyOp("0", q);
  2211. IF k = SymTab.KindImport THEN
  2212. SemError(230)
  2213. ELSIF k =
  2214. SymTab.KindProc THEN
  2215. (* bare procedure name:
  2216. a following ArgList
  2217. makes it a call;
  2218. otherwise Fact
  2219. reports 230 *)
  2220. ELSE
  2221. IF k = SymTab.KindField THEN
  2222. IF QbeGen.TopWith(qb) THEN
  2223. sfx := TRUE
  2224. ELSE SemError(230);
  2225. QbeGen.CopyOp("0", q)
  2226. END
  2227. END
  2228. END
  2229. END
  2230. END; .)
  2231. (. astDes := AST.MakeNode(AST.NkDesignator);
  2232. AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
  2233. IF fwd THEN AST.SetOp(astDes, 1) END; .)
  2234. { "[" Expr<it, iq>
  2235. (. AST.SetChild(astDes, AST.NChild(astDes),
  2236. AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
  2237. ELSIF SymTab.ClassOf(t) #
  2238. SymTab.ClArray THEN
  2239. SemError(217);
  2240. t := SymTab.InvalidType
  2241. ELSIF NOT SymTab.IsIntFamily(it)
  2242. AND (SymTab.ClassOf(it) #
  2243. SymTab.ClChar)
  2244. AND (SymTab.ClassOf(it) #
  2245. SymTab.ClEnum) THEN
  2246. SemError(218);
  2247. t := SymTab.InvalidType
  2248. ELSE
  2249. eT := SymTab.ArrayElem(t);
  2250. t := eT; sfx := TRUE
  2251. END; .)
  2252. { "," Expr<it, iq>
  2253. (. AST.SetChild(astDes, AST.NChild(astDes),
  2254. AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
  2255. ELSIF SymTab.ClassOf(t) #
  2256. SymTab.ClArray THEN
  2257. SemError(217);
  2258. t := SymTab.InvalidType
  2259. ELSIF NOT SymTab.IsIntFamily(it)
  2260. AND (SymTab.ClassOf(it) #
  2261. SymTab.ClChar)
  2262. AND (SymTab.ClassOf(it) #
  2263. SymTab.ClEnum) THEN
  2264. SemError(218);
  2265. t := SymTab.InvalidType
  2266. ELSE
  2267. eT := SymTab.ArrayElem(t);
  2268. t := eT; sfx := TRUE
  2269. END; .) }
  2270. "]"
  2271. | "." GetIdent<fn>
  2272. (. astSel := AST.MakeNode(AST.NkSelector);
  2273. AST.SetOp(astSel, AST.SelField);
  2274. AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
  2275. AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
  2276. (* qualified L.x: materialize
  2277. the export, then load it *)
  2278. IF NOT SymTab.MaterializeAlias(n,
  2279. fn, mal) THEN
  2280. SemError(201);
  2281. t := SymTab.InvalidType;
  2282. QbeGen.CopyOp("0", q)
  2283. ELSE
  2284. QbeGen.CopyOp(mal, qn);
  2285. t := SymTab.SymType(mal);
  2286. k := SymTab.SymKind(mal);
  2287. sfx := FALSE;
  2288. IF k = SymTab.KindProc THEN
  2289. (* call: ArgList supplies
  2290. the value *)
  2291. QbeGen.CopyOp("0", q)
  2292. END
  2293. END
  2294. ELSIF t = SymTab.InvalidType THEN
  2295. ELSIF (SymTab.ClassOf(t) #
  2296. SymTab.ClRecord)
  2297. AND (SymTab.ClassOf(t) #
  2298. SymTab.ClClass) THEN
  2299. SemError(215);
  2300. t := SymTab.InvalidType
  2301. ELSIF (SymTab.ClassOf(t) =
  2302. SymTab.ClClass)
  2303. AND SymTab.MethodExists(t, fn) THEN
  2304. (* obj.Method: bind the
  2305. method and pass obj as
  2306. the hidden receiver; q
  2307. already holds the
  2308. object's address *)
  2309. QbeGen.CopyOp(fn, n);
  2310. QbeGen.CopyOp(fn, qn);
  2311. methCls := t;
  2312. k := SymTab.KindProc;
  2313. t := SymTab.InvalidType
  2314. ELSIF NOT SymTab.FieldExists(t,
  2315. fn) THEN
  2316. SemError(216);
  2317. t := SymTab.InvalidType
  2318. ELSE
  2319. t := SymTab.FieldType(t, fn);
  2320. sfx := TRUE
  2321. END; .)
  2322. | "^"
  2323. (. astSel := AST.MakeNode(AST.NkSelector);
  2324. AST.SetOp(astSel, AST.SelDeref);
  2325. AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
  2326. ELSIF SymTab.ClassOf(t) #
  2327. SymTab.ClPtr THEN
  2328. SemError(219);
  2329. t := SymTab.InvalidType
  2330. ELSE
  2331. bt := SymTab.PtrBase(t);
  2332. IF bt = SymTab.InvalidType THEN
  2333. ELSE
  2334. t := bt;
  2335. sfx := TRUE
  2336. END
  2337. END; .) } (. astCur := astDes; .) .
  2338. (* Result suffix (ISO component after a function call): `F()^`,
  2339. `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
  2340. (a value, or a descriptor address for aggregates); each component
  2341. descends one level exactly like the Design components. *)
  2342. ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
  2343. VAR sfx: BOOLEAN; VAR node: AST.Node;
  2344. VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
  2345. VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
  2346. iq, ql, qlo, qhi, qe, qb:
  2347. QbeGen.QVal;
  2348. lo, hi, fo: INTEGER;
  2349. isOpen: BOOLEAN;
  2350. fname: SymTab.Name;
  2351. astWrap, astSel: AST.Node; .)
  2352. = "[" Expr<it, iq>
  2353. (. isM := FALSE;
  2354. IF AST.Kind(node) # AST.NkDesignator THEN
  2355. astWrap := AST.MakeNode(
  2356. AST.NkDesignator);
  2357. AST.SetChild(astWrap, 0, node);
  2358. node := astWrap
  2359. END;
  2360. AST.SetChild(node, AST.NChild(node),
  2361. AST.MakeUn(AST.NkSelector,
  2362. AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
  2363. ELSIF SymTab.ClassOf(t) #
  2364. SymTab.ClArray THEN
  2365. SemError(217);
  2366. t := SymTab.InvalidType
  2367. ELSIF NOT SymTab.IsIntFamily(it)
  2368. AND (SymTab.ClassOf(it) # SymTab.ClChar)
  2369. AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
  2370. SemError(218);
  2371. t := SymTab.InvalidType
  2372. ELSE
  2373. eT := SymTab.ArrayElem(t);
  2374. t := eT; sfx := TRUE
  2375. END; .)
  2376. "]"
  2377. | "." GetIdent<fname>
  2378. (. isM := FALSE;
  2379. IF AST.Kind(node) # AST.NkDesignator THEN
  2380. astWrap := AST.MakeNode(
  2381. AST.NkDesignator);
  2382. AST.SetChild(astWrap, 0, node);
  2383. node := astWrap
  2384. END;
  2385. AST.SetChild(node, AST.NChild(node),
  2386. AST.MakeUn(AST.NkSelector,
  2387. AST.SelField,
  2388. AST.MakeLeaf(AST.NkIdent,
  2389. fname))); IF t = SymTab.InvalidType THEN
  2390. ELSIF (SymTab.ClassOf(t) #
  2391. SymTab.ClRecord)
  2392. AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
  2393. SemError(215);
  2394. t := SymTab.InvalidType
  2395. ELSIF (SymTab.ClassOf(t) =
  2396. SymTab.ClClass)
  2397. AND SymTab.MethodExists(t, fname) THEN
  2398. (* a method on the call result:
  2399. a following ArgList makes
  2400. the call *)
  2401. mname := fname;
  2402. methCls := t; isM := TRUE;
  2403. t := SymTab.InvalidType
  2404. ELSIF NOT SymTab.FieldExists(t,
  2405. fname) THEN
  2406. SemError(216);
  2407. t := SymTab.InvalidType
  2408. ELSE
  2409. t := SymTab.FieldType(t, fname);
  2410. sfx := TRUE
  2411. END; .)
  2412. | "^" (. isM := FALSE;
  2413. IF AST.Kind(node) # AST.NkDesignator THEN
  2414. astWrap := AST.MakeNode(
  2415. AST.NkDesignator);
  2416. AST.SetChild(astWrap, 0, node);
  2417. node := astWrap
  2418. END;
  2419. astSel := AST.MakeNode(AST.NkSelector);
  2420. AST.SetOp(astSel, AST.SelDeref);
  2421. AST.SetChild(node,
  2422. AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
  2423. ELSIF SymTab.ClassOf(t) #
  2424. SymTab.ClPtr THEN
  2425. SemError(219);
  2426. t := SymTab.InvalidType
  2427. ELSE
  2428. bt := SymTab.PtrBase(t);
  2429. IF bt # SymTab.InvalidType THEN
  2430. t := bt; sfx := TRUE
  2431. END
  2432. END; .) .
  2433. Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2434. (. VAR t2: SymTab.TypeIndex;
  2435. op: INTEGER;
  2436. q2, qt, wl: QbeGen.QVal;
  2437. astA, astB: AST.Node;
  2438. astOp: INTEGER;
  2439. astMade: BOOLEAN;
  2440. isR: BOOLEAN; .)
  2441. = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
  2442. [ Rel<op> SimExpr<t2, q2>
  2443. (. astB := astCur; astMade := TRUE;
  2444. astOp := AST.OpEq;
  2445. IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
  2446. ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
  2447. ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
  2448. ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
  2449. ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
  2450. ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
  2451. ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
  2452. END;
  2453. IF op = SymTab.OpIn THEN
  2454. IF SymTab.InCheck(t, t2) THEN
  2455. IF (t = SymTab.InvalidType)
  2456. OR (t2 = SymTab.InvalidType) THEN
  2457. t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  2458. ELSE
  2459. t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
  2460. END
  2461. ELSE SemError(222); t := SymTab.InvalidType;
  2462. QbeGen.CopyOp("0", q)
  2463. END
  2464. ELSIF SymTab.RelCheck(t, t2, op) THEN
  2465. IF (t = SymTab.InvalidType)
  2466. OR (t2 = SymTab.InvalidType) THEN
  2467. t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  2468. ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
  2469. OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
  2470. IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
  2471. AND (op # SymTab.OpNeq2) THEN
  2472. SemError(213); t := SymTab.InvalidType;
  2473. QbeGen.CopyOp("0", q)
  2474. ELSE
  2475. t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
  2476. END
  2477. ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
  2478. OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  2479. t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
  2480. ELSIF SymTab.StrCompat(t, t2) THEN
  2481. QbeGen.StrEq(op, q, q2, qt);
  2482. t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  2483. ELSIF SymTab.IsLongFamily(t)
  2484. OR SymTab.IsLongFamily(t2) THEN
  2485. t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
  2486. ELSE
  2487. t := SymTab.BoolType();
  2488. QbeGen.CopyOp("@", q)
  2489. END
  2490. ELSE SemError(213); t := SymTab.InvalidType;
  2491. QbeGen.CopyOp("0", q)
  2492. END;
  2493. astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
  2494. (. IF NOT astMade THEN astCur := astA END; .)
  2495. (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
  2496. Rel<VAR op: INTEGER>
  2497. = "=" (. op := SymTab.OpEq; .)
  2498. | "#" (. op := SymTab.OpNeq1; .)
  2499. | "<" (. op := SymTab.OpLt; .)
  2500. | "<=" (. op := SymTab.OpLe; .)
  2501. | ">" (. op := SymTab.OpGt; .)
  2502. | ">=" (. op := SymTab.OpGe; .)
  2503. | "IN" (. op := SymTab.OpIn; .) .
  2504. SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2505. (. VAR t2, res2, lt, rt:
  2506. SymTab.TypeIndex;
  2507. op: INTEGER;
  2508. q2, qt, wq, qf, q2a, q2b:
  2509. QbeGen.QVal;
  2510. neg, isR, isL, folded:
  2511. BOOLEAN;
  2512. fok: BOOLEAN;
  2513. lw, rw, mw: CARDINAL;
  2514. lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
  2515. astA, astB: AST.Node;
  2516. astSign, astOp: INTEGER; .)
  2517. = (. neg := FALSE; astSign := 0; .)
  2518. [ "+" (. neg := TRUE; astSign := 1; .)
  2519. | "-" (. neg := TRUE; astSign := -1; .) ]
  2520. Term<t, q> (. astA := astCur;
  2521. IF neg AND QbeGen.IsImm(q) THEN
  2522. QbeGen.NegFold(q, q)
  2523. END;
  2524. IF astSign < 0 THEN
  2525. astCur := AST.MakeUn(
  2526. AST.NkUnary, AST.OpSub, astA);
  2527. astA := astCur
  2528. END; .)
  2529. { AddOp<op>
  2530. Term<t2, q2> (. astB := astCur; .)
  2531. (. astOp := AST.OpAdd;
  2532. IF op = SymTab.OpSub THEN astOp := AST.OpSub
  2533. ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
  2534. astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
  2535. astCur := astA;
  2536. IF op = SymTab.OpOr THEN
  2537. (* short-circuit: if q is true the RHS is skipped *)
  2538. IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
  2539. t := SymTab.BoolType()
  2540. ELSE SemError(212); t := SymTab.InvalidType END;
  2541. IF t # SymTab.InvalidType THEN
  2542. QbeGen.CopyOp("@", q)
  2543. ELSE QbeGen.CopyOp("0", q)
  2544. END
  2545. ELSIF (op = SymTab.OpAdd)
  2546. AND (SymTab.UStrCompat(t, t2)
  2547. OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
  2548. AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
  2549. OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
  2550. AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
  2551. OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
  2552. AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
  2553. (* UString concatenation: a UCHAR operand becomes a
  2554. 1-codepoint UString; the result is a descriptor in the
  2555. shim's concat buffer. Work on copies so neither
  2556. operand is clobbered. *)
  2557. t := SymTab.NewUStr();
  2558. QbeGen.CopyOp("@", q)
  2559. ELSIF (op = SymTab.OpAdd)
  2560. AND (SymTab.StrCompat(t, t2)
  2561. OR (SymTab.IsStrType(t)
  2562. AND (SymTab.ClassOf(t2) = SymTab.ClChar))
  2563. OR ((SymTab.ClassOf(t) = SymTab.ClChar)
  2564. AND SymTab.IsStrType(t2))) THEN
  2565. (* string concatenation; a CHAR operand becomes a
  2566. 1-character string literal. When both operands are
  2567. constants, fold to a single string literal so a
  2568. constructor element stays compile-time. *)
  2569. QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
  2570. qt, fok);
  2571. IF fok THEN QbeGen.CopyOp(qt, q)
  2572. ELSE QbeGen.CopyOp("@", q)
  2573. END;
  2574. t := SymTab.NewStr()
  2575. ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
  2576. AND (SymTab.ClassOf(t) = SymTab.ClSet)
  2577. AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  2578. lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
  2579. mw := lw;
  2580. IF rw > mw THEN mw := rw END;
  2581. t := SymTab.NewSet(
  2582. SymTab.NewSubR(0,
  2583. VAL(INTEGER, mw) * 32 - 1));
  2584. QbeGen.CopyOp("@", q)
  2585. ELSE
  2586. IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
  2587. lt := t; rt := t2; t := res2
  2588. ELSE SemError(211); t := SymTab.InvalidType END;
  2589. IF t # SymTab.InvalidType THEN
  2590. isL := SymTab.IsLongFamily(t);
  2591. isR := SymTab.ClassOf(t) = SymTab.ClReal;
  2592. folded := FALSE;
  2593. IF (NOT isL) AND (NOT isR)
  2594. AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
  2595. IF op = SymTab.OpAdd THEN
  2596. folded := QbeGen.Fold2(0, q, q2, qf)
  2597. ELSE
  2598. folded := QbeGen.Fold2(1, q, q2, qf)
  2599. END
  2600. END;
  2601. IF folded THEN QbeGen.CopyOp(qf, q)
  2602. ELSE
  2603. QbeGen.CopyOp("@", q)
  2604. END
  2605. ELSE QbeGen.CopyOp("0", q)
  2606. END
  2607. END; .) }
  2608. (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
  2609. AddOp<VAR op: INTEGER>
  2610. = "+" (. op := SymTab.OpAdd; .)
  2611. | "-" (. op := SymTab.OpSub; .)
  2612. | "OR" (. op := SymTab.OpOr; .) .
  2613. Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2614. (. VAR t2, res2, lt, rt:
  2615. SymTab.TypeIndex;
  2616. op: INTEGER;
  2617. q2, qt, wq, qf:
  2618. QbeGen.QVal;
  2619. isR, isL, folded: BOOLEAN;
  2620. lw, rw, mw: CARDINAL;
  2621. lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
  2622. astA, astB: AST.Node;
  2623. astOp: INTEGER; .)
  2624. = Fact<t, q> (. astA := astCur; .) { MulOp<op>
  2625. Fact<t2, q2> (. astB := astCur; .)
  2626. (. astOp := AST.OpMul;
  2627. IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
  2628. ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
  2629. ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
  2630. ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
  2631. astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
  2632. astCur := astA;
  2633. IF op = SymTab.OpAnd THEN
  2634. (* short-circuit: if q is false the RHS is skipped *)
  2635. IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
  2636. t := SymTab.BoolType()
  2637. ELSE SemError(212); t := SymTab.InvalidType END;
  2638. IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
  2639. ELSE QbeGen.CopyOp("0", q)
  2640. END
  2641. ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
  2642. AND (SymTab.ClassOf(t) = SymTab.ClSet)
  2643. AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  2644. lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
  2645. mw := lw;
  2646. IF rw > mw THEN mw := rw END;
  2647. t := SymTab.NewSet(
  2648. SymTab.NewSubR(0,
  2649. VAL(INTEGER, mw) * 32 - 1));
  2650. QbeGen.CopyOp("@", q)
  2651. ELSE
  2652. IF SymTab.ArithCheck(t, t2,
  2653. (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
  2654. res2) THEN
  2655. lt := t; rt := t2; t := res2
  2656. ELSE SemError(211); t := SymTab.InvalidType END;
  2657. IF t # SymTab.InvalidType THEN
  2658. isL := SymTab.IsLongFamily(t);
  2659. isR := SymTab.ClassOf(t) = SymTab.ClReal;
  2660. folded := FALSE;
  2661. IF (NOT isL) AND (NOT isR)
  2662. AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
  2663. IF op = SymTab.OpTimes THEN
  2664. folded := QbeGen.Fold2(2, q, q2, qf)
  2665. ELSIF op = SymTab.OpDiv THEN
  2666. folded := QbeGen.Fold2(3, q, q2, qf)
  2667. ELSIF op = SymTab.OpMod THEN
  2668. folded := QbeGen.Fold2(4, q, q2, qf)
  2669. END
  2670. END;
  2671. IF folded THEN QbeGen.CopyOp(qf, q)
  2672. ELSE
  2673. QbeGen.CopyOp("@", q)
  2674. END
  2675. ELSE QbeGen.CopyOp("0", q)
  2676. END
  2677. END; .) }
  2678. (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
  2679. MulOp<VAR op: INTEGER>
  2680. = "*" (. op := SymTab.OpTimes; .)
  2681. | "/" (. op := SymTab.OpSlash; .)
  2682. | "DIV" (. op := SymTab.OpDiv; .)
  2683. | "MOD" (. op := SymTab.OpMod; .)
  2684. | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
  2685. Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2686. (. VAR s: ARRAY [0 .. 255] OF CHAR;
  2687. et, dt, t2, st, ct2, et2:
  2688. SymTab.TypeIndex;
  2689. dk: INTEGER;
  2690. qd, q2, sq, qa, qm0, qr, qt:
  2691. QbeGen.QVal;
  2692. qn, vn: SymTab.Name;
  2693. vt: SymTab.TypeIndex;
  2694. c1, c2: INTEGER;
  2695. lo, hi: INTEGER;
  2696. isMax: BOOLEAN;
  2697. called, isHigh, sfx, isCh,
  2698. isU, uok, isStr: BOOLEAN;
  2699. ucp: INTEGER; astIsLit: BOOLEAN;
  2700. astD: AST.Node;
  2701. astCall: BOOLEAN;
  2702. astNode, astNot: AST.Node;
  2703. j: CARDINAL;
  2704. astArg2: AST.Node;
  2705. astBrace: AST.Node;
  2706. astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN; .)
  2707. = (. astIsLit := FALSE; .)
  2708. ( integer (. LexString(s);
  2709. QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
  2710. t := SymTab.IntType(); .)
  2711. | charConst (. LexString(s);
  2712. QbeGen.NormLit(s, q, isCh);
  2713. IF twoPhase THEN
  2714. astIsLit := TRUE;
  2715. astCur := AST.MakeLeaf(
  2716. AST.NkCharLit, s)
  2717. END;
  2718. t := SymTab.CharType(); .)
  2719. | real (. LexString(s);
  2720. QbeGen.NormReal(s, q);
  2721. IF twoPhase THEN
  2722. astIsLit := TRUE;
  2723. astCur := AST.MakeLeaf(
  2724. AST.NkRealLit, s)
  2725. END;
  2726. t := SymTab.RealType(); .)
  2727. | string (. LexString(s);
  2728. IF twoPhase THEN
  2729. astIsLit := TRUE;
  2730. astCur := AST.MakeLeaf(
  2731. AST.NkStrLit, s)
  2732. END;
  2733. IF SymTab.StrLen(s) = 3 THEN
  2734. t := SymTab.CharType();
  2735. QbeGen.IntStr(
  2736. QbeGen.CharVal(s), q)
  2737. ELSE t := SymTab.NewStr();
  2738. QbeGen.DeclStr(s, q);
  2739. (* a literal's value IS its
  2740. static descriptor address *)
  2741. END; .)
  2742. | ustring (. LexString(s);
  2743. IF twoPhase THEN
  2744. astIsLit := TRUE;
  2745. astCur := AST.MakeLeaf(
  2746. AST.NkStrLit, s)
  2747. END;
  2748. QbeGen.DeclUStr(s, q, isU, ucp,
  2749. uok);
  2750. IF NOT uok THEN
  2751. SemError(234);
  2752. t := SymTab.InvalidType
  2753. ELSIF isU THEN
  2754. t := SymTab.UCharType();
  2755. QbeGen.IntStr(ucp, q)
  2756. ELSE
  2757. t := SymTab.NewUStr();
  2758. END; .)
  2759. | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
  2760. astNArgs := 0; called := FALSE;
  2761. t := dt;
  2762. IF dk = SymTab.KindConst THEN
  2763. QbeGen.CopyOp(qd, q)
  2764. ELSE QbeGen.CopyOp("@", q)
  2765. END; .)
  2766. [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
  2767. astBrace := astCur; .) ]
  2768. [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
  2769. (. astCall := TRUE;
  2770. astNode := AstCallNode(astD);
  2771. astRes := astNode;
  2772. t := ct2;
  2773. QbeGen.CopyOp(q2, q);
  2774. sfx := FALSE; .)
  2775. { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
  2776. [ (. astNArgs := 0; .)
  2777. ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
  2778. (. astNode := AstCallNode(astRes);
  2779. astRes := astNode;
  2780. t := ct2;
  2781. QbeGen.CopyOp(q2, q);
  2782. sfx := FALSE; .) ] }
  2783. (. IF sfx THEN
  2784. IF t = SymTab.InvalidType THEN
  2785. QbeGen.CopyOp("0", q)
  2786. ELSIF (SymTab.ClassOf(t) #
  2787. SymTab.ClRecord)
  2788. AND (SymTab.ClassOf(t) # SymTab.ClSet)
  2789. AND (SymTab.ClassOf(t) # SymTab.ClArray)
  2790. AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
  2791. QbeGen.CopyOp("@", q)
  2792. END
  2793. END; .) ]
  2794. (. IF called THEN
  2795. astCur := astRes
  2796. ELSIF astCall THEN
  2797. astCur := astBrace
  2798. ELSE astCur := astD
  2799. END;
  2800. astIsLit := TRUE;
  2801. IF NOT called
  2802. AND (dk = SymTab.KindProc) THEN
  2803. (* bare zero-arg function
  2804. call (parentheses may be
  2805. omitted); a proper or
  2806. parameterised proc here
  2807. is 230 *)
  2808. IF (SymTab.ProcNPar(qn) = 0)
  2809. AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
  2810. t := SymTab.ProcRes(qn);
  2811. QbeGen.CopyOp("@", q);
  2812. astCur := AST.MakeNode(AST.NkCall);
  2813. AST.SetChild(astCur, 0, astD)
  2814. ELSE
  2815. t := SymTab.ProcTypeOf(qn);
  2816. QbeGen.CopyOp("@", q)
  2817. END
  2818. END; .)
  2819. | ( "HIGH" (. isHigh := TRUE; .)
  2820. | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
  2821. "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
  2822. isU := FALSE; .)
  2823. | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
  2824. isStr := TRUE;
  2825. isU := FALSE;
  2826. IF SymTab.StrLen(s) = 3 THEN
  2827. dt := SymTab.CharType();
  2828. QbeGen.IntStr(QbeGen.CharVal(s),
  2829. qd)
  2830. ELSE
  2831. dt := SymTab.NewStr();
  2832. QbeGen.DeclStr(s, qd);
  2833. END;
  2834. dk := -1;
  2835. qn[0] := CHR(0); .)
  2836. | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
  2837. QbeGen.DeclUStr(s, qd, isU, ucp,
  2838. uok);
  2839. isStr := FALSE;
  2840. IF NOT uok THEN
  2841. SemError(234);
  2842. dt := SymTab.InvalidType
  2843. ELSIF isU THEN
  2844. (* one codepoint: a UCHAR;
  2845. LEN is 1, HIGH is 0 *)
  2846. dt := SymTab.UCharType();
  2847. QbeGen.IntStr(ucp, qd)
  2848. ELSE
  2849. dt := SymTab.NewUStr();
  2850. END;
  2851. dk := -1;
  2852. qn[0] := CHR(0); .) )
  2853. ")"
  2854. (. astNode := AST.MakeNode(AST.NkCall);
  2855. IF isHigh THEN AST.SetChild(astNode, 0,
  2856. AST.MakeLeaf(AST.NkIdent, "HIGH"))
  2857. ELSE AST.SetChild(astNode, 0,
  2858. AST.MakeLeaf(AST.NkIdent, "LEN")) END;
  2859. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  2860. astCur := astNode; astIsLit := TRUE;
  2861. IF (dt # SymTab.InvalidType)
  2862. AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
  2863. (* UString: the count is
  2864. the descriptor header *)
  2865. t := SymTab.IntType();
  2866. QbeGen.CopyOp("@", q)
  2867. ELSIF (dt # SymTab.InvalidType)
  2868. AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
  2869. (* single UCHAR codepoint *)
  2870. IF isHigh THEN
  2871. QbeGen.CopyOp("0", qr)
  2872. ELSE
  2873. QbeGen.CopyOp("1", qr)
  2874. END;
  2875. t := SymTab.IntType();
  2876. QbeGen.CopyOp(qr, q)
  2877. ELSIF isStr THEN
  2878. (* fold: content length at
  2879. compile time *)
  2880. IF SymTab.StrLen(s) = 3 THEN
  2881. c1 := 1
  2882. ELSE
  2883. c1 :=
  2884. SymTab.StrLen(s) - 2
  2885. END;
  2886. IF isHigh THEN
  2887. DEC(c1)
  2888. END;
  2889. QbeGen.IntStr(c1, qr);
  2890. t := SymTab.IntType();
  2891. QbeGen.CopyOp(qr, q)
  2892. ELSIF dt = SymTab.InvalidType THEN
  2893. t := SymTab.InvalidType;
  2894. QbeGen.CopyOp("0", q)
  2895. ELSIF SymTab.ClassOf(dt) #
  2896. SymTab.ClArray THEN
  2897. SemError(217);
  2898. t := SymTab.InvalidType;
  2899. QbeGen.CopyOp("0", q)
  2900. ELSE
  2901. IF SymTab.IsOpenArray(dt) THEN
  2902. t := SymTab.IntType();
  2903. QbeGen.CopyOp("@", q)
  2904. ELSE
  2905. IF isHigh THEN
  2906. QbeGen.IntStr(
  2907. SymTab.ArrayHi(dt), qr)
  2908. ELSE
  2909. QbeGen.IntStr(VAL(
  2910. INTEGER,
  2911. SymTab.ArrayLen(dt)),
  2912. qr)
  2913. END;
  2914. t := SymTab.IntType();
  2915. QbeGen.CopyOp(qr, q)
  2916. END
  2917. END; .)
  2918. | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
  2919. (. astNode := AST.MakeNode(AST.NkCall);
  2920. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
  2921. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  2922. astCur := astNode; astIsLit := TRUE; .)
  2923. (. IF dt = SymTab.InvalidType THEN
  2924. t := SymTab.InvalidType;
  2925. QbeGen.CopyOp("0", q)
  2926. ELSE
  2927. QbeGen.IntStr(VAL(INTEGER,
  2928. SymTab.ObjectSize(dt)), q);
  2929. t := SymTab.IntType()
  2930. END; .)
  2931. | ( "SHIFT" (. isMax := FALSE; .)
  2932. | "ROTATE" (. isMax := TRUE; .) )
  2933. "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
  2934. (. astNode := AST.MakeNode(AST.NkCall);
  2935. IF isMax THEN AST.SetChild(astNode, 0,
  2936. AST.MakeLeaf(AST.NkIdent, "ROTATE"))
  2937. ELSE AST.SetChild(astNode, 0,
  2938. AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
  2939. IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
  2940. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
  2941. astCur := astNode; astIsLit := TRUE;
  2942. (* set shift/rotate: isMax
  2943. doubles as "rotate" *)
  2944. IF (et # SymTab.InvalidType)
  2945. AND (SymTab.ClassOf(et) =
  2946. SymTab.ClSet) THEN
  2947. t := et;
  2948. QbeGen.CopyOp("@", q)
  2949. ELSE SemError(230);
  2950. t := SymTab.InvalidType;
  2951. QbeGen.CopyOp("0", q)
  2952. END; .)
  2953. | ( "MIN" (. isMax := FALSE; .)
  2954. | "MAX" (. isMax := TRUE; .) )
  2955. "(" Design<dt, dk, qd, qn, sfx> ")"
  2956. (. astNode := AST.MakeNode(AST.NkCall);
  2957. IF isMax THEN AST.SetChild(astNode, 0,
  2958. AST.MakeLeaf(AST.NkIdent, "MAX"))
  2959. ELSE AST.SetChild(astNode, 0,
  2960. AST.MakeLeaf(AST.NkIdent, "MIN")) END;
  2961. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  2962. astCur := astNode; astIsLit := TRUE;
  2963. IF (dt # SymTab.InvalidType)
  2964. AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
  2965. (* REAL/LONGREAL: the
  2966. implementation bounds *)
  2967. IF isMax THEN
  2968. QbeGen.NormReal(
  2969. "3.402823e38", q)
  2970. ELSE QbeGen.NormReal(
  2971. "-3.402823e38", q)
  2972. END;
  2973. t := SymTab.RealType()
  2974. ELSIF (dt #
  2975. SymTab.InvalidType)
  2976. AND (SymTab.ClassOf(dt) =
  2977. SymTab.ClLong) THEN
  2978. IF isMax THEN
  2979. QbeGen.CopyOp(
  2980. "9223372036854775807", q)
  2981. ELSE QbeGen.CopyOp(
  2982. "-9223372036854775808", q)
  2983. END;
  2984. t := SymTab.LongType()
  2985. ELSIF SymTab.TypeBounds(dt, lo,
  2986. hi) THEN
  2987. IF isMax THEN
  2988. QbeGen.IntStr(hi, q)
  2989. ELSE QbeGen.IntStr(lo, q)
  2990. END;
  2991. t := SymTab.IntType()
  2992. ELSE SemError(230);
  2993. t := SymTab.InvalidType;
  2994. QbeGen.CopyOp("0", q)
  2995. END; .)
  2996. | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
  2997. (. astNode := AST.MakeNode(AST.NkCall);
  2998. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
  2999. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3000. astCur := astNode; astIsLit := TRUE; .)
  3001. (. IF dt = SymTab.InvalidType THEN
  3002. t := SymTab.InvalidType;
  3003. QbeGen.CopyOp("0", q)
  3004. ELSE
  3005. IF sfx
  3006. OR (dk = SymTab.KindVar)
  3007. OR (dk = SymTab.KindParam) THEN
  3008. QbeGen.CopyOp("@", q)
  3009. ELSE SemError(230);
  3010. QbeGen.CopyOp("0", q)
  3011. END;
  3012. t := SymTab.AddrType()
  3013. END; .)
  3014. | "CHR" "(" Expr<et, q> ")"
  3015. (. astNode := AST.MakeNode(AST.NkCall);
  3016. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
  3017. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3018. astCur := astNode; astIsLit := TRUE; .)
  3019. (. IF (et # SymTab.InvalidType)
  3020. AND NOT SymTab.IsIntFamily(et) THEN
  3021. SemError(211) END;
  3022. t := SymTab.CharType(); .)
  3023. | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
  3024. (. astNode := AST.MakeNode(AST.NkCall);
  3025. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
  3026. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3027. astCur := astNode; astIsLit := TRUE; .)
  3028. (. IF et # SymTab.InvalidType THEN
  3029. IF (SymTab.ClassOf(et) #
  3030. SymTab.ClChar)
  3031. AND (SymTab.ClassOf(et) #
  3032. SymTab.ClBool)
  3033. AND (SymTab.ClassOf(et) #
  3034. SymTab.ClEnum)
  3035. AND NOT SymTab.IsIntFamily(et) THEN
  3036. SemError(211) END
  3037. END;
  3038. t := SymTab.IntType(); .)
  3039. | "CAP" "(" Expr<et, q> ")"
  3040. (. astNode := AST.MakeNode(AST.NkCall);
  3041. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
  3042. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3043. astCur := astNode; astIsLit := TRUE; .)
  3044. (. QbeGen.CopyOp("@", q);
  3045. t := SymTab.CharType(); .)
  3046. | "UCHR" "(" Expr<et, q> ")"
  3047. (. astNode := AST.MakeNode(AST.NkCall);
  3048. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
  3049. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3050. astCur := astNode; astIsLit := TRUE; .)
  3051. (. (* UCHR: the UCHAR constructor.
  3052. CHAR -> UCHAR (identity);
  3053. INTEGER familly -> UCHAR
  3054. (codepoint value). *)
  3055. IF (et # SymTab.InvalidType)
  3056. AND (SymTab.ClassOf(et) # SymTab.ClChar)
  3057. AND NOT SymTab.IsIntFamily(et) THEN
  3058. SemError(211) END;
  3059. t := SymTab.UCharType(); .)
  3060. | "CHR8" "(" Expr<et, q> ")"
  3061. (. astNode := AST.MakeNode(AST.NkCall);
  3062. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
  3063. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3064. astCur := astNode; astIsLit := TRUE; .)
  3065. (. IF (et # SymTab.InvalidType)
  3066. AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
  3067. SemError(211) END;
  3068. t := SymTab.CharType(); .)
  3069. | "UORD" "(" Expr<et, q> ")"
  3070. (. astNode := AST.MakeNode(AST.NkCall);
  3071. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
  3072. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3073. astCur := astNode; astIsLit := TRUE; .)
  3074. (. (* UORD(u): the codepoint as a
  3075. 32-bit ordinal (INTEGER),
  3076. cf. ORD for CHAR. *)
  3077. IF (et # SymTab.InvalidType)
  3078. AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
  3079. SemError(211) END;
  3080. t := SymTab.IntType(); .)
  3081. | "ABS" "(" Expr<et, q> ")"
  3082. (. astNode := AST.MakeNode(AST.NkCall);
  3083. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
  3084. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
  3085. astCur := astNode; astIsLit := TRUE; .)
  3086. (. IF (et # SymTab.InvalidType)
  3087. AND NOT SymTab.IsIntFamily(et)
  3088. AND (SymTab.ClassOf(et) #
  3089. SymTab.ClReal) THEN
  3090. SemError(211)
  3091. ELSE QbeGen.CopyOp("@", q)
  3092. END;
  3093. t := et; .)
  3094. | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
  3095. (. astNode := AST.MakeNode(AST.NkCall);
  3096. AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
  3097. IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
  3098. IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
  3099. astCur := astNode; astIsLit := TRUE; .)
  3100. (. IF NOT SymTab.Lookup(vn) THEN
  3101. SemError(201);
  3102. t := SymTab.InvalidType
  3103. ELSE vt := SymTab.SymType(vn);
  3104. IF vt = SymTab.InvalidType THEN
  3105. t := SymTab.InvalidType
  3106. ELSIF et =
  3107. SymTab.InvalidType THEN
  3108. t := vt
  3109. ELSE
  3110. c1 := SymTab.ClassOf(et);
  3111. c2 := SymTab.ClassOf(vt);
  3112. IF (c1 = SymTab.ClInt)
  3113. AND (c2 = SymTab.ClLong) THEN
  3114. QbeGen.WidenLong(q, qa);
  3115. QbeGen.CopyOp(qa, q);
  3116. t := vt
  3117. ELSIF (c1 = SymTab.ClLong)
  3118. AND (c2 = SymTab.ClInt) THEN
  3119. QbeGen.NarrowLong(q, qa);
  3120. QbeGen.CopyOp(qa, q);
  3121. t := vt
  3122. ELSIF (c1 = SymTab.ClInt)
  3123. AND (c2 = SymTab.ClReal) THEN
  3124. QbeGen.ConvIR(q, qa);
  3125. QbeGen.CopyOp(qa, q);
  3126. t := vt
  3127. ELSIF (c1 = SymTab.ClLong)
  3128. AND (c2 = SymTab.ClReal) THEN
  3129. QbeGen.ConvLR(q, qa);
  3130. QbeGen.CopyOp(qa, q);
  3131. t := vt
  3132. ELSIF (c1 = SymTab.ClReal)
  3133. AND (c2 = SymTab.ClInt) THEN
  3134. QbeGen.ConvRI(q, qa);
  3135. QbeGen.CopyOp(qa, q);
  3136. t := vt
  3137. ELSIF (c1 = SymTab.ClReal)
  3138. AND (c2 = SymTab.ClLong) THEN
  3139. QbeGen.ConvRL(q, qa);
  3140. QbeGen.CopyOp(qa, q);
  3141. t := vt
  3142. ELSIF ((c1 = SymTab.ClInt)
  3143. OR (c1 =
  3144. SymTab.ClChar)
  3145. OR (c1 =
  3146. SymTab.ClBool)
  3147. OR (c1 =
  3148. SymTab.ClEnum))
  3149. AND ((c2 = SymTab.ClInt)
  3150. OR (c2 =
  3151. SymTab.ClChar)
  3152. OR (c2 =
  3153. SymTab.ClBool)
  3154. OR (c2 =
  3155. SymTab.ClEnum)) THEN
  3156. t := vt
  3157. ELSIF (c1 = SymTab.ClPtr)
  3158. AND (c2 = SymTab.ClPtr) THEN
  3159. t := vt
  3160. ELSIF (c1 = SymTab.ClReal)
  3161. AND (c2 = SymTab.ClReal) THEN
  3162. t := vt
  3163. ELSE SemError(230);
  3164. t := SymTab.InvalidType
  3165. END
  3166. END
  3167. END; .)
  3168. | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
  3169. | SetLit<st, sq> (. astIsLit := TRUE; t := st;
  3170. QbeGen.CopyOp(sq, q); .)
  3171. | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
  3172. IF SymTab.BoolCheck(t2) THEN
  3173. t := SymTab.BoolType()
  3174. ELSE SemError(212);
  3175. t := SymTab.InvalidType END;
  3176. IF t # SymTab.InvalidType THEN
  3177. QbeGen.CopyOp("@", q)
  3178. ELSE QbeGen.CopyOp("0", q)
  3179. END;
  3180. astIsLit := TRUE;
  3181. astCur := AST.MakeUn(
  3182. AST.NkUnary, AST.OpNot, astNot); .)
  3183. )
  3184. (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
  3185. (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
  3186. (* Set literals are SET OF [0..255] (8 words); elements validated
  3187. 0..255 statically when foldable (222 otherwise), runtime trap
  3188. for computed elements. Ranges always lower via SetRange. *)
  3189. SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  3190. (. VAR astNode: AST.Node; .)
  3191. = "{" (. t := SymTab.NewSet(
  3192. SymTab.NewSubR(0, 255));
  3193. astNode := AST.MakeNode(AST.NkSetLit);
  3194. QbeGen.NewSetTemp(8, q);
  3195. QbeGen.SetZero(q, 8); .)
  3196. [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
  3197. "}" (. astCur := astNode; .) .
  3198. (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
  3199. or ArrayName{...} (an array constructor, GNU Modula-2). The
  3200. declared type sets the width (set) or element type (array). *)
  3201. TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  3202. (. VAR nw: CARDINAL;
  3203. astNode, astTail: AST.Node;
  3204. savedCls: INTEGER; .)
  3205. = "{" (. savedCls := braceCls;
  3206. astNode := AST.MakeNode(AST.NkBraceLit);
  3207. AST.SetTy(astNode, vt);
  3208. astTail := astNode;
  3209. IF vt = SymTab.InvalidType THEN
  3210. braceCls := -1
  3211. ELSE braceCls :=
  3212. SymTab.ClassOf(vt)
  3213. END;
  3214. IF braceCls = SymTab.ClSet THEN
  3215. IF vt = SymTab.InvalidType THEN
  3216. nw := 8
  3217. ELSE nw := SymTab.SetWords(vt);
  3218. IF nw = 0 THEN nw := 8 END
  3219. END;
  3220. QbeGen.NewSetTemp(nw, q);
  3221. QbeGen.SetZero(q, nw)
  3222. ELSIF (braceCls =
  3223. SymTab.ClArray)
  3224. OR (braceCls =
  3225. SymTab.ClRecord)
  3226. OR (braceCls =
  3227. SymTab.ClClass) THEN
  3228. QbeGen.CtorBegin(vt)
  3229. ELSE
  3230. IF vt # SymTab.InvalidType THEN
  3231. SemError(230) END;
  3232. braceCls := -1
  3233. END; .)
  3234. [ BraceElem<vt, q, astNode, astTail>
  3235. { "," BraceElem<vt, q, astNode, astTail> } ]
  3236. "}" (. IF (braceCls = SymTab.ClArray)
  3237. OR (braceCls =
  3238. SymTab.ClRecord)
  3239. OR (braceCls =
  3240. SymTab.ClClass) THEN
  3241. QbeGen.CtorEnd(q)
  3242. ELSIF braceCls # SymTab.ClSet THEN
  3243. QbeGen.CopyOp("0", q)
  3244. END;
  3245. braceCls := savedCls; .)
  3246. (. astCur := astNode; .) .
  3247. BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
  3248. VAR node, tail: AST.Node>
  3249. (. VAR et, et2: SymTab.TypeIndex;
  3250. qe, q2: QbeGen.QVal;
  3251. v, v2, reps, k: INTEGER;
  3252. elem: SymTab.TypeIndex;
  3253. lo: INTEGER;
  3254. span: CARDINAL;
  3255. cl, cl2: INTEGER;
  3256. hasR, hasB: BOOLEAN;
  3257. astEl: AST.Node; .)
  3258. = (. hasR := FALSE; hasB := FALSE;
  3259. reps := 1; .)
  3260. Expr<et, qe> (. astEl := astCur; .)
  3261. [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
  3262. AST.NkSubrange, 0, astEl, astCur);
  3263. hasR := TRUE; .) ]
  3264. [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
  3265. (. IF braceCls = SymTab.ClSet THEN
  3266. IF hasB THEN SemError(230) END;
  3267. lo := SymTab.SetBaseLo(vt);
  3268. span := SymTab.SetCount(vt);
  3269. IF (et = SymTab.InvalidType)
  3270. OR (hasR AND (et2 =
  3271. SymTab.InvalidType)) THEN
  3272. ELSE cl :=
  3273. SymTab.ClassOf(et);
  3274. IF hasR THEN
  3275. cl2 :=
  3276. SymTab.ClassOf(et2)
  3277. ELSE cl2 := SymTab.ClInt
  3278. END;
  3279. IF NOT SymTab.SetElemClassOk(cl)
  3280. OR (hasR AND NOT
  3281. SymTab.SetElemClassOk(cl2))
  3282. THEN
  3283. SemError(222)
  3284. ELSIF hasR
  3285. AND SymTab.ConstInt(qe, v)
  3286. AND SymTab.ConstInt(q2,
  3287. v2)
  3288. AND ((v < lo)
  3289. OR (v2 < lo)
  3290. OR (v >= lo +
  3291. VAL(INTEGER, span))
  3292. OR (v2 >= lo +
  3293. VAL(INTEGER, span))
  3294. OR (v > v2)) THEN
  3295. SemError(222)
  3296. ELSIF hasR THEN
  3297. QbeGen.SetRange(sq, qe, q2,
  3298. lo, span)
  3299. ELSIF SymTab.ConstInt(qe,
  3300. v)
  3301. AND ((v < lo)
  3302. OR (v >= lo +
  3303. VAL(INTEGER,
  3304. span))) THEN
  3305. SemError(222)
  3306. ELSE QbeGen.SetBit(sq, qe,
  3307. lo, span)
  3308. END
  3309. END
  3310. ELSIF (braceCls = SymTab.ClArray)
  3311. OR (braceCls =
  3312. SymTab.ClRecord)
  3313. OR (braceCls =
  3314. SymTab.ClClass) THEN
  3315. IF hasR THEN SemError(230) END;
  3316. reps := 1;
  3317. IF hasB THEN
  3318. IF SymTab.ConstInt(q2, v2)
  3319. AND (v2 >= 1) THEN
  3320. reps := v2
  3321. ELSE SemError(230)
  3322. END
  3323. END;
  3324. k := 0;
  3325. WHILE k < reps DO
  3326. QbeGen.CtorElem(qe);
  3327. INC(k)
  3328. END
  3329. END; .)
  3330. (. (* the BY form repeats the
  3331. element; keep the AST in
  3332. step with CtorElem *)
  3333. k := 0;
  3334. WHILE k < reps DO
  3335. AstAppend(AST.NkBlock,
  3336. node, tail, astEl);
  3337. INC(k)
  3338. END; .) .
  3339. SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
  3340. qe, q2: QbeGen.QVal;
  3341. v, v2: INTEGER;
  3342. lo: INTEGER;
  3343. span: CARDINAL;
  3344. cl, cl2: INTEGER;
  3345. hasR: BOOLEAN;
  3346. astEl: AST.Node; .)
  3347. = (. hasR := FALSE; .)
  3348. Expr<et, qe> (. astEl := astCur; .)
  3349. [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
  3350. AST.NkSubrange, 0, astEl, astCur);
  3351. hasR := TRUE; .) ]
  3352. (. lo := SymTab.SetBaseLo(st);
  3353. span := SymTab.SetCount(st);
  3354. IF (et = SymTab.InvalidType)
  3355. OR (hasR AND (et2 =
  3356. SymTab.InvalidType)) THEN
  3357. ELSE cl :=
  3358. SymTab.ClassOf(et);
  3359. IF hasR THEN
  3360. cl2 :=
  3361. SymTab.ClassOf(et2)
  3362. ELSE cl2 := SymTab.ClInt
  3363. END;
  3364. IF NOT SymTab.SetElemClassOk(cl)
  3365. OR (hasR AND NOT
  3366. SymTab.SetElemClassOk(cl2))
  3367. THEN
  3368. SemError(222)
  3369. ELSIF hasR
  3370. AND SymTab.ConstInt(qe, v)
  3371. AND SymTab.ConstInt(q2,
  3372. v2)
  3373. AND ((v < lo)
  3374. OR (v2 < lo)
  3375. OR (v >= lo +
  3376. VAL(INTEGER, span))
  3377. OR (v2 >= lo +
  3378. VAL(INTEGER, span))
  3379. OR (v > v2)) THEN
  3380. SemError(222)
  3381. ELSIF hasR THEN
  3382. QbeGen.SetRange(sq, qe, q2,
  3383. lo, span)
  3384. ELSIF SymTab.ConstInt(qe,
  3385. v)
  3386. AND ((v < lo)
  3387. OR (v >= lo +
  3388. VAL(INTEGER,
  3389. span))) THEN
  3390. SemError(222)
  3391. ELSE QbeGen.SetBit(sq, qe,
  3392. lo, span)
  3393. END
  3394. END; .)
  3395. (. AST.SetChild(node,
  3396. AST.NChild(node), astEl); .) .
  3397. GetIdent<VAR n: SymTab.Name>
  3398. = ident (. LexName(n); .) .
  3399. END M2.