M2.lst 142 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259
  1. Coco/R - Compiler-Compiler V1.53
  2. Released by Pat Terry 17 September 2002
  3. Source file: M2.atg
  4. Grammar Tests:
  5. Deletable symbols:
  6. DeclSeq
  7. Undefined nonterminals: -- none --
  8. Unreachable nonterminals: -- none --
  9. Circular derivations: -- none --
  10. Underivable nonterminals: -- none --
  11. LL(1) conditions:
  12. LL(1) error in TypeBlock: "CLASS" is the start & successor of a deletable structure
  13. Listing:
  14. 1 COMPILER M2
  15. 2 (* Step 1 — minimal integer pipeline (m2compiler-V3).
  16. 3 Subset: program MODULE + CONST (literal) + VAR INTEGER +
  17. 4 assignment + integer expressions (+ - * DIV MOD, leading sign,
  18. 5 parens). Fresh QBE backend (QbeGen) to gen_ssa/<Module>.ssa;
  19. 6 assemble with qbe, link with cc.
  20. 7
  21. 8 Test convention: a global VAR ExitCode : INTEGER makes generated
  22. 9 $main return its value as the process exit code, else return 0.
  23. 10
  24. 11 Semantic errors reuse the V1/V2/Test2 family: 200 duplicate,
  25. 12 201 undeclared, 202 module name mismatch, 210 bad assignment,
  26. 13 211 bad arithmetic, 221 not a type, 230 not supported yet,
  27. 14 231 opaque type outside definition.
  28. 15 Scalar-phase TYPEs (named, integer subrange, enum) check fully;
  29. 16 composite forms wait for step 3. Procedure headings (formals,
  30. 17 result, FORWARD) enter scopes now; bodies parse + check with one
  31. 18 230 at END (lowering = step 4).
  32. 19 Statements: assignment, IF/ELSIF/ELSE, WHILE, REPEAT/UNTIL,
  33. 20 LOOP/EXIT (230 outside LOOP), FOR/TO/static-sign-BY, full CASE
  34. 21 (labels, ranges, ELSE; compare-chain), RETURN with 232 checks
  35. 22 (outside proc / value mismatch / missing value). WITH waits for
  36. 23 records (step 3). Boolean connectives are eager (or/and/xor);
  37. 24 relations yield 0/1 via cXXw.
  38. 25 Clarion-form classes (docs/OOP.txt): CLASS decl + single
  39. 26 inheritance + CLASS IMPLEMENTATION blocks, methods with ";"
  40. 27 (per the Table example, not the sketch's ","), VIRTUAL flagged.
  41. 28 Scopes and member checks now; lowering later (one 230 per
  42. 29 class/impl block). Classic identifiers: no underscores, so the
  43. 30 Table example's _names stay lexically out of reach.
  44. 31 Step 3.1 arrays: "ARRAY [lo..hi, ...] OF T" (folded literal
  45. 32 bounds, int/char) and open "ARRAY OF T" formals; index suffixes
  46. 33 with per-level checks (217/218, trap on breach via $abort);
  47. 34 whole-array ":=" with runtime count check + blit; string
  48. 35 literals lower as descriptors (1-char stays CHAR, empty works);
  49. 36 array/string "=" is 213 (no built-in whole comparison).
  50. 37 Step 3.3 sets: multi-word masks (no header, static words) over
  51. 38 bases ≤ 256 values; literals are SET OF [0..255] (222 on
  52. 39 out-of-span); + - * / as or/and/xor-not, IN with span trap,
  53. 40 =/# word-wise (lenient cross-base); CASE labels reject sets.
  54. 41 Step 3.4 records: flat blobs; array fields are pointers to static
  55. 42 descriptors (locked amendment — one layout per type); nested
  56. 43 records inline; static declaration-order offsets; field chains
  57. 44 mix with indexes; WITH pushes fields + bases (215/216);
  58. 45 whole-record deep copy; record/set/class "=" is 213.
  59. 46 Step 3.6 pointers: vars (l), NIL as a real type (FNil — assignment
  60. 47 and =/# work, everything else 210-214/222), ^ deref with sfx
  61. 48 discipline (address flows, load at use; chains compose),
  62. 49 pointer =/# via ceql/cnel (< > etc. are 213), NEW/DISPOSE as
  63. 50 builtin statements via extern malloc/free (recursive skeleton
  64. 51 init; DISPOSE shallow and nils, deviating from Wirth-undefined);
  65. 52 nil-deref is raw (no check). *)
  66. 53
  67. 54 IMPORT SymTab, QbeGen;
  68. 55
  69. 56 CHARACTERS
  70. 57 eol = CHR(13) .
  71. 58 lf = CHR(10) .
  72. 59 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
  73. 60 digit = "0123456789" .
  74. 61 hexDigit = digit + "ABCDEFabcdef" .
  75. 62 noQuote1 = ANY - "'" - eol .
  76. 63 noQuote2 = ANY - '"' - eol .
  77. 64
  78. 65 IGNORE CHR(9) .. CHR(13)
  79. 66
  80. 67 COMMENTS FROM "(*" TO "*)" NESTED
  81. 68 COMMENTS FROM "//" TO lf
  82. 69
  83. 70 TOKENS
  84. 71 ident = letter { letter | digit } .
  85. 72 integer = digit { digit }
  86. 73 | digit { digit } CONTEXT("..")
  87. 74 | "0x" hexDigit { hexDigit }
  88. 75 | "0X" hexDigit { hexDigit } .
  89. 76 real = digit { digit } "." { digit }
  90. 77 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
  91. 78 string = "'" { noQuote1 } "'"
  92. 79 | '"' { noQuote2 } '"' .
  93. 80 charConst = digit { digit } ( "C" | "c" ) .
  94. 81
  95. 82 PRODUCTIONS
  96. 83 M2
  97. 84 = Unit "." .
  98. 85 (* Units: program modules compile fully; DEFINITION and
  99. 86 IMPLEMENTATION modules parse + check now but lower in step 4
  100. 87 (each ends with one 230); same for nested local modules. *)
  101. 88 Unit
  102. 89 = DefUnit
  103. 90 | ImplUnit
  104. 91 | ProgModule .
  105. 92 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
  106. 93 and one program (last) into one image. Units share the symbol
  107. 94 table; imports materialize exported names. *)
  108. 95 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
  109. 96 = "DEFINITION" "MODULE"
  110. 97 GetIdent<m1> (. IF NOT SymTab.BeginDef(m1) THEN
  111. 98 SemError(200) END;
  112. 99 QbeGen.SetModule(m1); .)
  113. 100 ";"
  114. 101 { Import }
  115. 102 { ConstBlock | TypeBlock<TRUE> | VarBlock
  116. 103 | ProcHeading<pn> ";" (. SymTab.CloseProc;
  117. 104 QbeGen.AbortFunc; .) }
  118. 105 "END"
  119. 106 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
  120. 107 SemError(202) END;
  121. 108 SymTab.EndUnit; .) .
  122. 109 ImplUnit (. VAR m1, m2: SymTab.Name; .)
  123. 110 = "IMPLEMENTATION" "MODULE"
  124. 111 GetIdent<m1> (. IF NOT SymTab.BeginImpl(m1) THEN
  125. 112 SemError(201) END;
  126. 113 QbeGen.SetModule(m1); .)
  127. 114 ";"
  128. 115 { Import }
  129. 116 DeclSeq
  130. 117 [ "BEGIN" (. QbeGen.BeginInit(m1); .)
  131. 118 [ StatSeq ] (. QbeGen.EndInit; .) ]
  132. 119 "END"
  133. 120 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
  134. 121 SemError(202) END;
  135. 122 SymTab.EndUnit; .) .
  136. 123 ProgModule (. VAR m1, m2: SymTab.Name; .)
  137. 124 = "MODULE"
  138. 125 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
  139. 126 SemError(200) END;
  140. 127 QbeGen.SetModule(m1); .)
  141. 128 [ Priority ]
  142. 129 ";"
  143. 130 { Import }
  144. 131 DeclSeq
  145. 132 [ "BEGIN" (. QbeGen.BeginBody; .)
  146. 133 [ StatSeq ] ]
  147. 134 "END"
  148. 135 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
  149. 136 SemError(202) END;
  150. 137 QbeGen.EndModule(m1);
  151. 138 SymTab.EndUnit; .) .
  152. 139 DeclSeq
  153. 140 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
  154. 141 | NestedModule ";" | ClassItem ";" } .
  155. 142 (* Local module, Wirth form. Declarations lower like top-level ones
  156. 143 (same QBE module prefix); a BEGIN body becomes an init function
  157. 144 that main calls; the EXPORT list is hoisted into the enclosing
  158. 145 scope at END. *)
  159. 146 NestedModule (. VAR m1, m2: SymTab.Name;
  160. 147 expNames: ARRAY [0 .. 63] OF SymTab.Name;
  161. 148 expCount, k: CARDINAL; .)
  162. 149 = "MODULE"
  163. 150 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
  164. 151 SymTab.KindModule) THEN
  165. 152 SemError(200) END;
  166. 153 SymTab.PushScope;
  167. 154 expCount := 0; .)
  168. 155 [ Priority ]
  169. 156 ";"
  170. 157 { Import }
  171. 158 [ "EXPORT" [ "QUALIFIED" ]
  172. 159 GetIdent<expNames[expCount]> (. INC(expCount); .)
  173. 160 { "," GetIdent<expNames[expCount]>
  174. 161 (. INC(expCount); .) }
  175. 162 ";" ]
  176. 163 DeclSeq
  177. 164 [ "BEGIN" (. QbeGen.BeginInit(m1); .)
  178. 165 [ StatSeq ] (. QbeGen.EndInit; .) ]
  179. 166 "END"
  180. 167 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
  181. 168 SemError(202) END;
  182. 169 k := 0;
  183. 170 WHILE k < expCount DO
  184. 171 SymTab.ExportUp(expNames[k]);
  185. 172 INC(k)
  186. 173 END;
  187. 174 SymTab.PopScope; .) .
  188. 175 Priority
  189. 176 = "[" integer "]" (. SemError(230); .) .
  190. 177 (* Imports (4.3): FROM materializes the names (unqualified use);
  191. 178 plain IMPORT only demands the module exists — qualified `L.x`
  192. 179 materializes on first use (Design). *)
  193. 180 (* Unknown modules stay unchecked stubs (legacy, so hand-written
  194. 181 import lines don't fail); a known module's missing export is
  195. 182 201. *)
  196. 183 Import (. VAR n: SymTab.Name; .)
  197. 184 = "FROM"
  198. 185 GetIdent<n>
  199. 186 "IMPORT"
  200. 187 ImpList<n> ";"
  201. 188 | "IMPORT"
  202. 189 ImpModList ";" .
  203. 190 ImpList<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
  204. 191 = ImpName<mod>
  205. 192 { "," ImpName<mod> } .
  206. 193 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
  207. 194 accepted and ignored: the built-in applies regardless. *)
  208. 195 ImpName<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
  209. 196 = GetIdent<n> (. IF SymTab.ModKnown(mod)
  210. 197 AND NOT SymTab.ImportFrom(mod, n) THEN
  211. 198 SemError(201) END; .)
  212. 199 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
  213. 200 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
  214. 201 | "INC" | "DEC" ) .
  215. 202 ImpModList (. VAR n: SymTab.Name; .)
  216. 203 = GetIdent<n>
  217. 204 { "," GetIdent<n> } .
  218. 205 (* Opaque TYPE declarations (definition modules). The targetless
  219. 206 alias resolves to InvalidType until step 4 completes it. *)
  220. 207 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
  221. 208 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
  222. 209 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
  223. 210 TypeBlock<isDef: BOOLEAN>
  224. 211 = "TYPE" (. SymTab.BeginTypeBlock; .)
  225. 212 { TypeItem<isDef> ";" | ClassItem ";" }
  226. 213 (. SymTab.EndTypeBlock; .) .
  227. 214 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
  228. 215 t, op: SymTab.TypeIndex; .)
  229. 216 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
  230. 217 IF op = SymTab.InvalidType THEN
  231. 218 IF NOT SymTab.Enter(n,
  232. 219 SymTab.KindType) THEN
  233. 220 SemError(200) END
  234. 221 END; .)
  235. 222 ( "=" Type<t, FALSE> (. IF op # SymTab.InvalidType THEN
  236. 223 SymTab.SetTarget(op, t)
  237. 224 ELSE SymTab.SetSymType(n, t)
  238. 225 END; .)
  239. 226 | (. IF op # SymTab.InvalidType THEN
  240. 227 (* stays opaque *)
  241. 228 ELSIF NOT isDef THEN
  242. 229 SemError(231)
  243. 230 ELSE SymTab.SetSymType(n,
  244. 231 SymTab.NewAlias()) END; .) ) .
  245. 232 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
  246. 233 = TypeIdent<t>
  247. 234 | Subrange<t>
  248. 235 | Enum<t>
  249. 236 | ArrayType<t, allowOpen>
  250. 237 | SetType<t>
  251. 238 | RecordType<t>
  252. 239 | PointerType<t>
  253. 240 | ProcType<t> .
  254. 241 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
  255. 242 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
  256. 243 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
  257. 244 are code pointers; params are collected into the descriptor. *)
  258. 245 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
  259. 246 isV: BOOLEAN; .)
  260. 247 = "PROCEDURE" (. res := SymTab.InvalidType;
  261. 248 t := SymTab.NewProcType(res); .)
  262. 249 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
  263. 250 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
  264. 251 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
  265. 252 isV: BOOLEAN;
  266. 253 cnt, k: CARDINAL;
  267. 254 names: ARRAY [0 .. 15] OF SymTab.Name; .)
  268. 255 = (. isV := FALSE; cnt := 0; .)
  269. 256 [ "VAR" (. isV := TRUE; .) ]
  270. 257 GetIdent<names[cnt]> (. INC(cnt); .)
  271. 258 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
  272. 259 ( ":" Type<pt, FALSE> (. k := 0;
  273. 260 WHILE k < cnt DO
  274. 261 SymTab.ProcTypeAdd(t, isV, pt);
  275. 262 INC(k)
  276. 263 END; .)
  277. 264 | (. (* type-only parameter list:
  278. 265 each name is a type (GNU
  279. 266 shorthand used by the
  280. 267 Coco/R scanner frame) *)
  281. 268 k := 0;
  282. 269 WHILE k < cnt DO
  283. 270 IF SymTab.Lookup(names[k])
  284. 271 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
  285. 272 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
  286. 273 pt := SymTab.SymType(names[k])
  287. 274 ELSE SemError(201);
  288. 275 pt := SymTab.InvalidType
  289. 276 END;
  290. 277 SymTab.ProcTypeAdd(t, isV, pt);
  291. 278 INC(k)
  292. 279 END; .) ) .
  293. 280 (* Arrays: "OF" without bounds is an open formal (allowed only
  294. 281 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
  295. 282 out. Bounds are folded literals (int/char); anything else 230.
  296. 283 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
  297. 284 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
  298. 285 (. VAR elem: SymTab.TypeIndex;
  299. 286 ok: BOOLEAN;
  300. 287 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
  301. 288 nb, k: CARDINAL; .)
  302. 289 = "ARRAY"
  303. 290 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
  304. 291 SemError(230) END;
  305. 292 t := SymTab.NewOpenArray(elem); .)
  306. 293 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
  307. 294 BoundPair<ok>
  308. 295 { "," BoundPair<ok> }
  309. 296 "]" (. (* snapshot before the element
  310. 297 type, which reuses the bound
  311. 298 buffer for a nested ARRAY *)
  312. 299 nb := SymTab.BoundCount();
  313. 300 k := 0;
  314. 301 WHILE k < nb DO
  315. 302 bnds[k] := SymTab.BoundLo(k);
  316. 303 bndh[k] := SymTab.BoundHi(k);
  317. 304 INC(k)
  318. 305 END; .)
  319. 306 "OF" Type<elem, FALSE>
  320. 307 (. IF ok THEN
  321. 308 k := nb;
  322. 309 WHILE k > 0 DO
  323. 310 DEC(k);
  324. 311 elem := SymTab.NewArrayB(
  325. 312 elem, bnds[k], bndh[k])
  326. 313 END;
  327. 314 t := elem
  328. 315 ELSE t := SymTab.InvalidType
  329. 316 END; .) ) .
  330. 317 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
  331. 318 qlo, qhi: QbeGen.QVal;
  332. 319 lo, hi: INTEGER;
  333. 320 cl, cl2: INTEGER; .)
  334. 321 = Expr<tlo, qlo> ".." Expr<thi, qhi>
  335. 322 (. IF (tlo = SymTab.InvalidType)
  336. 323 OR (thi = SymTab.InvalidType) THEN
  337. 324 ok := FALSE
  338. 325 ELSE cl := SymTab.ClassOf(tlo);
  339. 326 cl2 := SymTab.ClassOf(thi);
  340. 327 IF ((cl # SymTab.ClInt)
  341. 328 AND (cl # SymTab.ClChar))
  342. 329 OR ((cl2 # SymTab.ClInt)
  343. 330 AND (cl2 # SymTab.ClChar)) THEN
  344. 331 SemError(230); ok := FALSE
  345. 332 ELSIF NOT SymTab.ConstInt(qlo, lo)
  346. 333 OR NOT SymTab.ConstInt(qhi, hi)
  347. 334 OR (lo > hi) THEN
  348. 335 SemError(230); ok := FALSE
  349. 336 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
  350. 337 SemError(230); ok := FALSE
  351. 338 END;
  352. 339 END; .) .
  353. 340 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
  354. 341 bounded subranges; enums wait for ordinals, INTEGER is
  355. 342 unbounded). Literals are SET OF [0..255]; assignment and
  356. 343 comparison across suitable bases are lenient (masks over min
  357. 344 words + zero-check extras), out-of-span literals are 222. *)
  358. 345 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
  359. 346 blo, bhi, bspan: INTEGER;
  360. 347 bcls: INTEGER; .)
  361. 348 = "SET" "OF" Type<base, FALSE>
  362. 349 (. IF base = SymTab.InvalidType THEN
  363. 350 t := SymTab.InvalidType
  364. 351 ELSE bcls :=
  365. 352 SymTab.ClassOf(base);
  366. 353 IF bcls = SymTab.ClBool THEN
  367. 354 blo := 0; bspan := 2
  368. 355 ELSIF bcls = SymTab.ClChar THEN
  369. 356 blo := 0; bspan := 256
  370. 357 ELSIF SymTab.SubBounds(base,
  371. 358 blo, bhi) THEN
  372. 359 bspan := bhi - blo + 1
  373. 360 ELSE bspan := 0 END;
  374. 361 IF (bspan <= 0)
  375. 362 OR (bspan > 256) THEN
  376. 363 SemError(230);
  377. 364 t := SymTab.InvalidType
  378. 365 ELSE t := SymTab.NewSet(base)
  379. 366 END
  380. 367 END; .) .
  381. 368 (* Records: flat blobs; array fields are pointers to static
  382. 369 descriptors (locked amendment), nested records inline. Field
  383. 370 offsets static and declaration-ordered. *)
  384. 371 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex; .)
  385. 372 = "RECORD" (. t := SymTab.NewRecord(); .)
  386. 373 [ RecField<t> { ";" [ RecField<t> ] } ]
  387. 374 "END" .
  388. 375 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
  389. 376 t2: SymTab.TypeIndex; .)
  390. 377 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
  391. 378 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
  392. 379 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
  393. 380 n) THEN
  394. 381 SemError(200) END; .)
  395. 382 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
  396. 383 n) THEN
  397. 384 SemError(200) END; .) } .
  398. 385 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
  399. 386 k: INTEGER;
  400. 387 dotted: BOOLEAN; .)
  401. 388 = GetIdent<n> (. dotted := FALSE;
  402. 389 IF NOT SymTab.Lookup(n) THEN
  403. 390 k := -1;
  404. 391 t := SymTab.ForwardType(n);
  405. 392 IF t = SymTab.InvalidType THEN
  406. 393 SemError(201)
  407. 394 END
  408. 395 ELSE k := SymTab.SymKind(n);
  409. 396 IF (k = SymTab.KindType)
  410. 397 OR (k = SymTab.KindPredef) THEN
  411. 398 t := SymTab.SymType(n)
  412. 399 ELSE t := SymTab.InvalidType
  413. 400 END
  414. 401 END; .)
  415. 402 [ "." GetIdent<qid> (. dotted := TRUE;
  416. 403 IF k = SymTab.KindModule THEN
  417. 404 t := SymTab.QualType(n, qid);
  418. 405 IF t = SymTab.InvalidType THEN
  419. 406 SemError(201)
  420. 407 END
  421. 408 ELSE SemError(221);
  422. 409 t := SymTab.InvalidType
  423. 410 END; .) ]
  424. 411 (. IF NOT dotted THEN
  425. 412 IF (k = SymTab.KindModule)
  426. 413 OR ((k # SymTab.KindType)
  427. 414 AND (k # SymTab.KindPredef)
  428. 415 AND (k # SymTab.KindImport)
  429. 416 AND (k # -1)) THEN
  430. 417 SemError(221)
  431. 418 END
  432. 419 END; .) .
  433. 420 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
  434. 421 qlo, qhi: QbeGen.QVal;
  435. 422 lo, hi: INTEGER; .)
  436. 423 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
  437. 424 (. IF (tlo = SymTab.InvalidType)
  438. 425 OR (thi = SymTab.InvalidType) THEN
  439. 426 t := SymTab.InvalidType
  440. 427 ELSIF (SymTab.ClassOf(tlo) #
  441. 428 SymTab.ClInt)
  442. 429 OR (SymTab.ClassOf(thi) #
  443. 430 SymTab.ClInt) THEN
  444. 431 SemError(230);
  445. 432 t := SymTab.InvalidType
  446. 433 ELSIF NOT SymTab.ConstInt(qlo, lo)
  447. 434 OR NOT SymTab.ConstInt(qhi, hi)
  448. 435 OR (lo > hi) THEN
  449. 436 SemError(230);
  450. 437 t := SymTab.InvalidType
  451. 438 ELSE t := SymTab.NewSubR(lo, hi)
  452. 439 END; .)
  453. 440 "]" .
  454. 441 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
  455. 442 = "(" (. t := SymTab.NewEnum(); .)
  456. 443 GetIdent<n> (. IF NOT SymTab.Enter(n,
  457. 444 SymTab.KindConst) THEN
  458. 445 SemError(200) END;
  459. 446 SymTab.SetSymType(n, t); .)
  460. 447 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
  461. 448 SymTab.KindConst) THEN
  462. 449 SemError(200) END;
  463. 450 SymTab.SetSymType(n, t); .) }
  464. 451 ")" .
  465. 452 (* Clarion-form classes (docs/OOP.txt): declaration + single
  466. 453 inheritance + IMPLEMENTATION blocks. Scopes and member checks
  467. 454 now; lowering (vtable, dispatch, THIS) later — one 230 per
  468. 455 class/impl block. Methods end with ";" per the Table example
  469. 456 (not "," as in the sketch). No underscores in identifiers. *)
  470. 457 (* Single CLASS item in both loops: separating declaration from
  471. 458 IMPLEMENTATION at the loop level needs 2-token lookahead
  472. 459 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
  473. 460 The second token decides after CLASS is consumed. A misplaced
  474. 461 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
  475. 462 whole unit ends 230 until lowering). *)
  476. 463 ClassItem
  477. 464 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
  478. 465 ClassRest (. VAR cn, m2, pn: SymTab.Name;
  479. 466 ct: SymTab.TypeIndex; .)
  480. 467 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
  481. 468 SymTab.KindType) THEN
  482. 469 SemError(200) END;
  483. 470 ct := SymTab.NewClass();
  484. 471 SymTab.SetSymType(cn, ct);
  485. 472 SymTab.PushClassScope(ct); .)
  486. 473 [ Parents<ct> ]
  487. 474 ";"
  488. 475 { ClassField<ct> ";" }
  489. 476 { MethodHeading<pn> ";" (. SymTab.CloseProc;
  490. 477 QbeGen.AbortFunc; .) }
  491. 478 "END"
  492. 479 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
  493. 480 SemError(202) END;
  494. 481 SymTab.PopScope;
  495. 482 SemError(230); .) .
  496. 483 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
  497. 484 = "(" Parent1<ct>
  498. 485 { "," GetIdent<p> (. SemError(230); .) }
  499. 486 ")" .
  500. 487 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
  501. 488 pt: SymTab.TypeIndex; .)
  502. 489 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
  503. 490 SemError(201)
  504. 491 ELSE pt := SymTab.SymType(p);
  505. 492 IF SymTab.ClassOf(pt) #
  506. 493 SymTab.ClClass THEN
  507. 494 SemError(230)
  508. 495 ELSE SymTab.SetParent(ct, pt)
  509. 496 END
  510. 497 END; .) .
  511. 498 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
  512. 499 t: SymTab.TypeIndex; .)
  513. 500 = GetIdent<n>
  514. 501 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
  515. 502 SymTab.KindConst) THEN
  516. 503 SemError(200) END;
  517. 504 IF SymTab.Lookup(rhs) THEN
  518. 505 SymTab.SetSymType(n,
  519. 506 SymTab.SymType(rhs))
  520. 507 END; .)
  521. 508 | (. IF NOT SymTab.FieldPending(ct,
  522. 509 n) THEN
  523. 510 SemError(200) END; .)
  524. 511 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
  525. 512 n) THEN
  526. 513 SemError(200) END; .) }
  527. 514 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t); .) ) .
  528. 515 MethodHeading<VAR pn: SymTab.Name> (. VAR wantVirt: BOOLEAN; .)
  529. 516 = (. wantVirt := FALSE; .)
  530. 517 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
  531. 518 ProcHeading<pn> (. IF wantVirt THEN
  532. 519 SymTab.MarkVirtual END; .) .
  533. 520 ClassImplRest (. VAR cn, m2: SymTab.Name;
  534. 521 ct: SymTab.TypeIndex; .)
  535. 522 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
  536. 523 SemError(201);
  537. 524 ct := SymTab.InvalidType
  538. 525 ELSE ct := SymTab.SymType(cn);
  539. 526 IF SymTab.ClassOf(ct) #
  540. 527 SymTab.ClClass THEN
  541. 528 SemError(230);
  542. 529 ct := SymTab.InvalidType
  543. 530 END
  544. 531 END;
  545. 532 IF ct #
  546. 533 SymTab.InvalidType THEN
  547. 534 IF NOT SymTab.PushClassMembers(
  548. 535 ct) THEN
  549. 536 SemError(230) END
  550. 537 END; .)
  551. 538 ";" { MethodImpl<ct> ";" }
  552. 539 [ "BEGIN"
  553. 540 [ StatSeq ] ]
  554. 541 "END"
  555. 542 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
  556. 543 SemError(202) END;
  557. 544 SymTab.PopScope;
  558. 545 SemError(230); .) .
  559. 546 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name; .)
  560. 547 = (. QbeGen.SetNoEmit(TRUE); .)
  561. 548 MethodHeading<pn> ";"
  562. 549 (. IF (ct #
  563. 550 SymTab.InvalidType)
  564. 551 AND NOT SymTab.MethodExists(ct,
  565. 552 pn) THEN
  566. 553 SemError(201) END; .)
  567. 554 ( "FORWARD" (. SymTab.MarkFwd;
  568. 555 SymTab.CloseProc; .)
  569. 556 | Block<pn> (. SymTab.CloseProc; .) )
  570. 557 (. QbeGen.AbortFunc;
  571. 558 QbeGen.SetNoEmit(FALSE);
  572. 559 SemError(230); .) .
  573. 560 ConstBlock
  574. 561 = "CONST" { ConstDecl ";" } .
  575. 562 ConstDecl (. VAR n: SymTab.Name;
  576. 563 t: SymTab.TypeIndex;
  577. 564 qv: QbeGen.QVal;
  578. 565 cls: INTEGER; .)
  579. 566 = GetIdent<n> (. IF NOT SymTab.Enter(n,
  580. 567 SymTab.KindConst) THEN
  581. 568 SemError(200) END; .)
  582. 569 "="
  583. 570 Expr<t, qv> (. SymTab.SetSymType(n, t);
  584. 571 cls := SymTab.ClassOf(t);
  585. 572 IF cls = SymTab.ClStr THEN
  586. 573 SemError(230)
  587. 574 ELSIF NOT QbeGen.IsImm(qv) THEN
  588. 575 SemError(230) END;
  589. 576 SymTab.SetSymVal(n, qv);
  590. 577 QbeGen.DeclConst(n, qv, t); .) .
  591. 578 VarBlock
  592. 579 = "VAR" { VarDecl ";" } .
  593. 580 VarDecl (. VAR nm: SymTab.Name;
  594. 581 t: SymTab.TypeIndex;
  595. 582 i: CARDINAL;
  596. 583 cls: INTEGER; .)
  597. 584 = VarIdents ":"
  598. 585 Type<t, FALSE> (. cls := SymTab.ClassOf(t);
  599. 586 IF (t # SymTab.InvalidType)
  600. 587 AND (cls # SymTab.ClInt)
  601. 588 AND (cls # SymTab.ClBool)
  602. 589 AND (cls # SymTab.ClChar)
  603. 590 AND (cls # SymTab.ClReal)
  604. 591 AND (cls # SymTab.ClArray)
  605. 592 AND (cls # SymTab.ClSet)
  606. 593 AND (cls # SymTab.ClRecord)
  607. 594 AND (cls # SymTab.ClPtr)
  608. 595 AND (cls # SymTab.ClLong)
  609. 596 AND (cls # SymTab.ClProc) THEN
  610. 597 SemError(230) END;
  611. 598 IF QbeGen.LocFull() THEN
  612. 599 SemError(233) END;
  613. 600 i := 0;
  614. 601 WHILE i < SymTab.PendCount() DO
  615. 602 SymTab.PendName(i, nm);
  616. 603 QbeGen.DeclVar(nm, t);
  617. 604 INC(i)
  618. 605 END;
  619. 606 SymTab.FixPending(t); .) .
  620. 607 VarIdents (. VAR n: SymTab.Name; .)
  621. 608 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
  622. 609 SymTab.KindVar) THEN
  623. 610 SemError(200) END; .)
  624. 611 { ","
  625. 612 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
  626. 613 SymTab.KindVar) THEN
  627. 614 SemError(200) END; .) } .
  628. 615 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
  629. 616 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
  630. 617 SemError(200) END; .)
  631. 618 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
  632. 619 SemError(200) END; .) } .
  633. 620 (* Procedure headings enter scopes/params/result and buffer the
  634. 621 QBE header; bodies lower to functions (4.1, module level only).
  635. 622 FORWARD marks; the body heading re-enters (signature compare
  636. 623 deferred). Nested procedures parse + check, lowering = 4.2. *)
  637. 624 ProcHeading<VAR pn: SymTab.Name> (. VAR t: SymTab.TypeIndex;
  638. 625 mg: QbeGen.QVal; .)
  639. 626 = "PROCEDURE"
  640. 627 GetIdent<pn> (. IF NOT SymTab.EnterProc(pn) THEN
  641. 628 IF NOT SymTab.ReenterProc(pn) THEN
  642. 629 IF NOT SymTab.ResumeProc(pn) THEN
  643. 630 SemError(200) END
  644. 631 END
  645. 632 END;
  646. 633 QbeGen.Mangled(pn,
  647. 634 SymTab.ProcUid(pn), mg);
  648. 635 QbeGen.BeginFunc(mg); .)
  649. 636 [ FormalParams ]
  650. 637 [ ":" TypeIdent<t> (. SymTab.SetProcRes(t);
  651. 638 QbeGen.SetFuncRes(t);
  652. 639 IF (t #
  653. 640 SymTab.InvalidType)
  654. 641 AND ((SymTab.ClassOf(t)
  655. 642 = SymTab.ClArray)
  656. 643 OR (SymTab.ClassOf(t)
  657. 644 = SymTab.ClRecord)
  658. 645 OR (SymTab.ClassOf(t)
  659. 646 = SymTab.ClSet)
  660. 647 OR (SymTab.ClassOf(t)
  661. 648 = SymTab.ClClass)) THEN
  662. 649 SemError(230) END; .) ] .
  663. 650 FormalParams
  664. 651 = "(" [ ParamSection { ";" ParamSection } ] ")" .
  665. 652 ParamSection (. VAR t: SymTab.TypeIndex;
  666. 653 nm: SymTab.Name;
  667. 654 i: CARDINAL;
  668. 655 isV: BOOLEAN; .)
  669. 656 = (. isV := FALSE; .)
  670. 657 [ "VAR" (. isV := TRUE; .) ]
  671. 658 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
  672. 659 WHILE i < SymTab.PendCount() DO
  673. 660 SymTab.PendName(i, nm);
  674. 661 (* value open arrays are
  675. 662 passed as descriptor
  676. 663 addresses (no copy):
  677. 664 same representation as
  678. 665 VAR formals *)
  679. 666 IF NOT QbeGen.FuncParam(nm,
  680. 667 isV
  681. 668 OR SymTab.IsOpenArray(t),
  682. 669 t) THEN
  683. 670 SemError(233) END;
  684. 671 INC(i)
  685. 672 END;
  686. 673 SymTab.FixPending(t); .) .
  687. 674 (* Nested procedures lower like top-level ones (4.2): the
  688. 675 static link gives them their parent's frame. Methods keep
  689. 676 parse-now/230-later. *)
  690. 677 ProcDecl (. VAR pn: SymTab.Name; .)
  691. 678 = ProcHeading<pn> ";"
  692. 679 ( "FORWARD" (. SymTab.MarkFwd;
  693. 680 SymTab.CloseProc;
  694. 681 QbeGen.AbortFunc; .)
  695. 682 | "EXTERNAL" (. SymTab.MarkExternal("");
  696. 683 SymTab.CloseProc;
  697. 684 QbeGen.AbortFunc; .)
  698. 685 | (. QbeGen.EndFuncHeader; .)
  699. 686 Block<pn> (. SymTab.CloseProc;
  700. 687 QbeGen.EndFunc(
  701. 688 SymTab.ProcRes(pn)); .) ) .
  702. 689 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
  703. 690 = DeclSeq
  704. 691 [ "BEGIN"
  705. 692 [ StatSeq ] ]
  706. 693 "END"
  707. 694 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
  708. 695 SemError(202) END; .) .
  709. 696 StatSeq
  710. 697 = Statement { ";" [ Statement ] } .
  711. 698 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
  712. 699 are accepted: the statement after ';' is optional. *)
  713. 700 Statement (. VAR lx: QbeGen.QVal; .)
  714. 701 = AssOrCall
  715. 702 | IfStat
  716. 703 | WhileStat
  717. 704 | RepeatStat
  718. 705 | LoopStat
  719. 706 | ForStat
  720. 707 | CaseStat
  721. 708 | WithStat
  722. 709 | ReturnStat
  723. 710 | HaltStat
  724. 711 | NewStat
  725. 712 | DisposeStat
  726. 713 | IncDecStat
  727. 714 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
  728. 715 QbeGen.Jmp(lx)
  729. 716 ELSE SemError(230) END; .) .
  730. 717 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
  731. 718 integer designator. *)
  732. 719 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
  733. 720 dk: INTEGER;
  734. 721 qd, qv, qn2, qstep:
  735. 722 QbeGen.QVal;
  736. 723 qn: SymTab.Name;
  737. 724 sfx, isInc: BOOLEAN; .)
  738. 725 = (. isInc := TRUE; .)
  739. 726 ( "INC" (. isInc := TRUE; .)
  740. 727 | "DEC" (. isInc := FALSE; .) )
  741. 728 "(" (. QbeGen.CopyOp("1", qstep); .)
  742. 729 Design<dt, dk, qd, qn, sfx>
  743. 730 [ "," Expr<et2, qstep> ]
  744. 731 ")" (. IF dt = SymTab.InvalidType THEN
  745. 732 ELSIF (dk # SymTab.KindVar)
  746. 733 AND (dk # SymTab.KindParam)
  747. 734 AND (dk # SymTab.KindField) THEN
  748. 735 SemError(210)
  749. 736 ELSIF NOT SymTab.IsIntFamily(dt) THEN
  750. 737 SemError(211)
  751. 738 ELSE
  752. 739 IF sfx
  753. 740 OR (dk = SymTab.KindField) THEN
  754. 741 QbeGen.ElemLoad(qd, dt, qv)
  755. 742 ELSE QbeGen.LoadVar(qn,
  756. 743 FALSE, qv)
  757. 744 END;
  758. 745 QbeGen.NewTemp(qn2);
  759. 746 IF isInc THEN
  760. 747 QbeGen.Op3("add", qn2, qv,
  761. 748 qstep, FALSE)
  762. 749 ELSE QbeGen.Op3("sub", qn2, qv,
  763. 750 qstep, FALSE)
  764. 751 END;
  765. 752 IF sfx
  766. 753 OR (dk = SymTab.KindField) THEN
  767. 754 QbeGen.ElemStore(qd, qn2,
  768. 755 dt)
  769. 756 ELSE QbeGen.StoreVar(qn,
  770. 757 qn2, FALSE)
  771. 758 END
  772. 759 END; .) .
  773. 760 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
  774. 761 Targets are pointer designators; DISPOSE nils afterwards (safer
  775. 762 than Wirth-undefined; documented). DISPOSE is shallow. *)
  776. 763 NewStat (. VAR dt: SymTab.TypeIndex;
  777. 764 dk: INTEGER;
  778. 765 qd, qm: QbeGen.QVal;
  779. 766 qn: SymTab.Name;
  780. 767 sfx: BOOLEAN;
  781. 768 bt: SymTab.TypeIndex; .)
  782. 769 = "NEW" "(" Design<dt, dk, qd, qn, sfx> ")"
  783. 770 (. IF dt = SymTab.InvalidType THEN
  784. 771 ELSIF (dk # SymTab.KindVar)
  785. 772 AND (dk # SymTab.KindParam)
  786. 773 AND (dk # SymTab.KindField) THEN
  787. 774 SemError(210)
  788. 775 ELSIF SymTab.ClassOf(dt) #
  789. 776 SymTab.ClPtr THEN
  790. 777 SemError(219)
  791. 778 ELSE bt := SymTab.PtrBase(dt);
  792. 779 IF bt #
  793. 780 SymTab.InvalidType THEN
  794. 781 QbeGen.NewHeap(bt, qm);
  795. 782 QbeGen.InitHeap(qm, bt);
  796. 783 IF sfx
  797. 784 OR (dk =
  798. 785 SymTab.KindField) THEN
  799. 786 QbeGen.ElemStore(qd, qm,
  800. 787 dt)
  801. 788 ELSE QbeGen.StorePtr(qn,
  802. 789 qm)
  803. 790 END
  804. 791 END
  805. 792 END; .) .
  806. 793 DisposeStat (. VAR dt: SymTab.TypeIndex;
  807. 794 dk: INTEGER;
  808. 795 qd, qv: QbeGen.QVal;
  809. 796 qn: SymTab.Name;
  810. 797 sfx: BOOLEAN; .)
  811. 798 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> ")"
  812. 799 (. IF dt = SymTab.InvalidType THEN
  813. 800 ELSIF (dk # SymTab.KindVar)
  814. 801 AND (dk # SymTab.KindParam)
  815. 802 AND (dk # SymTab.KindField) THEN
  816. 803 SemError(210)
  817. 804 ELSIF SymTab.ClassOf(dt) #
  818. 805 SymTab.ClPtr THEN
  819. 806 SemError(219)
  820. 807 ELSE
  821. 808 IF sfx
  822. 809 OR (dk =
  823. 810 SymTab.KindField) THEN
  824. 811 QbeGen.ElemLoad(qd, dt,
  825. 812 qv)
  826. 813 ELSE QbeGen.LoadPtr(qn, qv)
  827. 814 END;
  828. 815 QbeGen.FreeHeap(qv);
  829. 816 IF sfx
  830. 817 OR (dk =
  831. 818 SymTab.KindField) THEN
  832. 819 QbeGen.ElemStore(qd, "0",
  833. 820 dt)
  834. 821 ELSE QbeGen.StorePtr(qn,
  835. 822 "0")
  836. 823 END
  837. 824 END; .) .
  838. 825 (* WITH pushes each record's fields (inner wins) plus its base
  839. 826 address; field designators resolve through both stacks. *)
  840. 827 WithStat (. VAR nW: CARDINAL; .)
  841. 828 = "WITH" (. nW := 0; .)
  842. 829 WithItem<nW> { "," WithItem<nW> }
  843. 830 "DO" [ StatSeq ] "END"
  844. 831 (. WHILE nW > 0 DO
  845. 832 SymTab.PopScope;
  846. 833 QbeGen.PopWith;
  847. 834 DEC(nW)
  848. 835 END; .) .
  849. 836 WithItem<VAR nW: CARDINAL> (. VAR dt: SymTab.TypeIndex;
  850. 837 dk: INTEGER;
  851. 838 qd, qe: QbeGen.QVal;
  852. 839 qn: SymTab.Name;
  853. 840 sfx: BOOLEAN; .)
  854. 841 = Design<dt, dk, qd, qn, sfx>
  855. 842 (. IF dt = SymTab.InvalidType THEN
  856. 843 ELSIF (SymTab.ClassOf(dt) #
  857. 844 SymTab.ClRecord)
  858. 845 AND (SymTab.ClassOf(dt) #
  859. 846 SymTab.ClClass) THEN
  860. 847 SemError(215)
  861. 848 ELSIF SymTab.PushRecord(dt) THEN
  862. 849 QbeGen.PushWith(qd);
  863. 850 INC(nW)
  864. 851 END; .) .
  865. 852 (* Assignment or procedure-statement call (4.1, module level).
  866. 853 Bare `P;` is a syntax error; function-as-statement is 233. *)
  867. 854 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
  868. 855 dk: INTEGER;
  869. 856 qd, qe, qt, ql: QbeGen.QVal;
  870. 857 qn: SymTab.Name;
  871. 858 ct2, res0: SymTab.TypeIndex;
  872. 859 q2, mg0: QbeGen.QVal;
  873. 860 isR, conv, wconv: BOOLEAN;
  874. 861 called, sfx: BOOLEAN; .)
  875. 862 = Design<dt, dk, qd, qn, sfx>
  876. 863 ( ":="
  877. 864 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
  878. 865 AND (dk # SymTab.KindVar)
  879. 866 AND (dk # SymTab.KindParam)
  880. 867 AND (dk # SymTab.KindField) THEN
  881. 868 SemError(210)
  882. 869 ELSIF NOT SymTab.Assignable(et,
  883. 870 dt) THEN
  884. 871 SemError(210)
  885. 872 ELSIF (dt # SymTab.InvalidType)
  886. 873 AND (SymTab.ClassOf(dt) =
  887. 874 SymTab.ClClass) THEN
  888. 875 SemError(230) END;
  889. 876 isR := (dt #
  890. 877 SymTab.InvalidType)
  891. 878 AND (SymTab.ClassOf(dt)
  892. 879 = SymTab.ClReal);
  893. 880 conv := isR
  894. 881 AND SymTab.IsIntFamily(et);
  895. 882 wconv := (dt #
  896. 883 SymTab.InvalidType)
  897. 884 AND SymTab.IsLongFamily(dt)
  898. 885 AND SymTab.IsIntFamily(et);
  899. 886 IF ((dk = SymTab.KindVar)
  900. 887 OR (dk = SymTab.KindParam)
  901. 888 OR (dk = SymTab.KindField))
  902. 889 AND (dt # SymTab.InvalidType)
  903. 890 AND (et # SymTab.InvalidType)
  904. 891 AND (SymTab.ClassOf(dt) #
  905. 892 SymTab.ClClass) THEN
  906. 893 IF sfx
  907. 894 OR (dk = SymTab.KindField) THEN
  908. 895 IF SymTab.ClassOf(dt) =
  909. 896 SymTab.ClArray THEN
  910. 897 QbeGen.CopyArray(qd, qe,
  911. 898 dt)
  912. 899 ELSIF SymTab.ClassOf(dt) =
  913. 900 SymTab.ClSet THEN
  914. 901 QbeGen.CopySet(qd, qe,
  915. 902 SymTab.SetWords(dt),
  916. 903 SymTab.SetWords(et))
  917. 904 ELSIF SymTab.ClassOf(dt) =
  918. 905 SymTab.ClRecord THEN
  919. 906 QbeGen.CopyRecord(qd, qe,
  920. 907 dt)
  921. 908 ELSIF SymTab.IsLongFamily(dt) THEN
  922. 909 IF wconv THEN
  923. 910 QbeGen.WidenLong(qe, ql);
  924. 911 QbeGen.ElemStore(qd, ql,
  925. 912 dt)
  926. 913 ELSE QbeGen.ElemStore(qd, qe,
  927. 914 dt)
  928. 915 END
  929. 916 ELSIF conv THEN
  930. 917 QbeGen.ConvIR(qe, qt);
  931. 918 QbeGen.ElemStore(qd, qt,
  932. 919 dt)
  933. 920 ELSE QbeGen.ElemStore(qd, qe,
  934. 921 dt)
  935. 922 END
  936. 923 ELSIF SymTab.ClassOf(dt) =
  937. 924 SymTab.ClArray THEN
  938. 925 QbeGen.CopyArray(qd, qe, dt)
  939. 926 ELSIF SymTab.ClassOf(dt) =
  940. 927 SymTab.ClSet THEN
  941. 928 QbeGen.CopySet(qd, qe,
  942. 929 SymTab.SetWords(dt),
  943. 930 SymTab.SetWords(et))
  944. 931 ELSIF SymTab.ClassOf(dt) =
  945. 932 SymTab.ClRecord THEN
  946. 933 QbeGen.CopyRecord(qd, qe, dt)
  947. 934 ELSIF (SymTab.ClassOf(dt) =
  948. 935 SymTab.ClPtr)
  949. 936 OR (SymTab.ClassOf(dt) =
  950. 937 SymTab.ClProc) THEN
  951. 938 QbeGen.StorePtr(qn, qe)
  952. 939 ELSIF SymTab.IsLongFamily(dt) THEN
  953. 940 IF wconv THEN
  954. 941 QbeGen.WidenLong(qe, ql);
  955. 942 QbeGen.StoreLong(qn, ql)
  956. 943 ELSE QbeGen.StoreLong(qn, qe)
  957. 944 END
  958. 945 ELSIF conv THEN
  959. 946 QbeGen.ConvIR(qe, qt);
  960. 947 QbeGen.StoreVar(qn, qt, TRUE)
  961. 948 ELSE
  962. 949 QbeGen.StoreVar(qn, qe, isR)
  963. 950 END
  964. 951 END; .)
  965. 952 | ArgList<qn, dt, qd, FALSE, ct2, q2, called>
  966. 953 | (* bare `P;`: proper parameterless
  967. 954 procedure call; anything else
  968. 955 here is 233 (was a bare syntax
  969. 956 error before 4.2) *)
  970. 957 (. IF (dk = SymTab.KindProc)
  971. 958 AND NOT sfx THEN
  972. 959 res0 := SymTab.ProcRes(qn);
  973. 960 IF res0 #
  974. 961 SymTab.InvalidType THEN
  975. 962 SemError(233)
  976. 963 ELSIF SymTab.ProcNPar(qn) #
  977. 964 0 THEN
  978. 965 SemError(233)
  979. 966 ELSE QbeGen.Mangled(qn,
  980. 967 SymTab.ProcUid(qn), mg0);
  981. 968 QbeGen.CallBegin(mg0,
  982. 969 res0,
  983. 970 SymTab.ProcDepthOf(qn),
  984. 971 SymTab.IsExternal(qn));
  985. 972 QbeGen.CallEnd(FALSE, q2)
  986. 973 END
  987. 974 ELSE SemError(233)
  988. 975 END; .) ) .
  989. 976 (* Actual-parameter list shared by statement and expression calls.
  990. 977 want selects CallEnd's result handling; t/q carry the call
  991. 978 value (statement calls discard). Arity/type failures are 233;
  992. 979 evaluation code still emits so the .ssa stays assembleable. *)
  993. 980 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
  994. 981 want: BOOLEAN;
  995. 982 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
  996. 983 VAR called: BOOLEAN> (. VAR i: CARDINAL;
  997. 984 res: SymTab.TypeIndex;
  998. 985 mg: QbeGen.QVal;
  999. 986 ok, ind: BOOLEAN; .)
  1000. 987 = "(" (. called := TRUE;
  1001. 988 ok := TRUE;
  1002. 989 ind := FALSE;
  1003. 990 IF SymTab.SymKind(pn) =
  1004. 991 SymTab.KindProc THEN
  1005. 992 res := SymTab.ProcRes(pn);
  1006. 993 QbeGen.Mangled(pn,
  1007. 994 SymTab.ProcUid(pn), mg);
  1008. 995 QbeGen.CallBegin(mg, res,
  1009. 996 SymTab.ProcDepthOf(pn),
  1010. 997 SymTab.IsExternal(pn))
  1011. 998 ELSIF (pt # SymTab.InvalidType)
  1012. 999 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
  1013. 1000 ind := TRUE;
  1014. 1001 res :=
  1015. 1002 SymTab.ProcTypeRes(pt);
  1016. 1003 QbeGen.CallBeginInd(callee,
  1017. 1004 res, FALSE)
  1018. 1005 ELSE SemError(233);
  1019. 1006 ok := FALSE;
  1020. 1007 res := SymTab.InvalidType
  1021. 1008 END;
  1022. 1009 i := 0; .)
  1023. 1010 [ ActParam<pn, pt, ind, i> (. INC(i); .)
  1024. 1011 { "," ActParam<pn, pt, ind, i> (. INC(i); .) } ]
  1025. 1012 ")" (. IF ok THEN
  1026. 1013 IF ind THEN
  1027. 1014 IF i #
  1028. 1015 SymTab.ProcTypeNPar(pt) THEN
  1029. 1016 SemError(233); ok := FALSE
  1030. 1017 END
  1031. 1018 ELSIF i #
  1032. 1019 SymTab.ProcNPar(pn) THEN
  1033. 1020 SemError(233); ok := FALSE
  1034. 1021 END
  1035. 1022 END;
  1036. 1023 IF NOT ok THEN
  1037. 1024 t := SymTab.InvalidType;
  1038. 1025 QbeGen.CopyOp("0", q)
  1039. 1026 ELSIF want THEN
  1040. 1027 IF res =
  1041. 1028 SymTab.InvalidType THEN
  1042. 1029 SemError(233);
  1043. 1030 t := SymTab.InvalidType;
  1044. 1031 QbeGen.CopyOp("0", q)
  1045. 1032 ELSE t := res;
  1046. 1033 QbeGen.CallEnd(TRUE, q)
  1047. 1034 END
  1048. 1035 ELSE
  1049. 1036 IF res #
  1050. 1037 SymTab.InvalidType THEN
  1051. 1038 SemError(233)
  1052. 1039 END;
  1053. 1040 t := SymTab.InvalidType;
  1054. 1041 QbeGen.CopyOp("0", q);
  1055. 1042 QbeGen.CallEnd(FALSE, q)
  1056. 1043 END; .) .
  1057. 1044 (* One actual: VAR formals take recorded designator addresses
  1058. 1045 (233 otherwise); value formals take converted expressions. *)
  1059. 1046 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
  1060. 1047 i: CARDINAL> (. VAR at, ft: SymTab.TypeIndex;
  1061. 1048 qe, qa, qt: QbeGen.QVal;
  1062. 1049 isV, conv: BOOLEAN; .)
  1063. 1050 = Expr<at, qe> (. IF ind THEN
  1064. 1051 ft :=
  1065. 1052 SymTab.ProcTypeParamType(pt,
  1066. 1053 i);
  1067. 1054 isV :=
  1068. 1055 SymTab.ProcTypeParamIsVar(pt,
  1069. 1056 i)
  1070. 1057 ELSE
  1071. 1058 ft := SymTab.ParamType(pn, i);
  1072. 1059 isV := SymTab.ParamIsVar(pn, i)
  1073. 1060 END;
  1074. 1061 IF (at = SymTab.InvalidType)
  1075. 1062 OR (ft =
  1076. 1063 SymTab.InvalidType) THEN
  1077. 1064 ELSIF isV THEN
  1078. 1065 IF (SymTab.ClassOf(at)
  1079. 1066 = SymTab.ClChar)
  1080. 1067 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
  1081. 1068 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
  1082. 1069 = SymTab.ClChar)
  1083. 1070 AND QbeGen.IsImm(qe) THEN
  1084. 1071 (* 1-char string
  1085. 1072 literal passed to
  1086. 1073 a VAR ARRAY OF CHAR *)
  1087. 1074 QbeGen.DeclCharStr(qe,
  1088. 1075 qa);
  1089. 1076 IF NOT QbeGen.CallArg(qa,
  1090. 1077 "l") THEN
  1091. 1078 SemError(233)
  1092. 1079 END
  1093. 1080 ELSIF NOT QbeGen.AddrOfVal(qe,
  1094. 1081 qa) THEN
  1095. 1082 SemError(233)
  1096. 1083 ELSIF NOT SymTab.VarParamOk(at,
  1097. 1084 ft) THEN
  1098. 1085 SemError(233)
  1099. 1086 ELSIF NOT QbeGen.CallArg(qa,
  1100. 1087 "l") THEN
  1101. 1088 SemError(233)
  1102. 1089 END
  1103. 1090 ELSE
  1104. 1091 IF (SymTab.ClassOf(at)
  1105. 1092 = SymTab.ClChar)
  1106. 1093 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
  1107. 1094 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
  1108. 1095 = SymTab.ClChar)
  1109. 1096 AND QbeGen.IsImm(qe) THEN
  1110. 1097 (* 1-char string
  1111. 1098 literal passed to
  1112. 1099 ARRAY OF CHAR *)
  1113. 1100 QbeGen.DeclCharStr(qe,
  1114. 1101 qa);
  1115. 1102 IF NOT QbeGen.CallArg(qa,
  1116. 1103 "l") THEN
  1117. 1104 SemError(233)
  1118. 1105 END
  1119. 1106 ELSIF NOT SymTab.Assignable(at,
  1120. 1107 ft) THEN
  1121. 1108 SemError(233)
  1122. 1109 ELSE
  1123. 1110 conv := (SymTab.ClassOf(
  1124. 1111 ft) = SymTab.ClReal)
  1125. 1112 AND SymTab.IsIntFamily(at);
  1126. 1113 IF conv THEN
  1127. 1114 QbeGen.ConvIR(qe, qt);
  1128. 1115 IF NOT QbeGen.CallArg(qt,
  1129. 1116 "d") THEN
  1130. 1117 SemError(233)
  1131. 1118 END
  1132. 1119 ELSIF NOT QbeGen.CallArg(qe,
  1133. 1120 QbeGen.ArgClass(ft)) THEN
  1134. 1121 SemError(233)
  1135. 1122 END
  1136. 1123 END
  1137. 1124 END; .) .
  1138. 1125 IfStat (. VAR t: SymTab.TypeIndex;
  1139. 1126 q, lThen, lElse, lEnd:
  1140. 1127 QbeGen.QVal;
  1141. 1128 hasElse: BOOLEAN; .)
  1142. 1129 = "IF" (. hasElse := FALSE; .)
  1143. 1130 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
  1144. 1131 SemError(214) END;
  1145. 1132 QbeGen.NewLabel(lThen);
  1146. 1133 QbeGen.NewLabel(lElse);
  1147. 1134 QbeGen.NewLabel(lEnd);
  1148. 1135 QbeGen.Jnz(q, lThen, lElse);
  1149. 1136 QbeGen.EmitLabel(lThen); .)
  1150. 1137 "THEN" [ StatSeq ] (. QbeGen.Jmp(lEnd); .)
  1151. 1138 { "ELSIF" (. QbeGen.EmitLabel(lElse);
  1152. 1139 QbeGen.NewLabel(lElse); .)
  1153. 1140 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
  1154. 1141 SemError(214) END;
  1155. 1142 QbeGen.NewLabel(lThen);
  1156. 1143 QbeGen.Jnz(q, lThen, lElse);
  1157. 1144 QbeGen.EmitLabel(lThen); .)
  1158. 1145 "THEN" [ StatSeq ] (. QbeGen.Jmp(lEnd); .) }
  1159. 1146 [ "ELSE" (. QbeGen.EmitLabel(lElse);
  1160. 1147 hasElse := TRUE; .)
  1161. 1148 [ StatSeq ] ]
  1162. 1149 "END" (. IF hasElse THEN
  1163. 1150 QbeGen.EmitLabel(lEnd)
  1164. 1151 ELSE QbeGen.EmitLabel(lElse);
  1165. 1152 QbeGen.EmitLabel(lEnd)
  1166. 1153 END; .) .
  1167. 1154 WhileStat (. VAR t: SymTab.TypeIndex;
  1168. 1155 q, lTop, lBody, lEnd:
  1169. 1156 QbeGen.QVal; .)
  1170. 1157 = "WHILE" (. QbeGen.NewLabel(lTop);
  1171. 1158 QbeGen.NewLabel(lBody);
  1172. 1159 QbeGen.NewLabel(lEnd);
  1173. 1160 QbeGen.EmitLabel(lTop); .)
  1174. 1161 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
  1175. 1162 SemError(214) END;
  1176. 1163 QbeGen.Jnz(q, lBody, lEnd);
  1177. 1164 QbeGen.EmitLabel(lBody); .)
  1178. 1165 "DO" [ StatSeq ] (. QbeGen.Jmp(lTop); .)
  1179. 1166 "END" (. QbeGen.EmitLabel(lEnd); .) .
  1180. 1167 RepeatStat (. VAR t: SymTab.TypeIndex;
  1181. 1168 q, lTop, lEnd: QbeGen.QVal; .)
  1182. 1169 = "REPEAT" (. QbeGen.NewLabel(lTop);
  1183. 1170 QbeGen.NewLabel(lEnd);
  1184. 1171 QbeGen.EmitLabel(lTop); .)
  1185. 1172 [ StatSeq ]
  1186. 1173 "UNTIL" Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
  1187. 1174 SemError(214) END;
  1188. 1175 QbeGen.Jnz(q, lEnd, lTop);
  1189. 1176 QbeGen.EmitLabel(lEnd); .) .
  1190. 1177 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
  1191. 1178 = "LOOP" (. QbeGen.NewLabel(lTop);
  1192. 1179 QbeGen.NewLabel(lEnd);
  1193. 1180 QbeGen.PushLoop(lEnd);
  1194. 1181 QbeGen.EmitLabel(lTop); .)
  1195. 1182 [ StatSeq ]
  1196. 1183 "END" (. QbeGen.Jmp(lTop);
  1197. 1184 QbeGen.PopLoop;
  1198. 1185 QbeGen.EmitLabel(lEnd); .) .
  1199. 1186 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
  1200. 1187 Runtime direction would need a compare-select; the literal
  1201. 1188 sign picks cslew/csegew at "DO" time. *)
  1202. 1189 ForStat (. VAR lv: SymTab.Name;
  1203. 1190 tlo, thi, tby:
  1204. 1191 SymTab.TypeIndex;
  1205. 1192 qlo, qhi, qby, qt, qk, qb:
  1206. 1193 QbeGen.QVal;
  1207. 1194 lTop, lBody, lEnd:
  1208. 1195 QbeGen.QVal;
  1209. 1196 by: INTEGER;
  1210. 1197 ok: BOOLEAN; .)
  1211. 1198 = "FOR" (. by := 1; .)
  1212. 1199 GetIdent<lv> (. ok := SymTab.Lookup(lv);
  1213. 1200 IF NOT ok THEN
  1214. 1201 SemError(201)
  1215. 1202 ELSIF (SymTab.SymKind(lv) #
  1216. 1203 SymTab.KindVar)
  1217. 1204 AND (SymTab.SymKind(lv) #
  1218. 1205 SymTab.KindParam) THEN
  1219. 1206 SemError(220); ok := FALSE
  1220. 1207 ELSIF NOT SymTab.IsIntFamily(
  1221. 1208 SymTab.SymType(lv)) THEN
  1222. 1209 SemError(220); ok := FALSE
  1223. 1210 END; .)
  1224. 1211 ":=" Expr<tlo, qlo> (. IF NOT SymTab.IsIntFamily(tlo) THEN
  1225. 1212 SemError(220); ok := FALSE
  1226. 1213 END; .)
  1227. 1214 "TO" Expr<thi, qhi> (. IF NOT SymTab.IsIntFamily(thi) THEN
  1228. 1215 SemError(220); ok := FALSE
  1229. 1216 END; .)
  1230. 1217 [ "BY" Expr<tby, qby> (. IF (tby #
  1231. 1218 SymTab.InvalidType)
  1232. 1219 AND NOT SymTab.IsIntFamily(tby) THEN
  1233. 1220 SemError(220); ok := FALSE
  1234. 1221 END;
  1235. 1222 IF NOT SymTab.ConstInt(qby, by) THEN
  1236. 1223 SemError(230); by := 1
  1237. 1224 ELSIF by = 0 THEN
  1238. 1225 SemError(220); by := 1
  1239. 1226 END; .) ]
  1240. 1227 "DO" (. IF ok THEN
  1241. 1228 QbeGen.StoreVar(lv, qlo,
  1242. 1229 FALSE) END;
  1243. 1230 QbeGen.NewLabel(lTop);
  1244. 1231 QbeGen.NewLabel(lBody);
  1245. 1232 QbeGen.NewLabel(lEnd);
  1246. 1233 QbeGen.EmitLabel(lTop);
  1247. 1234 QbeGen.LoadVar(lv, FALSE, qt);
  1248. 1235 QbeGen.NewTemp(qk);
  1249. 1236 IF by > 0 THEN
  1250. 1237 QbeGen.Op3("cslew", qk,
  1251. 1238 qt, qhi, FALSE)
  1252. 1239 ELSE QbeGen.Op3("csgew", qk,
  1253. 1240 qt, qhi, FALSE)
  1254. 1241 END;
  1255. 1242 QbeGen.Jnz(qk, lBody, lEnd);
  1256. 1243 QbeGen.EmitLabel(lBody); .)
  1257. 1244 [ StatSeq ]
  1258. 1245 "END" (. IF ok THEN
  1259. 1246 QbeGen.LoadVar(lv, FALSE,
  1260. 1247 qt);
  1261. 1248 QbeGen.IntStr(by, qb);
  1262. 1249 QbeGen.NewTemp(qk);
  1263. 1250 QbeGen.Op3("add", qk,
  1264. 1251 qt, qb, FALSE);
  1265. 1252 QbeGen.StoreVar(lv, qk,
  1266. 1253 FALSE) END;
  1267. 1254 QbeGen.Jmp(lTop);
  1268. 1255 QbeGen.EmitLabel(lEnd); .) .
  1269. 1256 CaseStat (. VAR tsel: SymTab.TypeIndex;
  1270. 1257 qsel, lEnd: QbeGen.QVal; .)
  1271. 1258 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
  1272. 1259 "OF" CaseAlt<tsel, qsel, lEnd>
  1273. 1260 { "|" CaseAlt<tsel, qsel, lEnd> }
  1274. 1261 [ "ELSE" [ StatSeq ] ]
  1275. 1262 "END" (. QbeGen.EmitLabel(lEnd); .) .
  1276. 1263 (* Compare-chain lowering: each alternative ends its match-tests
  1277. 1264 with "jmp lAfter", so the no-match fallthrough skips the body:
  1278. 1265 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
  1279. 1266 lAfter:". Falls into the next alternative, ELSE, or END. *)
  1280. 1267 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
  1281. 1268 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
  1282. 1269 = (. QbeGen.NewLabel(lBody);
  1283. 1270 QbeGen.NewLabel(lAfter); .)
  1284. 1271 CaseLabel<tsel, qsel, lBody>
  1285. 1272 { "," CaseLabel<tsel, qsel, lBody> }
  1286. 1273 ":" (. QbeGen.Jmp(lAfter);
  1287. 1274 QbeGen.EmitLabel(lBody); .)
  1288. 1275 [ StatSeq ] (. QbeGen.Jmp(lEnd);
  1289. 1276 QbeGen.EmitLabel(lAfter); .) .
  1290. 1277 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
  1291. 1278 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
  1292. 1279 q2, q3, qc, qd, qe:
  1293. 1280 QbeGen.QVal;
  1294. 1281 lNext: QbeGen.QVal; .)
  1295. 1282 = Expr<t2, q2> (. IF (t2 #
  1296. 1283 SymTab.InvalidType)
  1297. 1284 AND (tsel #
  1298. 1285 SymTab.InvalidType)
  1299. 1286 AND ((SymTab.ClassOf(t2) =
  1300. 1287 SymTab.ClSet)
  1301. 1288 OR (SymTab.ClassOf(tsel) =
  1302. 1289 SymTab.ClSet)) THEN
  1303. 1290 SemError(230)
  1304. 1291 ELSIF (t2 #
  1305. 1292 SymTab.InvalidType)
  1306. 1293 AND (tsel #
  1307. 1294 SymTab.InvalidType)
  1308. 1295 AND NOT SymTab.EqCheck(t2,
  1309. 1296 tsel) THEN
  1310. 1297 SemError(213) END;
  1311. 1298 IF NOT QbeGen.IsImm(q2) THEN
  1312. 1299 SemError(230);
  1313. 1300 QbeGen.CopyOp("0", q2)
  1314. 1301 END;
  1315. 1302 QbeGen.NewLabel(lNext);
  1316. 1303 QbeGen.Cmp(SymTab.OpEq,
  1317. 1304 qsel, q2, qc, FALSE);
  1318. 1305 QbeGen.Jnz(qc, lBody, lNext);
  1319. 1306 QbeGen.EmitLabel(lNext); .)
  1320. 1307 [ ".." Expr<t3, q3> (. IF (t3 #
  1321. 1308 SymTab.InvalidType)
  1322. 1309 AND (tsel #
  1323. 1310 SymTab.InvalidType)
  1324. 1311 AND NOT SymTab.EqCheck(t3,
  1325. 1312 tsel) THEN
  1326. 1313 SemError(213) END;
  1327. 1314 IF NOT QbeGen.IsImm(q3) THEN
  1328. 1315 SemError(230);
  1329. 1316 QbeGen.CopyOp("0", q3)
  1330. 1317 END;
  1331. 1318 QbeGen.Cmp(SymTab.OpGe,
  1332. 1319 qsel, q2, qc, FALSE);
  1333. 1320 QbeGen.Cmp(SymTab.OpLe,
  1334. 1321 qsel, q3, qd, FALSE);
  1335. 1322 QbeGen.NewTemp(qe);
  1336. 1323 QbeGen.Op3("and", qe, qc, qd,
  1337. 1324 FALSE);
  1338. 1325 QbeGen.NewLabel(lNext);
  1339. 1326 QbeGen.Jnz(qe, lBody, lNext);
  1340. 1327 QbeGen.EmitLabel(lNext); .) ] .
  1341. 1328 ReturnStat (. VAR t: SymTab.TypeIndex;
  1342. 1329 q, qt: QbeGen.QVal;
  1343. 1330 res: SymTab.TypeIndex;
  1344. 1331 hadE, conv: BOOLEAN; .)
  1345. 1332 = "RETURN" (. hadE := FALSE; .)
  1346. 1333 [ Expr<t, q> (. hadE := TRUE; .) ]
  1347. 1334 (. conv := FALSE;
  1348. 1335 IF NOT SymTab.InProc() THEN
  1349. 1336 SemError(232)
  1350. 1337 ELSE res := SymTab.CurRes();
  1351. 1338 IF NOT hadE THEN
  1352. 1339 IF res #
  1353. 1340 SymTab.InvalidType THEN
  1354. 1341 SemError(232)
  1355. 1342 ELSE QbeGen.EmitRet(q,
  1356. 1343 FALSE)
  1357. 1344 END
  1358. 1345 ELSIF (res =
  1359. 1346 SymTab.InvalidType)
  1360. 1347 OR (t #
  1361. 1348 SymTab.InvalidType)
  1362. 1349 AND NOT SymTab.Assignable(t,
  1363. 1350 res) THEN
  1364. 1351 SemError(232)
  1365. 1352 ELSE
  1366. 1353 conv := (SymTab.ClassOf(
  1367. 1354 res) = SymTab.ClReal)
  1368. 1355 AND SymTab.IsIntFamily(t);
  1369. 1356 IF conv THEN
  1370. 1357 QbeGen.ConvIR(q, qt);
  1371. 1358 QbeGen.EmitRet(qt, TRUE)
  1372. 1359 ELSE QbeGen.EmitRet(q, TRUE)
  1373. 1360 END
  1374. 1361 END
  1375. 1362 END; .) .
  1376. 1363 HaltStat (. VAR t: SymTab.TypeIndex;
  1377. 1364 q: QbeGen.QVal; .)
  1378. 1365 = "HALT" [ "(" Expr<t, q> ")" ] (. QbeGen.HaltQ; .) .
  1379. 1366 (* Designator: scalar loads, array addresses, and index suffixes.
  1380. 1367 Each index descends one level (bounds-checked, trap on breach);
  1381. 1368 nested levels reload the inner descriptor address. q ends as the
  1382. 1369 value (scalars), the descriptor address (plain arrays), or the
  1383. 1370 element address (indexed); sfx marks the indexed form. *)
  1384. 1371 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  1385. 1372 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
  1386. 1373 (. VAR n, fn, mal: SymTab.Name;
  1387. 1374 cls: INTEGER;
  1388. 1375 curT, it, eT, bt:
  1389. 1376 SymTab.TypeIndex;
  1390. 1377 iq, ql, qlo, qhi, qe:
  1391. 1378 QbeGen.QVal;
  1392. 1379 lo, hi: INTEGER;
  1393. 1380 fo: INTEGER;
  1394. 1381 isOpen: BOOLEAN;
  1395. 1382 qb, cv: QbeGen.QVal; .)
  1396. 1383 = GetIdent<n> (. QbeGen.CopyOp(n, qn);
  1397. 1384 sfx := FALSE;
  1398. 1385 IF NOT SymTab.Lookup(n) THEN
  1399. 1386 SemError(201);
  1400. 1387 t := SymTab.InvalidType;
  1401. 1388 k := -1;
  1402. 1389 QbeGen.CopyOp("0", q)
  1403. 1390 ELSE
  1404. 1391 t := SymTab.SymType(n);
  1405. 1392 k := SymTab.SymKind(n);
  1406. 1393 IF k = SymTab.KindConst THEN
  1407. 1394 IF SymTab.Equal(n,
  1408. 1395 "TRUE") THEN
  1409. 1396 t := SymTab.BoolType();
  1410. 1397 QbeGen.CopyOp("1", q)
  1411. 1398 ELSIF SymTab.Equal(n,
  1412. 1399 "FALSE") THEN
  1413. 1400 t := SymTab.BoolType();
  1414. 1401 QbeGen.CopyOp("0", q)
  1415. 1402 ELSIF SymTab.Equal(n,
  1416. 1403 "NIL") THEN
  1417. 1404 QbeGen.CopyOp("0", q)
  1418. 1405 ELSE
  1419. 1406 cls :=
  1420. 1407 SymTab.ClassOf(t);
  1421. 1408 IF (t #
  1422. 1409 SymTab.InvalidType)
  1423. 1410 AND ((cls = SymTab.ClInt)
  1424. 1411 OR (cls
  1425. 1412 = SymTab.ClChar)
  1426. 1413 OR (cls
  1427. 1414 = SymTab.ClReal)
  1428. 1415 OR (cls
  1429. 1416 = SymTab.ClNil)) THEN
  1430. 1417 IF cls = SymTab.ClNil THEN
  1431. 1418 QbeGen.CopyOp("0", q)
  1432. 1419 ELSIF ((cls
  1433. 1420 = SymTab.ClInt)
  1434. 1421 OR (cls
  1435. 1422 = SymTab.ClChar))
  1436. 1423 AND SymTab.GetSymVal(n, cv)
  1437. 1424 AND QbeGen.IsImm(cv) THEN
  1438. 1425 QbeGen.CopyOp(cv, q)
  1439. 1426 ELSE
  1440. 1427 QbeGen.LoadVar(n,
  1441. 1428 cls = SymTab.ClReal,
  1442. 1429 q)
  1443. 1430 END
  1444. 1431 ELSE
  1445. 1432 IF t #
  1446. 1433 SymTab.InvalidType THEN
  1447. 1434 SemError(230)
  1448. 1435 END;
  1449. 1436 QbeGen.CopyOp("0", q)
  1450. 1437 END
  1451. 1438 END
  1452. 1439 ELSIF (k = SymTab.KindVar)
  1453. 1440 OR (k = SymTab.KindParam) THEN
  1454. 1441 cls :=
  1455. 1442 SymTab.ClassOf(t);
  1456. 1443 IF (cls = SymTab.ClInt)
  1457. 1444 OR (cls = SymTab.ClBool)
  1458. 1445 OR (cls = SymTab.ClChar)
  1459. 1446 OR (cls
  1460. 1447 = SymTab.ClReal) THEN
  1461. 1448 QbeGen.LoadVar(n,
  1462. 1449 cls = SymTab.ClReal, q)
  1463. 1450 ELSIF (cls = SymTab.ClPtr)
  1464. 1451 OR (cls = SymTab.ClProc) THEN
  1465. 1452 QbeGen.LoadPtr(n, q)
  1466. 1453 ELSIF cls = SymTab.ClLong THEN
  1467. 1454 QbeGen.LoadLong(n, q)
  1468. 1455 ELSIF (cls
  1469. 1456 = SymTab.ClArray)
  1470. 1457 OR (cls
  1471. 1458 = SymTab.ClSet)
  1472. 1459 OR (cls
  1473. 1460 = SymTab.ClRecord)
  1474. 1461 OR (cls
  1475. 1462 = SymTab.ClClass) THEN
  1476. 1463 QbeGen.AddrOf(n, q)
  1477. 1464 ELSE SemError(230);
  1478. 1465 QbeGen.CopyOp("0", q)
  1479. 1466 END
  1480. 1467 ELSE QbeGen.CopyOp("0", q);
  1481. 1468 IF k = SymTab.KindImport THEN
  1482. 1469 SemError(230)
  1483. 1470 ELSIF k =
  1484. 1471 SymTab.KindProc THEN
  1485. 1472 (* bare procedure name:
  1486. 1473 a following ArgList
  1487. 1474 makes it a call;
  1488. 1475 otherwise Fact
  1489. 1476 reports 230 *)
  1490. 1477 ELSE
  1491. 1478 IF k = SymTab.KindField THEN
  1492. 1479 IF QbeGen.TopWith(qb) THEN
  1493. 1480 fo :=
  1494. 1481 SymTab.FieldOffset(
  1495. 1482 SymTab.FieldOwner(n),
  1496. 1483 n);
  1497. 1484 QbeGen.FieldAddr(qb,
  1498. 1485 fo, q);
  1499. 1486 sfx := TRUE
  1500. 1487 ELSE SemError(230);
  1501. 1488 QbeGen.CopyOp("0", q)
  1502. 1489 END
  1503. 1490 END
  1504. 1491 END
  1505. 1492 END
  1506. 1493 END; .)
  1507. 1494 { "[" Expr<it, iq>
  1508. 1495 (. IF t = SymTab.InvalidType THEN
  1509. 1496 ELSIF SymTab.ClassOf(t) #
  1510. 1497 SymTab.ClArray THEN
  1511. 1498 SemError(217);
  1512. 1499 t := SymTab.InvalidType
  1513. 1500 ELSIF NOT SymTab.IsIntFamily(it)
  1514. 1501 AND (SymTab.ClassOf(it) #
  1515. 1502 SymTab.ClChar) THEN
  1516. 1503 SemError(218);
  1517. 1504 t := SymTab.InvalidType
  1518. 1505 ELSE
  1519. 1506 QbeGen.WidenIndex(iq, ql);
  1520. 1507 isOpen :=
  1521. 1508 SymTab.IsOpenArray(t);
  1522. 1509 IF isOpen THEN
  1523. 1510 QbeGen.CopyOp("0", qlo);
  1524. 1511 QbeGen.OpenHi(q, qhi)
  1525. 1512 ELSE
  1526. 1513 lo := SymTab.ArrayLo(t);
  1527. 1514 hi := SymTab.ArrayHi(t);
  1528. 1515 QbeGen.IntStr(lo, qlo);
  1529. 1516 QbeGen.IntStr(hi, qhi)
  1530. 1517 END;
  1531. 1518 QbeGen.CheckRange(ql, qlo,
  1532. 1519 qhi);
  1533. 1520 eT := SymTab.ArrayElem(t);
  1534. 1521 QbeGen.ElemAddr(q, ql, qlo,
  1535. 1522 t, qe);
  1536. 1523 IF SymTab.ClassOf(eT) =
  1537. 1524 SymTab.ClArray THEN
  1538. 1525 QbeGen.ElemLoad(qe, eT, q)
  1539. 1526 ELSE QbeGen.CopyOp(qe, q)
  1540. 1527 END;
  1541. 1528 t := eT; sfx := TRUE
  1542. 1529 END; .)
  1543. 1530 { "," Expr<it, iq>
  1544. 1531 (. IF t = SymTab.InvalidType THEN
  1545. 1532 ELSIF SymTab.ClassOf(t) #
  1546. 1533 SymTab.ClArray THEN
  1547. 1534 SemError(217);
  1548. 1535 t := SymTab.InvalidType
  1549. 1536 ELSIF NOT SymTab.IsIntFamily(it)
  1550. 1537 AND (SymTab.ClassOf(it) #
  1551. 1538 SymTab.ClChar) THEN
  1552. 1539 SemError(218);
  1553. 1540 t := SymTab.InvalidType
  1554. 1541 ELSE
  1555. 1542 QbeGen.WidenIndex(iq, ql);
  1556. 1543 isOpen :=
  1557. 1544 SymTab.IsOpenArray(t);
  1558. 1545 IF isOpen THEN
  1559. 1546 QbeGen.CopyOp("0", qlo);
  1560. 1547 QbeGen.OpenHi(q, qhi)
  1561. 1548 ELSE
  1562. 1549 lo := SymTab.ArrayLo(t);
  1563. 1550 hi := SymTab.ArrayHi(t);
  1564. 1551 QbeGen.IntStr(lo, qlo);
  1565. 1552 QbeGen.IntStr(hi, qhi)
  1566. 1553 END;
  1567. 1554 QbeGen.CheckRange(ql, qlo,
  1568. 1555 qhi);
  1569. 1556 eT := SymTab.ArrayElem(t);
  1570. 1557 QbeGen.ElemAddr(q, ql, qlo,
  1571. 1558 t, qe);
  1572. 1559 IF SymTab.ClassOf(eT) =
  1573. 1560 SymTab.ClArray THEN
  1574. 1561 QbeGen.ElemLoad(qe, eT, q)
  1575. 1562 ELSE QbeGen.CopyOp(qe, q)
  1576. 1563 END;
  1577. 1564 t := eT; sfx := TRUE
  1578. 1565 END; .) }
  1579. 1566 "]"
  1580. 1567 | "." GetIdent<fn>
  1581. 1568 (. IF k = SymTab.KindModule THEN
  1582. 1569 (* qualified L.x: materialize
  1583. 1570 the export, then load it *)
  1584. 1571 IF NOT SymTab.MaterializeAlias(n,
  1585. 1572 fn, mal) THEN
  1586. 1573 SemError(201);
  1587. 1574 t := SymTab.InvalidType;
  1588. 1575 QbeGen.CopyOp("0", q)
  1589. 1576 ELSE
  1590. 1577 QbeGen.CopyOp(mal, qn);
  1591. 1578 t := SymTab.SymType(mal);
  1592. 1579 k := SymTab.SymKind(mal);
  1593. 1580 sfx := FALSE;
  1594. 1581 IF k = SymTab.KindProc THEN
  1595. 1582 (* call: ArgList supplies
  1596. 1583 the value *)
  1597. 1584 QbeGen.CopyOp("0", q)
  1598. 1585 ELSIF NOT QbeGen.LoadDesignator(
  1599. 1586 mal, t, k, q) THEN
  1600. 1587 SemError(230);
  1601. 1588 QbeGen.CopyOp("0", q)
  1602. 1589 END
  1603. 1590 END
  1604. 1591 ELSIF t = SymTab.InvalidType THEN
  1605. 1592 ELSIF (SymTab.ClassOf(t) #
  1606. 1593 SymTab.ClRecord)
  1607. 1594 AND (SymTab.ClassOf(t) #
  1608. 1595 SymTab.ClClass) THEN
  1609. 1596 SemError(215);
  1610. 1597 t := SymTab.InvalidType
  1611. 1598 ELSIF NOT SymTab.FieldExists(t,
  1612. 1599 fn) THEN
  1613. 1600 SemError(216);
  1614. 1601 t := SymTab.InvalidType
  1615. 1602 ELSE
  1616. 1603 fo := SymTab.FieldOffset(t,
  1617. 1604 fn);
  1618. 1605 t := SymTab.FieldType(t, fn);
  1619. 1606 QbeGen.FieldAddr(q, fo, qe);
  1620. 1607 (* array fields are inline:
  1621. 1608 the field address is the
  1622. 1609 descriptor, like records *)
  1623. 1610 QbeGen.CopyOp(qe, q);
  1624. 1611 sfx := TRUE
  1625. 1612 END; .)
  1626. 1613 | "^"
  1627. 1614 (. IF t = SymTab.InvalidType THEN
  1628. 1615 ELSIF SymTab.ClassOf(t) #
  1629. 1616 SymTab.ClPtr THEN
  1630. 1617 SemError(219);
  1631. 1618 t := SymTab.InvalidType
  1632. 1619 ELSE
  1633. 1620 bt := SymTab.PtrBase(t);
  1634. 1621 IF bt = SymTab.InvalidType THEN
  1635. 1622 ELSE
  1636. 1623 IF sfx THEN
  1637. 1624 QbeGen.ElemLoad(q, t,
  1638. 1625 qb);
  1639. 1626 QbeGen.CopyOp(qb, q)
  1640. 1627 END;
  1641. 1628 t := bt;
  1642. 1629 IF (SymTab.ClassOf(bt) =
  1643. 1630 SymTab.ClInt)
  1644. 1631 OR (SymTab.ClassOf(bt) =
  1645. 1632 SymTab.ClBool)
  1646. 1633 OR (SymTab.ClassOf(bt) =
  1647. 1634 SymTab.ClChar)
  1648. 1635 OR (SymTab.ClassOf(bt) =
  1649. 1636 SymTab.ClReal) THEN
  1650. 1637 sfx := TRUE
  1651. 1638 ELSE sfx := FALSE
  1652. 1639 END
  1653. 1640 END
  1654. 1641 END; .) } .
  1655. 1642 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  1656. 1643 (. VAR t2: SymTab.TypeIndex;
  1657. 1644 op: INTEGER;
  1658. 1645 q2, qt, wl: QbeGen.QVal;
  1659. 1646 isR: BOOLEAN; .)
  1660. 1647 = SimExpr<t, q>
  1661. 1648 [ Rel<op> SimExpr<t2, q2>
  1662. 1649 (. IF op = SymTab.OpIn THEN
  1663. 1650 IF SymTab.InCheck(t, t2) THEN
  1664. 1651 IF (t = SymTab.InvalidType)
  1665. 1652 OR (t2 = SymTab.InvalidType) THEN
  1666. 1653 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  1667. 1654 ELSE
  1668. 1655 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
  1669. 1656 SymTab.SetCount(t2), qt);
  1670. 1657 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  1671. 1658 END
  1672. 1659 ELSE SemError(222); t := SymTab.InvalidType;
  1673. 1660 QbeGen.CopyOp("0", q)
  1674. 1661 END
  1675. 1662 ELSIF SymTab.RelCheck(t, t2, op) THEN
  1676. 1663 IF (t = SymTab.InvalidType)
  1677. 1664 OR (t2 = SymTab.InvalidType) THEN
  1678. 1665 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  1679. 1666 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
  1680. 1667 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
  1681. 1668 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
  1682. 1669 AND (op # SymTab.OpNeq2) THEN
  1683. 1670 SemError(213); t := SymTab.InvalidType;
  1684. 1671 QbeGen.CopyOp("0", q)
  1685. 1672 ELSE
  1686. 1673 QbeGen.CmpL(op, q, q2, qt);
  1687. 1674 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  1688. 1675 END
  1689. 1676 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
  1690. 1677 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  1691. 1678 QbeGen.CmpSet(op, q, q2,
  1692. 1679 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
  1693. 1680 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  1694. 1681 ELSIF SymTab.IsLongFamily(t)
  1695. 1682 OR SymTab.IsLongFamily(t2) THEN
  1696. 1683 IF SymTab.IsIntFamily(t) THEN
  1697. 1684 QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
  1698. 1685 END;
  1699. 1686 IF SymTab.IsIntFamily(t2) THEN
  1700. 1687 QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
  1701. 1688 END;
  1702. 1689 QbeGen.CmpLong(op, q, q2, qt);
  1703. 1690 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
  1704. 1691 ELSE
  1705. 1692 isR := SymTab.ClassOf(t) = SymTab.ClReal;
  1706. 1693 t := SymTab.BoolType();
  1707. 1694 QbeGen.Cmp(op, q, q2, qt, isR);
  1708. 1695 QbeGen.CopyOp(qt, q)
  1709. 1696 END
  1710. 1697 ELSE SemError(213); t := SymTab.InvalidType;
  1711. 1698 QbeGen.CopyOp("0", q)
  1712. 1699 END; .) ] .
  1713. 1700 Rel<VAR op: INTEGER>
  1714. 1701 = "=" (. op := SymTab.OpEq; .)
  1715. 1702 | "#" (. op := SymTab.OpNeq1; .)
  1716. 1703 | "<" (. op := SymTab.OpLt; .)
  1717. 1704 | "<=" (. op := SymTab.OpLe; .)
  1718. 1705 | ">" (. op := SymTab.OpGt; .)
  1719. 1706 | ">=" (. op := SymTab.OpGe; .)
  1720. 1707 | "IN" (. op := SymTab.OpIn; .) .
  1721. 1708 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  1722. 1709 (. VAR t2, res2, lt, rt:
  1723. 1710 SymTab.TypeIndex;
  1724. 1711 op: INTEGER;
  1725. 1712 q2, qt, wq, qf:
  1726. 1713 QbeGen.QVal;
  1727. 1714 neg, isR, isL, folded:
  1728. 1715 BOOLEAN;
  1729. 1716 lw, rw, mw: CARDINAL; .)
  1730. 1717 = (. neg := FALSE; .)
  1731. 1718 [ "+" | "-" (. neg := TRUE; .) ]
  1732. 1719 Term<t, q> (. IF neg THEN
  1733. 1720 IF QbeGen.IsImm(q) THEN
  1734. 1721 QbeGen.NegFold(q, q)
  1735. 1722 ELSE QbeGen.NewTemp(qt);
  1736. 1723 QbeGen.NegQ(q, qt,
  1737. 1724 SymTab.ClassOf(t)
  1738. 1725 = SymTab.ClReal);
  1739. 1726 QbeGen.CopyOp(qt, q)
  1740. 1727 END
  1741. 1728 END; .)
  1742. 1729 { AddOp<op> Term<t2, q2>
  1743. 1730 (. IF op = SymTab.OpOr THEN
  1744. 1731 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
  1745. 1732 t := SymTab.BoolType()
  1746. 1733 ELSE SemError(212); t := SymTab.InvalidType END;
  1747. 1734 IF t # SymTab.InvalidType THEN
  1748. 1735 QbeGen.NewTemp(qt);
  1749. 1736 QbeGen.Op3("or", qt, q, q2, FALSE);
  1750. 1737 QbeGen.CopyOp(qt, q)
  1751. 1738 ELSE QbeGen.CopyOp("0", q)
  1752. 1739 END
  1753. 1740 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
  1754. 1741 AND (SymTab.ClassOf(t) = SymTab.ClSet)
  1755. 1742 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  1756. 1743 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
  1757. 1744 mw := lw;
  1758. 1745 IF rw > mw THEN mw := rw END;
  1759. 1746 IF op = SymTab.OpAdd THEN
  1760. 1747 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
  1761. 1748 ELSE
  1762. 1749 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
  1763. 1750 END;
  1764. 1751 t := SymTab.NewSet(
  1765. 1752 SymTab.NewSubR(0,
  1766. 1753 VAL(INTEGER, mw) * 32 - 1));
  1767. 1754 QbeGen.CopyOp(qt, q)
  1768. 1755 ELSE
  1769. 1756 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
  1770. 1757 lt := t; rt := t2; t := res2
  1771. 1758 ELSE SemError(211); t := SymTab.InvalidType END;
  1772. 1759 IF t # SymTab.InvalidType THEN
  1773. 1760 isL := SymTab.IsLongFamily(t);
  1774. 1761 isR := SymTab.ClassOf(t) = SymTab.ClReal;
  1775. 1762 folded := FALSE;
  1776. 1763 IF (NOT isL) AND (NOT isR)
  1777. 1764 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
  1778. 1765 IF op = SymTab.OpAdd THEN
  1779. 1766 folded := QbeGen.Fold2(0, q, q2, qf)
  1780. 1767 ELSE
  1781. 1768 folded := QbeGen.Fold2(1, q, q2, qf)
  1782. 1769 END
  1783. 1770 END;
  1784. 1771 IF folded THEN QbeGen.CopyOp(qf, q)
  1785. 1772 ELSE
  1786. 1773 IF isL THEN
  1787. 1774 IF SymTab.IsIntFamily(lt) THEN
  1788. 1775 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
  1789. 1776 END;
  1790. 1777 IF SymTab.IsIntFamily(rt) THEN
  1791. 1778 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
  1792. 1779 END;
  1793. 1780 QbeGen.NewTemp(qt);
  1794. 1781 IF op = SymTab.OpAdd THEN
  1795. 1782 QbeGen.Op3L("add", qt, q, q2)
  1796. 1783 ELSE
  1797. 1784 QbeGen.Op3L("sub", qt, q, q2)
  1798. 1785 END
  1799. 1786 ELSE
  1800. 1787 QbeGen.NewTemp(qt);
  1801. 1788 IF op = SymTab.OpAdd THEN
  1802. 1789 QbeGen.Op3("add", qt, q, q2, isR)
  1803. 1790 ELSE
  1804. 1791 QbeGen.Op3("sub", qt, q, q2, isR)
  1805. 1792 END
  1806. 1793 END;
  1807. 1794 QbeGen.CopyOp(qt, q)
  1808. 1795 END
  1809. 1796 ELSE QbeGen.CopyOp("0", q)
  1810. 1797 END
  1811. 1798 END; .) } .
  1812. 1799 AddOp<VAR op: INTEGER>
  1813. 1800 = "+" (. op := SymTab.OpAdd; .)
  1814. 1801 | "-" (. op := SymTab.OpSub; .)
  1815. 1802 | "OR" (. op := SymTab.OpOr; .) .
  1816. 1803 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  1817. 1804 (. VAR t2, res2, lt, rt:
  1818. 1805 SymTab.TypeIndex;
  1819. 1806 op: INTEGER;
  1820. 1807 q2, qt, wq, qf:
  1821. 1808 QbeGen.QVal;
  1822. 1809 isR, isL, folded: BOOLEAN;
  1823. 1810 lw, rw, mw: CARDINAL; .)
  1824. 1811 = Fact<t, q> { MulOp<op> Fact<t2, q2>
  1825. 1812 (. IF op = SymTab.OpAnd THEN
  1826. 1813 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
  1827. 1814 t := SymTab.BoolType()
  1828. 1815 ELSE SemError(212); t := SymTab.InvalidType END;
  1829. 1816 IF t # SymTab.InvalidType THEN
  1830. 1817 QbeGen.NewTemp(qt);
  1831. 1818 QbeGen.Op3("and", qt, q, q2, FALSE);
  1832. 1819 QbeGen.CopyOp(qt, q)
  1833. 1820 ELSE QbeGen.CopyOp("0", q)
  1834. 1821 END
  1835. 1822 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
  1836. 1823 AND (SymTab.ClassOf(t) = SymTab.ClSet)
  1837. 1824 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  1838. 1825 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
  1839. 1826 mw := lw;
  1840. 1827 IF rw > mw THEN mw := rw END;
  1841. 1828 IF op = SymTab.OpTimes THEN
  1842. 1829 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
  1843. 1830 ELSE
  1844. 1831 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
  1845. 1832 END;
  1846. 1833 t := SymTab.NewSet(
  1847. 1834 SymTab.NewSubR(0,
  1848. 1835 VAL(INTEGER, mw) * 32 - 1));
  1849. 1836 QbeGen.CopyOp(qt, q)
  1850. 1837 ELSE
  1851. 1838 IF SymTab.ArithCheck(t, t2,
  1852. 1839 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
  1853. 1840 res2) THEN
  1854. 1841 lt := t; rt := t2; t := res2
  1855. 1842 ELSE SemError(211); t := SymTab.InvalidType END;
  1856. 1843 IF t # SymTab.InvalidType THEN
  1857. 1844 isL := SymTab.IsLongFamily(t);
  1858. 1845 isR := SymTab.ClassOf(t) = SymTab.ClReal;
  1859. 1846 folded := FALSE;
  1860. 1847 IF (NOT isL) AND (NOT isR)
  1861. 1848 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
  1862. 1849 IF op = SymTab.OpTimes THEN
  1863. 1850 folded := QbeGen.Fold2(2, q, q2, qf)
  1864. 1851 ELSIF op = SymTab.OpDiv THEN
  1865. 1852 folded := QbeGen.Fold2(3, q, q2, qf)
  1866. 1853 ELSIF op = SymTab.OpMod THEN
  1867. 1854 folded := QbeGen.Fold2(4, q, q2, qf)
  1868. 1855 END
  1869. 1856 END;
  1870. 1857 IF folded THEN QbeGen.CopyOp(qf, q)
  1871. 1858 ELSE
  1872. 1859 IF isL THEN
  1873. 1860 IF SymTab.IsIntFamily(lt) THEN
  1874. 1861 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
  1875. 1862 END;
  1876. 1863 IF SymTab.IsIntFamily(rt) THEN
  1877. 1864 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
  1878. 1865 END;
  1879. 1866 QbeGen.NewTemp(qt);
  1880. 1867 IF op = SymTab.OpTimes THEN
  1881. 1868 QbeGen.Op3L("mul", qt, q, q2)
  1882. 1869 ELSIF (op = SymTab.OpDiv)
  1883. 1870 OR (op = SymTab.OpSlash) THEN
  1884. 1871 QbeGen.Op3L("div", qt, q, q2)
  1885. 1872 ELSE
  1886. 1873 QbeGen.Op3L("rem", qt, q, q2)
  1887. 1874 END
  1888. 1875 ELSE
  1889. 1876 QbeGen.NewTemp(qt);
  1890. 1877 IF op = SymTab.OpTimes THEN
  1891. 1878 QbeGen.Op3("mul", qt, q, q2, isR)
  1892. 1879 ELSIF (op = SymTab.OpDiv)
  1893. 1880 OR (op = SymTab.OpSlash) THEN
  1894. 1881 QbeGen.Op3("div", qt, q, q2, isR)
  1895. 1882 ELSE
  1896. 1883 QbeGen.Op3("rem", qt, q, q2, isR)
  1897. 1884 END
  1898. 1885 END;
  1899. 1886 QbeGen.CopyOp(qt, q)
  1900. 1887 END
  1901. 1888 ELSE QbeGen.CopyOp("0", q)
  1902. 1889 END
  1903. 1890 END; .) } .
  1904. 1891 MulOp<VAR op: INTEGER>
  1905. 1892 = "*" (. op := SymTab.OpTimes; .)
  1906. 1893 | "/" (. op := SymTab.OpSlash; .)
  1907. 1894 | "DIV" (. op := SymTab.OpDiv; .)
  1908. 1895 | "MOD" (. op := SymTab.OpMod; .)
  1909. 1896 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
  1910. 1897 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  1911. 1898 (. VAR s: ARRAY [0 .. 255] OF CHAR;
  1912. 1899 et, dt, t2, st, ct2:
  1913. 1900 SymTab.TypeIndex;
  1914. 1901 dk: INTEGER;
  1915. 1902 qd, q2, sq, qa, qm0, qr:
  1916. 1903 QbeGen.QVal;
  1917. 1904 qn, vn: SymTab.Name;
  1918. 1905 vt: SymTab.TypeIndex;
  1919. 1906 c1, c2: INTEGER;
  1920. 1907 called, isHigh, sfx, isCh:
  1921. 1908 BOOLEAN; .)
  1922. 1909 = integer (. LexString(s);
  1923. 1910 QbeGen.NormInt(s, q);
  1924. 1911 t := SymTab.IntType(); .)
  1925. 1912 | charConst (. LexString(s);
  1926. 1913 QbeGen.NormLit(s, q, isCh);
  1927. 1914 t := SymTab.CharType(); .)
  1928. 1915 | real (. LexString(s);
  1929. 1916 QbeGen.NormReal(s, q);
  1930. 1917 t := SymTab.RealType(); .)
  1931. 1918 | string (. LexString(s);
  1932. 1919 IF SymTab.StrLen(s) = 3 THEN
  1933. 1920 t := SymTab.CharType();
  1934. 1921 QbeGen.IntStr(
  1935. 1922 QbeGen.CharVal(s), q)
  1936. 1923 ELSE t := SymTab.NewStr();
  1937. 1924 QbeGen.DeclStr(s, q);
  1938. 1925 (* a literal's value IS its
  1939. 1926 static descriptor address *)
  1940. 1927 QbeGen.NoteAddr(q, q)
  1941. 1928 END; .)
  1942. 1929 | Design<dt, dk, qd, qn, sfx> (. called := FALSE;
  1943. 1930 t := dt;
  1944. 1931 IF sfx THEN
  1945. 1932 IF dt =
  1946. 1933 SymTab.InvalidType THEN
  1947. 1934 QbeGen.CopyOp("0", q)
  1948. 1935 ELSIF (SymTab.ClassOf(dt) =
  1949. 1936 SymTab.ClRecord)
  1950. 1937 OR (SymTab.ClassOf(dt) =
  1951. 1938 SymTab.ClSet)
  1952. 1939 OR (SymTab.ClassOf(dt) =
  1953. 1940 SymTab.ClArray)
  1954. 1941 OR (SymTab.ClassOf(dt) =
  1955. 1942 SymTab.ClClass) THEN
  1956. 1943 QbeGen.CopyOp(qd, q)
  1957. 1944 ELSE QbeGen.ElemLoad(qd, dt,
  1958. 1945 q)
  1959. 1946 END
  1960. 1947 ELSE QbeGen.CopyOp(qd, q)
  1961. 1948 END;
  1962. 1949 IF (dk = SymTab.KindVar)
  1963. 1950 OR (dk = SymTab.KindParam)
  1964. 1951 OR (dk =
  1965. 1952 SymTab.KindField) THEN
  1966. 1953 IF sfx THEN
  1967. 1954 QbeGen.NoteAddr(q, qd)
  1968. 1955 ELSE
  1969. 1956 QbeGen.AddrOf(qn, qa);
  1970. 1957 QbeGen.NoteAddr(q, qa)
  1971. 1958 END
  1972. 1959 ELSIF sfx
  1973. 1960 AND (dt #
  1974. 1961 SymTab.InvalidType)
  1975. 1962 AND ((SymTab.ClassOf(dt) =
  1976. 1963 SymTab.ClArray)
  1977. 1964 OR (SymTab.ClassOf(dt) =
  1978. 1965 SymTab.ClSet)
  1979. 1966 OR (SymTab.ClassOf(dt) =
  1980. 1967 SymTab.ClRecord)) THEN
  1981. 1968 QbeGen.NoteAddr(qd, qd)
  1982. 1969 END; .)
  1983. 1970 [ TypedSetLit<dt, q> (. t := dt; .) ]
  1984. 1971 [ ArgList<qn, dt, qd, TRUE, ct2, q2, called>
  1985. 1972 (. t := ct2;
  1986. 1973 QbeGen.CopyOp(q2, q); .) ]
  1987. 1974 (. IF NOT called
  1988. 1975 AND (dk = SymTab.KindProc) THEN
  1989. 1976 (* bare zero-arg function
  1990. 1977 call (parentheses may be
  1991. 1978 omitted); a proper or
  1992. 1979 parameterised proc here
  1993. 1980 is 230 *)
  1994. 1981 IF (SymTab.ProcNPar(qn) = 0)
  1995. 1982 AND (SymTab.ProcRes(qn) #
  1996. 1983 SymTab.InvalidType) THEN
  1997. 1984 QbeGen.Mangled(qn,
  1998. 1985 SymTab.ProcUid(qn), qm0);
  1999. 1986 QbeGen.CallBegin(qm0,
  2000. 1987 SymTab.ProcRes(qn),
  2001. 1988 SymTab.ProcDepthOf(qn),
  2002. 1989 SymTab.IsExternal(qn));
  2003. 1990 QbeGen.CallEnd(TRUE, q);
  2004. 1991 t := SymTab.ProcRes(qn)
  2005. 1992 ELSE
  2006. 1993 (* procedure used as a
  2007. 1994 value (assign to a
  2008. 1995 procedure variable):
  2009. 1996 its code address *)
  2010. 1997 t := SymTab.ProcTypeOf(qn);
  2011. 1998 QbeGen.Mangled(qn,
  2012. 1999 SymTab.ProcUid(qn), qm0);
  2013. 2000 QbeGen.ProcAddr(qm0, q)
  2014. 2001 END
  2015. 2002 END; .)
  2016. 2003 | ( "HIGH" (. isHigh := TRUE; .)
  2017. 2004 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
  2018. 2005 "(" Design<dt, dk, qd, qn, sfx> ")"
  2019. 2006 (. IF dt = SymTab.InvalidType THEN
  2020. 2007 ELSIF SymTab.ClassOf(dt) #
  2021. 2008 SymTab.ClArray THEN
  2022. 2009 SemError(217);
  2023. 2010 t := SymTab.InvalidType;
  2024. 2011 QbeGen.CopyOp("0", q)
  2025. 2012 ELSE
  2026. 2013 IF isHigh THEN
  2027. 2014 IF SymTab.IsOpenArray(dt) THEN
  2028. 2015 QbeGen.OpenHi(qd, qr)
  2029. 2016 ELSE
  2030. 2017 QbeGen.IntStr(
  2031. 2018 SymTab.ArrayHi(dt), qr)
  2032. 2019 END
  2033. 2020 ELSE
  2034. 2021 IF SymTab.IsOpenArray(dt) THEN
  2035. 2022 QbeGen.LoadCount(qd, qr)
  2036. 2023 ELSE
  2037. 2024 QbeGen.IntStr(VAL(
  2038. 2025 INTEGER,
  2039. 2026 SymTab.ArrayLen(dt)),
  2040. 2027 qr)
  2041. 2028 END
  2042. 2029 END;
  2043. 2030 t := SymTab.IntType();
  2044. 2031 QbeGen.CopyOp(qr, q)
  2045. 2032 END; .)
  2046. 2033 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
  2047. 2034 (. IF dt = SymTab.InvalidType THEN
  2048. 2035 t := SymTab.InvalidType;
  2049. 2036 QbeGen.CopyOp("0", q)
  2050. 2037 ELSE
  2051. 2038 QbeGen.IntStr(VAL(INTEGER,
  2052. 2039 SymTab.ObjectSize(dt)), q);
  2053. 2040 t := SymTab.IntType()
  2054. 2041 END; .)
  2055. 2042 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
  2056. 2043 (. IF dt = SymTab.InvalidType THEN
  2057. 2044 t := SymTab.InvalidType;
  2058. 2045 QbeGen.CopyOp("0", q)
  2059. 2046 ELSE
  2060. 2047 IF sfx THEN
  2061. 2048 QbeGen.CopyOp(qd, q)
  2062. 2049 ELSIF (dk = SymTab.KindVar)
  2063. 2050 OR (dk = SymTab.KindParam) THEN
  2064. 2051 QbeGen.AddrOf(qn, q)
  2065. 2052 ELSE SemError(230);
  2066. 2053 QbeGen.CopyOp("0", q)
  2067. 2054 END;
  2068. 2055 t := SymTab.AddrType()
  2069. 2056 END; .)
  2070. 2057 | "CHR" "(" Expr<et, q> ")"
  2071. 2058 (. IF (et # SymTab.InvalidType)
  2072. 2059 AND NOT SymTab.IsIntFamily(et) THEN
  2073. 2060 SemError(211) END;
  2074. 2061 t := SymTab.CharType(); .)
  2075. 2062 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
  2076. 2063 (. IF et # SymTab.InvalidType THEN
  2077. 2064 IF (SymTab.ClassOf(et) #
  2078. 2065 SymTab.ClChar)
  2079. 2066 AND (SymTab.ClassOf(et) #
  2080. 2067 SymTab.ClBool)
  2081. 2068 AND (SymTab.ClassOf(et) #
  2082. 2069 SymTab.ClEnum)
  2083. 2070 AND NOT SymTab.IsIntFamily(et) THEN
  2084. 2071 SemError(211) END
  2085. 2072 END;
  2086. 2073 t := SymTab.IntType(); .)
  2087. 2074 | "CAP" "(" Expr<et, q> ")"
  2088. 2075 (. QbeGen.CapQ(q, qa);
  2089. 2076 QbeGen.CopyOp(qa, q);
  2090. 2077 t := SymTab.CharType(); .)
  2091. 2078 | "ABS" "(" Expr<et, q> ")"
  2092. 2079 (. IF (et # SymTab.InvalidType)
  2093. 2080 AND NOT SymTab.IsIntFamily(et)
  2094. 2081 AND (SymTab.ClassOf(et) #
  2095. 2082 SymTab.ClReal) THEN
  2096. 2083 SemError(211)
  2097. 2084 ELSE QbeGen.AbsQ(q, qa,
  2098. 2085 SymTab.ClassOf(et) =
  2099. 2086 SymTab.ClReal);
  2100. 2087 QbeGen.CopyOp(qa, q)
  2101. 2088 END;
  2102. 2089 t := et; .)
  2103. 2090 | "VAL" "(" GetIdent<vn> "," Expr<et, q> ")"
  2104. 2091 (. IF NOT SymTab.Lookup(vn) THEN
  2105. 2092 SemError(201);
  2106. 2093 t := SymTab.InvalidType
  2107. 2094 ELSE vt := SymTab.SymType(vn);
  2108. 2095 IF vt = SymTab.InvalidType THEN
  2109. 2096 t := SymTab.InvalidType
  2110. 2097 ELSIF et =
  2111. 2098 SymTab.InvalidType THEN
  2112. 2099 t := vt
  2113. 2100 ELSE
  2114. 2101 c1 := SymTab.ClassOf(et);
  2115. 2102 c2 := SymTab.ClassOf(vt);
  2116. 2103 IF ((c1 = SymTab.ClInt)
  2117. 2104 OR (c1 =
  2118. 2105 SymTab.ClChar)
  2119. 2106 OR (c1 =
  2120. 2107 SymTab.ClBool)
  2121. 2108 OR (c1 =
  2122. 2109 SymTab.ClEnum))
  2123. 2110 AND ((c2 = SymTab.ClInt)
  2124. 2111 OR (c2 =
  2125. 2112 SymTab.ClChar)
  2126. 2113 OR (c2 =
  2127. 2114 SymTab.ClBool)
  2128. 2115 OR (c2 =
  2129. 2116 SymTab.ClEnum)) THEN
  2130. 2117 t := vt
  2131. 2118 ELSIF (c1 = SymTab.ClPtr)
  2132. 2119 AND (c2 = SymTab.ClPtr) THEN
  2133. 2120 t := vt
  2134. 2121 ELSIF (c1 = SymTab.ClReal)
  2135. 2122 AND (c2 = SymTab.ClReal) THEN
  2136. 2123 t := vt
  2137. 2124 ELSE SemError(230);
  2138. 2125 t := SymTab.InvalidType
  2139. 2126 END
  2140. 2127 END
  2141. 2128 END; .)
  2142. 2129 | "(" Expr<et, q> ")" (. t := et; .)
  2143. 2130 | SetLit<st, sq> (. t := st;
  2144. 2131 QbeGen.CopyOp(sq, q); .)
  2145. 2132 | ( "NOT" | "~" ) Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
  2146. 2133 t := SymTab.BoolType()
  2147. 2134 ELSE SemError(212);
  2148. 2135 t := SymTab.InvalidType END;
  2149. 2136 IF t # SymTab.InvalidType THEN
  2150. 2137 QbeGen.NotQ(q2, q)
  2151. 2138 ELSE QbeGen.CopyOp("0", q)
  2152. 2139 END; .) .
  2153. 2140 (* Set literals are SET OF [0..255] (8 words); elements validated
  2154. 2141 0..255 statically when foldable (222 otherwise), runtime trap
  2155. 2142 for computed elements. Ranges always lower via SetRange. *)
  2156. 2143 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2157. 2144 = "{" (. t := SymTab.NewSet(
  2158. 2145 SymTab.NewSubR(0, 255));
  2159. 2146 QbeGen.NewSetTemp(8, q);
  2160. 2147 QbeGen.SetZero(q, 8); .)
  2161. 2148 [ SetElem<t, q> { "," SetElem<t, q> } ]
  2162. 2149 "}" .
  2163. 2150 (* Typed set constructor: TypeName{ elems } — e.g. BITSET{0},
  2164. 2151 BITSET{}. The declared type (not SET OF [0..255]) sets the
  2165. 2152 width and element span. *)
  2166. 2153 TypedSetLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2167. 2154 (. VAR nw: CARDINAL; .)
  2168. 2155 = "{" (. IF SymTab.ClassOf(vt) #
  2169. 2156 SymTab.ClSet THEN
  2170. 2157 SemError(230); nw := 8
  2171. 2158 ELSE nw := SymTab.SetWords(vt);
  2172. 2159 IF nw = 0 THEN nw := 8 END
  2173. 2160 END;
  2174. 2161 QbeGen.NewSetTemp(nw, q);
  2175. 2162 QbeGen.SetZero(q, nw); .)
  2176. 2163 [ SetElem<vt, q> { "," SetElem<vt, q> } ]
  2177. 2164 "}" .
  2178. 2165 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
  2179. 2166 qe, q2: QbeGen.QVal;
  2180. 2167 v, v2: INTEGER;
  2181. 2168 lo: INTEGER;
  2182. 2169 span: CARDINAL;
  2183. 2170 cl, cl2: INTEGER;
  2184. 2171 hasR: BOOLEAN; .)
  2185. 2172 = (. hasR := FALSE; .)
  2186. 2173 Expr<et, qe>
  2187. 2174 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
  2188. 2175 (. lo := SymTab.SetBaseLo(st);
  2189. 2176 span := SymTab.SetCount(st);
  2190. 2177 IF (et = SymTab.InvalidType)
  2191. 2178 OR (hasR AND (et2 =
  2192. 2179 SymTab.InvalidType)) THEN
  2193. 2180 ELSE cl :=
  2194. 2181 SymTab.ClassOf(et);
  2195. 2182 IF hasR THEN
  2196. 2183 cl2 :=
  2197. 2184 SymTab.ClassOf(et2)
  2198. 2185 ELSE cl2 := SymTab.ClInt
  2199. 2186 END;
  2200. 2187 IF ((cl # SymTab.ClInt)
  2201. 2188 AND (cl # SymTab.ClChar)
  2202. 2189 AND (cl # SymTab.ClBool))
  2203. 2190 OR (hasR AND
  2204. 2191 ((cl2
  2205. 2192 # SymTab.ClInt)
  2206. 2193 AND (cl2
  2207. 2194 # SymTab.ClChar)
  2208. 2195 AND (cl2
  2209. 2196 # SymTab.ClBool))) THEN
  2210. 2197 SemError(222)
  2211. 2198 ELSIF hasR
  2212. 2199 AND SymTab.ConstInt(qe, v)
  2213. 2200 AND SymTab.ConstInt(q2,
  2214. 2201 v2)
  2215. 2202 AND ((v < lo)
  2216. 2203 OR (v2 < lo)
  2217. 2204 OR (v >= lo +
  2218. 2205 VAL(INTEGER, span))
  2219. 2206 OR (v2 >= lo +
  2220. 2207 VAL(INTEGER, span))
  2221. 2208 OR (v > v2)) THEN
  2222. 2209 SemError(222)
  2223. 2210 ELSIF hasR THEN
  2224. 2211 QbeGen.SetRange(sq, qe, q2,
  2225. 2212 lo, span)
  2226. 2213 ELSIF SymTab.ConstInt(qe,
  2227. 2214 v)
  2228. 2215 AND ((v < lo)
  2229. 2216 OR (v >= lo +
  2230. 2217 VAL(INTEGER,
  2231. 2218 span))) THEN
  2232. 2219 SemError(222)
  2233. 2220 ELSE QbeGen.SetBit(sq, qe,
  2234. 2221 lo, span)
  2235. 2222 END
  2236. 2223 END; .) .
  2237. 2224 GetIdent<VAR n: SymTab.Name>
  2238. 2225 = ident (. LexName(n); .) .
  2239. 2226
  2240. 2227 END M2.
  2241. 0 errors
  2242. Statistics:
  2243. nr of terminals: 94 (limit 400)
  2244. nr of non-terminals: 78 (limit 210)
  2245. nr of pragmas: 0 (limit 406)
  2246. nr of symbolnodes: 172 (limit 500)
  2247. nr of graphnodes: 862 (limit 1500)
  2248. nr of conditionsets: 9 (limit 100)
  2249. nr of charactersets: 12 (limit 250)