|
|
@@ -50,1042 +50,1217 @@ Listing:
|
|
|
33 with per-level checks (217/218, trap on breach via $abort);
|
|
|
34 whole-array ":=" with runtime count check + blit; string
|
|
|
35 literals lower as descriptors (1-char stays CHAR, empty works);
|
|
|
- 36 array/string "=" is 213 (no built-in whole comparison). *)
|
|
|
- 37
|
|
|
- 38 IMPORT SymTab, QbeGen;
|
|
|
- 39
|
|
|
- 40 CHARACTERS
|
|
|
- 41 eol = CHR(13) .
|
|
|
- 42 lf = CHR(10) .
|
|
|
- 43 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
- 44 digit = "0123456789" .
|
|
|
- 45 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
- 46 noQuote1 = ANY - "'" - eol .
|
|
|
- 47 noQuote2 = ANY - '"' - eol .
|
|
|
- 48
|
|
|
- 49 IGNORE CHR(9) .. CHR(13)
|
|
|
- 50
|
|
|
- 51 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
- 52 COMMENTS FROM "//" TO lf
|
|
|
- 53
|
|
|
- 54 TOKENS
|
|
|
- 55 ident = letter { letter | digit } .
|
|
|
- 56 integer = digit { digit }
|
|
|
- 57 | digit { digit } CONTEXT("..")
|
|
|
- 58 | "0x" hexDigit { hexDigit }
|
|
|
- 59 | "0X" hexDigit { hexDigit } .
|
|
|
- 60 real = digit { digit } "." { digit }
|
|
|
- 61 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
- 62 string = "'" { noQuote1 } "'"
|
|
|
- 63 | '"' { noQuote2 } '"' .
|
|
|
- 64
|
|
|
- 65 PRODUCTIONS
|
|
|
- 66 M2
|
|
|
- 67 = Unit "." .
|
|
|
- 68 (* Units: program modules compile fully; DEFINITION and
|
|
|
- 69 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
- 70 (each ends with one 230); same for nested local modules. *)
|
|
|
- 71 Unit
|
|
|
- 72 = DefUnit
|
|
|
- 73 | ImplUnit
|
|
|
- 74 | ProgModule .
|
|
|
- 75 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
- 76 = "DEFINITION" "MODULE"
|
|
|
- 77 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
- 78 IF ~SymTab.Enter(m1,
|
|
|
- 79 SymTab.KindModule) THEN
|
|
|
- 80 SemError(200) END; .)
|
|
|
- 81 ";"
|
|
|
- 82 { Import }
|
|
|
- 83 { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
- 84 | ProcHeading<pn> ";" (. SymTab.CloseProc; .) }
|
|
|
- 85 "END"
|
|
|
- 86 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
- 87 SemError(202) END; .)
|
|
|
- 88 (. QbeGen.CloseModule;
|
|
|
- 89 SemError(230);
|
|
|
- 90 SymTab.PrintTable; .) .
|
|
|
- 91 ImplUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
- 92 = "IMPLEMENTATION" "MODULE"
|
|
|
- 93 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
- 94 IF ~SymTab.Enter(m1,
|
|
|
- 95 SymTab.KindModule) THEN
|
|
|
- 96 SemError(200) END; .)
|
|
|
- 97 ";"
|
|
|
- 98 { Import }
|
|
|
- 99 DeclSeq
|
|
|
- 100 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
- 101 [ StatSeq ] ]
|
|
|
- 102 "END"
|
|
|
- 103 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
- 104 SemError(202) END; .)
|
|
|
- 105 (. QbeGen.CloseModule;
|
|
|
- 106 SemError(230);
|
|
|
- 107 SymTab.PrintTable; .) .
|
|
|
- 108 ProgModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
- 109 = "MODULE"
|
|
|
- 110 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
- 111 IF ~SymTab.Enter(m1,
|
|
|
- 112 SymTab.KindModule) THEN
|
|
|
- 113 SemError(200) END; .)
|
|
|
- 114 [ Priority ]
|
|
|
- 115 ";"
|
|
|
- 116 { Import }
|
|
|
- 117 DeclSeq
|
|
|
- 118 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
- 119 [ StatSeq ] ]
|
|
|
- 120 "END"
|
|
|
- 121 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
- 122 SemError(202) END; .)
|
|
|
- 123 (. QbeGen.EndModule;
|
|
|
- 124 SymTab.PrintTable; .) .
|
|
|
- 125 DeclSeq
|
|
|
- 126 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
- 127 | NestedModule ";" | ClassItem ";" } .
|
|
|
- 128 (* Local module, Wirth form. Parses + checks fully (own scope);
|
|
|
- 129 lowering waits for step 4, marked by one 230 at END. *)
|
|
|
- 130 NestedModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
- 131 = "MODULE"
|
|
|
- 132 GetIdent<m1> (. IF ~SymTab.Enter(m1,
|
|
|
- 133 SymTab.KindModule) THEN
|
|
|
- 134 SemError(200) END;
|
|
|
- 135 SymTab.PushScope; .)
|
|
|
- 136 [ Priority ]
|
|
|
- 137 ";"
|
|
|
- 138 { Import }
|
|
|
- 139 [ Export ]
|
|
|
- 140 DeclSeq
|
|
|
- 141 [ "BEGIN"
|
|
|
- 142 [ StatSeq ] ]
|
|
|
- 143 "END"
|
|
|
- 144 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
- 145 SemError(202) END;
|
|
|
- 146 SymTab.PopScope;
|
|
|
- 147 SemError(230); .) .
|
|
|
- 148 Priority
|
|
|
- 149 = "[" integer "]" (. SemError(230); .) .
|
|
|
- 150 Export (. VAR nm: SymTab.Name; .)
|
|
|
- 151 = "EXPORT" (* names wire up in step 4 *)
|
|
|
- 152 [ "QUALIFIED" ]
|
|
|
- 153 GetIdent<nm>
|
|
|
- 154 { "," GetIdent<nm> }
|
|
|
- 155 ";" .
|
|
|
- 156 Import (. VAR n: SymTab.Name; .)
|
|
|
- 157 = "FROM"
|
|
|
- 158 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
- 159 SymTab.KindImport) THEN
|
|
|
- 160 SemError(200) END; .)
|
|
|
- 161 "IMPORT"
|
|
|
- 162 ImpList ";"
|
|
|
- 163 | "IMPORT"
|
|
|
- 164 ImpList ";" .
|
|
|
- 165 ImpList (. VAR n: SymTab.Name; .)
|
|
|
- 166 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
- 167 SymTab.KindImport) THEN
|
|
|
- 168 SemError(200) END; .)
|
|
|
- 169 { ","
|
|
|
- 170 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ 36 array/string "=" is 213 (no built-in whole comparison).
|
|
|
+ 37 Step 3.3 sets: multi-word masks (no header, static words) over
|
|
|
+ 38 bases ≤ 256 values; literals are SET OF [0..255] (222 on
|
|
|
+ 39 out-of-span); + - * / as or/and/xor-not, IN with span trap,
|
|
|
+ 40 =/# word-wise (lenient cross-base); CASE labels reject sets. *)
|
|
|
+ 41
|
|
|
+ 42 IMPORT SymTab, QbeGen;
|
|
|
+ 43
|
|
|
+ 44 CHARACTERS
|
|
|
+ 45 eol = CHR(13) .
|
|
|
+ 46 lf = CHR(10) .
|
|
|
+ 47 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
+ 48 digit = "0123456789" .
|
|
|
+ 49 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
+ 50 noQuote1 = ANY - "'" - eol .
|
|
|
+ 51 noQuote2 = ANY - '"' - eol .
|
|
|
+ 52
|
|
|
+ 53 IGNORE CHR(9) .. CHR(13)
|
|
|
+ 54
|
|
|
+ 55 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
+ 56 COMMENTS FROM "//" TO lf
|
|
|
+ 57
|
|
|
+ 58 TOKENS
|
|
|
+ 59 ident = letter { letter | digit } .
|
|
|
+ 60 integer = digit { digit }
|
|
|
+ 61 | digit { digit } CONTEXT("..")
|
|
|
+ 62 | "0x" hexDigit { hexDigit }
|
|
|
+ 63 | "0X" hexDigit { hexDigit } .
|
|
|
+ 64 real = digit { digit } "." { digit }
|
|
|
+ 65 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
+ 66 string = "'" { noQuote1 } "'"
|
|
|
+ 67 | '"' { noQuote2 } '"' .
|
|
|
+ 68
|
|
|
+ 69 PRODUCTIONS
|
|
|
+ 70 M2
|
|
|
+ 71 = Unit "." .
|
|
|
+ 72 (* Units: program modules compile fully; DEFINITION and
|
|
|
+ 73 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
+ 74 (each ends with one 230); same for nested local modules. *)
|
|
|
+ 75 Unit
|
|
|
+ 76 = DefUnit
|
|
|
+ 77 | ImplUnit
|
|
|
+ 78 | ProgModule .
|
|
|
+ 79 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
+ 80 = "DEFINITION" "MODULE"
|
|
|
+ 81 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
+ 82 IF ~SymTab.Enter(m1,
|
|
|
+ 83 SymTab.KindModule) THEN
|
|
|
+ 84 SemError(200) END; .)
|
|
|
+ 85 ";"
|
|
|
+ 86 { Import }
|
|
|
+ 87 { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
+ 88 | ProcHeading<pn> ";" (. SymTab.CloseProc; .) }
|
|
|
+ 89 "END"
|
|
|
+ 90 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
+ 91 SemError(202) END; .)
|
|
|
+ 92 (. QbeGen.CloseModule;
|
|
|
+ 93 SemError(230);
|
|
|
+ 94 SymTab.PrintTable; .) .
|
|
|
+ 95 ImplUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ 96 = "IMPLEMENTATION" "MODULE"
|
|
|
+ 97 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
+ 98 IF ~SymTab.Enter(m1,
|
|
|
+ 99 SymTab.KindModule) THEN
|
|
|
+ 100 SemError(200) END; .)
|
|
|
+ 101 ";"
|
|
|
+ 102 { Import }
|
|
|
+ 103 DeclSeq
|
|
|
+ 104 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
+ 105 [ StatSeq ] ]
|
|
|
+ 106 "END"
|
|
|
+ 107 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
+ 108 SemError(202) END; .)
|
|
|
+ 109 (. QbeGen.CloseModule;
|
|
|
+ 110 SemError(230);
|
|
|
+ 111 SymTab.PrintTable; .) .
|
|
|
+ 112 ProgModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ 113 = "MODULE"
|
|
|
+ 114 GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
|
|
|
+ 115 IF ~SymTab.Enter(m1,
|
|
|
+ 116 SymTab.KindModule) THEN
|
|
|
+ 117 SemError(200) END; .)
|
|
|
+ 118 [ Priority ]
|
|
|
+ 119 ";"
|
|
|
+ 120 { Import }
|
|
|
+ 121 DeclSeq
|
|
|
+ 122 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
+ 123 [ StatSeq ] ]
|
|
|
+ 124 "END"
|
|
|
+ 125 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
+ 126 SemError(202) END; .)
|
|
|
+ 127 (. QbeGen.EndModule;
|
|
|
+ 128 SymTab.PrintTable; .) .
|
|
|
+ 129 DeclSeq
|
|
|
+ 130 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
+ 131 | NestedModule ";" | ClassItem ";" } .
|
|
|
+ 132 (* Local module, Wirth form. Parses + checks fully (own scope);
|
|
|
+ 133 lowering waits for step 4, marked by one 230 at END. *)
|
|
|
+ 134 NestedModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ 135 = "MODULE"
|
|
|
+ 136 GetIdent<m1> (. IF ~SymTab.Enter(m1,
|
|
|
+ 137 SymTab.KindModule) THEN
|
|
|
+ 138 SemError(200) END;
|
|
|
+ 139 SymTab.PushScope; .)
|
|
|
+ 140 [ Priority ]
|
|
|
+ 141 ";"
|
|
|
+ 142 { Import }
|
|
|
+ 143 [ Export ]
|
|
|
+ 144 DeclSeq
|
|
|
+ 145 [ "BEGIN"
|
|
|
+ 146 [ StatSeq ] ]
|
|
|
+ 147 "END"
|
|
|
+ 148 GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
|
|
|
+ 149 SemError(202) END;
|
|
|
+ 150 SymTab.PopScope;
|
|
|
+ 151 SemError(230); .) .
|
|
|
+ 152 Priority
|
|
|
+ 153 = "[" integer "]" (. SemError(230); .) .
|
|
|
+ 154 Export (. VAR nm: SymTab.Name; .)
|
|
|
+ 155 = "EXPORT" (* names wire up in step 4 *)
|
|
|
+ 156 [ "QUALIFIED" ]
|
|
|
+ 157 GetIdent<nm>
|
|
|
+ 158 { "," GetIdent<nm> }
|
|
|
+ 159 ";" .
|
|
|
+ 160 Import (. VAR n: SymTab.Name; .)
|
|
|
+ 161 = "FROM"
|
|
|
+ 162 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ 163 SymTab.KindImport) THEN
|
|
|
+ 164 SemError(200) END; .)
|
|
|
+ 165 "IMPORT"
|
|
|
+ 166 ImpList ";"
|
|
|
+ 167 | "IMPORT"
|
|
|
+ 168 ImpList ";" .
|
|
|
+ 169 ImpList (. VAR n: SymTab.Name; .)
|
|
|
+ 170 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
171 SymTab.KindImport) THEN
|
|
|
- 172 SemError(200) END; .) } .
|
|
|
- 173 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
- 174 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
- 175 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
- 176 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
- 177 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
- 178 TypeBlock<isDef: BOOLEAN>
|
|
|
- 179 = "TYPE" { TypeItem<isDef> ";" | ClassItem ";" } .
|
|
|
- 180 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
- 181 t: SymTab.TypeIndex; .)
|
|
|
- 182 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
- 183 SymTab.KindType) THEN
|
|
|
- 184 SemError(200) END; .)
|
|
|
- 185 ( "=" Type<t, FALSE> (. SymTab.SetSymType(n, t); .)
|
|
|
- 186 | (. IF ~isDef THEN
|
|
|
- 187 SemError(231) END;
|
|
|
- 188 SymTab.SetSymType(n,
|
|
|
- 189 SymTab.NewAlias()); .) ) .
|
|
|
- 190 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 191 = TypeIdent<t>
|
|
|
- 192 | Subrange<t>
|
|
|
- 193 | Enum<t>
|
|
|
- 194 | ArrayType<t, allowOpen> .
|
|
|
- 195 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
- 196 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
- 197 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
- 198 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
- 199 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 200 (. VAR elem: SymTab.TypeIndex;
|
|
|
- 201 ok: BOOLEAN; .)
|
|
|
- 202 = "ARRAY"
|
|
|
- 203 ( "OF" Type<elem, FALSE> (. IF ~allowOpen THEN
|
|
|
- 204 SemError(230) END;
|
|
|
- 205 t := SymTab.NewOpenArray(elem); .)
|
|
|
- 206 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
- 207 BoundPair<ok>
|
|
|
- 208 { "," BoundPair<ok> }
|
|
|
- 209 "]" "OF" Type<elem, FALSE>
|
|
|
- 210 (. IF ok THEN
|
|
|
- 211 t := SymTab.NestArray(elem)
|
|
|
- 212 ELSE t := SymTab.InvalidType
|
|
|
- 213 END; .) ) .
|
|
|
- 214 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 215 qlo, qhi: QbeGen.QVal;
|
|
|
- 216 lo, hi: INTEGER;
|
|
|
- 217 cl, cl2: INTEGER; .)
|
|
|
- 218 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 219 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 220 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 221 ok := FALSE
|
|
|
- 222 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
- 223 cl2 := SymTab.ClassOf(thi);
|
|
|
- 224 IF ((cl # SymTab.ClInt)
|
|
|
- 225 & (cl # SymTab.ClChar))
|
|
|
- 226 OR ((cl2 # SymTab.ClInt)
|
|
|
- 227 & (cl2 # SymTab.ClChar)) THEN
|
|
|
- 228 SemError(230); ok := FALSE
|
|
|
- 229 ELSIF ~SymTab.ConstInt(qlo, lo)
|
|
|
- 230 OR ~SymTab.ConstInt(qhi, hi)
|
|
|
- 231 OR (lo > hi) THEN
|
|
|
- 232 SemError(230); ok := FALSE
|
|
|
- 233 ELSIF ~SymTab.BoundAdd(lo, hi) THEN
|
|
|
- 234 SemError(230); ok := FALSE
|
|
|
- 235 END; .) .
|
|
|
- 236 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 237 k: INTEGER; .)
|
|
|
- 238 = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
|
|
|
- 239 SemError(201);
|
|
|
- 240 t := SymTab.InvalidType
|
|
|
- 241 ELSE k := SymTab.SymKind(n);
|
|
|
- 242 IF (k = SymTab.KindType)
|
|
|
- 243 OR (k = SymTab.KindPredef) THEN
|
|
|
- 244 t := SymTab.SymType(n)
|
|
|
- 245 ELSIF k = SymTab.KindImport THEN
|
|
|
- 246 t := SymTab.InvalidType
|
|
|
- 247 ELSE SemError(221);
|
|
|
- 248 t := SymTab.InvalidType
|
|
|
- 249 END
|
|
|
- 250 END; .) .
|
|
|
- 251 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 252 qlo, qhi: QbeGen.QVal;
|
|
|
- 253 lo, hi: INTEGER; .)
|
|
|
- 254 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 255 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 256 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 257 t := SymTab.InvalidType
|
|
|
- 258 ELSIF (SymTab.ClassOf(tlo) #
|
|
|
- 259 SymTab.ClInt)
|
|
|
- 260 OR (SymTab.ClassOf(thi) #
|
|
|
- 261 SymTab.ClInt) THEN
|
|
|
- 262 SemError(230);
|
|
|
- 263 t := SymTab.InvalidType
|
|
|
- 264 ELSIF ~SymTab.ConstInt(qlo, lo)
|
|
|
- 265 OR ~SymTab.ConstInt(qhi, hi)
|
|
|
- 266 OR (lo > hi) THEN
|
|
|
- 267 SemError(230);
|
|
|
- 268 t := SymTab.InvalidType
|
|
|
- 269 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
- 270 END; .)
|
|
|
- 271 "]" .
|
|
|
- 272 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
- 273 = "(" (. t := SymTab.NewEnum(); .)
|
|
|
- 274 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
- 275 SymTab.KindConst) THEN
|
|
|
- 276 SemError(200) END;
|
|
|
- 277 SymTab.SetSymType(n, t); .)
|
|
|
- 278 { "," GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
- 279 SymTab.KindConst) THEN
|
|
|
- 280 SemError(200) END;
|
|
|
- 281 SymTab.SetSymType(n, t); .) }
|
|
|
- 282 ")" .
|
|
|
- 283 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
- 284 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
- 285 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
- 286 class/impl block. Methods end with ";" per the Table example
|
|
|
- 287 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
- 288 (* Single CLASS item in both loops: separating declaration from
|
|
|
- 289 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
- 290 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
- 291 The second token decides after CLASS is consumed. A misplaced
|
|
|
- 292 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
- 293 whole unit ends 230 until lowering). *)
|
|
|
- 294 ClassItem
|
|
|
- 295 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
- 296 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
- 297 ct: SymTab.TypeIndex; .)
|
|
|
- 298 = GetIdent<cn> (. IF ~SymTab.Enter(cn,
|
|
|
- 299 SymTab.KindType) THEN
|
|
|
- 300 SemError(200) END;
|
|
|
- 301 ct := SymTab.NewClass();
|
|
|
- 302 SymTab.SetSymType(cn, ct);
|
|
|
- 303 SymTab.PushClassScope(ct); .)
|
|
|
- 304 [ Parents<ct> ]
|
|
|
- 305 ";"
|
|
|
- 306 { ClassField<ct> ";" }
|
|
|
- 307 { MethodHeading<pn> ";" (. SymTab.CloseProc; .) }
|
|
|
- 308 "END"
|
|
|
- 309 GetIdent<m2> (. IF ~SymTab.Equal(cn, m2) THEN
|
|
|
- 310 SemError(202) END;
|
|
|
- 311 SymTab.PopScope;
|
|
|
- 312 SemError(230); .) .
|
|
|
- 313 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
- 314 = "(" Parent1<ct>
|
|
|
- 315 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
- 316 ")" .
|
|
|
- 317 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
- 318 pt: SymTab.TypeIndex; .)
|
|
|
- 319 = GetIdent<p> (. IF ~SymTab.Lookup(p) THEN
|
|
|
- 320 SemError(201)
|
|
|
- 321 ELSE pt := SymTab.SymType(p);
|
|
|
- 322 IF SymTab.ClassOf(pt) #
|
|
|
- 323 SymTab.ClClass THEN
|
|
|
- 324 SemError(230)
|
|
|
- 325 ELSE SymTab.SetParent(ct, pt)
|
|
|
- 326 END
|
|
|
- 327 END; .) .
|
|
|
- 328 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
- 329 t: SymTab.TypeIndex; .)
|
|
|
- 330 = GetIdent<n>
|
|
|
- 331 ( "=" GetIdent<rhs> (. IF ~SymTab.Enter(n,
|
|
|
- 332 SymTab.KindConst) THEN
|
|
|
+ 172 SemError(200) END; .)
|
|
|
+ 173 { ","
|
|
|
+ 174 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ 175 SymTab.KindImport) THEN
|
|
|
+ 176 SemError(200) END; .) } .
|
|
|
+ 177 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
+ 178 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
+ 179 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
+ 180 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
+ 181 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
+ 182 TypeBlock<isDef: BOOLEAN>
|
|
|
+ 183 = "TYPE" { TypeItem<isDef> ";" | ClassItem ";" } .
|
|
|
+ 184 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
+ 185 t: SymTab.TypeIndex; .)
|
|
|
+ 186 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ 187 SymTab.KindType) THEN
|
|
|
+ 188 SemError(200) END; .)
|
|
|
+ 189 ( "=" Type<t, FALSE> (. SymTab.SetSymType(n, t); .)
|
|
|
+ 190 | (. IF ~isDef THEN
|
|
|
+ 191 SemError(231) END;
|
|
|
+ 192 SymTab.SetSymType(n,
|
|
|
+ 193 SymTab.NewAlias()); .) ) .
|
|
|
+ 194 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 195 = TypeIdent<t>
|
|
|
+ 196 | Subrange<t>
|
|
|
+ 197 | Enum<t>
|
|
|
+ 198 | ArrayType<t, allowOpen>
|
|
|
+ 199 | SetType<t> .
|
|
|
+ 200 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
+ 201 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
+ 202 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
+ 203 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
+ 204 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 205 (. VAR elem: SymTab.TypeIndex;
|
|
|
+ 206 ok: BOOLEAN; .)
|
|
|
+ 207 = "ARRAY"
|
|
|
+ 208 ( "OF" Type<elem, FALSE> (. IF ~allowOpen THEN
|
|
|
+ 209 SemError(230) END;
|
|
|
+ 210 t := SymTab.NewOpenArray(elem); .)
|
|
|
+ 211 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
+ 212 BoundPair<ok>
|
|
|
+ 213 { "," BoundPair<ok> }
|
|
|
+ 214 "]" "OF" Type<elem, FALSE>
|
|
|
+ 215 (. IF ok THEN
|
|
|
+ 216 t := SymTab.NestArray(elem)
|
|
|
+ 217 ELSE t := SymTab.InvalidType
|
|
|
+ 218 END; .) ) .
|
|
|
+ 219 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 220 qlo, qhi: QbeGen.QVal;
|
|
|
+ 221 lo, hi: INTEGER;
|
|
|
+ 222 cl, cl2: INTEGER; .)
|
|
|
+ 223 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 224 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 225 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 226 ok := FALSE
|
|
|
+ 227 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
+ 228 cl2 := SymTab.ClassOf(thi);
|
|
|
+ 229 IF ((cl # SymTab.ClInt)
|
|
|
+ 230 & (cl # SymTab.ClChar))
|
|
|
+ 231 OR ((cl2 # SymTab.ClInt)
|
|
|
+ 232 & (cl2 # SymTab.ClChar)) THEN
|
|
|
+ 233 SemError(230); ok := FALSE
|
|
|
+ 234 ELSIF ~SymTab.ConstInt(qlo, lo)
|
|
|
+ 235 OR ~SymTab.ConstInt(qhi, hi)
|
|
|
+ 236 OR (lo > hi) THEN
|
|
|
+ 237 SemError(230); ok := FALSE
|
|
|
+ 238 ELSIF ~SymTab.BoundAdd(lo, hi) THEN
|
|
|
+ 239 SemError(230); ok := FALSE
|
|
|
+ 240 END; .) .
|
|
|
+ 241 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
+ 242 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
+ 243 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
+ 244 comparison across suitable bases are lenient (masks over min
|
|
|
+ 245 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
+ 246 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
+ 247 blo, bhi, bspan: INTEGER;
|
|
|
+ 248 bcls: INTEGER; .)
|
|
|
+ 249 = "SET" "OF" Type<base, FALSE>
|
|
|
+ 250 (. IF base = SymTab.InvalidType THEN
|
|
|
+ 251 t := SymTab.InvalidType
|
|
|
+ 252 ELSE bcls :=
|
|
|
+ 253 SymTab.ClassOf(base);
|
|
|
+ 254 IF bcls = SymTab.ClBool THEN
|
|
|
+ 255 blo := 0; bspan := 2
|
|
|
+ 256 ELSIF bcls = SymTab.ClChar THEN
|
|
|
+ 257 blo := 0; bspan := 256
|
|
|
+ 258 ELSIF SymTab.SubBounds(base,
|
|
|
+ 259 blo, bhi) THEN
|
|
|
+ 260 bspan := bhi - blo + 1
|
|
|
+ 261 ELSE bspan := 0 END;
|
|
|
+ 262 IF (bspan <= 0)
|
|
|
+ 263 OR (bspan > 256) THEN
|
|
|
+ 264 SemError(230);
|
|
|
+ 265 t := SymTab.InvalidType
|
|
|
+ 266 ELSE t := SymTab.NewSet(base)
|
|
|
+ 267 END
|
|
|
+ 268 END; .) .
|
|
|
+ 269 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 270 k: INTEGER; .)
|
|
|
+ 271 = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
|
|
|
+ 272 SemError(201);
|
|
|
+ 273 t := SymTab.InvalidType
|
|
|
+ 274 ELSE k := SymTab.SymKind(n);
|
|
|
+ 275 IF (k = SymTab.KindType)
|
|
|
+ 276 OR (k = SymTab.KindPredef) THEN
|
|
|
+ 277 t := SymTab.SymType(n)
|
|
|
+ 278 ELSIF k = SymTab.KindImport THEN
|
|
|
+ 279 t := SymTab.InvalidType
|
|
|
+ 280 ELSE SemError(221);
|
|
|
+ 281 t := SymTab.InvalidType
|
|
|
+ 282 END
|
|
|
+ 283 END; .) .
|
|
|
+ 284 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 285 qlo, qhi: QbeGen.QVal;
|
|
|
+ 286 lo, hi: INTEGER; .)
|
|
|
+ 287 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 288 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 289 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 290 t := SymTab.InvalidType
|
|
|
+ 291 ELSIF (SymTab.ClassOf(tlo) #
|
|
|
+ 292 SymTab.ClInt)
|
|
|
+ 293 OR (SymTab.ClassOf(thi) #
|
|
|
+ 294 SymTab.ClInt) THEN
|
|
|
+ 295 SemError(230);
|
|
|
+ 296 t := SymTab.InvalidType
|
|
|
+ 297 ELSIF ~SymTab.ConstInt(qlo, lo)
|
|
|
+ 298 OR ~SymTab.ConstInt(qhi, hi)
|
|
|
+ 299 OR (lo > hi) THEN
|
|
|
+ 300 SemError(230);
|
|
|
+ 301 t := SymTab.InvalidType
|
|
|
+ 302 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
+ 303 END; .)
|
|
|
+ 304 "]" .
|
|
|
+ 305 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
+ 306 = "(" (. t := SymTab.NewEnum(); .)
|
|
|
+ 307 GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ 308 SymTab.KindConst) THEN
|
|
|
+ 309 SemError(200) END;
|
|
|
+ 310 SymTab.SetSymType(n, t); .)
|
|
|
+ 311 { "," GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ 312 SymTab.KindConst) THEN
|
|
|
+ 313 SemError(200) END;
|
|
|
+ 314 SymTab.SetSymType(n, t); .) }
|
|
|
+ 315 ")" .
|
|
|
+ 316 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
+ 317 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
+ 318 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
+ 319 class/impl block. Methods end with ";" per the Table example
|
|
|
+ 320 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
+ 321 (* Single CLASS item in both loops: separating declaration from
|
|
|
+ 322 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
+ 323 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
+ 324 The second token decides after CLASS is consumed. A misplaced
|
|
|
+ 325 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
+ 326 whole unit ends 230 until lowering). *)
|
|
|
+ 327 ClassItem
|
|
|
+ 328 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
+ 329 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
+ 330 ct: SymTab.TypeIndex; .)
|
|
|
+ 331 = GetIdent<cn> (. IF ~SymTab.Enter(cn,
|
|
|
+ 332 SymTab.KindType) THEN
|
|
|
333 SemError(200) END;
|
|
|
- 334 IF SymTab.Lookup(rhs) THEN
|
|
|
- 335 SymTab.SetSymType(n,
|
|
|
- 336 SymTab.SymType(rhs))
|
|
|
- 337 END; .)
|
|
|
- 338 | (. IF ~SymTab.FieldPending(ct,
|
|
|
- 339 n) THEN
|
|
|
- 340 SemError(200) END; .)
|
|
|
- 341 { "," GetIdent<n> (. IF ~SymTab.FieldPending(ct,
|
|
|
- 342 n) THEN
|
|
|
- 343 SemError(200) END; .) }
|
|
|
- 344 ":" TypeIdent<t> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
- 345 MethodHeading<VAR pn: SymTab.Name> (. VAR wantVirt: BOOLEAN; .)
|
|
|
- 346 = (. wantVirt := FALSE; .)
|
|
|
- 347 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
- 348 ProcHeading<pn> (. IF wantVirt THEN
|
|
|
- 349 SymTab.MarkVirtual END; .) .
|
|
|
- 350 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
- 351 ct: SymTab.TypeIndex; .)
|
|
|
- 352 = GetIdent<cn> (. IF ~SymTab.Lookup(cn) THEN
|
|
|
- 353 SemError(201);
|
|
|
- 354 ct := SymTab.InvalidType
|
|
|
- 355 ELSE ct := SymTab.SymType(cn);
|
|
|
- 356 IF SymTab.ClassOf(ct) #
|
|
|
- 357 SymTab.ClClass THEN
|
|
|
- 358 SemError(230);
|
|
|
- 359 ct := SymTab.InvalidType
|
|
|
- 360 END
|
|
|
- 361 END;
|
|
|
- 362 IF ct #
|
|
|
- 363 SymTab.InvalidType THEN
|
|
|
- 364 IF ~SymTab.PushClassMembers(
|
|
|
- 365 ct) THEN
|
|
|
- 366 SemError(230) END
|
|
|
- 367 END; .)
|
|
|
- 368 ";" { MethodImpl<ct> ";" }
|
|
|
- 369 [ "BEGIN"
|
|
|
- 370 [ StatSeq ] ]
|
|
|
- 371 "END"
|
|
|
- 372 GetIdent<m2> (. IF ~SymTab.Equal(cn, m2) THEN
|
|
|
- 373 SemError(202) END;
|
|
|
- 374 SymTab.PopScope;
|
|
|
- 375 SemError(230); .) .
|
|
|
- 376 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name; .)
|
|
|
- 377 = MethodHeading<pn> ";"
|
|
|
- 378 (. IF (ct #
|
|
|
- 379 SymTab.InvalidType)
|
|
|
- 380 & ~SymTab.MethodExists(ct,
|
|
|
- 381 pn) THEN
|
|
|
- 382 SemError(201) END; .)
|
|
|
- 383 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
- 384 SymTab.CloseProc; .)
|
|
|
- 385 | Block<pn> (. SymTab.CloseProc;
|
|
|
- 386 SemError(230); .) ) .
|
|
|
- 387 ConstBlock
|
|
|
- 388 = "CONST" { ConstDecl ";" } .
|
|
|
- 389 ConstDecl (. VAR n: SymTab.Name;
|
|
|
- 390 t: SymTab.TypeIndex;
|
|
|
- 391 qv: QbeGen.QVal;
|
|
|
- 392 cls: INTEGER; .)
|
|
|
- 393 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
- 394 SymTab.KindConst) THEN
|
|
|
- 395 SemError(200) END; .)
|
|
|
- 396 "="
|
|
|
- 397 Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
- 398 cls := SymTab.ClassOf(t);
|
|
|
- 399 IF cls = SymTab.ClStr THEN
|
|
|
- 400 SemError(230)
|
|
|
- 401 ELSIF ~QbeGen.IsImm(qv) THEN
|
|
|
- 402 SemError(230) END;
|
|
|
- 403 QbeGen.DeclConst(n, qv, t); .) .
|
|
|
- 404 VarBlock
|
|
|
- 405 = "VAR" { VarDecl ";" } .
|
|
|
- 406 VarDecl (. VAR nm: SymTab.Name;
|
|
|
- 407 t: SymTab.TypeIndex;
|
|
|
- 408 i: CARDINAL;
|
|
|
- 409 cls: INTEGER; .)
|
|
|
- 410 = VarIdents ":"
|
|
|
- 411 Type<t, FALSE> (. cls := SymTab.ClassOf(t);
|
|
|
- 412 IF (t # SymTab.InvalidType)
|
|
|
- 413 & (cls # SymTab.ClInt)
|
|
|
- 414 & (cls # SymTab.ClBool)
|
|
|
- 415 & (cls # SymTab.ClChar)
|
|
|
- 416 & (cls # SymTab.ClReal)
|
|
|
- 417 & (cls # SymTab.ClArray) THEN
|
|
|
- 418 SemError(230) END;
|
|
|
- 419 i := 0;
|
|
|
- 420 WHILE i < SymTab.PendCount() DO
|
|
|
- 421 SymTab.PendName(i, nm);
|
|
|
- 422 QbeGen.DeclVar(nm, t);
|
|
|
- 423 INC(i)
|
|
|
- 424 END;
|
|
|
- 425 SymTab.FixPending(t); .) .
|
|
|
- 426 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
- 427 = GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
- 428 SymTab.KindVar) THEN
|
|
|
- 429 SemError(200) END; .)
|
|
|
- 430 { ","
|
|
|
- 431 GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
- 432 SymTab.KindVar) THEN
|
|
|
- 433 SemError(200) END; .) } .
|
|
|
- 434 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
- 435 = GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
- 436 SemError(200) END; .)
|
|
|
- 437 { "," GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
- 438 SemError(200) END; .) } .
|
|
|
- 439 (* Procedure headings enter now (scopes, params, result); bodies
|
|
|
- 440 parse + check with one 230 at END (lowering = step 4).
|
|
|
- 441 FORWARD marks; the body heading re-enters (signature compare
|
|
|
- 442 tightens in step 4). *)
|
|
|
- 443 ProcHeading<VAR pn: SymTab.Name> (. VAR t: SymTab.TypeIndex; .)
|
|
|
- 444 = "PROCEDURE"
|
|
|
- 445 GetIdent<pn> (. IF ~SymTab.EnterProc(pn) THEN
|
|
|
- 446 IF ~SymTab.ReenterProc(pn) THEN
|
|
|
- 447 SemError(200) END
|
|
|
- 448 END; .)
|
|
|
- 449 [ FormalParams ]
|
|
|
- 450 [ ":" TypeIdent<t> (. SymTab.SetProcRes(t);
|
|
|
- 451 IF (t #
|
|
|
- 452 SymTab.InvalidType)
|
|
|
- 453 & (SymTab.ClassOf(t)
|
|
|
- 454 = SymTab.ClArray) THEN
|
|
|
- 455 SemError(230) END; .) ] .
|
|
|
- 456 FormalParams
|
|
|
- 457 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
- 458 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
- 459 isV: BOOLEAN; .)
|
|
|
- 460 = (. isV := FALSE; .)
|
|
|
- 461 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 462 ParIdents<isV> ":" Type<t, TRUE> (. SymTab.FixPending(t); .) .
|
|
|
- 463 ProcDecl (. VAR pn, m2: SymTab.Name; .)
|
|
|
- 464 = ProcHeading<pn> ";"
|
|
|
- 465 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
- 466 SymTab.CloseProc; .)
|
|
|
- 467 | Block<pn> (. SymTab.CloseProc;
|
|
|
- 468 SemError(230); .) ) .
|
|
|
- 469 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
- 470 = DeclSeq
|
|
|
- 471 [ "BEGIN"
|
|
|
- 472 [ StatSeq ] ]
|
|
|
- 473 "END"
|
|
|
- 474 GetIdent<m2> (. IF ~SymTab.Equal(pn, m2) THEN
|
|
|
- 475 SemError(202) END; .) .
|
|
|
- 476 StatSeq
|
|
|
- 477 = Statement { ";" Statement } .
|
|
|
- 478 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
- 479 = Assign
|
|
|
- 480 | IfStat
|
|
|
- 481 | WhileStat
|
|
|
- 482 | RepeatStat
|
|
|
- 483 | LoopStat
|
|
|
- 484 | ForStat
|
|
|
- 485 | CaseStat
|
|
|
- 486 | ReturnStat
|
|
|
- 487 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
- 488 QbeGen.Jmp(lx)
|
|
|
- 489 ELSE SemError(230) END; .) .
|
|
|
- 490 Assign (. VAR dt, et: SymTab.TypeIndex;
|
|
|
- 491 dk: INTEGER;
|
|
|
- 492 qd, qe, qt: QbeGen.QVal;
|
|
|
- 493 qn: SymTab.Name;
|
|
|
- 494 isR, conv: BOOLEAN;
|
|
|
- 495 sfx: BOOLEAN; .)
|
|
|
- 496 = Design<dt, dk, qd, qn, sfx> ":="
|
|
|
- 497 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
- 498 & (dk # SymTab.KindVar)
|
|
|
- 499 & (dk # SymTab.KindParam) THEN
|
|
|
- 500 SemError(210)
|
|
|
- 501 ELSIF ~SymTab.Assignable(et,
|
|
|
- 502 dt) THEN
|
|
|
- 503 SemError(210) END;
|
|
|
- 504 isR := (dt #
|
|
|
- 505 SymTab.InvalidType)
|
|
|
- 506 & (SymTab.ClassOf(dt)
|
|
|
- 507 = SymTab.ClReal);
|
|
|
- 508 conv := isR
|
|
|
- 509 & SymTab.IsIntFamily(et);
|
|
|
- 510 IF ((dk = SymTab.KindVar)
|
|
|
- 511 OR (dk = SymTab.KindParam))
|
|
|
- 512 & (dt # SymTab.InvalidType)
|
|
|
- 513 & (et # SymTab.InvalidType) THEN
|
|
|
- 514 IF sfx THEN
|
|
|
- 515 IF SymTab.ClassOf(dt) =
|
|
|
- 516 SymTab.ClArray THEN
|
|
|
- 517 QbeGen.CopyArray(qd, qe,
|
|
|
- 518 dt)
|
|
|
- 519 ELSIF conv THEN
|
|
|
- 520 QbeGen.ConvIR(qe, qt);
|
|
|
- 521 QbeGen.ElemStore(qd, qt,
|
|
|
- 522 dt)
|
|
|
- 523 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
- 524 dt)
|
|
|
- 525 END
|
|
|
- 526 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 527 SymTab.ClArray THEN
|
|
|
- 528 QbeGen.CopyArray(qd, qe, dt)
|
|
|
- 529 ELSIF conv THEN
|
|
|
- 530 QbeGen.ConvIR(qe, qt);
|
|
|
- 531 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
- 532 ELSE
|
|
|
- 533 QbeGen.StoreVar(qn, qe, isR)
|
|
|
- 534 END
|
|
|
- 535 END; .) .
|
|
|
- 536 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 537 q, lThen, lElse, lEnd:
|
|
|
- 538 QbeGen.QVal;
|
|
|
- 539 hasElse: BOOLEAN; .)
|
|
|
- 540 = "IF" (. hasElse := FALSE; .)
|
|
|
- 541 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
- 542 SemError(214) END;
|
|
|
- 543 QbeGen.NewLabel(lThen);
|
|
|
- 544 QbeGen.NewLabel(lElse);
|
|
|
- 545 QbeGen.NewLabel(lEnd);
|
|
|
- 546 QbeGen.Jnz(q, lThen, lElse);
|
|
|
- 547 QbeGen.EmitLabel(lThen); .)
|
|
|
- 548 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .)
|
|
|
- 549 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
- 550 QbeGen.NewLabel(lElse); .)
|
|
|
- 551 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
- 552 SemError(214) END;
|
|
|
- 553 QbeGen.NewLabel(lThen);
|
|
|
- 554 QbeGen.Jnz(q, lThen, lElse);
|
|
|
- 555 QbeGen.EmitLabel(lThen); .)
|
|
|
- 556 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .) }
|
|
|
- 557 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
- 558 hasElse := TRUE; .)
|
|
|
- 559 StatSeq ]
|
|
|
- 560 "END" (. IF hasElse THEN
|
|
|
- 561 QbeGen.EmitLabel(lEnd)
|
|
|
- 562 ELSE QbeGen.EmitLabel(lElse);
|
|
|
- 563 QbeGen.EmitLabel(lEnd)
|
|
|
- 564 END; .) .
|
|
|
- 565 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 566 q, lTop, lBody, lEnd:
|
|
|
- 567 QbeGen.QVal; .)
|
|
|
- 568 = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
- 569 QbeGen.NewLabel(lBody);
|
|
|
- 570 QbeGen.NewLabel(lEnd);
|
|
|
- 571 QbeGen.EmitLabel(lTop); .)
|
|
|
- 572 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
- 573 SemError(214) END;
|
|
|
- 574 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
- 575 QbeGen.EmitLabel(lBody); .)
|
|
|
- 576 "DO" StatSeq (. QbeGen.Jmp(lTop); .)
|
|
|
- 577 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 578 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 579 q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
- 580 = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
- 581 QbeGen.NewLabel(lEnd);
|
|
|
- 582 QbeGen.EmitLabel(lTop); .)
|
|
|
- 583 StatSeq
|
|
|
- 584 "UNTIL" Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
- 585 SemError(214) END;
|
|
|
- 586 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
- 587 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 588 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
- 589 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
- 590 QbeGen.NewLabel(lEnd);
|
|
|
- 591 QbeGen.PushLoop(lEnd);
|
|
|
- 592 QbeGen.EmitLabel(lTop); .)
|
|
|
- 593 StatSeq
|
|
|
- 594 "END" (. QbeGen.Jmp(lTop);
|
|
|
- 595 QbeGen.PopLoop;
|
|
|
- 596 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 597 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 598 Runtime direction would need a compare-select; the literal
|
|
|
- 599 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 600 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 601 tlo, thi, tby:
|
|
|
- 602 SymTab.TypeIndex;
|
|
|
- 603 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 604 QbeGen.QVal;
|
|
|
- 605 lTop, lBody, lEnd:
|
|
|
- 606 QbeGen.QVal;
|
|
|
- 607 by: INTEGER;
|
|
|
- 608 ok: BOOLEAN; .)
|
|
|
- 609 = "FOR" (. by := 1; .)
|
|
|
- 610 GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
- 611 IF ~ok THEN
|
|
|
- 612 SemError(201)
|
|
|
- 613 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 614 SymTab.KindVar)
|
|
|
- 615 & (SymTab.SymKind(lv) #
|
|
|
- 616 SymTab.KindParam) THEN
|
|
|
- 617 SemError(220); ok := FALSE
|
|
|
- 618 ELSIF ~SymTab.IsIntFamily(
|
|
|
- 619 SymTab.SymType(lv)) THEN
|
|
|
- 620 SemError(220); ok := FALSE
|
|
|
- 621 END; .)
|
|
|
- 622 ":=" Expr<tlo, qlo> (. IF ~SymTab.IsIntFamily(tlo) THEN
|
|
|
- 623 SemError(220); ok := FALSE
|
|
|
- 624 END; .)
|
|
|
- 625 "TO" Expr<thi, qhi> (. IF ~SymTab.IsIntFamily(thi) THEN
|
|
|
- 626 SemError(220); ok := FALSE
|
|
|
- 627 END; .)
|
|
|
- 628 [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
- 629 SymTab.InvalidType)
|
|
|
- 630 & ~SymTab.IsIntFamily(tby) THEN
|
|
|
- 631 SemError(220); ok := FALSE
|
|
|
- 632 END;
|
|
|
- 633 IF ~SymTab.ConstInt(qby, by) THEN
|
|
|
- 634 SemError(230); by := 1
|
|
|
- 635 ELSIF by = 0 THEN
|
|
|
- 636 SemError(220); by := 1
|
|
|
- 637 END; .) ]
|
|
|
- 638 "DO" (. IF ok THEN
|
|
|
- 639 QbeGen.StoreVar(lv, qlo,
|
|
|
- 640 FALSE) END;
|
|
|
- 641 QbeGen.NewLabel(lTop);
|
|
|
- 642 QbeGen.NewLabel(lBody);
|
|
|
- 643 QbeGen.NewLabel(lEnd);
|
|
|
- 644 QbeGen.EmitLabel(lTop);
|
|
|
- 645 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
- 646 QbeGen.NewTemp(qk);
|
|
|
- 647 IF by > 0 THEN
|
|
|
- 648 QbeGen.Op3("cslew", qk,
|
|
|
- 649 qt, qhi, FALSE)
|
|
|
- 650 ELSE QbeGen.Op3("csgew", qk,
|
|
|
- 651 qt, qhi, FALSE)
|
|
|
- 652 END;
|
|
|
- 653 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
- 654 QbeGen.EmitLabel(lBody); .)
|
|
|
- 655 StatSeq
|
|
|
- 656 "END" (. IF ok THEN
|
|
|
- 657 QbeGen.LoadVar(lv, FALSE,
|
|
|
- 658 qt);
|
|
|
- 659 QbeGen.IntStr(by, qb);
|
|
|
- 660 QbeGen.NewTemp(qk);
|
|
|
- 661 QbeGen.Op3("add", qk,
|
|
|
- 662 qt, qb, FALSE);
|
|
|
- 663 QbeGen.StoreVar(lv, qk,
|
|
|
- 664 FALSE) END;
|
|
|
- 665 QbeGen.Jmp(lTop);
|
|
|
- 666 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 667 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 668 qsel, lEnd: QbeGen.QVal; .)
|
|
|
- 669 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
- 670 "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
- 671 { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
- 672 [ "ELSE" StatSeq ]
|
|
|
- 673 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 674 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 675 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 676 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 677 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 678 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 679 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
- 680 = (. QbeGen.NewLabel(lBody);
|
|
|
- 681 QbeGen.NewLabel(lAfter); .)
|
|
|
- 682 CaseLabel<tsel, qsel, lBody>
|
|
|
- 683 { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
- 684 ":" (. QbeGen.Jmp(lAfter);
|
|
|
- 685 QbeGen.EmitLabel(lBody); .)
|
|
|
- 686 StatSeq (. QbeGen.Jmp(lEnd);
|
|
|
- 687 QbeGen.EmitLabel(lAfter); .) .
|
|
|
- 688 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 689 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 690 q2, q3, qc, qd, qe:
|
|
|
- 691 QbeGen.QVal;
|
|
|
- 692 lNext: QbeGen.QVal; .)
|
|
|
- 693 = Expr<t2, q2> (. IF (t2 #
|
|
|
- 694 SymTab.InvalidType)
|
|
|
- 695 & (tsel #
|
|
|
- 696 SymTab.InvalidType)
|
|
|
- 697 & ~SymTab.EqCheck(t2,
|
|
|
- 698 tsel) THEN
|
|
|
- 699 SemError(213) END;
|
|
|
- 700 IF ~QbeGen.IsImm(q2) THEN
|
|
|
- 701 SemError(230);
|
|
|
- 702 QbeGen.CopyOp("0", q2)
|
|
|
- 703 END;
|
|
|
- 704 QbeGen.NewLabel(lNext);
|
|
|
- 705 QbeGen.Cmp(SymTab.OpEq,
|
|
|
- 706 qsel, q2, qc, FALSE);
|
|
|
- 707 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
- 708 QbeGen.EmitLabel(lNext); .)
|
|
|
- 709 [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
- 710 SymTab.InvalidType)
|
|
|
- 711 & (tsel #
|
|
|
- 712 SymTab.InvalidType)
|
|
|
- 713 & ~SymTab.EqCheck(t3,
|
|
|
- 714 tsel) THEN
|
|
|
- 715 SemError(213) END;
|
|
|
- 716 IF ~QbeGen.IsImm(q3) THEN
|
|
|
- 717 SemError(230);
|
|
|
- 718 QbeGen.CopyOp("0", q3)
|
|
|
- 719 END;
|
|
|
- 720 QbeGen.Cmp(SymTab.OpGe,
|
|
|
- 721 qsel, q2, qc, FALSE);
|
|
|
- 722 QbeGen.Cmp(SymTab.OpLe,
|
|
|
- 723 qsel, q3, qd, FALSE);
|
|
|
- 724 QbeGen.NewTemp(qe);
|
|
|
- 725 QbeGen.Op3("and", qe, qc, qd,
|
|
|
- 726 FALSE);
|
|
|
- 727 QbeGen.NewLabel(lNext);
|
|
|
- 728 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
- 729 QbeGen.EmitLabel(lNext); .) ] .
|
|
|
- 730 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 731 q: QbeGen.QVal;
|
|
|
- 732 res: SymTab.TypeIndex;
|
|
|
- 733 hadE: BOOLEAN; .)
|
|
|
- 734 = "RETURN" (. hadE := FALSE; .)
|
|
|
- 735 [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
- 736 (. IF ~SymTab.InProc() THEN
|
|
|
- 737 SemError(232)
|
|
|
- 738 ELSE res := SymTab.CurRes();
|
|
|
- 739 IF ~hadE THEN
|
|
|
- 740 IF res #
|
|
|
- 741 SymTab.InvalidType THEN
|
|
|
- 742 SemError(232) END
|
|
|
- 743 ELSIF (res =
|
|
|
- 744 SymTab.InvalidType)
|
|
|
- 745 OR (t #
|
|
|
- 746 SymTab.InvalidType)
|
|
|
- 747 & ~SymTab.Assignable(t,
|
|
|
- 748 res) THEN
|
|
|
- 749 SemError(232)
|
|
|
- 750 END
|
|
|
- 751 END; .) .
|
|
|
- 752 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 753 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 754 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 755 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 756 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 757 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 758 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 759 (. VAR n: SymTab.Name;
|
|
|
- 760 cls: INTEGER;
|
|
|
- 761 it, eT: SymTab.TypeIndex;
|
|
|
- 762 iq, ql, qlo, qhi, qe:
|
|
|
- 763 QbeGen.QVal;
|
|
|
- 764 lo, hi: INTEGER;
|
|
|
- 765 isOpen: BOOLEAN; .)
|
|
|
- 766 = GetIdent<n> (. QbeGen.CopyOp(n, qn);
|
|
|
- 767 sfx := FALSE;
|
|
|
- 768 IF ~SymTab.Lookup(n) THEN
|
|
|
- 769 SemError(201);
|
|
|
- 770 t := SymTab.InvalidType;
|
|
|
- 771 k := -1;
|
|
|
- 772 QbeGen.CopyOp("0", q)
|
|
|
- 773 ELSE
|
|
|
- 774 t := SymTab.SymType(n);
|
|
|
- 775 k := SymTab.SymKind(n);
|
|
|
- 776 IF k = SymTab.KindConst THEN
|
|
|
- 777 IF SymTab.Equal(n,
|
|
|
- 778 "TRUE") THEN
|
|
|
- 779 t := SymTab.BoolType();
|
|
|
- 780 QbeGen.CopyOp("1", q)
|
|
|
- 781 ELSIF SymTab.Equal(n,
|
|
|
- 782 "FALSE") THEN
|
|
|
- 783 t := SymTab.BoolType();
|
|
|
- 784 QbeGen.CopyOp("0", q)
|
|
|
- 785 ELSE
|
|
|
- 786 cls :=
|
|
|
- 787 SymTab.ClassOf(t);
|
|
|
- 788 IF (t #
|
|
|
- 789 SymTab.InvalidType)
|
|
|
- 790 & ((cls = SymTab.ClInt)
|
|
|
- 791 OR (cls
|
|
|
- 792 = SymTab.ClChar)
|
|
|
- 793 OR (cls
|
|
|
- 794 = SymTab.ClReal)) THEN
|
|
|
- 795 QbeGen.LoadVar(n,
|
|
|
- 796 cls = SymTab.ClReal, q)
|
|
|
- 797 ELSE
|
|
|
- 798 IF t #
|
|
|
- 799 SymTab.InvalidType THEN
|
|
|
- 800 SemError(230)
|
|
|
- 801 END;
|
|
|
- 802 QbeGen.CopyOp("0", q)
|
|
|
- 803 END
|
|
|
- 804 END
|
|
|
- 805 ELSIF (k = SymTab.KindVar)
|
|
|
- 806 OR (k = SymTab.KindParam) THEN
|
|
|
- 807 cls :=
|
|
|
- 808 SymTab.ClassOf(t);
|
|
|
- 809 IF (cls = SymTab.ClInt)
|
|
|
- 810 OR (cls = SymTab.ClBool)
|
|
|
- 811 OR (cls = SymTab.ClChar)
|
|
|
- 812 OR (cls
|
|
|
- 813 = SymTab.ClReal) THEN
|
|
|
- 814 QbeGen.LoadVar(n,
|
|
|
- 815 cls = SymTab.ClReal, q)
|
|
|
- 816 ELSIF cls
|
|
|
- 817 = SymTab.ClArray THEN
|
|
|
- 818 QbeGen.AddrOf(n, q)
|
|
|
- 819 ELSE SemError(230);
|
|
|
- 820 QbeGen.CopyOp("0", q)
|
|
|
- 821 END
|
|
|
- 822 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 823 IF (k = SymTab.KindImport)
|
|
|
- 824 OR (k = SymTab.KindProc)
|
|
|
- 825 OR (k
|
|
|
- 826 = SymTab.KindField) THEN
|
|
|
- 827 SemError(230)
|
|
|
- 828 END
|
|
|
- 829 END
|
|
|
- 830 END; .)
|
|
|
- 831 { "[" Expr<it, iq>
|
|
|
- 832 (. IF t = SymTab.InvalidType THEN
|
|
|
- 833 ELSIF SymTab.ClassOf(t) #
|
|
|
- 834 SymTab.ClArray THEN
|
|
|
- 835 SemError(217);
|
|
|
- 836 t := SymTab.InvalidType
|
|
|
- 837 ELSIF ~SymTab.IsIntFamily(it)
|
|
|
- 838 & (SymTab.ClassOf(it) #
|
|
|
- 839 SymTab.ClChar) THEN
|
|
|
- 840 SemError(218);
|
|
|
- 841 t := SymTab.InvalidType
|
|
|
- 842 ELSE
|
|
|
- 843 QbeGen.WidenIndex(iq, ql);
|
|
|
- 844 isOpen :=
|
|
|
- 845 SymTab.IsOpenArray(t);
|
|
|
- 846 IF isOpen THEN
|
|
|
- 847 QbeGen.CopyOp("0", qlo);
|
|
|
- 848 QbeGen.OpenHi(q, qhi)
|
|
|
- 849 ELSE
|
|
|
- 850 lo := SymTab.ArrayLo(t);
|
|
|
- 851 hi := SymTab.ArrayHi(t);
|
|
|
- 852 QbeGen.IntStr(lo, qlo);
|
|
|
- 853 QbeGen.IntStr(hi, qhi)
|
|
|
- 854 END;
|
|
|
- 855 QbeGen.CheckRange(ql, qlo,
|
|
|
- 856 qhi);
|
|
|
- 857 eT := SymTab.ArrayElem(t);
|
|
|
- 858 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
- 859 t, qe);
|
|
|
- 860 IF SymTab.ClassOf(eT) =
|
|
|
- 861 SymTab.ClArray THEN
|
|
|
- 862 QbeGen.ElemLoad(qe, eT, q)
|
|
|
- 863 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 864 END;
|
|
|
- 865 t := eT; sfx := TRUE
|
|
|
- 866 END; .)
|
|
|
- 867 { "," Expr<it, iq>
|
|
|
- 868 (. IF t = SymTab.InvalidType THEN
|
|
|
- 869 ELSIF SymTab.ClassOf(t) #
|
|
|
- 870 SymTab.ClArray THEN
|
|
|
- 871 SemError(217);
|
|
|
- 872 t := SymTab.InvalidType
|
|
|
- 873 ELSIF ~SymTab.IsIntFamily(it)
|
|
|
- 874 & (SymTab.ClassOf(it) #
|
|
|
- 875 SymTab.ClChar) THEN
|
|
|
- 876 SemError(218);
|
|
|
- 877 t := SymTab.InvalidType
|
|
|
- 878 ELSE
|
|
|
- 879 QbeGen.WidenIndex(iq, ql);
|
|
|
- 880 isOpen :=
|
|
|
- 881 SymTab.IsOpenArray(t);
|
|
|
- 882 IF isOpen THEN
|
|
|
- 883 QbeGen.CopyOp("0", qlo);
|
|
|
- 884 QbeGen.OpenHi(q, qhi)
|
|
|
- 885 ELSE
|
|
|
- 886 lo := SymTab.ArrayLo(t);
|
|
|
- 887 hi := SymTab.ArrayHi(t);
|
|
|
- 888 QbeGen.IntStr(lo, qlo);
|
|
|
- 889 QbeGen.IntStr(hi, qhi)
|
|
|
- 890 END;
|
|
|
- 891 QbeGen.CheckRange(ql, qlo,
|
|
|
- 892 qhi);
|
|
|
- 893 eT := SymTab.ArrayElem(t);
|
|
|
- 894 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
- 895 t, qe);
|
|
|
- 896 IF SymTab.ClassOf(eT) =
|
|
|
- 897 SymTab.ClArray THEN
|
|
|
- 898 QbeGen.ElemLoad(qe, eT, q)
|
|
|
- 899 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 900 END;
|
|
|
- 901 t := eT; sfx := TRUE
|
|
|
- 902 END; .) }
|
|
|
- 903 "]" } .
|
|
|
- 904 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 905 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 906 op: INTEGER;
|
|
|
- 907 q2, qt: QbeGen.QVal;
|
|
|
- 908 isR: BOOLEAN; .)
|
|
|
- 909 = SimExpr<t, q>
|
|
|
- 910 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 911 (. IF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 912 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 913 t := SymTab.BoolType()
|
|
|
- 914 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 915 isR := FALSE END;
|
|
|
- 916 IF t # SymTab.InvalidType THEN
|
|
|
- 917 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
- 918 QbeGen.CopyOp(qt, q)
|
|
|
- 919 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 920 END; .) ] .
|
|
|
- 921 Rel<VAR op: INTEGER>
|
|
|
- 922 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 923 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 924 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 925 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 926 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 927 | ">=" (. op := SymTab.OpGe; .) .
|
|
|
- 928 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 929 (. VAR t2, res2: SymTab.TypeIndex;
|
|
|
- 930 op: INTEGER;
|
|
|
- 931 q2, qt: QbeGen.QVal;
|
|
|
- 932 neg, isR: BOOLEAN; .)
|
|
|
- 933 = (. neg := FALSE; .)
|
|
|
- 934 [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
- 935 Term<t, q> (. IF neg THEN
|
|
|
- 936 IF QbeGen.IsImm(q) THEN
|
|
|
- 937 QbeGen.NegFold(q, q)
|
|
|
- 938 ELSE QbeGen.NewTemp(qt);
|
|
|
- 939 QbeGen.NegQ(q, qt,
|
|
|
- 940 SymTab.ClassOf(t)
|
|
|
- 941 = SymTab.ClReal);
|
|
|
- 942 QbeGen.CopyOp(qt, q)
|
|
|
- 943 END
|
|
|
- 944 END; .)
|
|
|
- 945 { AddOp<op> Term<t2, q2>
|
|
|
- 946 (. IF op = SymTab.OpOr THEN
|
|
|
- 947 IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
- 948 t := SymTab.BoolType()
|
|
|
- 949 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 950 IF t # SymTab.InvalidType THEN
|
|
|
- 951 QbeGen.NewTemp(qt);
|
|
|
- 952 QbeGen.Op3("or", qt, q, q2, FALSE);
|
|
|
- 953 QbeGen.CopyOp(qt, q)
|
|
|
- 954 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 955 END
|
|
|
- 956 ELSE
|
|
|
- 957 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 958 t := res2
|
|
|
- 959 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 960 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 961 IF t # SymTab.InvalidType THEN
|
|
|
- 962 QbeGen.NewTemp(qt);
|
|
|
- 963 IF op = SymTab.OpAdd THEN
|
|
|
- 964 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
- 965 ELSE
|
|
|
- 966 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
- 967 END;
|
|
|
- 968 QbeGen.CopyOp(qt, q)
|
|
|
- 969 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 970 END
|
|
|
- 971 END; .) } .
|
|
|
- 972 AddOp<VAR op: INTEGER>
|
|
|
- 973 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 974 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 975 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 976 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 977 (. VAR t2, res2: SymTab.TypeIndex;
|
|
|
- 978 op: INTEGER;
|
|
|
- 979 q2, qt: QbeGen.QVal;
|
|
|
- 980 isR: BOOLEAN; .)
|
|
|
- 981 = Fact<t, q> { MulOp<op> Fact<t2, q2>
|
|
|
- 982 (. IF op = SymTab.OpAnd THEN
|
|
|
- 983 IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
- 984 t := SymTab.BoolType()
|
|
|
- 985 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 986 IF t # SymTab.InvalidType THEN
|
|
|
- 987 QbeGen.NewTemp(qt);
|
|
|
- 988 QbeGen.Op3("and", qt, q, q2, FALSE);
|
|
|
- 989 QbeGen.CopyOp(qt, q)
|
|
|
- 990 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 991 END
|
|
|
- 992 ELSE
|
|
|
- 993 IF SymTab.ArithCheck(t, t2,
|
|
|
- 994 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 995 res2) THEN t := res2
|
|
|
- 996 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 997 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 998 IF t # SymTab.InvalidType THEN
|
|
|
- 999 QbeGen.NewTemp(qt);
|
|
|
- 1000 IF op = SymTab.OpTimes THEN
|
|
|
- 1001 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
- 1002 ELSIF (op = SymTab.OpDiv)
|
|
|
- 1003 OR (op = SymTab.OpSlash) THEN
|
|
|
- 1004 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
- 1005 ELSE
|
|
|
- 1006 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
- 1007 END;
|
|
|
- 1008 QbeGen.CopyOp(qt, q)
|
|
|
- 1009 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 1010 END
|
|
|
- 1011 END; .) } .
|
|
|
- 1012 MulOp<VAR op: INTEGER>
|
|
|
- 1013 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 1014 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 1015 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 1016 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 1017 | "AND" (. op := SymTab.OpAnd; .) .
|
|
|
- 1018 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1019 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 1020 et, dt, t2: SymTab.TypeIndex;
|
|
|
- 1021 dk: INTEGER;
|
|
|
- 1022 qd, q2: QbeGen.QVal;
|
|
|
- 1023 qn: SymTab.Name;
|
|
|
- 1024 sfx: BOOLEAN; .)
|
|
|
- 1025 = integer (. LexString(s);
|
|
|
- 1026 QbeGen.NormInt(s, q);
|
|
|
- 1027 t := SymTab.IntType(); .)
|
|
|
- 1028 | real (. LexString(s);
|
|
|
- 1029 QbeGen.NormReal(s, q);
|
|
|
- 1030 t := SymTab.RealType(); .)
|
|
|
- 1031 | string (. LexString(s);
|
|
|
- 1032 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 1033 t := SymTab.CharType();
|
|
|
- 1034 QbeGen.IntStr(
|
|
|
- 1035 QbeGen.CharVal(s), q)
|
|
|
- 1036 ELSE t := SymTab.NewStr();
|
|
|
- 1037 QbeGen.DeclStr(s, q)
|
|
|
- 1038 END; .)
|
|
|
- 1039 | Design<dt, dk, qd, qn, sfx> (. t := dt;
|
|
|
- 1040 IF sfx THEN
|
|
|
- 1041 IF dt #
|
|
|
- 1042 SymTab.InvalidType THEN
|
|
|
- 1043 QbeGen.ElemLoad(qd, dt, q)
|
|
|
- 1044 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 1045 END
|
|
|
- 1046 ELSE QbeGen.CopyOp(qd, q)
|
|
|
- 1047 END; .)
|
|
|
- 1048 | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
- 1049 | "NOT" Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
- 1050 t := SymTab.BoolType()
|
|
|
- 1051 ELSE SemError(212);
|
|
|
- 1052 t := SymTab.InvalidType END;
|
|
|
- 1053 IF t # SymTab.InvalidType THEN
|
|
|
- 1054 QbeGen.NotQ(q2, q)
|
|
|
- 1055 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 1056 END; .) .
|
|
|
- 1057 GetIdent<VAR n: SymTab.Name>
|
|
|
- 1058 = ident (. LexName(n); .) .
|
|
|
- 1059
|
|
|
- 1060 END M2.
|
|
|
+ 334 ct := SymTab.NewClass();
|
|
|
+ 335 SymTab.SetSymType(cn, ct);
|
|
|
+ 336 SymTab.PushClassScope(ct); .)
|
|
|
+ 337 [ Parents<ct> ]
|
|
|
+ 338 ";"
|
|
|
+ 339 { ClassField<ct> ";" }
|
|
|
+ 340 { MethodHeading<pn> ";" (. SymTab.CloseProc; .) }
|
|
|
+ 341 "END"
|
|
|
+ 342 GetIdent<m2> (. IF ~SymTab.Equal(cn, m2) THEN
|
|
|
+ 343 SemError(202) END;
|
|
|
+ 344 SymTab.PopScope;
|
|
|
+ 345 SemError(230); .) .
|
|
|
+ 346 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
+ 347 = "(" Parent1<ct>
|
|
|
+ 348 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
+ 349 ")" .
|
|
|
+ 350 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
+ 351 pt: SymTab.TypeIndex; .)
|
|
|
+ 352 = GetIdent<p> (. IF ~SymTab.Lookup(p) THEN
|
|
|
+ 353 SemError(201)
|
|
|
+ 354 ELSE pt := SymTab.SymType(p);
|
|
|
+ 355 IF SymTab.ClassOf(pt) #
|
|
|
+ 356 SymTab.ClClass THEN
|
|
|
+ 357 SemError(230)
|
|
|
+ 358 ELSE SymTab.SetParent(ct, pt)
|
|
|
+ 359 END
|
|
|
+ 360 END; .) .
|
|
|
+ 361 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
+ 362 t: SymTab.TypeIndex; .)
|
|
|
+ 363 = GetIdent<n>
|
|
|
+ 364 ( "=" GetIdent<rhs> (. IF ~SymTab.Enter(n,
|
|
|
+ 365 SymTab.KindConst) THEN
|
|
|
+ 366 SemError(200) END;
|
|
|
+ 367 IF SymTab.Lookup(rhs) THEN
|
|
|
+ 368 SymTab.SetSymType(n,
|
|
|
+ 369 SymTab.SymType(rhs))
|
|
|
+ 370 END; .)
|
|
|
+ 371 | (. IF ~SymTab.FieldPending(ct,
|
|
|
+ 372 n) THEN
|
|
|
+ 373 SemError(200) END; .)
|
|
|
+ 374 { "," GetIdent<n> (. IF ~SymTab.FieldPending(ct,
|
|
|
+ 375 n) THEN
|
|
|
+ 376 SemError(200) END; .) }
|
|
|
+ 377 ":" TypeIdent<t> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
+ 378 MethodHeading<VAR pn: SymTab.Name> (. VAR wantVirt: BOOLEAN; .)
|
|
|
+ 379 = (. wantVirt := FALSE; .)
|
|
|
+ 380 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
+ 381 ProcHeading<pn> (. IF wantVirt THEN
|
|
|
+ 382 SymTab.MarkVirtual END; .) .
|
|
|
+ 383 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
+ 384 ct: SymTab.TypeIndex; .)
|
|
|
+ 385 = GetIdent<cn> (. IF ~SymTab.Lookup(cn) THEN
|
|
|
+ 386 SemError(201);
|
|
|
+ 387 ct := SymTab.InvalidType
|
|
|
+ 388 ELSE ct := SymTab.SymType(cn);
|
|
|
+ 389 IF SymTab.ClassOf(ct) #
|
|
|
+ 390 SymTab.ClClass THEN
|
|
|
+ 391 SemError(230);
|
|
|
+ 392 ct := SymTab.InvalidType
|
|
|
+ 393 END
|
|
|
+ 394 END;
|
|
|
+ 395 IF ct #
|
|
|
+ 396 SymTab.InvalidType THEN
|
|
|
+ 397 IF ~SymTab.PushClassMembers(
|
|
|
+ 398 ct) THEN
|
|
|
+ 399 SemError(230) END
|
|
|
+ 400 END; .)
|
|
|
+ 401 ";" { MethodImpl<ct> ";" }
|
|
|
+ 402 [ "BEGIN"
|
|
|
+ 403 [ StatSeq ] ]
|
|
|
+ 404 "END"
|
|
|
+ 405 GetIdent<m2> (. IF ~SymTab.Equal(cn, m2) THEN
|
|
|
+ 406 SemError(202) END;
|
|
|
+ 407 SymTab.PopScope;
|
|
|
+ 408 SemError(230); .) .
|
|
|
+ 409 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name; .)
|
|
|
+ 410 = MethodHeading<pn> ";"
|
|
|
+ 411 (. IF (ct #
|
|
|
+ 412 SymTab.InvalidType)
|
|
|
+ 413 & ~SymTab.MethodExists(ct,
|
|
|
+ 414 pn) THEN
|
|
|
+ 415 SemError(201) END; .)
|
|
|
+ 416 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
+ 417 SymTab.CloseProc; .)
|
|
|
+ 418 | Block<pn> (. SymTab.CloseProc;
|
|
|
+ 419 SemError(230); .) ) .
|
|
|
+ 420 ConstBlock
|
|
|
+ 421 = "CONST" { ConstDecl ";" } .
|
|
|
+ 422 ConstDecl (. VAR n: SymTab.Name;
|
|
|
+ 423 t: SymTab.TypeIndex;
|
|
|
+ 424 qv: QbeGen.QVal;
|
|
|
+ 425 cls: INTEGER; .)
|
|
|
+ 426 = GetIdent<n> (. IF ~SymTab.Enter(n,
|
|
|
+ 427 SymTab.KindConst) THEN
|
|
|
+ 428 SemError(200) END; .)
|
|
|
+ 429 "="
|
|
|
+ 430 Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
+ 431 cls := SymTab.ClassOf(t);
|
|
|
+ 432 IF cls = SymTab.ClStr THEN
|
|
|
+ 433 SemError(230)
|
|
|
+ 434 ELSIF ~QbeGen.IsImm(qv) THEN
|
|
|
+ 435 SemError(230) END;
|
|
|
+ 436 QbeGen.DeclConst(n, qv, t); .) .
|
|
|
+ 437 VarBlock
|
|
|
+ 438 = "VAR" { VarDecl ";" } .
|
|
|
+ 439 VarDecl (. VAR nm: SymTab.Name;
|
|
|
+ 440 t: SymTab.TypeIndex;
|
|
|
+ 441 i: CARDINAL;
|
|
|
+ 442 cls: INTEGER; .)
|
|
|
+ 443 = VarIdents ":"
|
|
|
+ 444 Type<t, FALSE> (. cls := SymTab.ClassOf(t);
|
|
|
+ 445 IF (t # SymTab.InvalidType)
|
|
|
+ 446 & (cls # SymTab.ClInt)
|
|
|
+ 447 & (cls # SymTab.ClBool)
|
|
|
+ 448 & (cls # SymTab.ClChar)
|
|
|
+ 449 & (cls # SymTab.ClReal)
|
|
|
+ 450 & (cls # SymTab.ClArray)
|
|
|
+ 451 & (cls # SymTab.ClSet) THEN
|
|
|
+ 452 SemError(230) END;
|
|
|
+ 453 i := 0;
|
|
|
+ 454 WHILE i < SymTab.PendCount() DO
|
|
|
+ 455 SymTab.PendName(i, nm);
|
|
|
+ 456 QbeGen.DeclVar(nm, t);
|
|
|
+ 457 INC(i)
|
|
|
+ 458 END;
|
|
|
+ 459 SymTab.FixPending(t); .) .
|
|
|
+ 460 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
+ 461 = GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
+ 462 SymTab.KindVar) THEN
|
|
|
+ 463 SemError(200) END; .)
|
|
|
+ 464 { ","
|
|
|
+ 465 GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
+ 466 SymTab.KindVar) THEN
|
|
|
+ 467 SemError(200) END; .) } .
|
|
|
+ 468 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ 469 = GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
+ 470 SemError(200) END; .)
|
|
|
+ 471 { "," GetIdent<n> (. IF ~SymTab.EnterParam(n, isV) THEN
|
|
|
+ 472 SemError(200) END; .) } .
|
|
|
+ 473 (* Procedure headings enter now (scopes, params, result); bodies
|
|
|
+ 474 parse + check with one 230 at END (lowering = step 4).
|
|
|
+ 475 FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ 476 tightens in step 4). *)
|
|
|
+ 477 ProcHeading<VAR pn: SymTab.Name> (. VAR t: SymTab.TypeIndex; .)
|
|
|
+ 478 = "PROCEDURE"
|
|
|
+ 479 GetIdent<pn> (. IF ~SymTab.EnterProc(pn) THEN
|
|
|
+ 480 IF ~SymTab.ReenterProc(pn) THEN
|
|
|
+ 481 SemError(200) END
|
|
|
+ 482 END; .)
|
|
|
+ 483 [ FormalParams ]
|
|
|
+ 484 [ ":" TypeIdent<t> (. SymTab.SetProcRes(t);
|
|
|
+ 485 IF (t #
|
|
|
+ 486 SymTab.InvalidType)
|
|
|
+ 487 & (SymTab.ClassOf(t)
|
|
|
+ 488 = SymTab.ClArray) THEN
|
|
|
+ 489 SemError(230) END; .) ] .
|
|
|
+ 490 FormalParams
|
|
|
+ 491 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ 492 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ 493 isV: BOOLEAN; .)
|
|
|
+ 494 = (. isV := FALSE; .)
|
|
|
+ 495 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 496 ParIdents<isV> ":" Type<t, TRUE> (. SymTab.FixPending(t); .) .
|
|
|
+ 497 ProcDecl (. VAR pn, m2: SymTab.Name; .)
|
|
|
+ 498 = ProcHeading<pn> ";"
|
|
|
+ 499 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
+ 500 SymTab.CloseProc; .)
|
|
|
+ 501 | Block<pn> (. SymTab.CloseProc;
|
|
|
+ 502 SemError(230); .) ) .
|
|
|
+ 503 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
+ 504 = DeclSeq
|
|
|
+ 505 [ "BEGIN"
|
|
|
+ 506 [ StatSeq ] ]
|
|
|
+ 507 "END"
|
|
|
+ 508 GetIdent<m2> (. IF ~SymTab.Equal(pn, m2) THEN
|
|
|
+ 509 SemError(202) END; .) .
|
|
|
+ 510 StatSeq
|
|
|
+ 511 = Statement { ";" Statement } .
|
|
|
+ 512 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
+ 513 = Assign
|
|
|
+ 514 | IfStat
|
|
|
+ 515 | WhileStat
|
|
|
+ 516 | RepeatStat
|
|
|
+ 517 | LoopStat
|
|
|
+ 518 | ForStat
|
|
|
+ 519 | CaseStat
|
|
|
+ 520 | ReturnStat
|
|
|
+ 521 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
+ 522 QbeGen.Jmp(lx)
|
|
|
+ 523 ELSE SemError(230) END; .) .
|
|
|
+ 524 Assign (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ 525 dk: INTEGER;
|
|
|
+ 526 qd, qe, qt: QbeGen.QVal;
|
|
|
+ 527 qn: SymTab.Name;
|
|
|
+ 528 isR, conv: BOOLEAN;
|
|
|
+ 529 sfx: BOOLEAN; .)
|
|
|
+ 530 = Design<dt, dk, qd, qn, sfx> ":="
|
|
|
+ 531 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
+ 532 & (dk # SymTab.KindVar)
|
|
|
+ 533 & (dk # SymTab.KindParam) THEN
|
|
|
+ 534 SemError(210)
|
|
|
+ 535 ELSIF ~SymTab.Assignable(et,
|
|
|
+ 536 dt) THEN
|
|
|
+ 537 SemError(210) END;
|
|
|
+ 538 isR := (dt #
|
|
|
+ 539 SymTab.InvalidType)
|
|
|
+ 540 & (SymTab.ClassOf(dt)
|
|
|
+ 541 = SymTab.ClReal);
|
|
|
+ 542 conv := isR
|
|
|
+ 543 & SymTab.IsIntFamily(et);
|
|
|
+ 544 IF ((dk = SymTab.KindVar)
|
|
|
+ 545 OR (dk = SymTab.KindParam))
|
|
|
+ 546 & (dt # SymTab.InvalidType)
|
|
|
+ 547 & (et # SymTab.InvalidType) THEN
|
|
|
+ 548 IF sfx THEN
|
|
|
+ 549 IF SymTab.ClassOf(dt) =
|
|
|
+ 550 SymTab.ClArray THEN
|
|
|
+ 551 QbeGen.CopyArray(qd, qe,
|
|
|
+ 552 dt)
|
|
|
+ 553 ELSIF conv THEN
|
|
|
+ 554 QbeGen.ConvIR(qe, qt);
|
|
|
+ 555 QbeGen.ElemStore(qd, qt,
|
|
|
+ 556 dt)
|
|
|
+ 557 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
+ 558 dt)
|
|
|
+ 559 END
|
|
|
+ 560 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 561 SymTab.ClArray THEN
|
|
|
+ 562 QbeGen.CopyArray(qd, qe, dt)
|
|
|
+ 563 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 564 SymTab.ClSet THEN
|
|
|
+ 565 QbeGen.CopySet(qd, qe,
|
|
|
+ 566 SymTab.SetWords(dt),
|
|
|
+ 567 SymTab.SetWords(et))
|
|
|
+ 568 ELSIF conv THEN
|
|
|
+ 569 QbeGen.ConvIR(qe, qt);
|
|
|
+ 570 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
+ 571 ELSE
|
|
|
+ 572 QbeGen.StoreVar(qn, qe, isR)
|
|
|
+ 573 END
|
|
|
+ 574 END; .) .
|
|
|
+ 575 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 576 q, lThen, lElse, lEnd:
|
|
|
+ 577 QbeGen.QVal;
|
|
|
+ 578 hasElse: BOOLEAN; .)
|
|
|
+ 579 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 580 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ 581 SemError(214) END;
|
|
|
+ 582 QbeGen.NewLabel(lThen);
|
|
|
+ 583 QbeGen.NewLabel(lElse);
|
|
|
+ 584 QbeGen.NewLabel(lEnd);
|
|
|
+ 585 QbeGen.Jnz(q, lThen, lElse);
|
|
|
+ 586 QbeGen.EmitLabel(lThen); .)
|
|
|
+ 587 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .)
|
|
|
+ 588 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
+ 589 QbeGen.NewLabel(lElse); .)
|
|
|
+ 590 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ 591 SemError(214) END;
|
|
|
+ 592 QbeGen.NewLabel(lThen);
|
|
|
+ 593 QbeGen.Jnz(q, lThen, lElse);
|
|
|
+ 594 QbeGen.EmitLabel(lThen); .)
|
|
|
+ 595 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .) }
|
|
|
+ 596 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
+ 597 hasElse := TRUE; .)
|
|
|
+ 598 StatSeq ]
|
|
|
+ 599 "END" (. IF hasElse THEN
|
|
|
+ 600 QbeGen.EmitLabel(lEnd)
|
|
|
+ 601 ELSE QbeGen.EmitLabel(lElse);
|
|
|
+ 602 QbeGen.EmitLabel(lEnd)
|
|
|
+ 603 END; .) .
|
|
|
+ 604 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 605 q, lTop, lBody, lEnd:
|
|
|
+ 606 QbeGen.QVal; .)
|
|
|
+ 607 = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
+ 608 QbeGen.NewLabel(lBody);
|
|
|
+ 609 QbeGen.NewLabel(lEnd);
|
|
|
+ 610 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 611 Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ 612 SemError(214) END;
|
|
|
+ 613 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
+ 614 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 615 "DO" StatSeq (. QbeGen.Jmp(lTop); .)
|
|
|
+ 616 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 617 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 618 q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
+ 619 = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
+ 620 QbeGen.NewLabel(lEnd);
|
|
|
+ 621 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 622 StatSeq
|
|
|
+ 623 "UNTIL" Expr<t, q> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ 624 SemError(214) END;
|
|
|
+ 625 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
+ 626 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 627 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
+ 628 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
+ 629 QbeGen.NewLabel(lEnd);
|
|
|
+ 630 QbeGen.PushLoop(lEnd);
|
|
|
+ 631 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 632 StatSeq
|
|
|
+ 633 "END" (. QbeGen.Jmp(lTop);
|
|
|
+ 634 QbeGen.PopLoop;
|
|
|
+ 635 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 636 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 637 Runtime direction would need a compare-select; the literal
|
|
|
+ 638 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 639 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 640 tlo, thi, tby:
|
|
|
+ 641 SymTab.TypeIndex;
|
|
|
+ 642 qlo, qhi, qby, qt, qk, qb:
|
|
|
+ 643 QbeGen.QVal;
|
|
|
+ 644 lTop, lBody, lEnd:
|
|
|
+ 645 QbeGen.QVal;
|
|
|
+ 646 by: INTEGER;
|
|
|
+ 647 ok: BOOLEAN; .)
|
|
|
+ 648 = "FOR" (. by := 1; .)
|
|
|
+ 649 GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
+ 650 IF ~ok THEN
|
|
|
+ 651 SemError(201)
|
|
|
+ 652 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 653 SymTab.KindVar)
|
|
|
+ 654 & (SymTab.SymKind(lv) #
|
|
|
+ 655 SymTab.KindParam) THEN
|
|
|
+ 656 SemError(220); ok := FALSE
|
|
|
+ 657 ELSIF ~SymTab.IsIntFamily(
|
|
|
+ 658 SymTab.SymType(lv)) THEN
|
|
|
+ 659 SemError(220); ok := FALSE
|
|
|
+ 660 END; .)
|
|
|
+ 661 ":=" Expr<tlo, qlo> (. IF ~SymTab.IsIntFamily(tlo) THEN
|
|
|
+ 662 SemError(220); ok := FALSE
|
|
|
+ 663 END; .)
|
|
|
+ 664 "TO" Expr<thi, qhi> (. IF ~SymTab.IsIntFamily(thi) THEN
|
|
|
+ 665 SemError(220); ok := FALSE
|
|
|
+ 666 END; .)
|
|
|
+ 667 [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
+ 668 SymTab.InvalidType)
|
|
|
+ 669 & ~SymTab.IsIntFamily(tby) THEN
|
|
|
+ 670 SemError(220); ok := FALSE
|
|
|
+ 671 END;
|
|
|
+ 672 IF ~SymTab.ConstInt(qby, by) THEN
|
|
|
+ 673 SemError(230); by := 1
|
|
|
+ 674 ELSIF by = 0 THEN
|
|
|
+ 675 SemError(220); by := 1
|
|
|
+ 676 END; .) ]
|
|
|
+ 677 "DO" (. IF ok THEN
|
|
|
+ 678 QbeGen.StoreVar(lv, qlo,
|
|
|
+ 679 FALSE) END;
|
|
|
+ 680 QbeGen.NewLabel(lTop);
|
|
|
+ 681 QbeGen.NewLabel(lBody);
|
|
|
+ 682 QbeGen.NewLabel(lEnd);
|
|
|
+ 683 QbeGen.EmitLabel(lTop);
|
|
|
+ 684 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
+ 685 QbeGen.NewTemp(qk);
|
|
|
+ 686 IF by > 0 THEN
|
|
|
+ 687 QbeGen.Op3("cslew", qk,
|
|
|
+ 688 qt, qhi, FALSE)
|
|
|
+ 689 ELSE QbeGen.Op3("csgew", qk,
|
|
|
+ 690 qt, qhi, FALSE)
|
|
|
+ 691 END;
|
|
|
+ 692 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
+ 693 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 694 StatSeq
|
|
|
+ 695 "END" (. IF ok THEN
|
|
|
+ 696 QbeGen.LoadVar(lv, FALSE,
|
|
|
+ 697 qt);
|
|
|
+ 698 QbeGen.IntStr(by, qb);
|
|
|
+ 699 QbeGen.NewTemp(qk);
|
|
|
+ 700 QbeGen.Op3("add", qk,
|
|
|
+ 701 qt, qb, FALSE);
|
|
|
+ 702 QbeGen.StoreVar(lv, qk,
|
|
|
+ 703 FALSE) END;
|
|
|
+ 704 QbeGen.Jmp(lTop);
|
|
|
+ 705 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 706 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 707 qsel, lEnd: QbeGen.QVal; .)
|
|
|
+ 708 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
+ 709 "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
+ 710 { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
+ 711 [ "ELSE" StatSeq ]
|
|
|
+ 712 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 713 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 714 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 715 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 716 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 717 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 718 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
+ 719 = (. QbeGen.NewLabel(lBody);
|
|
|
+ 720 QbeGen.NewLabel(lAfter); .)
|
|
|
+ 721 CaseLabel<tsel, qsel, lBody>
|
|
|
+ 722 { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
+ 723 ":" (. QbeGen.Jmp(lAfter);
|
|
|
+ 724 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 725 StatSeq (. QbeGen.Jmp(lEnd);
|
|
|
+ 726 QbeGen.EmitLabel(lAfter); .) .
|
|
|
+ 727 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 728 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 729 q2, q3, qc, qd, qe:
|
|
|
+ 730 QbeGen.QVal;
|
|
|
+ 731 lNext: QbeGen.QVal; .)
|
|
|
+ 732 = Expr<t2, q2> (. IF (t2 #
|
|
|
+ 733 SymTab.InvalidType)
|
|
|
+ 734 & (tsel #
|
|
|
+ 735 SymTab.InvalidType)
|
|
|
+ 736 & ((SymTab.ClassOf(t2) =
|
|
|
+ 737 SymTab.ClSet)
|
|
|
+ 738 OR (SymTab.ClassOf(tsel) =
|
|
|
+ 739 SymTab.ClSet)) THEN
|
|
|
+ 740 SemError(230)
|
|
|
+ 741 ELSIF (t2 #
|
|
|
+ 742 SymTab.InvalidType)
|
|
|
+ 743 & (tsel #
|
|
|
+ 744 SymTab.InvalidType)
|
|
|
+ 745 & ~SymTab.EqCheck(t2,
|
|
|
+ 746 tsel) THEN
|
|
|
+ 747 SemError(213) END;
|
|
|
+ 748 IF ~QbeGen.IsImm(q2) THEN
|
|
|
+ 749 SemError(230);
|
|
|
+ 750 QbeGen.CopyOp("0", q2)
|
|
|
+ 751 END;
|
|
|
+ 752 QbeGen.NewLabel(lNext);
|
|
|
+ 753 QbeGen.Cmp(SymTab.OpEq,
|
|
|
+ 754 qsel, q2, qc, FALSE);
|
|
|
+ 755 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
+ 756 QbeGen.EmitLabel(lNext); .)
|
|
|
+ 757 [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
+ 758 SymTab.InvalidType)
|
|
|
+ 759 & (tsel #
|
|
|
+ 760 SymTab.InvalidType)
|
|
|
+ 761 & ~SymTab.EqCheck(t3,
|
|
|
+ 762 tsel) THEN
|
|
|
+ 763 SemError(213) END;
|
|
|
+ 764 IF ~QbeGen.IsImm(q3) THEN
|
|
|
+ 765 SemError(230);
|
|
|
+ 766 QbeGen.CopyOp("0", q3)
|
|
|
+ 767 END;
|
|
|
+ 768 QbeGen.Cmp(SymTab.OpGe,
|
|
|
+ 769 qsel, q2, qc, FALSE);
|
|
|
+ 770 QbeGen.Cmp(SymTab.OpLe,
|
|
|
+ 771 qsel, q3, qd, FALSE);
|
|
|
+ 772 QbeGen.NewTemp(qe);
|
|
|
+ 773 QbeGen.Op3("and", qe, qc, qd,
|
|
|
+ 774 FALSE);
|
|
|
+ 775 QbeGen.NewLabel(lNext);
|
|
|
+ 776 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
+ 777 QbeGen.EmitLabel(lNext); .) ] .
|
|
|
+ 778 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 779 q: QbeGen.QVal;
|
|
|
+ 780 res: SymTab.TypeIndex;
|
|
|
+ 781 hadE: BOOLEAN; .)
|
|
|
+ 782 = "RETURN" (. hadE := FALSE; .)
|
|
|
+ 783 [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
+ 784 (. IF ~SymTab.InProc() THEN
|
|
|
+ 785 SemError(232)
|
|
|
+ 786 ELSE res := SymTab.CurRes();
|
|
|
+ 787 IF ~hadE THEN
|
|
|
+ 788 IF res #
|
|
|
+ 789 SymTab.InvalidType THEN
|
|
|
+ 790 SemError(232) END
|
|
|
+ 791 ELSIF (res =
|
|
|
+ 792 SymTab.InvalidType)
|
|
|
+ 793 OR (t #
|
|
|
+ 794 SymTab.InvalidType)
|
|
|
+ 795 & ~SymTab.Assignable(t,
|
|
|
+ 796 res) THEN
|
|
|
+ 797 SemError(232)
|
|
|
+ 798 END
|
|
|
+ 799 END; .) .
|
|
|
+ 800 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 801 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 802 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 803 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 804 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 805 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 806 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 807 (. VAR n: SymTab.Name;
|
|
|
+ 808 cls: INTEGER;
|
|
|
+ 809 it, eT: SymTab.TypeIndex;
|
|
|
+ 810 iq, ql, qlo, qhi, qe:
|
|
|
+ 811 QbeGen.QVal;
|
|
|
+ 812 lo, hi: INTEGER;
|
|
|
+ 813 isOpen: BOOLEAN; .)
|
|
|
+ 814 = GetIdent<n> (. QbeGen.CopyOp(n, qn);
|
|
|
+ 815 sfx := FALSE;
|
|
|
+ 816 IF ~SymTab.Lookup(n) THEN
|
|
|
+ 817 SemError(201);
|
|
|
+ 818 t := SymTab.InvalidType;
|
|
|
+ 819 k := -1;
|
|
|
+ 820 QbeGen.CopyOp("0", q)
|
|
|
+ 821 ELSE
|
|
|
+ 822 t := SymTab.SymType(n);
|
|
|
+ 823 k := SymTab.SymKind(n);
|
|
|
+ 824 IF k = SymTab.KindConst THEN
|
|
|
+ 825 IF SymTab.Equal(n,
|
|
|
+ 826 "TRUE") THEN
|
|
|
+ 827 t := SymTab.BoolType();
|
|
|
+ 828 QbeGen.CopyOp("1", q)
|
|
|
+ 829 ELSIF SymTab.Equal(n,
|
|
|
+ 830 "FALSE") THEN
|
|
|
+ 831 t := SymTab.BoolType();
|
|
|
+ 832 QbeGen.CopyOp("0", q)
|
|
|
+ 833 ELSE
|
|
|
+ 834 cls :=
|
|
|
+ 835 SymTab.ClassOf(t);
|
|
|
+ 836 IF (t #
|
|
|
+ 837 SymTab.InvalidType)
|
|
|
+ 838 & ((cls = SymTab.ClInt)
|
|
|
+ 839 OR (cls
|
|
|
+ 840 = SymTab.ClChar)
|
|
|
+ 841 OR (cls
|
|
|
+ 842 = SymTab.ClReal)) THEN
|
|
|
+ 843 QbeGen.LoadVar(n,
|
|
|
+ 844 cls = SymTab.ClReal, q)
|
|
|
+ 845 ELSE
|
|
|
+ 846 IF t #
|
|
|
+ 847 SymTab.InvalidType THEN
|
|
|
+ 848 SemError(230)
|
|
|
+ 849 END;
|
|
|
+ 850 QbeGen.CopyOp("0", q)
|
|
|
+ 851 END
|
|
|
+ 852 END
|
|
|
+ 853 ELSIF (k = SymTab.KindVar)
|
|
|
+ 854 OR (k = SymTab.KindParam) THEN
|
|
|
+ 855 cls :=
|
|
|
+ 856 SymTab.ClassOf(t);
|
|
|
+ 857 IF (cls = SymTab.ClInt)
|
|
|
+ 858 OR (cls = SymTab.ClBool)
|
|
|
+ 859 OR (cls = SymTab.ClChar)
|
|
|
+ 860 OR (cls
|
|
|
+ 861 = SymTab.ClReal) THEN
|
|
|
+ 862 QbeGen.LoadVar(n,
|
|
|
+ 863 cls = SymTab.ClReal, q)
|
|
|
+ 864 ELSIF (cls
|
|
|
+ 865 = SymTab.ClArray)
|
|
|
+ 866 OR (cls
|
|
|
+ 867 = SymTab.ClSet) THEN
|
|
|
+ 868 QbeGen.AddrOf(n, q)
|
|
|
+ 869 ELSE SemError(230);
|
|
|
+ 870 QbeGen.CopyOp("0", q)
|
|
|
+ 871 END
|
|
|
+ 872 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 873 IF (k = SymTab.KindImport)
|
|
|
+ 874 OR (k = SymTab.KindProc)
|
|
|
+ 875 OR (k
|
|
|
+ 876 = SymTab.KindField) THEN
|
|
|
+ 877 SemError(230)
|
|
|
+ 878 END
|
|
|
+ 879 END
|
|
|
+ 880 END; .)
|
|
|
+ 881 { "[" Expr<it, iq>
|
|
|
+ 882 (. IF t = SymTab.InvalidType THEN
|
|
|
+ 883 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 884 SymTab.ClArray THEN
|
|
|
+ 885 SemError(217);
|
|
|
+ 886 t := SymTab.InvalidType
|
|
|
+ 887 ELSIF ~SymTab.IsIntFamily(it)
|
|
|
+ 888 & (SymTab.ClassOf(it) #
|
|
|
+ 889 SymTab.ClChar) THEN
|
|
|
+ 890 SemError(218);
|
|
|
+ 891 t := SymTab.InvalidType
|
|
|
+ 892 ELSE
|
|
|
+ 893 QbeGen.WidenIndex(iq, ql);
|
|
|
+ 894 isOpen :=
|
|
|
+ 895 SymTab.IsOpenArray(t);
|
|
|
+ 896 IF isOpen THEN
|
|
|
+ 897 QbeGen.CopyOp("0", qlo);
|
|
|
+ 898 QbeGen.OpenHi(q, qhi)
|
|
|
+ 899 ELSE
|
|
|
+ 900 lo := SymTab.ArrayLo(t);
|
|
|
+ 901 hi := SymTab.ArrayHi(t);
|
|
|
+ 902 QbeGen.IntStr(lo, qlo);
|
|
|
+ 903 QbeGen.IntStr(hi, qhi)
|
|
|
+ 904 END;
|
|
|
+ 905 QbeGen.CheckRange(ql, qlo,
|
|
|
+ 906 qhi);
|
|
|
+ 907 eT := SymTab.ArrayElem(t);
|
|
|
+ 908 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
+ 909 t, qe);
|
|
|
+ 910 IF SymTab.ClassOf(eT) =
|
|
|
+ 911 SymTab.ClArray THEN
|
|
|
+ 912 QbeGen.ElemLoad(qe, eT, q)
|
|
|
+ 913 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 914 END;
|
|
|
+ 915 t := eT; sfx := TRUE
|
|
|
+ 916 END; .)
|
|
|
+ 917 { "," Expr<it, iq>
|
|
|
+ 918 (. IF t = SymTab.InvalidType THEN
|
|
|
+ 919 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 920 SymTab.ClArray THEN
|
|
|
+ 921 SemError(217);
|
|
|
+ 922 t := SymTab.InvalidType
|
|
|
+ 923 ELSIF ~SymTab.IsIntFamily(it)
|
|
|
+ 924 & (SymTab.ClassOf(it) #
|
|
|
+ 925 SymTab.ClChar) THEN
|
|
|
+ 926 SemError(218);
|
|
|
+ 927 t := SymTab.InvalidType
|
|
|
+ 928 ELSE
|
|
|
+ 929 QbeGen.WidenIndex(iq, ql);
|
|
|
+ 930 isOpen :=
|
|
|
+ 931 SymTab.IsOpenArray(t);
|
|
|
+ 932 IF isOpen THEN
|
|
|
+ 933 QbeGen.CopyOp("0", qlo);
|
|
|
+ 934 QbeGen.OpenHi(q, qhi)
|
|
|
+ 935 ELSE
|
|
|
+ 936 lo := SymTab.ArrayLo(t);
|
|
|
+ 937 hi := SymTab.ArrayHi(t);
|
|
|
+ 938 QbeGen.IntStr(lo, qlo);
|
|
|
+ 939 QbeGen.IntStr(hi, qhi)
|
|
|
+ 940 END;
|
|
|
+ 941 QbeGen.CheckRange(ql, qlo,
|
|
|
+ 942 qhi);
|
|
|
+ 943 eT := SymTab.ArrayElem(t);
|
|
|
+ 944 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
+ 945 t, qe);
|
|
|
+ 946 IF SymTab.ClassOf(eT) =
|
|
|
+ 947 SymTab.ClArray THEN
|
|
|
+ 948 QbeGen.ElemLoad(qe, eT, q)
|
|
|
+ 949 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 950 END;
|
|
|
+ 951 t := eT; sfx := TRUE
|
|
|
+ 952 END; .) }
|
|
|
+ 953 "]" } .
|
|
|
+ 954 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 955 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 956 op: INTEGER;
|
|
|
+ 957 q2, qt: QbeGen.QVal;
|
|
|
+ 958 isR: BOOLEAN; .)
|
|
|
+ 959 = SimExpr<t, q>
|
|
|
+ 960 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 961 (. IF op = SymTab.OpIn THEN
|
|
|
+ 962 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 963 IF (t = SymTab.InvalidType)
|
|
|
+ 964 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 965 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 966 ELSE
|
|
|
+ 967 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
|
|
|
+ 968 SymTab.SetCount(t2), qt);
|
|
|
+ 969 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 970 END
|
|
|
+ 971 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 972 QbeGen.CopyOp("0", q)
|
|
|
+ 973 END
|
|
|
+ 974 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 975 IF (t = SymTab.InvalidType)
|
|
|
+ 976 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 977 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 978 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 979 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 980 QbeGen.CmpSet(op, q, q2,
|
|
|
+ 981 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
|
|
|
+ 982 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 983 ELSE
|
|
|
+ 984 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 985 t := SymTab.BoolType();
|
|
|
+ 986 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
+ 987 QbeGen.CopyOp(qt, q)
|
|
|
+ 988 END
|
|
|
+ 989 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 990 QbeGen.CopyOp("0", q)
|
|
|
+ 991 END; .) ] .
|
|
|
+ 992 Rel<VAR op: INTEGER>
|
|
|
+ 993 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 994 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 995 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 996 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 997 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 998 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 999 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 1000 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1001 (. VAR t2, res2: SymTab.TypeIndex;
|
|
|
+ 1002 op: INTEGER;
|
|
|
+ 1003 q2, qt: QbeGen.QVal;
|
|
|
+ 1004 neg, isR: BOOLEAN;
|
|
|
+ 1005 lw, rw, mw: CARDINAL; .)
|
|
|
+ 1006 = (. neg := FALSE; .)
|
|
|
+ 1007 [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
+ 1008 Term<t, q> (. IF neg THEN
|
|
|
+ 1009 IF QbeGen.IsImm(q) THEN
|
|
|
+ 1010 QbeGen.NegFold(q, q)
|
|
|
+ 1011 ELSE QbeGen.NewTemp(qt);
|
|
|
+ 1012 QbeGen.NegQ(q, qt,
|
|
|
+ 1013 SymTab.ClassOf(t)
|
|
|
+ 1014 = SymTab.ClReal);
|
|
|
+ 1015 QbeGen.CopyOp(qt, q)
|
|
|
+ 1016 END
|
|
|
+ 1017 END; .)
|
|
|
+ 1018 { AddOp<op> Term<t2, q2>
|
|
|
+ 1019 (. IF op = SymTab.OpOr THEN
|
|
|
+ 1020 IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
+ 1021 t := SymTab.BoolType()
|
|
|
+ 1022 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 1023 IF t # SymTab.InvalidType THEN
|
|
|
+ 1024 QbeGen.NewTemp(qt);
|
|
|
+ 1025 QbeGen.Op3("or", qt, q, q2, FALSE);
|
|
|
+ 1026 QbeGen.CopyOp(qt, q)
|
|
|
+ 1027 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1028 END
|
|
|
+ 1029 ELSIF (t # SymTab.InvalidType) & (t2 # SymTab.InvalidType)
|
|
|
+ 1030 & (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 1031 & (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 1032 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 1033 mw := lw;
|
|
|
+ 1034 IF rw > mw THEN mw := rw END;
|
|
|
+ 1035 IF op = SymTab.OpAdd THEN
|
|
|
+ 1036 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
|
|
|
+ 1037 ELSE
|
|
|
+ 1038 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
|
|
|
+ 1039 END;
|
|
|
+ 1040 t := SymTab.NewSet(
|
|
|
+ 1041 SymTab.NewSubR(0,
|
|
|
+ 1042 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 1043 QbeGen.CopyOp(qt, q)
|
|
|
+ 1044 ELSE
|
|
|
+ 1045 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 1046 t := res2
|
|
|
+ 1047 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 1048 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 1049 IF t # SymTab.InvalidType THEN
|
|
|
+ 1050 QbeGen.NewTemp(qt);
|
|
|
+ 1051 IF op = SymTab.OpAdd THEN
|
|
|
+ 1052 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
+ 1053 ELSE
|
|
|
+ 1054 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
+ 1055 END;
|
|
|
+ 1056 QbeGen.CopyOp(qt, q)
|
|
|
+ 1057 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1058 END
|
|
|
+ 1059 END; .) } .
|
|
|
+ 1060 AddOp<VAR op: INTEGER>
|
|
|
+ 1061 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 1062 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 1063 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 1064 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1065 (. VAR t2, res2: SymTab.TypeIndex;
|
|
|
+ 1066 op: INTEGER;
|
|
|
+ 1067 q2, qt: QbeGen.QVal;
|
|
|
+ 1068 isR: BOOLEAN;
|
|
|
+ 1069 lw, rw, mw: CARDINAL; .)
|
|
|
+ 1070 = Fact<t, q> { MulOp<op> Fact<t2, q2>
|
|
|
+ 1071 (. IF op = SymTab.OpAnd THEN
|
|
|
+ 1072 IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
+ 1073 t := SymTab.BoolType()
|
|
|
+ 1074 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 1075 IF t # SymTab.InvalidType THEN
|
|
|
+ 1076 QbeGen.NewTemp(qt);
|
|
|
+ 1077 QbeGen.Op3("and", qt, q, q2, FALSE);
|
|
|
+ 1078 QbeGen.CopyOp(qt, q)
|
|
|
+ 1079 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1080 END
|
|
|
+ 1081 ELSIF (t # SymTab.InvalidType) & (t2 # SymTab.InvalidType)
|
|
|
+ 1082 & (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 1083 & (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 1084 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 1085 mw := lw;
|
|
|
+ 1086 IF rw > mw THEN mw := rw END;
|
|
|
+ 1087 IF op = SymTab.OpTimes THEN
|
|
|
+ 1088 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
|
|
|
+ 1089 ELSE
|
|
|
+ 1090 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
|
|
|
+ 1091 END;
|
|
|
+ 1092 t := SymTab.NewSet(
|
|
|
+ 1093 SymTab.NewSubR(0,
|
|
|
+ 1094 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 1095 QbeGen.CopyOp(qt, q)
|
|
|
+ 1096 ELSE
|
|
|
+ 1097 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 1098 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 1099 res2) THEN t := res2
|
|
|
+ 1100 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 1101 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 1102 IF t # SymTab.InvalidType THEN
|
|
|
+ 1103 QbeGen.NewTemp(qt);
|
|
|
+ 1104 IF op = SymTab.OpTimes THEN
|
|
|
+ 1105 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
+ 1106 ELSIF (op = SymTab.OpDiv)
|
|
|
+ 1107 OR (op = SymTab.OpSlash) THEN
|
|
|
+ 1108 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
+ 1109 ELSE
|
|
|
+ 1110 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
+ 1111 END;
|
|
|
+ 1112 QbeGen.CopyOp(qt, q)
|
|
|
+ 1113 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1114 END
|
|
|
+ 1115 END; .) } .
|
|
|
+ 1116 MulOp<VAR op: INTEGER>
|
|
|
+ 1117 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 1118 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 1119 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 1120 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 1121 | "AND" (. op := SymTab.OpAnd; .) .
|
|
|
+ 1122 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1123 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 1124 et, dt, t2, st: SymTab.TypeIndex;
|
|
|
+ 1125 dk: INTEGER;
|
|
|
+ 1126 qd, q2, sq: QbeGen.QVal;
|
|
|
+ 1127 qn: SymTab.Name;
|
|
|
+ 1128 sfx: BOOLEAN; .)
|
|
|
+ 1129 = integer (. LexString(s);
|
|
|
+ 1130 QbeGen.NormInt(s, q);
|
|
|
+ 1131 t := SymTab.IntType(); .)
|
|
|
+ 1132 | real (. LexString(s);
|
|
|
+ 1133 QbeGen.NormReal(s, q);
|
|
|
+ 1134 t := SymTab.RealType(); .)
|
|
|
+ 1135 | string (. LexString(s);
|
|
|
+ 1136 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 1137 t := SymTab.CharType();
|
|
|
+ 1138 QbeGen.IntStr(
|
|
|
+ 1139 QbeGen.CharVal(s), q)
|
|
|
+ 1140 ELSE t := SymTab.NewStr();
|
|
|
+ 1141 QbeGen.DeclStr(s, q)
|
|
|
+ 1142 END; .)
|
|
|
+ 1143 | Design<dt, dk, qd, qn, sfx> (. t := dt;
|
|
|
+ 1144 IF sfx THEN
|
|
|
+ 1145 IF dt #
|
|
|
+ 1146 SymTab.InvalidType THEN
|
|
|
+ 1147 QbeGen.ElemLoad(qd, dt, q)
|
|
|
+ 1148 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1149 END
|
|
|
+ 1150 ELSE QbeGen.CopyOp(qd, q)
|
|
|
+ 1151 END; .)
|
|
|
+ 1152 | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
+ 1153 | SetLit<st, sq> (. t := st;
|
|
|
+ 1154 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 1155 | "NOT" Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 1156 t := SymTab.BoolType()
|
|
|
+ 1157 ELSE SemError(212);
|
|
|
+ 1158 t := SymTab.InvalidType END;
|
|
|
+ 1159 IF t # SymTab.InvalidType THEN
|
|
|
+ 1160 QbeGen.NotQ(q2, q)
|
|
|
+ 1161 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1162 END; .) .
|
|
|
+ 1163 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 1164 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 1165 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 1166 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1167 = "{" (. t := SymTab.NewSet(
|
|
|
+ 1168 SymTab.NewSubR(0, 255));
|
|
|
+ 1169 QbeGen.NewSetTemp(8, q);
|
|
|
+ 1170 QbeGen.SetZero(q, 8); .)
|
|
|
+ 1171 [ SetElem<t, q> { "," SetElem<t, q> } ]
|
|
|
+ 1172 "}" .
|
|
|
+ 1173 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 1174 qe, q2: QbeGen.QVal;
|
|
|
+ 1175 v, v2: INTEGER;
|
|
|
+ 1176 lo: INTEGER;
|
|
|
+ 1177 span: CARDINAL;
|
|
|
+ 1178 cl, cl2: INTEGER;
|
|
|
+ 1179 hasR: BOOLEAN; .)
|
|
|
+ 1180 = (. hasR := FALSE; .)
|
|
|
+ 1181 Expr<et, qe>
|
|
|
+ 1182 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
+ 1183 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 1184 span := SymTab.SetCount(st);
|
|
|
+ 1185 IF (et = SymTab.InvalidType)
|
|
|
+ 1186 OR (hasR & (et2 =
|
|
|
+ 1187 SymTab.InvalidType)) THEN
|
|
|
+ 1188 ELSE cl :=
|
|
|
+ 1189 SymTab.ClassOf(et);
|
|
|
+ 1190 IF hasR THEN
|
|
|
+ 1191 cl2 :=
|
|
|
+ 1192 SymTab.ClassOf(et2)
|
|
|
+ 1193 ELSE cl2 := SymTab.ClInt
|
|
|
+ 1194 END;
|
|
|
+ 1195 IF ((cl # SymTab.ClInt)
|
|
|
+ 1196 & (cl # SymTab.ClChar)
|
|
|
+ 1197 & (cl # SymTab.ClBool))
|
|
|
+ 1198 OR (hasR &
|
|
|
+ 1199 ((cl2
|
|
|
+ 1200 # SymTab.ClInt)
|
|
|
+ 1201 & (cl2
|
|
|
+ 1202 # SymTab.ClChar)
|
|
|
+ 1203 & (cl2
|
|
|
+ 1204 # SymTab.ClBool))) THEN
|
|
|
+ 1205 SemError(222)
|
|
|
+ 1206 ELSIF hasR
|
|
|
+ 1207 & SymTab.ConstInt(qe, v)
|
|
|
+ 1208 & SymTab.ConstInt(q2,
|
|
|
+ 1209 v2)
|
|
|
+ 1210 & ((v < lo)
|
|
|
+ 1211 OR (v2 < lo)
|
|
|
+ 1212 OR (v >= lo +
|
|
|
+ 1213 VAL(INTEGER, span))
|
|
|
+ 1214 OR (v2 >= lo +
|
|
|
+ 1215 VAL(INTEGER, span))
|
|
|
+ 1216 OR (v > v2)) THEN
|
|
|
+ 1217 SemError(222)
|
|
|
+ 1218 ELSIF hasR THEN
|
|
|
+ 1219 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 1220 lo, span)
|
|
|
+ 1221 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 1222 v)
|
|
|
+ 1223 & ((v < lo)
|
|
|
+ 1224 OR (v >= lo +
|
|
|
+ 1225 VAL(INTEGER,
|
|
|
+ 1226 span))) THEN
|
|
|
+ 1227 SemError(222)
|
|
|
+ 1228 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 1229 lo, span)
|
|
|
+ 1230 END
|
|
|
+ 1231 END; .) .
|
|
|
+ 1232 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 1233 = ident (. LexName(n); .) .
|
|
|
+ 1234
|
|
|
+ 1235 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|
|
|
|
|
|
Statistics:
|
|
|
|
|
|
- nr of terminals: 65 (limit 400)
|
|
|
- nr of non-terminals: 59 (limit 210)
|
|
|
- nr of pragmas: 0 (limit 435)
|
|
|
- nr of symbolnodes: 124 (limit 500)
|
|
|
- nr of graphnodes: 552 (limit 1500)
|
|
|
+ nr of terminals: 69 (limit 400)
|
|
|
+ nr of non-terminals: 62 (limit 210)
|
|
|
+ nr of pragmas: 0 (limit 431)
|
|
|
+ nr of symbolnodes: 131 (limit 500)
|
|
|
+ nr of graphnodes: 579 (limit 1500)
|
|
|
nr of conditionsets: 6 (limit 100)
|
|
|
nr of charactersets: 11 (limit 250)
|
|
|
|