M2.lst 131 KB

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