M2.lst 142 KB

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