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