M2.lst 144 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303
  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 lTrue, lNext, lDone, qr, qs:
  1739. 1726 QbeGen.QVal; .)
  1740. 1727 = (. neg := FALSE; .)
  1741. 1728 [ "+" | "-" (. neg := TRUE; .) ]
  1742. 1729 Term<t, q> (. IF neg THEN
  1743. 1730 IF QbeGen.IsImm(q) THEN
  1744. 1731 QbeGen.NegFold(q, q)
  1745. 1732 ELSE QbeGen.NewTemp(qt);
  1746. 1733 QbeGen.NegQ(q, qt,
  1747. 1734 SymTab.ClassOf(t)
  1748. 1735 = SymTab.ClReal);
  1749. 1736 QbeGen.CopyOp(qt, q)
  1750. 1737 END
  1751. 1738 END; .)
  1752. 1739 { AddOp<op> (. IF op = SymTab.OpOr THEN
  1753. 1740 QbeGen.DelayBegin END; .)
  1754. 1741 Term<t2, q2> (. IF op = SymTab.OpOr THEN
  1755. 1742 QbeGen.DelayEnd END; .)
  1756. 1743 (. IF op = SymTab.OpOr THEN
  1757. 1744 (* short-circuit: if q is true the RHS is skipped *)
  1758. 1745 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
  1759. 1746 t := SymTab.BoolType()
  1760. 1747 ELSE SemError(212); t := SymTab.InvalidType END;
  1761. 1748 IF t # SymTab.InvalidType THEN
  1762. 1749 QbeGen.Slot4(qs);
  1763. 1750 QbeGen.NewLabel(lTrue);
  1764. 1751 QbeGen.NewLabel(lNext);
  1765. 1752 QbeGen.NewLabel(lDone);
  1766. 1753 QbeGen.Jnz(q, lTrue, lNext);
  1767. 1754 QbeGen.EmitLabel(lTrue);
  1768. 1755 QbeGen.StoreW(qs, "1");
  1769. 1756 QbeGen.Jmp(lDone);
  1770. 1757 QbeGen.EmitLabel(lNext);
  1771. 1758 QbeGen.DelayFlush;
  1772. 1759 QbeGen.StoreW(qs, q2);
  1773. 1760 QbeGen.Jmp(lDone);
  1774. 1761 QbeGen.EmitLabel(lDone);
  1775. 1762 QbeGen.LoadW(qs, qr);
  1776. 1763 QbeGen.CopyOp(qr, q)
  1777. 1764 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
  1778. 1765 END
  1779. 1766 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
  1780. 1767 AND (SymTab.ClassOf(t) = SymTab.ClSet)
  1781. 1768 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  1782. 1769 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
  1783. 1770 mw := lw;
  1784. 1771 IF rw > mw THEN mw := rw END;
  1785. 1772 IF op = SymTab.OpAdd THEN
  1786. 1773 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
  1787. 1774 ELSE
  1788. 1775 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
  1789. 1776 END;
  1790. 1777 t := SymTab.NewSet(
  1791. 1778 SymTab.NewSubR(0,
  1792. 1779 VAL(INTEGER, mw) * 32 - 1));
  1793. 1780 QbeGen.CopyOp(qt, q)
  1794. 1781 ELSE
  1795. 1782 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
  1796. 1783 lt := t; rt := t2; t := res2
  1797. 1784 ELSE SemError(211); t := SymTab.InvalidType END;
  1798. 1785 IF t # SymTab.InvalidType THEN
  1799. 1786 isL := SymTab.IsLongFamily(t);
  1800. 1787 isR := SymTab.ClassOf(t) = SymTab.ClReal;
  1801. 1788 folded := FALSE;
  1802. 1789 IF (NOT isL) AND (NOT isR)
  1803. 1790 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
  1804. 1791 IF op = SymTab.OpAdd THEN
  1805. 1792 folded := QbeGen.Fold2(0, q, q2, qf)
  1806. 1793 ELSE
  1807. 1794 folded := QbeGen.Fold2(1, q, q2, qf)
  1808. 1795 END
  1809. 1796 END;
  1810. 1797 IF folded THEN QbeGen.CopyOp(qf, q)
  1811. 1798 ELSE
  1812. 1799 IF isL THEN
  1813. 1800 IF SymTab.IsIntFamily(lt) THEN
  1814. 1801 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
  1815. 1802 END;
  1816. 1803 IF SymTab.IsIntFamily(rt) THEN
  1817. 1804 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
  1818. 1805 END;
  1819. 1806 QbeGen.NewTemp(qt);
  1820. 1807 IF op = SymTab.OpAdd THEN
  1821. 1808 QbeGen.Op3L("add", qt, q, q2)
  1822. 1809 ELSE
  1823. 1810 QbeGen.Op3L("sub", qt, q, q2)
  1824. 1811 END
  1825. 1812 ELSE
  1826. 1813 QbeGen.NewTemp(qt);
  1827. 1814 IF op = SymTab.OpAdd THEN
  1828. 1815 QbeGen.Op3("add", qt, q, q2, isR)
  1829. 1816 ELSE
  1830. 1817 QbeGen.Op3("sub", qt, q, q2, isR)
  1831. 1818 END
  1832. 1819 END;
  1833. 1820 QbeGen.CopyOp(qt, q)
  1834. 1821 END
  1835. 1822 ELSE QbeGen.CopyOp("0", q)
  1836. 1823 END
  1837. 1824 END; .) } .
  1838. 1825 AddOp<VAR op: INTEGER>
  1839. 1826 = "+" (. op := SymTab.OpAdd; .)
  1840. 1827 | "-" (. op := SymTab.OpSub; .)
  1841. 1828 | "OR" (. op := SymTab.OpOr; .) .
  1842. 1829 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  1843. 1830 (. VAR t2, res2, lt, rt:
  1844. 1831 SymTab.TypeIndex;
  1845. 1832 op: INTEGER;
  1846. 1833 q2, qt, wq, qf:
  1847. 1834 QbeGen.QVal;
  1848. 1835 isR, isL, folded: BOOLEAN;
  1849. 1836 lw, rw, mw: CARDINAL;
  1850. 1837 lNext, lFalse, lDone, qr, qs:
  1851. 1838 QbeGen.QVal; .)
  1852. 1839 = Fact<t, q> { MulOp<op> (. IF op = SymTab.OpAnd THEN
  1853. 1840 QbeGen.DelayBegin END; .)
  1854. 1841 Fact<t2, q2> (. IF op = SymTab.OpAnd THEN
  1855. 1842 QbeGen.DelayEnd END; .)
  1856. 1843 (. IF op = SymTab.OpAnd THEN
  1857. 1844 (* short-circuit: if q is false the RHS is skipped *)
  1858. 1845 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
  1859. 1846 t := SymTab.BoolType()
  1860. 1847 ELSE SemError(212); t := SymTab.InvalidType END;
  1861. 1848 IF t # SymTab.InvalidType THEN
  1862. 1849 QbeGen.Slot4(qs);
  1863. 1850 QbeGen.NewLabel(lNext);
  1864. 1851 QbeGen.NewLabel(lFalse);
  1865. 1852 QbeGen.NewLabel(lDone);
  1866. 1853 QbeGen.Jnz(q, lNext, lFalse);
  1867. 1854 QbeGen.EmitLabel(lNext);
  1868. 1855 QbeGen.DelayFlush;
  1869. 1856 QbeGen.StoreW(qs, q2);
  1870. 1857 QbeGen.Jmp(lDone);
  1871. 1858 QbeGen.EmitLabel(lFalse);
  1872. 1859 QbeGen.StoreW(qs, "0");
  1873. 1860 QbeGen.Jmp(lDone);
  1874. 1861 QbeGen.EmitLabel(lDone);
  1875. 1862 QbeGen.LoadW(qs, qr);
  1876. 1863 QbeGen.CopyOp(qr, q)
  1877. 1864 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
  1878. 1865 END
  1879. 1866 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
  1880. 1867 AND (SymTab.ClassOf(t) = SymTab.ClSet)
  1881. 1868 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
  1882. 1869 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
  1883. 1870 mw := lw;
  1884. 1871 IF rw > mw THEN mw := rw END;
  1885. 1872 IF op = SymTab.OpTimes THEN
  1886. 1873 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
  1887. 1874 ELSE
  1888. 1875 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
  1889. 1876 END;
  1890. 1877 t := SymTab.NewSet(
  1891. 1878 SymTab.NewSubR(0,
  1892. 1879 VAL(INTEGER, mw) * 32 - 1));
  1893. 1880 QbeGen.CopyOp(qt, q)
  1894. 1881 ELSE
  1895. 1882 IF SymTab.ArithCheck(t, t2,
  1896. 1883 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
  1897. 1884 res2) THEN
  1898. 1885 lt := t; rt := t2; t := res2
  1899. 1886 ELSE SemError(211); t := SymTab.InvalidType END;
  1900. 1887 IF t # SymTab.InvalidType THEN
  1901. 1888 isL := SymTab.IsLongFamily(t);
  1902. 1889 isR := SymTab.ClassOf(t) = SymTab.ClReal;
  1903. 1890 folded := FALSE;
  1904. 1891 IF (NOT isL) AND (NOT isR)
  1905. 1892 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
  1906. 1893 IF op = SymTab.OpTimes THEN
  1907. 1894 folded := QbeGen.Fold2(2, q, q2, qf)
  1908. 1895 ELSIF op = SymTab.OpDiv THEN
  1909. 1896 folded := QbeGen.Fold2(3, q, q2, qf)
  1910. 1897 ELSIF op = SymTab.OpMod THEN
  1911. 1898 folded := QbeGen.Fold2(4, q, q2, qf)
  1912. 1899 END
  1913. 1900 END;
  1914. 1901 IF folded THEN QbeGen.CopyOp(qf, q)
  1915. 1902 ELSE
  1916. 1903 IF isL THEN
  1917. 1904 IF SymTab.IsIntFamily(lt) THEN
  1918. 1905 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
  1919. 1906 END;
  1920. 1907 IF SymTab.IsIntFamily(rt) THEN
  1921. 1908 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
  1922. 1909 END;
  1923. 1910 QbeGen.NewTemp(qt);
  1924. 1911 IF op = SymTab.OpTimes THEN
  1925. 1912 QbeGen.Op3L("mul", qt, q, q2)
  1926. 1913 ELSIF (op = SymTab.OpDiv)
  1927. 1914 OR (op = SymTab.OpSlash) THEN
  1928. 1915 QbeGen.Op3L("div", qt, q, q2)
  1929. 1916 ELSE
  1930. 1917 QbeGen.Op3L("rem", qt, q, q2)
  1931. 1918 END
  1932. 1919 ELSE
  1933. 1920 QbeGen.NewTemp(qt);
  1934. 1921 IF op = SymTab.OpTimes THEN
  1935. 1922 QbeGen.Op3("mul", qt, q, q2, isR)
  1936. 1923 ELSIF (op = SymTab.OpDiv)
  1937. 1924 OR (op = SymTab.OpSlash) THEN
  1938. 1925 QbeGen.Op3("div", qt, q, q2, isR)
  1939. 1926 ELSE
  1940. 1927 QbeGen.Op3("rem", qt, q, q2, isR)
  1941. 1928 END
  1942. 1929 END;
  1943. 1930 QbeGen.CopyOp(qt, q)
  1944. 1931 END
  1945. 1932 ELSE QbeGen.CopyOp("0", q)
  1946. 1933 END
  1947. 1934 END; .) } .
  1948. 1935 MulOp<VAR op: INTEGER>
  1949. 1936 = "*" (. op := SymTab.OpTimes; .)
  1950. 1937 | "/" (. op := SymTab.OpSlash; .)
  1951. 1938 | "DIV" (. op := SymTab.OpDiv; .)
  1952. 1939 | "MOD" (. op := SymTab.OpMod; .)
  1953. 1940 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
  1954. 1941 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  1955. 1942 (. VAR s: ARRAY [0 .. 255] OF CHAR;
  1956. 1943 et, dt, t2, st, ct2:
  1957. 1944 SymTab.TypeIndex;
  1958. 1945 dk: INTEGER;
  1959. 1946 qd, q2, sq, qa, qm0, qr:
  1960. 1947 QbeGen.QVal;
  1961. 1948 qn, vn: SymTab.Name;
  1962. 1949 vt: SymTab.TypeIndex;
  1963. 1950 c1, c2: INTEGER;
  1964. 1951 called, isHigh, sfx, isCh:
  1965. 1952 BOOLEAN; .)
  1966. 1953 = integer (. LexString(s);
  1967. 1954 QbeGen.NormInt(s, q);
  1968. 1955 t := SymTab.IntType(); .)
  1969. 1956 | charConst (. LexString(s);
  1970. 1957 QbeGen.NormLit(s, q, isCh);
  1971. 1958 t := SymTab.CharType(); .)
  1972. 1959 | real (. LexString(s);
  1973. 1960 QbeGen.NormReal(s, q);
  1974. 1961 t := SymTab.RealType(); .)
  1975. 1962 | string (. LexString(s);
  1976. 1963 IF SymTab.StrLen(s) = 3 THEN
  1977. 1964 t := SymTab.CharType();
  1978. 1965 QbeGen.IntStr(
  1979. 1966 QbeGen.CharVal(s), q)
  1980. 1967 ELSE t := SymTab.NewStr();
  1981. 1968 QbeGen.DeclStr(s, q);
  1982. 1969 (* a literal's value IS its
  1983. 1970 static descriptor address *)
  1984. 1971 QbeGen.NoteAddr(q, q)
  1985. 1972 END; .)
  1986. 1973 | Design<dt, dk, qd, qn, sfx> (. called := FALSE;
  1987. 1974 t := dt;
  1988. 1975 IF sfx THEN
  1989. 1976 IF dt =
  1990. 1977 SymTab.InvalidType THEN
  1991. 1978 QbeGen.CopyOp("0", q)
  1992. 1979 ELSIF (SymTab.ClassOf(dt) =
  1993. 1980 SymTab.ClRecord)
  1994. 1981 OR (SymTab.ClassOf(dt) =
  1995. 1982 SymTab.ClSet)
  1996. 1983 OR (SymTab.ClassOf(dt) =
  1997. 1984 SymTab.ClArray)
  1998. 1985 OR (SymTab.ClassOf(dt) =
  1999. 1986 SymTab.ClClass) THEN
  2000. 1987 QbeGen.CopyOp(qd, q)
  2001. 1988 ELSE QbeGen.ElemLoad(qd, dt,
  2002. 1989 q)
  2003. 1990 END
  2004. 1991 ELSE QbeGen.CopyOp(qd, q)
  2005. 1992 END;
  2006. 1993 IF (dk = SymTab.KindVar)
  2007. 1994 OR (dk = SymTab.KindParam)
  2008. 1995 OR (dk =
  2009. 1996 SymTab.KindField) THEN
  2010. 1997 IF sfx THEN
  2011. 1998 QbeGen.NoteAddr(q, qd)
  2012. 1999 ELSE
  2013. 2000 QbeGen.AddrOf(qn, qa);
  2014. 2001 QbeGen.NoteAddr(q, qa)
  2015. 2002 END
  2016. 2003 ELSIF sfx
  2017. 2004 AND (dt #
  2018. 2005 SymTab.InvalidType)
  2019. 2006 AND ((SymTab.ClassOf(dt) =
  2020. 2007 SymTab.ClArray)
  2021. 2008 OR (SymTab.ClassOf(dt) =
  2022. 2009 SymTab.ClSet)
  2023. 2010 OR (SymTab.ClassOf(dt) =
  2024. 2011 SymTab.ClRecord)) THEN
  2025. 2012 QbeGen.NoteAddr(qd, qd)
  2026. 2013 END; .)
  2027. 2014 [ TypedSetLit<dt, q> (. t := dt; .) ]
  2028. 2015 [ ArgList<qn, dt, qd, TRUE, ct2, q2, called>
  2029. 2016 (. t := ct2;
  2030. 2017 QbeGen.CopyOp(q2, q); .) ]
  2031. 2018 (. IF NOT called
  2032. 2019 AND (dk = SymTab.KindProc) THEN
  2033. 2020 (* bare zero-arg function
  2034. 2021 call (parentheses may be
  2035. 2022 omitted); a proper or
  2036. 2023 parameterised proc here
  2037. 2024 is 230 *)
  2038. 2025 IF (SymTab.ProcNPar(qn) = 0)
  2039. 2026 AND (SymTab.ProcRes(qn) #
  2040. 2027 SymTab.InvalidType) THEN
  2041. 2028 QbeGen.Mangled(qn,
  2042. 2029 SymTab.ProcUid(qn), qm0);
  2043. 2030 QbeGen.CallBegin(qm0,
  2044. 2031 SymTab.ProcRes(qn),
  2045. 2032 SymTab.ProcDepthOf(qn),
  2046. 2033 SymTab.IsExternal(qn));
  2047. 2034 QbeGen.CallEnd(TRUE, q);
  2048. 2035 t := SymTab.ProcRes(qn)
  2049. 2036 ELSE
  2050. 2037 (* procedure used as a
  2051. 2038 value (assign to a
  2052. 2039 procedure variable):
  2053. 2040 its code address *)
  2054. 2041 t := SymTab.ProcTypeOf(qn);
  2055. 2042 QbeGen.Mangled(qn,
  2056. 2043 SymTab.ProcUid(qn), qm0);
  2057. 2044 QbeGen.ProcAddr(qm0, q)
  2058. 2045 END
  2059. 2046 END; .)
  2060. 2047 | ( "HIGH" (. isHigh := TRUE; .)
  2061. 2048 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
  2062. 2049 "(" Design<dt, dk, qd, qn, sfx> ")"
  2063. 2050 (. IF dt = SymTab.InvalidType THEN
  2064. 2051 ELSIF SymTab.ClassOf(dt) #
  2065. 2052 SymTab.ClArray THEN
  2066. 2053 SemError(217);
  2067. 2054 t := SymTab.InvalidType;
  2068. 2055 QbeGen.CopyOp("0", q)
  2069. 2056 ELSE
  2070. 2057 IF isHigh THEN
  2071. 2058 IF SymTab.IsOpenArray(dt) THEN
  2072. 2059 QbeGen.OpenHi(qd, qr)
  2073. 2060 ELSE
  2074. 2061 QbeGen.IntStr(
  2075. 2062 SymTab.ArrayHi(dt), qr)
  2076. 2063 END
  2077. 2064 ELSE
  2078. 2065 IF SymTab.IsOpenArray(dt) THEN
  2079. 2066 QbeGen.LoadCount(qd, qr)
  2080. 2067 ELSE
  2081. 2068 QbeGen.IntStr(VAL(
  2082. 2069 INTEGER,
  2083. 2070 SymTab.ArrayLen(dt)),
  2084. 2071 qr)
  2085. 2072 END
  2086. 2073 END;
  2087. 2074 t := SymTab.IntType();
  2088. 2075 QbeGen.CopyOp(qr, q)
  2089. 2076 END; .)
  2090. 2077 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
  2091. 2078 (. IF dt = SymTab.InvalidType THEN
  2092. 2079 t := SymTab.InvalidType;
  2093. 2080 QbeGen.CopyOp("0", q)
  2094. 2081 ELSE
  2095. 2082 QbeGen.IntStr(VAL(INTEGER,
  2096. 2083 SymTab.ObjectSize(dt)), q);
  2097. 2084 t := SymTab.IntType()
  2098. 2085 END; .)
  2099. 2086 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
  2100. 2087 (. IF dt = SymTab.InvalidType THEN
  2101. 2088 t := SymTab.InvalidType;
  2102. 2089 QbeGen.CopyOp("0", q)
  2103. 2090 ELSE
  2104. 2091 IF sfx THEN
  2105. 2092 QbeGen.CopyOp(qd, q)
  2106. 2093 ELSIF (dk = SymTab.KindVar)
  2107. 2094 OR (dk = SymTab.KindParam) THEN
  2108. 2095 QbeGen.AddrOf(qn, q)
  2109. 2096 ELSE SemError(230);
  2110. 2097 QbeGen.CopyOp("0", q)
  2111. 2098 END;
  2112. 2099 t := SymTab.AddrType()
  2113. 2100 END; .)
  2114. 2101 | "CHR" "(" Expr<et, q> ")"
  2115. 2102 (. IF (et # SymTab.InvalidType)
  2116. 2103 AND NOT SymTab.IsIntFamily(et) THEN
  2117. 2104 SemError(211) END;
  2118. 2105 t := SymTab.CharType(); .)
  2119. 2106 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
  2120. 2107 (. IF et # SymTab.InvalidType THEN
  2121. 2108 IF (SymTab.ClassOf(et) #
  2122. 2109 SymTab.ClChar)
  2123. 2110 AND (SymTab.ClassOf(et) #
  2124. 2111 SymTab.ClBool)
  2125. 2112 AND (SymTab.ClassOf(et) #
  2126. 2113 SymTab.ClEnum)
  2127. 2114 AND NOT SymTab.IsIntFamily(et) THEN
  2128. 2115 SemError(211) END
  2129. 2116 END;
  2130. 2117 t := SymTab.IntType(); .)
  2131. 2118 | "CAP" "(" Expr<et, q> ")"
  2132. 2119 (. QbeGen.CapQ(q, qa);
  2133. 2120 QbeGen.CopyOp(qa, q);
  2134. 2121 t := SymTab.CharType(); .)
  2135. 2122 | "ABS" "(" Expr<et, q> ")"
  2136. 2123 (. IF (et # SymTab.InvalidType)
  2137. 2124 AND NOT SymTab.IsIntFamily(et)
  2138. 2125 AND (SymTab.ClassOf(et) #
  2139. 2126 SymTab.ClReal) THEN
  2140. 2127 SemError(211)
  2141. 2128 ELSE QbeGen.AbsQ(q, qa,
  2142. 2129 SymTab.ClassOf(et) =
  2143. 2130 SymTab.ClReal);
  2144. 2131 QbeGen.CopyOp(qa, q)
  2145. 2132 END;
  2146. 2133 t := et; .)
  2147. 2134 | "VAL" "(" GetIdent<vn> "," Expr<et, q> ")"
  2148. 2135 (. IF NOT SymTab.Lookup(vn) THEN
  2149. 2136 SemError(201);
  2150. 2137 t := SymTab.InvalidType
  2151. 2138 ELSE vt := SymTab.SymType(vn);
  2152. 2139 IF vt = SymTab.InvalidType THEN
  2153. 2140 t := SymTab.InvalidType
  2154. 2141 ELSIF et =
  2155. 2142 SymTab.InvalidType THEN
  2156. 2143 t := vt
  2157. 2144 ELSE
  2158. 2145 c1 := SymTab.ClassOf(et);
  2159. 2146 c2 := SymTab.ClassOf(vt);
  2160. 2147 IF ((c1 = SymTab.ClInt)
  2161. 2148 OR (c1 =
  2162. 2149 SymTab.ClChar)
  2163. 2150 OR (c1 =
  2164. 2151 SymTab.ClBool)
  2165. 2152 OR (c1 =
  2166. 2153 SymTab.ClEnum))
  2167. 2154 AND ((c2 = SymTab.ClInt)
  2168. 2155 OR (c2 =
  2169. 2156 SymTab.ClChar)
  2170. 2157 OR (c2 =
  2171. 2158 SymTab.ClBool)
  2172. 2159 OR (c2 =
  2173. 2160 SymTab.ClEnum)) THEN
  2174. 2161 t := vt
  2175. 2162 ELSIF (c1 = SymTab.ClPtr)
  2176. 2163 AND (c2 = SymTab.ClPtr) THEN
  2177. 2164 t := vt
  2178. 2165 ELSIF (c1 = SymTab.ClReal)
  2179. 2166 AND (c2 = SymTab.ClReal) THEN
  2180. 2167 t := vt
  2181. 2168 ELSE SemError(230);
  2182. 2169 t := SymTab.InvalidType
  2183. 2170 END
  2184. 2171 END
  2185. 2172 END; .)
  2186. 2173 | "(" Expr<et, q> ")" (. t := et; .)
  2187. 2174 | SetLit<st, sq> (. t := st;
  2188. 2175 QbeGen.CopyOp(sq, q); .)
  2189. 2176 | ( "NOT" | "~" ) Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
  2190. 2177 t := SymTab.BoolType()
  2191. 2178 ELSE SemError(212);
  2192. 2179 t := SymTab.InvalidType END;
  2193. 2180 IF t # SymTab.InvalidType THEN
  2194. 2181 QbeGen.NotQ(q2, q)
  2195. 2182 ELSE QbeGen.CopyOp("0", q)
  2196. 2183 END; .) .
  2197. 2184 (* Set literals are SET OF [0..255] (8 words); elements validated
  2198. 2185 0..255 statically when foldable (222 otherwise), runtime trap
  2199. 2186 for computed elements. Ranges always lower via SetRange. *)
  2200. 2187 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2201. 2188 = "{" (. t := SymTab.NewSet(
  2202. 2189 SymTab.NewSubR(0, 255));
  2203. 2190 QbeGen.NewSetTemp(8, q);
  2204. 2191 QbeGen.SetZero(q, 8); .)
  2205. 2192 [ SetElem<t, q> { "," SetElem<t, q> } ]
  2206. 2193 "}" .
  2207. 2194 (* Typed set constructor: TypeName{ elems } — e.g. BITSET{0},
  2208. 2195 BITSET{}. The declared type (not SET OF [0..255]) sets the
  2209. 2196 width and element span. *)
  2210. 2197 TypedSetLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  2211. 2198 (. VAR nw: CARDINAL; .)
  2212. 2199 = "{" (. IF SymTab.ClassOf(vt) #
  2213. 2200 SymTab.ClSet THEN
  2214. 2201 SemError(230); nw := 8
  2215. 2202 ELSE nw := SymTab.SetWords(vt);
  2216. 2203 IF nw = 0 THEN nw := 8 END
  2217. 2204 END;
  2218. 2205 QbeGen.NewSetTemp(nw, q);
  2219. 2206 QbeGen.SetZero(q, nw); .)
  2220. 2207 [ SetElem<vt, q> { "," SetElem<vt, q> } ]
  2221. 2208 "}" .
  2222. 2209 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
  2223. 2210 qe, q2: QbeGen.QVal;
  2224. 2211 v, v2: INTEGER;
  2225. 2212 lo: INTEGER;
  2226. 2213 span: CARDINAL;
  2227. 2214 cl, cl2: INTEGER;
  2228. 2215 hasR: BOOLEAN; .)
  2229. 2216 = (. hasR := FALSE; .)
  2230. 2217 Expr<et, qe>
  2231. 2218 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
  2232. 2219 (. lo := SymTab.SetBaseLo(st);
  2233. 2220 span := SymTab.SetCount(st);
  2234. 2221 IF (et = SymTab.InvalidType)
  2235. 2222 OR (hasR AND (et2 =
  2236. 2223 SymTab.InvalidType)) THEN
  2237. 2224 ELSE cl :=
  2238. 2225 SymTab.ClassOf(et);
  2239. 2226 IF hasR THEN
  2240. 2227 cl2 :=
  2241. 2228 SymTab.ClassOf(et2)
  2242. 2229 ELSE cl2 := SymTab.ClInt
  2243. 2230 END;
  2244. 2231 IF ((cl # SymTab.ClInt)
  2245. 2232 AND (cl # SymTab.ClChar)
  2246. 2233 AND (cl # SymTab.ClBool))
  2247. 2234 OR (hasR AND
  2248. 2235 ((cl2
  2249. 2236 # SymTab.ClInt)
  2250. 2237 AND (cl2
  2251. 2238 # SymTab.ClChar)
  2252. 2239 AND (cl2
  2253. 2240 # SymTab.ClBool))) THEN
  2254. 2241 SemError(222)
  2255. 2242 ELSIF hasR
  2256. 2243 AND SymTab.ConstInt(qe, v)
  2257. 2244 AND SymTab.ConstInt(q2,
  2258. 2245 v2)
  2259. 2246 AND ((v < lo)
  2260. 2247 OR (v2 < lo)
  2261. 2248 OR (v >= lo +
  2262. 2249 VAL(INTEGER, span))
  2263. 2250 OR (v2 >= lo +
  2264. 2251 VAL(INTEGER, span))
  2265. 2252 OR (v > v2)) THEN
  2266. 2253 SemError(222)
  2267. 2254 ELSIF hasR THEN
  2268. 2255 QbeGen.SetRange(sq, qe, q2,
  2269. 2256 lo, span)
  2270. 2257 ELSIF SymTab.ConstInt(qe,
  2271. 2258 v)
  2272. 2259 AND ((v < lo)
  2273. 2260 OR (v >= lo +
  2274. 2261 VAL(INTEGER,
  2275. 2262 span))) THEN
  2276. 2263 SemError(222)
  2277. 2264 ELSE QbeGen.SetBit(sq, qe,
  2278. 2265 lo, span)
  2279. 2266 END
  2280. 2267 END; .) .
  2281. 2268 GetIdent<VAR n: SymTab.Name>
  2282. 2269 = ident (. LexName(n); .) .
  2283. 2270
  2284. 2271 END M2.
  2285. 0 errors
  2286. Statistics:
  2287. nr of terminals: 94 (limit 400)
  2288. nr of non-terminals: 78 (limit 210)
  2289. nr of pragmas: 0 (limit 406)
  2290. nr of symbolnodes: 172 (limit 500)
  2291. nr of graphnodes: 866 (limit 1500)
  2292. nr of conditionsets: 9 (limit 100)
  2293. nr of charactersets: 12 (limit 250)