M2.lst 118 KB

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