M2.lst 116 KB

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