|
@@ -85,3053 +85,3117 @@ Listing:
|
|
|
67 nPendVar: CARDINAL;
|
|
67 nPendVar: CARDINAL;
|
|
|
68 pendVarName: ARRAY [0 .. 255] OF SymTab.Name;
|
|
68 pendVarName: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
69 pendVarT: ARRAY [0 .. 255] OF SymTab.TypeIndex;
|
|
69 pendVarT: ARRAY [0 .. 255] OF SymTab.TypeIndex;
|
|
|
- 70
|
|
|
|
|
- 71 PROCEDURE FlushPend;
|
|
|
|
|
- 72 (* Emit module-level globals whose forward type is now resolved. *)
|
|
|
|
|
- 73 VAR k: CARDINAL;
|
|
|
|
|
- 74 BEGIN
|
|
|
|
|
- 75 k := 0;
|
|
|
|
|
- 76 WHILE k < nPendVar DO
|
|
|
|
|
- 77 QbeGen.DeclVar(pendVarName[k], pendVarT[k]);
|
|
|
|
|
- 78 INC(k)
|
|
|
|
|
- 79 END;
|
|
|
|
|
- 80 nPendVar := 0
|
|
|
|
|
- 81 END FlushPend;
|
|
|
|
|
- 82
|
|
|
|
|
- 83 CHARACTERS
|
|
|
|
|
- 84 eol = CHR(13) .
|
|
|
|
|
- 85 lf = CHR(10) .
|
|
|
|
|
- 86 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
|
|
- 87 digit = "0123456789" .
|
|
|
|
|
- 88 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
|
|
- 89 noQuote1 = ANY - "'" - eol .
|
|
|
|
|
- 90 noQuote2 = ANY - '"' - eol .
|
|
|
|
|
- 91
|
|
|
|
|
- 92 IGNORE CHR(9) .. CHR(13)
|
|
|
|
|
- 93
|
|
|
|
|
- 94 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
|
|
- 95 COMMENTS FROM "//" TO lf
|
|
|
|
|
- 96
|
|
|
|
|
- 97 TOKENS
|
|
|
|
|
- 98 ident = letter { letter | digit } .
|
|
|
|
|
- 99 integer = digit { digit }
|
|
|
|
|
- 100 | digit { digit } CONTEXT("..")
|
|
|
|
|
- 101 | "0x" hexDigit { hexDigit }
|
|
|
|
|
- 102 | "0X" hexDigit { hexDigit } .
|
|
|
|
|
- 103 real = digit { digit } "." { digit }
|
|
|
|
|
- 104 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
|
|
- 105 string = "'" { noQuote1 } "'"
|
|
|
|
|
- 106 | '"' { noQuote2 } '"' .
|
|
|
|
|
- 107 charConst = digit { digit } ( "C" | "c" ) .
|
|
|
|
|
- 108 ustring = ( "U" | "u" ) ( "'" { noQuote1 } "'" | '"' { noQuote2 } '"' ) .
|
|
|
|
|
- 109
|
|
|
|
|
- 110 PRODUCTIONS
|
|
|
|
|
- 111 M2
|
|
|
|
|
- 112 = Unit "." .
|
|
|
|
|
- 113 (* Units: program modules compile fully; DEFINITION and
|
|
|
|
|
- 114 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
|
|
- 115 (each ends with one 230); same for nested local modules. *)
|
|
|
|
|
- 116 Unit
|
|
|
|
|
- 117 = DefUnit
|
|
|
|
|
- 118 | ImplUnit
|
|
|
|
|
- 119 | ProgModule .
|
|
|
|
|
- 120 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
|
|
- 121 and one program (last) into one image. Units share the symbol
|
|
|
|
|
- 122 table; imports materialize exported names. *)
|
|
|
|
|
- 123 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
|
|
- 124 = "DEFINITION" "MODULE"
|
|
|
|
|
- 125 GetIdent<m1> (. IF NOT SymTab.BeginDef(m1) THEN
|
|
|
|
|
- 126 SemError(200) END;
|
|
|
|
|
- 127 QbeGen.SetModule(m1); .)
|
|
|
|
|
- 128 ";"
|
|
|
|
|
- 129 { Import }
|
|
|
|
|
- 130 [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
|
|
- 131 list: parsed, and the
|
|
|
|
|
- 132 names are already exported
|
|
|
|
|
- 133 by the module scope *) .)
|
|
|
|
|
- 134 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
|
|
- 135 { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
|
|
- 136 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
- 137 (. SymTab.CloseProc;
|
|
|
|
|
- 138 QbeGen.AbortFunc; .) }
|
|
|
|
|
- 139 "END"
|
|
|
|
|
- 140 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 141 SemError(202) END;
|
|
|
|
|
- 142 SymTab.EndUnit; .) .
|
|
|
|
|
- 143 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
- 144 k: CARDINAL;
|
|
|
|
|
- 145 fname: SymTab.Name;
|
|
|
|
|
- 146 unres: BOOLEAN; .)
|
|
|
|
|
- 147 = "IMPLEMENTATION" "MODULE"
|
|
|
|
|
- 148 GetIdent<m1> (. IF NOT SymTab.BeginImpl(m1) THEN
|
|
|
|
|
- 149 SemError(201) END;
|
|
|
|
|
- 150 nPendVar := 0;
|
|
|
|
|
- 151 QbeGen.SetModule(m1); .)
|
|
|
|
|
- 152 ";"
|
|
|
|
|
- 153 { Import }
|
|
|
|
|
- 154 DeclSeq
|
|
|
|
|
- 155 [ "BEGIN" (. FlushPend;
|
|
|
|
|
- 156 k := 0;
|
|
|
|
|
- 157 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 158 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 159 IF unres THEN SemError(201) END;
|
|
|
|
|
- 160 INC(k)
|
|
|
|
|
- 161 END;
|
|
|
|
|
- 162 SymTab.FwdClear;
|
|
|
|
|
- 163 QbeGen.BeginInit(m1); .)
|
|
|
|
|
- 164 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
|
|
- 165 "END"
|
|
|
|
|
- 166 GetIdent<m2> (. FlushPend;
|
|
|
|
|
- 167 k := 0;
|
|
|
|
|
- 168 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 169 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 170 IF unres THEN SemError(201) END;
|
|
|
|
|
- 171 INC(k)
|
|
|
|
|
- 172 END;
|
|
|
|
|
- 173 SymTab.FwdClear;
|
|
|
|
|
- 174 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 175 SemError(202) END;
|
|
|
|
|
- 176 SymTab.EndUnit; .) .
|
|
|
|
|
- 177 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
- 178 k: CARDINAL;
|
|
|
|
|
- 179 fname: SymTab.Name;
|
|
|
|
|
- 180 unres: BOOLEAN; .)
|
|
|
|
|
- 181 = "MODULE"
|
|
|
|
|
- 182 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
|
|
- 183 SemError(200) END;
|
|
|
|
|
- 184 nPendVar := 0;
|
|
|
|
|
- 185 QbeGen.SetModule(m1); .)
|
|
|
|
|
- 186 [ Priority ]
|
|
|
|
|
- 187 ";"
|
|
|
|
|
- 188 { Import }
|
|
|
|
|
- 189 DeclSeq
|
|
|
|
|
- 190 [ "BEGIN" (. FlushPend;
|
|
|
|
|
- 191 k := 0;
|
|
|
|
|
- 192 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 193 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 194 IF unres THEN SemError(201) END;
|
|
|
|
|
- 195 INC(k)
|
|
|
|
|
- 196 END;
|
|
|
|
|
- 197 SymTab.FwdClear;
|
|
|
|
|
- 198 QbeGen.BeginBody; .)
|
|
|
|
|
- 199 [ StatSeq ] ]
|
|
|
|
|
- 200 "END"
|
|
|
|
|
- 201 GetIdent<m2> (. FlushPend;
|
|
|
|
|
- 202 k := 0;
|
|
|
|
|
- 203 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 204 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 205 IF unres THEN SemError(201) END;
|
|
|
|
|
- 206 INC(k)
|
|
|
|
|
- 207 END;
|
|
|
|
|
- 208 SymTab.FwdClear;
|
|
|
|
|
- 209 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 210 SemError(202) END;
|
|
|
|
|
- 211 QbeGen.EndModule(m1);
|
|
|
|
|
- 212 SymTab.EndUnit; .) .
|
|
|
|
|
- 213 DeclSeq
|
|
|
|
|
- 214 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
|
|
- 215 | NestedModule ";" | ClassItem ";" } .
|
|
|
|
|
- 216 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
|
|
- 217 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
|
|
- 218 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
|
|
- 219 scope at END. *)
|
|
|
|
|
- 220 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
- 221 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
|
|
- 222 expCount, k: CARDINAL; .)
|
|
|
|
|
- 223 = "MODULE"
|
|
|
|
|
- 224 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
|
|
- 225 SymTab.KindModule) THEN
|
|
|
|
|
|
|
+ 70 (* Forward module-level variables referenced from a procedure body. *)
|
|
|
|
|
+ 71 nFvarRefs: CARDINAL;
|
|
|
|
|
+ 72 fvarId: ARRAY [0 .. 255] OF INTEGER;
|
|
|
|
|
+ 73 fvarSlot: ARRAY [0 .. 255] OF INTEGER;
|
|
|
|
|
+ 74
|
|
|
|
|
+ 75 PROCEDURE FlushPend;
|
|
|
|
|
+ 76 (* Emit module-level globals whose forward type is now resolved. *)
|
|
|
|
|
+ 77 VAR k: CARDINAL;
|
|
|
|
|
+ 78 BEGIN
|
|
|
|
|
+ 79 k := 0;
|
|
|
|
|
+ 80 WHILE k < nPendVar DO
|
|
|
|
|
+ 81 QbeGen.DeclVar(pendVarName[k], pendVarT[k]);
|
|
|
|
|
+ 82 INC(k)
|
|
|
|
|
+ 83 END;
|
|
|
|
|
+ 84 nPendVar := 0
|
|
|
|
|
+ 85 END FlushPend;
|
|
|
|
|
+ 86
|
|
|
|
|
+ 87 PROCEDURE FwdVarNote (id, slot: INTEGER);
|
|
|
|
|
+ 88 BEGIN
|
|
|
|
|
+ 89 IF nFvarRefs <= HIGH(fvarId) THEN
|
|
|
|
|
+ 90 fvarId[nFvarRefs] := id;
|
|
|
|
|
+ 91 fvarSlot[nFvarRefs] := slot;
|
|
|
|
|
+ 92 INC(nFvarRefs)
|
|
|
|
|
+ 93 END
|
|
|
|
|
+ 94 END FwdVarNote;
|
|
|
|
|
+ 95
|
|
|
|
|
+ 96 PROCEDURE FwdVarFlush;
|
|
|
|
|
+ 97 (* At module end: resolve every forward reference against the declared
|
|
|
|
|
+ 98 names (an unresolved one is 201) and patch its placeholder symbol. *)
|
|
|
|
|
+ 99 VAR k: CARDINAL; nm, g: SymTab.Name; cls: INTEGER; oper: CHAR;
|
|
|
|
|
+ 100 t: SymTab.TypeIndex; ok: BOOLEAN;
|
|
|
|
|
+ 101 BEGIN
|
|
|
|
|
+ 102 k := 0;
|
|
|
|
|
+ 103 WHILE k < nFvarRefs DO
|
|
|
|
|
+ 104 SymTab.FwdVarName(fvarId[k], nm);
|
|
|
|
|
+ 105 IF nm[0] # CHR(0) THEN
|
|
|
|
|
+ 106 IF NOT SymTab.FwdVarResolve(fvarId[k]) THEN
|
|
|
|
|
+ 107 SemError(201)
|
|
|
|
|
+ 108 ELSE
|
|
|
|
|
+ 109 t := SymTab.FwdVarType(fvarId[k]);
|
|
|
|
|
+ 110 cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 111 IF cls = SymTab.ClReal THEN oper := "d"
|
|
|
|
|
+ 112 ELSIF SymTab.IsLongFamily(t) THEN oper := "l"
|
|
|
|
|
+ 113 ELSE oper := "w"
|
|
|
|
|
+ 114 END;
|
|
|
|
|
+ 115 ok := SymTab.GlobalRef(nm, g);
|
|
|
|
|
+ 116 QbeGen.FwdPatch(fvarSlot[k], fvarSlot[k], nm, oper, ok)
|
|
|
|
|
+ 117 END
|
|
|
|
|
+ 118 END;
|
|
|
|
|
+ 119 INC(k)
|
|
|
|
|
+ 120 END;
|
|
|
|
|
+ 121 nFvarRefs := 0
|
|
|
|
|
+ 122 END FwdVarFlush;
|
|
|
|
|
+ 123
|
|
|
|
|
+ 124 CHARACTERS
|
|
|
|
|
+ 125 eol = CHR(13) .
|
|
|
|
|
+ 126 lf = CHR(10) .
|
|
|
|
|
+ 127 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
|
|
+ 128 digit = "0123456789" .
|
|
|
|
|
+ 129 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
|
|
+ 130 noQuote1 = ANY - "'" - eol .
|
|
|
|
|
+ 131 noQuote2 = ANY - '"' - eol .
|
|
|
|
|
+ 132
|
|
|
|
|
+ 133 IGNORE CHR(9) .. CHR(13)
|
|
|
|
|
+ 134
|
|
|
|
|
+ 135 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
|
|
+ 136 COMMENTS FROM "//" TO lf
|
|
|
|
|
+ 137
|
|
|
|
|
+ 138 TOKENS
|
|
|
|
|
+ 139 ident = letter { letter | digit } .
|
|
|
|
|
+ 140 integer = digit { digit }
|
|
|
|
|
+ 141 | digit { digit } CONTEXT("..")
|
|
|
|
|
+ 142 | "0x" hexDigit { hexDigit }
|
|
|
|
|
+ 143 | "0X" hexDigit { hexDigit } .
|
|
|
|
|
+ 144 real = digit { digit } "." { digit }
|
|
|
|
|
+ 145 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
|
|
+ 146 string = "'" { noQuote1 } "'"
|
|
|
|
|
+ 147 | '"' { noQuote2 } '"' .
|
|
|
|
|
+ 148 charConst = digit { digit } ( "C" | "c" ) .
|
|
|
|
|
+ 149 ustring = ( "U" | "u" ) ( "'" { noQuote1 } "'" | '"' { noQuote2 } '"' ) .
|
|
|
|
|
+ 150
|
|
|
|
|
+ 151 PRODUCTIONS
|
|
|
|
|
+ 152 M2
|
|
|
|
|
+ 153 = Unit "." .
|
|
|
|
|
+ 154 (* Units: program modules compile fully; DEFINITION and
|
|
|
|
|
+ 155 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
|
|
+ 156 (each ends with one 230); same for nested local modules. *)
|
|
|
|
|
+ 157 Unit
|
|
|
|
|
+ 158 = DefUnit
|
|
|
|
|
+ 159 | ImplUnit
|
|
|
|
|
+ 160 | ProgModule .
|
|
|
|
|
+ 161 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
|
|
+ 162 and one program (last) into one image. Units share the symbol
|
|
|
|
|
+ 163 table; imports materialize exported names. *)
|
|
|
|
|
+ 164 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
|
|
+ 165 = "DEFINITION" "MODULE"
|
|
|
|
|
+ 166 GetIdent<m1> (. IF NOT SymTab.BeginDef(m1) THEN
|
|
|
|
|
+ 167 SemError(200) END;
|
|
|
|
|
+ 168 QbeGen.SetModule(m1); .)
|
|
|
|
|
+ 169 ";"
|
|
|
|
|
+ 170 { Import }
|
|
|
|
|
+ 171 [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
|
|
+ 172 list: parsed, and the
|
|
|
|
|
+ 173 names are already exported
|
|
|
|
|
+ 174 by the module scope *) .)
|
|
|
|
|
+ 175 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
|
|
+ 176 { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
|
|
+ 177 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
+ 178 (. SymTab.CloseProc;
|
|
|
|
|
+ 179 QbeGen.AbortFunc; .) }
|
|
|
|
|
+ 180 "END"
|
|
|
|
|
+ 181 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 182 SemError(202) END;
|
|
|
|
|
+ 183 SymTab.EndUnit; .) .
|
|
|
|
|
+ 184 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
+ 185 k: CARDINAL;
|
|
|
|
|
+ 186 fname: SymTab.Name;
|
|
|
|
|
+ 187 unres: BOOLEAN; .)
|
|
|
|
|
+ 188 = "IMPLEMENTATION" "MODULE"
|
|
|
|
|
+ 189 GetIdent<m1> (. IF NOT SymTab.BeginImpl(m1) THEN
|
|
|
|
|
+ 190 SemError(201) END;
|
|
|
|
|
+ 191 nPendVar := 0;
|
|
|
|
|
+ 192 QbeGen.SetModule(m1); .)
|
|
|
|
|
+ 193 ";"
|
|
|
|
|
+ 194 { Import }
|
|
|
|
|
+ 195 DeclSeq
|
|
|
|
|
+ 196 [ "BEGIN" (. FlushPend;
|
|
|
|
|
+ 197 k := 0;
|
|
|
|
|
+ 198 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 199 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 200 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 201 INC(k)
|
|
|
|
|
+ 202 END;
|
|
|
|
|
+ 203 SymTab.FwdClear;
|
|
|
|
|
+ 204 FwdVarFlush;
|
|
|
|
|
+ 205 QbeGen.BeginInit(m1); .)
|
|
|
|
|
+ 206 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
|
|
+ 207 "END"
|
|
|
|
|
+ 208 GetIdent<m2> (. FlushPend;
|
|
|
|
|
+ 209 k := 0;
|
|
|
|
|
+ 210 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 211 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 212 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 213 INC(k)
|
|
|
|
|
+ 214 END;
|
|
|
|
|
+ 215 SymTab.FwdClear;
|
|
|
|
|
+ 216 FwdVarFlush;
|
|
|
|
|
+ 217 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 218 SemError(202) END;
|
|
|
|
|
+ 219 SymTab.EndUnit; .) .
|
|
|
|
|
+ 220 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
+ 221 k: CARDINAL;
|
|
|
|
|
+ 222 fname: SymTab.Name;
|
|
|
|
|
+ 223 unres: BOOLEAN; .)
|
|
|
|
|
+ 224 = "MODULE"
|
|
|
|
|
+ 225 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
226 SemError(200) END;
|
|
226 SemError(200) END;
|
|
|
- 227 SymTab.PushScope;
|
|
|
|
|
- 228 expCount := 0; .)
|
|
|
|
|
|
|
+ 227 nPendVar := 0;
|
|
|
|
|
+ 228 QbeGen.SetModule(m1); .)
|
|
|
229 [ Priority ]
|
|
229 [ Priority ]
|
|
|
230 ";"
|
|
230 ";"
|
|
|
231 { Import }
|
|
231 { Import }
|
|
|
- 232 [ "EXPORT" [ "QUALIFIED" ]
|
|
|
|
|
- 233 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
|
|
- 234 { "," GetIdent<expNames[expCount]>
|
|
|
|
|
- 235 (. INC(expCount); .) }
|
|
|
|
|
- 236 ";" ]
|
|
|
|
|
- 237 DeclSeq
|
|
|
|
|
- 238 [ "BEGIN" (. QbeGen.BeginInit(m1); .)
|
|
|
|
|
- 239 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
|
|
- 240 "END"
|
|
|
|
|
- 241 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 242 SemError(202) END;
|
|
|
|
|
- 243 k := 0;
|
|
|
|
|
- 244 WHILE k < expCount DO
|
|
|
|
|
- 245 SymTab.ExportUp(expNames[k]);
|
|
|
|
|
- 246 INC(k)
|
|
|
|
|
- 247 END;
|
|
|
|
|
- 248 SymTab.PopScope; .) .
|
|
|
|
|
- 249 Priority
|
|
|
|
|
- 250 = "[" integer "]" (. SemError(230); .) .
|
|
|
|
|
- 251 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
|
|
- 252 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
|
|
- 253 materializes on first use (Design). *)
|
|
|
|
|
- 254 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
|
|
- 255 import lines don't fail); a known module's missing export is
|
|
|
|
|
- 256 201. *)
|
|
|
|
|
- 257 Import (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 258 = "FROM"
|
|
|
|
|
- 259 GetIdent<n>
|
|
|
|
|
- 260 "IMPORT"
|
|
|
|
|
- 261 ImpList<n> ";"
|
|
|
|
|
- 262 | "IMPORT"
|
|
|
|
|
- 263 ImpModList ";" .
|
|
|
|
|
- 264 ImpList<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 265 = ImpName<mod>
|
|
|
|
|
- 266 { "," ImpName<mod> } .
|
|
|
|
|
- 267 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
|
|
- 268 accepted and ignored: the built-in applies regardless. *)
|
|
|
|
|
- 269 ImpName<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 270 = GetIdent<n> (. IF SymTab.Equal(mod, "libc") THEN
|
|
|
|
|
- 271 (* intrinsic C library:
|
|
|
|
|
- 272 permissive external *)
|
|
|
|
|
- 273 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
|
|
- 274 SemError(201) END
|
|
|
|
|
- 275 ELSIF SymTab.ModKnown(mod)
|
|
|
|
|
- 276 AND NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
|
|
- 277 SemError(201) END; .)
|
|
|
|
|
- 278 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
|
|
- 279 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
|
|
- 280 | "UCHR" | "CHR8" | "UORD"
|
|
|
|
|
- 281 | "INC" | "DEC" ) .
|
|
|
|
|
- 282 ImpModList (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 283 = GetIdent<n>
|
|
|
|
|
- 284 { "," GetIdent<n> } .
|
|
|
|
|
- 285 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
|
|
- 286 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
|
|
- 287 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
|
|
- 288 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
|
|
- 289 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
|
|
- 290 TypeBlock<isDef: BOOLEAN>
|
|
|
|
|
- 291 = "TYPE" (. SymTab.BeginTypeBlock; .)
|
|
|
|
|
- 292 { TypeItem<isDef> ";" | ClassItem ";" }
|
|
|
|
|
- 293 (. SymTab.EndTypeBlock; .) .
|
|
|
|
|
- 294 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
|
|
- 295 t, op: SymTab.TypeIndex; .)
|
|
|
|
|
- 296 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
|
|
- 297 IF op = SymTab.InvalidType THEN
|
|
|
|
|
- 298 IF NOT SymTab.Enter(n,
|
|
|
|
|
- 299 SymTab.KindType) THEN
|
|
|
|
|
- 300 SemError(200) END
|
|
|
|
|
- 301 END; .)
|
|
|
|
|
- 302 ( "=" Type<t, FALSE> (. IF op # SymTab.InvalidType THEN
|
|
|
|
|
- 303 SymTab.SetTarget(op, t)
|
|
|
|
|
- 304 ELSE SymTab.SetSymType(n, t)
|
|
|
|
|
- 305 END; .)
|
|
|
|
|
- 306 | (. IF op # SymTab.InvalidType THEN
|
|
|
|
|
- 307 (* stays opaque *)
|
|
|
|
|
- 308 ELSIF NOT isDef THEN
|
|
|
|
|
- 309 SemError(231)
|
|
|
|
|
- 310 ELSE SymTab.SetSymType(n,
|
|
|
|
|
- 311 SymTab.NewAlias()) END; .) ) .
|
|
|
|
|
- 312 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
- 313 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
|
|
- 314 | Subrange<t>
|
|
|
|
|
- 315 | Enum<t>
|
|
|
|
|
- 316 | ArrayType<t, allowOpen>
|
|
|
|
|
- 317 | SetType<t>
|
|
|
|
|
- 318 | RecordType<t>
|
|
|
|
|
- 319 | PointerType<t>
|
|
|
|
|
- 320 | ProcType<t> .
|
|
|
|
|
- 321 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
|
|
- 322 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
|
|
- 323 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
|
|
- 324 are code pointers; params are collected into the descriptor. *)
|
|
|
|
|
- 325 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
|
|
- 326 isV: BOOLEAN; .)
|
|
|
|
|
- 327 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
|
|
- 328 t := SymTab.NewProcType(res); .)
|
|
|
|
|
- 329 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
|
|
- 330 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
|
|
- 331 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
|
|
- 332 isV: BOOLEAN;
|
|
|
|
|
- 333 cnt, k: CARDINAL;
|
|
|
|
|
- 334 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
|
|
- 335 = (. isV := FALSE; cnt := 0; .)
|
|
|
|
|
- 336 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
- 337 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
|
|
- 338 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
|
|
- 339 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
|
|
- 340 WHILE k < cnt DO
|
|
|
|
|
- 341 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
- 342 INC(k)
|
|
|
|
|
- 343 END; .)
|
|
|
|
|
- 344 | (. (* type-only parameter list:
|
|
|
|
|
- 345 each name is a type (GNU
|
|
|
|
|
- 346 shorthand used by the
|
|
|
|
|
- 347 Coco/R scanner frame) *)
|
|
|
|
|
- 348 k := 0;
|
|
|
|
|
- 349 WHILE k < cnt DO
|
|
|
|
|
- 350 IF SymTab.Lookup(names[k])
|
|
|
|
|
- 351 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
|
|
- 352 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
|
|
- 353 pt := SymTab.SymType(names[k])
|
|
|
|
|
- 354 ELSE SemError(201);
|
|
|
|
|
- 355 pt := SymTab.InvalidType
|
|
|
|
|
- 356 END;
|
|
|
|
|
- 357 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
- 358 INC(k)
|
|
|
|
|
- 359 END; .) )
|
|
|
|
|
- 360 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
|
|
- 361 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
|
|
- 362 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
|
|
- 363 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
|
|
- 364 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
|
|
- 365 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
|
|
- 366 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
|
|
- 367 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
- 368 (. VAR elem: SymTab.TypeIndex;
|
|
|
|
|
- 369 ok: BOOLEAN;
|
|
|
|
|
- 370 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
|
|
- 371 nb, k: CARDINAL;
|
|
|
|
|
- 372 idx: SymTab.TypeIndex;
|
|
|
|
|
- 373 ilo, ihi: INTEGER; .)
|
|
|
|
|
- 374 = "ARRAY"
|
|
|
|
|
- 375 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
|
|
- 376 SemError(230) END;
|
|
|
|
|
- 377 t := SymTab.NewOpenArray(elem); .)
|
|
|
|
|
- 378 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
|
|
- 379 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
|
|
- 380 type's ordinal bounds give the
|
|
|
|
|
- 381 [lo..hi] pair *)
|
|
|
|
|
- 382 IF SymTab.TypeBounds(idx, ilo,
|
|
|
|
|
- 383 ihi)
|
|
|
|
|
- 384 THEN t := SymTab.NewArrayB(elem,
|
|
|
|
|
- 385 ilo, ihi)
|
|
|
|
|
- 386 ELSE SemError(230);
|
|
|
|
|
- 387 t := SymTab.InvalidType
|
|
|
|
|
|
|
+ 232 DeclSeq
|
|
|
|
|
+ 233 [ "BEGIN" (. FlushPend;
|
|
|
|
|
+ 234 k := 0;
|
|
|
|
|
+ 235 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 236 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 237 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 238 INC(k)
|
|
|
|
|
+ 239 END;
|
|
|
|
|
+ 240 SymTab.FwdClear;
|
|
|
|
|
+ 241 FwdVarFlush;
|
|
|
|
|
+ 242 QbeGen.BeginBody; .)
|
|
|
|
|
+ 243 [ StatSeq ] ]
|
|
|
|
|
+ 244 "END"
|
|
|
|
|
+ 245 GetIdent<m2> (. FlushPend;
|
|
|
|
|
+ 246 k := 0;
|
|
|
|
|
+ 247 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 248 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 249 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 250 INC(k)
|
|
|
|
|
+ 251 END;
|
|
|
|
|
+ 252 SymTab.FwdClear;
|
|
|
|
|
+ 253 FwdVarFlush;
|
|
|
|
|
+ 254 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 255 SemError(202) END;
|
|
|
|
|
+ 256 QbeGen.EndModule(m1);
|
|
|
|
|
+ 257 SymTab.EndUnit; .) .
|
|
|
|
|
+ 258 DeclSeq
|
|
|
|
|
+ 259 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
|
|
+ 260 | NestedModule ";" | ClassItem ";" } .
|
|
|
|
|
+ 261 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
|
|
+ 262 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
|
|
+ 263 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
|
|
+ 264 scope at END. *)
|
|
|
|
|
+ 265 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
+ 266 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
|
|
+ 267 expCount, k: CARDINAL; .)
|
|
|
|
|
+ 268 = "MODULE"
|
|
|
|
|
+ 269 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
|
|
+ 270 SymTab.KindModule) THEN
|
|
|
|
|
+ 271 SemError(200) END;
|
|
|
|
|
+ 272 SymTab.PushScope;
|
|
|
|
|
+ 273 expCount := 0; .)
|
|
|
|
|
+ 274 [ Priority ]
|
|
|
|
|
+ 275 ";"
|
|
|
|
|
+ 276 { Import }
|
|
|
|
|
+ 277 [ "EXPORT" [ "QUALIFIED" ]
|
|
|
|
|
+ 278 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
|
|
+ 279 { "," GetIdent<expNames[expCount]>
|
|
|
|
|
+ 280 (. INC(expCount); .) }
|
|
|
|
|
+ 281 ";" ]
|
|
|
|
|
+ 282 DeclSeq
|
|
|
|
|
+ 283 [ "BEGIN" (. QbeGen.BeginInit(m1); .)
|
|
|
|
|
+ 284 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
|
|
+ 285 "END"
|
|
|
|
|
+ 286 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 287 SemError(202) END;
|
|
|
|
|
+ 288 k := 0;
|
|
|
|
|
+ 289 WHILE k < expCount DO
|
|
|
|
|
+ 290 SymTab.ExportUp(expNames[k]);
|
|
|
|
|
+ 291 INC(k)
|
|
|
|
|
+ 292 END;
|
|
|
|
|
+ 293 SymTab.PopScope; .) .
|
|
|
|
|
+ 294 Priority
|
|
|
|
|
+ 295 = "[" integer "]" (. SemError(230); .) .
|
|
|
|
|
+ 296 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
|
|
+ 297 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
|
|
+ 298 materializes on first use (Design). *)
|
|
|
|
|
+ 299 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
|
|
+ 300 import lines don't fail); a known module's missing export is
|
|
|
|
|
+ 301 201. *)
|
|
|
|
|
+ 302 Import (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 303 = "FROM"
|
|
|
|
|
+ 304 GetIdent<n>
|
|
|
|
|
+ 305 "IMPORT"
|
|
|
|
|
+ 306 ImpList<n> ";"
|
|
|
|
|
+ 307 | "IMPORT"
|
|
|
|
|
+ 308 ImpModList ";" .
|
|
|
|
|
+ 309 ImpList<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 310 = ImpName<mod>
|
|
|
|
|
+ 311 { "," ImpName<mod> } .
|
|
|
|
|
+ 312 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
|
|
+ 313 accepted and ignored: the built-in applies regardless. *)
|
|
|
|
|
+ 314 ImpName<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 315 = GetIdent<n> (. IF SymTab.Equal(mod, "libc") THEN
|
|
|
|
|
+ 316 (* intrinsic C library:
|
|
|
|
|
+ 317 permissive external *)
|
|
|
|
|
+ 318 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
|
|
+ 319 SemError(201) END
|
|
|
|
|
+ 320 ELSIF SymTab.ModKnown(mod)
|
|
|
|
|
+ 321 AND NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
|
|
+ 322 SemError(201) END; .)
|
|
|
|
|
+ 323 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
|
|
+ 324 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
|
|
+ 325 | "UCHR" | "CHR8" | "UORD"
|
|
|
|
|
+ 326 | "INC" | "DEC" ) .
|
|
|
|
|
+ 327 ImpModList (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 328 = GetIdent<n>
|
|
|
|
|
+ 329 { "," GetIdent<n> } .
|
|
|
|
|
+ 330 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
|
|
+ 331 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
|
|
+ 332 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
|
|
+ 333 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
|
|
+ 334 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
|
|
+ 335 TypeBlock<isDef: BOOLEAN>
|
|
|
|
|
+ 336 = "TYPE" (. SymTab.BeginTypeBlock; .)
|
|
|
|
|
+ 337 { TypeItem<isDef> ";" | ClassItem ";" }
|
|
|
|
|
+ 338 (. SymTab.EndTypeBlock; .) .
|
|
|
|
|
+ 339 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 340 t, op: SymTab.TypeIndex; .)
|
|
|
|
|
+ 341 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
|
|
+ 342 IF op = SymTab.InvalidType THEN
|
|
|
|
|
+ 343 IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 344 SymTab.KindType) THEN
|
|
|
|
|
+ 345 SemError(200) END
|
|
|
|
|
+ 346 END; .)
|
|
|
|
|
+ 347 ( "=" Type<t, FALSE> (. IF op # SymTab.InvalidType THEN
|
|
|
|
|
+ 348 SymTab.SetTarget(op, t)
|
|
|
|
|
+ 349 ELSE SymTab.SetSymType(n, t)
|
|
|
|
|
+ 350 END; .)
|
|
|
|
|
+ 351 | (. IF op # SymTab.InvalidType THEN
|
|
|
|
|
+ 352 (* stays opaque *)
|
|
|
|
|
+ 353 ELSIF NOT isDef THEN
|
|
|
|
|
+ 354 SemError(231)
|
|
|
|
|
+ 355 ELSE SymTab.SetSymType(n,
|
|
|
|
|
+ 356 SymTab.NewAlias()) END; .) ) .
|
|
|
|
|
+ 357 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
+ 358 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
|
|
+ 359 | Subrange<t>
|
|
|
|
|
+ 360 | Enum<t>
|
|
|
|
|
+ 361 | ArrayType<t, allowOpen>
|
|
|
|
|
+ 362 | SetType<t>
|
|
|
|
|
+ 363 | RecordType<t>
|
|
|
|
|
+ 364 | PointerType<t>
|
|
|
|
|
+ 365 | ProcType<t> .
|
|
|
|
|
+ 366 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
|
|
+ 367 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
|
|
+ 368 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
|
|
+ 369 are code pointers; params are collected into the descriptor. *)
|
|
|
|
|
+ 370 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
|
|
+ 371 isV: BOOLEAN; .)
|
|
|
|
|
+ 372 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
|
|
+ 373 t := SymTab.NewProcType(res); .)
|
|
|
|
|
+ 374 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
|
|
+ 375 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
|
|
+ 376 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
|
|
+ 377 isV: BOOLEAN;
|
|
|
|
|
+ 378 cnt, k: CARDINAL;
|
|
|
|
|
+ 379 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
|
|
+ 380 = (. isV := FALSE; cnt := 0; .)
|
|
|
|
|
+ 381 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
+ 382 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
|
|
+ 383 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
|
|
+ 384 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
|
|
+ 385 WHILE k < cnt DO
|
|
|
|
|
+ 386 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
+ 387 INC(k)
|
|
|
388 END; .)
|
|
388 END; .)
|
|
|
- 389 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
|
|
- 390 BoundPair<ok>
|
|
|
|
|
- 391 { "," BoundPair<ok> }
|
|
|
|
|
- 392 "]" (. (* snapshot before the element
|
|
|
|
|
- 393 type, which reuses the bound
|
|
|
|
|
- 394 buffer for a nested ARRAY *)
|
|
|
|
|
- 395 nb := SymTab.BoundCount();
|
|
|
|
|
- 396 k := 0;
|
|
|
|
|
- 397 WHILE k < nb DO
|
|
|
|
|
- 398 bnds[k] := SymTab.BoundLo(k);
|
|
|
|
|
- 399 bndh[k] := SymTab.BoundHi(k);
|
|
|
|
|
- 400 INC(k)
|
|
|
|
|
- 401 END; .)
|
|
|
|
|
- 402 "OF" Type<elem, FALSE>
|
|
|
|
|
- 403 (. IF ok THEN
|
|
|
|
|
- 404 k := nb;
|
|
|
|
|
- 405 WHILE k > 0 DO
|
|
|
|
|
- 406 DEC(k);
|
|
|
|
|
- 407 elem := SymTab.NewArrayB(
|
|
|
|
|
- 408 elem, bnds[k], bndh[k])
|
|
|
|
|
- 409 END;
|
|
|
|
|
- 410 t := elem
|
|
|
|
|
- 411 ELSE t := SymTab.InvalidType
|
|
|
|
|
- 412 END; .) ) .
|
|
|
|
|
- 413 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
- 414 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
- 415 lo, hi: INTEGER;
|
|
|
|
|
- 416 cl, cl2: INTEGER; .)
|
|
|
|
|
- 417 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
- 418 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
- 419 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
- 420 ok := FALSE
|
|
|
|
|
- 421 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
|
|
- 422 cl2 := SymTab.ClassOf(thi);
|
|
|
|
|
- 423 IF ((cl # SymTab.ClInt)
|
|
|
|
|
- 424 AND (cl # SymTab.ClChar))
|
|
|
|
|
- 425 OR ((cl2 # SymTab.ClInt)
|
|
|
|
|
- 426 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
|
|
- 427 SemError(230); ok := FALSE
|
|
|
|
|
- 428 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
- 429 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
- 430 OR (lo > hi) THEN
|
|
|
|
|
- 431 SemError(230); ok := FALSE
|
|
|
|
|
- 432 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
|
|
- 433 SemError(230); ok := FALSE
|
|
|
|
|
- 434 END;
|
|
|
|
|
- 435 END; .) .
|
|
|
|
|
- 436 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
|
|
- 437 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
|
|
- 438 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
|
|
- 439 comparison across suitable bases are lenient (masks over min
|
|
|
|
|
- 440 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
|
|
- 441 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
|
|
- 442 blo, bhi, bspan: INTEGER;
|
|
|
|
|
- 443 bcls: INTEGER; .)
|
|
|
|
|
- 444 = "SET" "OF" Type<base, FALSE>
|
|
|
|
|
- 445 (. IF base = SymTab.InvalidType THEN
|
|
|
|
|
- 446 t := SymTab.InvalidType
|
|
|
|
|
- 447 ELSE bcls :=
|
|
|
|
|
- 448 SymTab.ClassOf(base);
|
|
|
|
|
- 449 IF bcls = SymTab.ClBool THEN
|
|
|
|
|
- 450 blo := 0; bspan := 2
|
|
|
|
|
- 451 ELSIF bcls = SymTab.ClChar THEN
|
|
|
|
|
- 452 blo := 0; bspan := 256
|
|
|
|
|
- 453 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
|
|
- 454 blo := 0;
|
|
|
|
|
- 455 bspan := VAL(INTEGER,
|
|
|
|
|
- 456 SymTab.EnumCount(base))
|
|
|
|
|
- 457 ELSIF SymTab.SubBounds(base,
|
|
|
|
|
- 458 blo, bhi) THEN
|
|
|
|
|
- 459 bspan := bhi - blo + 1
|
|
|
|
|
- 460 ELSE bspan := 0 END;
|
|
|
|
|
- 461 IF (bspan <= 0)
|
|
|
|
|
- 462 OR (bspan > 65536) THEN
|
|
|
|
|
- 463 SemError(230);
|
|
|
|
|
- 464 t := SymTab.InvalidType
|
|
|
|
|
- 465 ELSE t := SymTab.NewSet(base)
|
|
|
|
|
- 466 END
|
|
|
|
|
- 467 END; .) .
|
|
|
|
|
- 468 (* Records: flat blobs; array fields are pointers to static
|
|
|
|
|
- 469 descriptors (locked amendment), nested records inline. Field
|
|
|
|
|
- 470 offsets static and declaration-ordered. *)
|
|
|
|
|
- 471 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
|
|
- 472 variant part is a `CASE ... END` item; because it starts with the
|
|
|
|
|
- 473 CASE keyword it is unambiguously distinguishable from a field
|
|
|
|
|
- 474 (which starts with an identifier). *)
|
|
|
|
|
- 475 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
- 476 tagOk: BOOLEAN; .)
|
|
|
|
|
- 477 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
|
|
- 478 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
|
|
- 479 "END" .
|
|
|
|
|
- 480 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
|
|
- 481 = RecField<rec>
|
|
|
|
|
- 482 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
|
|
- 483 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
|
|
- 484 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
|
|
- 485 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
|
|
- 486 tagN: SymTab.Name; .)
|
|
|
|
|
- 487 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
- 488 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
- 489 tagN) THEN
|
|
|
|
|
- 490 SemError(200) END; .)
|
|
|
|
|
- 491 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
|
|
- 492 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
|
|
- 493 SemError(224)
|
|
|
|
|
- 494 END;
|
|
|
|
|
- 495 SymTab.FixPendingF(rec, tagT);
|
|
|
|
|
- 496 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
|
|
- 497 "OF"
|
|
|
|
|
- 498 RecFieldList<rec>
|
|
|
|
|
- 499 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
- 500 RecFieldList<rec> }
|
|
|
|
|
- 501 "END" .
|
|
|
|
|
- 502 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
|
|
- 503 lv1, lv2: QbeGen.QVal; .)
|
|
|
|
|
- 504 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
|
|
- 505 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
|
|
- 506 (* Variant case label: a constant (or a constant range). Values are
|
|
|
|
|
- 507 not interpreted (the layout overlays regardless). *)
|
|
|
|
|
- 508 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 509 (. VAR lname: SymTab.Name; .)
|
|
|
|
|
- 510 = ( ident (. LexName(lname);
|
|
|
|
|
- 511 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 512 t := SymTab.IntType(); .)
|
|
|
|
|
- 513 | integer (. LexString(lname);
|
|
|
|
|
- 514 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 515 t := SymTab.IntType(); .)
|
|
|
|
|
- 516 | charConst (. LexString(lname);
|
|
|
|
|
- 517 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 518 t := SymTab.CharType(); .) ) .
|
|
|
|
|
- 519 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
- 520 t2: SymTab.TypeIndex; .)
|
|
|
|
|
- 521 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
|
|
- 522 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 523 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
- 524 n) THEN
|
|
|
|
|
- 525 SemError(200) END; .)
|
|
|
|
|
- 526 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
- 527 n) THEN
|
|
|
|
|
- 528 SemError(200) END; .) } .
|
|
|
|
|
- 529 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
|
|
- 530 k: INTEGER;
|
|
|
|
|
- 531 dotted: BOOLEAN; .)
|
|
|
|
|
- 532 = GetIdent<n> (. dotted := FALSE;
|
|
|
|
|
- 533 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
- 534 k := -1;
|
|
|
|
|
- 535 t := SymTab.ForwardType(n);
|
|
|
|
|
- 536 IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 537 SemError(201)
|
|
|
|
|
- 538 END
|
|
|
|
|
- 539 ELSE k := SymTab.SymKind(n);
|
|
|
|
|
- 540 IF (k = SymTab.KindType)
|
|
|
|
|
- 541 OR (k = SymTab.KindPredef) THEN
|
|
|
|
|
- 542 t := SymTab.SymType(n)
|
|
|
|
|
- 543 ELSE t := SymTab.InvalidType
|
|
|
|
|
- 544 END
|
|
|
|
|
- 545 END; .)
|
|
|
|
|
- 546 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
|
|
- 547 IF k = SymTab.KindModule THEN
|
|
|
|
|
- 548 t := SymTab.QualType(n, qid);
|
|
|
|
|
- 549 IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 550 SemError(201)
|
|
|
|
|
- 551 END
|
|
|
|
|
- 552 ELSE SemError(221);
|
|
|
|
|
- 553 t := SymTab.InvalidType
|
|
|
|
|
- 554 END; .) ]
|
|
|
|
|
- 555 (. IF NOT dotted THEN
|
|
|
|
|
- 556 IF (k = SymTab.KindModule)
|
|
|
|
|
- 557 OR ((k # SymTab.KindType)
|
|
|
|
|
- 558 AND (k # SymTab.KindPredef)
|
|
|
|
|
- 559 AND (k # SymTab.KindImport)
|
|
|
|
|
- 560 AND (k # -1)) THEN
|
|
|
|
|
- 561 SemError(221)
|
|
|
|
|
- 562 END
|
|
|
|
|
- 563 END; .) .
|
|
|
|
|
- 564 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
- 565 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
- 566 lo, hi: INTEGER; .)
|
|
|
|
|
- 567 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
- 568 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
- 569 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
- 570 t := SymTab.InvalidType
|
|
|
|
|
- 571 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
|
|
- 572 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
|
|
- 573 SemError(230);
|
|
|
|
|
- 574 t := SymTab.InvalidType
|
|
|
|
|
- 575 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
- 576 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
- 577 OR (lo > hi) THEN
|
|
|
|
|
- 578 SemError(230);
|
|
|
|
|
- 579 t := SymTab.InvalidType
|
|
|
|
|
- 580 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
|
|
- 581 END; .)
|
|
|
|
|
- 582 "]" .
|
|
|
|
|
- 583 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
- 584 ord: INTEGER;
|
|
|
|
|
- 585 qv: QbeGen.QVal; .)
|
|
|
|
|
- 586 = "(" (. t := SymTab.NewEnum();
|
|
|
|
|
- 587 ord := 0; .)
|
|
|
|
|
- 588 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 589 SymTab.KindConst) THEN
|
|
|
|
|
- 590 SemError(200) END;
|
|
|
|
|
- 591 SymTab.SetSymType(n, t);
|
|
|
|
|
- 592 QbeGen.IntStr(ord, qv);
|
|
|
|
|
- 593 SymTab.SetSymVal(n, qv);
|
|
|
|
|
- 594 INC(ord); .)
|
|
|
|
|
- 595 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 596 SymTab.KindConst) THEN
|
|
|
|
|
- 597 SemError(200) END;
|
|
|
|
|
- 598 SymTab.SetSymType(n, t);
|
|
|
|
|
- 599 QbeGen.IntStr(ord, qv);
|
|
|
|
|
- 600 SymTab.SetSymVal(n, qv);
|
|
|
|
|
- 601 INC(ord); .) }
|
|
|
|
|
- 602 ")" (. SymTab.SetEnumCount(t,
|
|
|
|
|
- 603 VAL(CARDINAL, ord)); .) .
|
|
|
|
|
- 604 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
|
|
- 605 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
|
|
- 606 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
|
|
- 607 class/impl block. Methods end with ";" per the Table example
|
|
|
|
|
- 608 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
|
|
- 609 (* Single CLASS item in both loops: separating declaration from
|
|
|
|
|
- 610 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
|
|
- 611 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
|
|
- 612 The second token decides after CLASS is consumed. A misplaced
|
|
|
|
|
- 613 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
|
|
- 614 whole unit ends 230 until lowering). *)
|
|
|
|
|
- 615 ClassItem
|
|
|
|
|
- 616 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
|
|
- 617 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
|
|
- 618 ct: SymTab.TypeIndex; .)
|
|
|
|
|
- 619 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
|
|
- 620 SymTab.KindType) THEN
|
|
|
|
|
- 621 SemError(200) END;
|
|
|
|
|
- 622 ct := SymTab.NewClass();
|
|
|
|
|
- 623 SymTab.SetSymType(cn, ct);
|
|
|
|
|
- 624 SymTab.PushClassScope(ct); .)
|
|
|
|
|
- 625 [ Parents<ct> ]
|
|
|
|
|
- 626 ";"
|
|
|
|
|
- 627 { ClassField<ct> ";" }
|
|
|
|
|
- 628 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
- 629 (. SymTab.CloseProc;
|
|
|
|
|
- 630 QbeGen.AbortFunc; .) }
|
|
|
|
|
- 631 "END"
|
|
|
|
|
- 632 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
- 633 SemError(202) END;
|
|
|
|
|
- 634 SymTab.LayoutClass(ct);
|
|
|
|
|
- 635 SymTab.PopScope; .) .
|
|
|
|
|
- 636 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
|
|
- 637 = "(" Parent1<ct>
|
|
|
|
|
- 638 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
|
|
- 639 ")" .
|
|
|
|
|
- 640 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
|
|
- 641 pt: SymTab.TypeIndex; .)
|
|
|
|
|
- 642 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
|
|
- 643 SemError(201)
|
|
|
|
|
- 644 ELSE pt := SymTab.SymType(p);
|
|
|
|
|
- 645 IF SymTab.ClassOf(pt) #
|
|
|
|
|
- 646 SymTab.ClClass THEN
|
|
|
|
|
- 647 SemError(230)
|
|
|
|
|
- 648 ELSE SymTab.SetParent(ct, pt)
|
|
|
|
|
- 649 END
|
|
|
|
|
- 650 END; .) .
|
|
|
|
|
- 651 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
|
|
- 652 t: SymTab.TypeIndex; .)
|
|
|
|
|
- 653 = GetIdent<n>
|
|
|
|
|
- 654 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 655 SymTab.KindConst) THEN
|
|
|
|
|
- 656 SemError(200) END;
|
|
|
|
|
- 657 IF SymTab.Lookup(rhs) THEN
|
|
|
|
|
- 658 SymTab.SetSymType(n,
|
|
|
|
|
- 659 SymTab.SymType(rhs))
|
|
|
|
|
- 660 END; .)
|
|
|
|
|
- 661 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
- 662 n) THEN
|
|
|
|
|
- 663 SemError(200) END; .)
|
|
|
|
|
- 664 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
- 665 n) THEN
|
|
|
|
|
- 666 SemError(200) END; .) }
|
|
|
|
|
- 667 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
|
|
- 668 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
|
|
- 669 (. VAR wantVirt: BOOLEAN; .)
|
|
|
|
|
- 670 = (. wantVirt := FALSE; .)
|
|
|
|
|
- 671 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
|
|
- 672 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
|
|
- 673 SymTab.MarkVirtual END; .) .
|
|
|
|
|
- 674 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
|
|
- 675 ct: SymTab.TypeIndex; .)
|
|
|
|
|
- 676 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
|
|
- 677 SemError(201);
|
|
|
|
|
- 678 ct := SymTab.InvalidType
|
|
|
|
|
- 679 ELSE ct := SymTab.SymType(cn);
|
|
|
|
|
- 680 IF SymTab.ClassOf(ct) #
|
|
|
|
|
- 681 SymTab.ClClass THEN
|
|
|
|
|
- 682 SemError(230);
|
|
|
|
|
- 683 ct := SymTab.InvalidType
|
|
|
|
|
- 684 END
|
|
|
|
|
- 685 END;
|
|
|
|
|
- 686 IF ct #
|
|
|
|
|
- 687 SymTab.InvalidType THEN
|
|
|
|
|
- 688 IF NOT SymTab.PushClassMembers(
|
|
|
|
|
- 689 ct) THEN
|
|
|
|
|
- 690 SemError(230) END;
|
|
|
|
|
- 691 SymTab.PushImplClass(ct)
|
|
|
|
|
- 692 END; .)
|
|
|
|
|
- 693 ";" { MethodImpl<ct> ";" }
|
|
|
|
|
- 694 [ "BEGIN" (. QbeGen.BeginInit(cn); .)
|
|
|
|
|
- 695 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
|
|
- 696 "END"
|
|
|
|
|
- 697 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
- 698 SemError(202) END;
|
|
|
|
|
- 699 SymTab.PopImplClass;
|
|
|
|
|
- 700 SymTab.PopScope; .) .
|
|
|
|
|
- 701 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
|
|
- 702 thisQ: QbeGen.QVal;
|
|
|
|
|
- 703 methRes: SymTab.TypeIndex; .)
|
|
|
|
|
- 704 = MethodHeading<pn, ct> ";"
|
|
|
|
|
- 705 (. IF (ct #
|
|
|
|
|
- 706 SymTab.InvalidType)
|
|
|
|
|
- 707 AND NOT SymTab.MethodExists(ct,
|
|
|
|
|
- 708 pn) THEN
|
|
|
|
|
- 709 SemError(201) END; .)
|
|
|
|
|
- 710 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
|
|
- 711 QbeGen.AbortFunc;
|
|
|
|
|
- 712 SymTab.CloseProc; .)
|
|
|
|
|
- 713 | (. QbeGen.EndFuncHeader;
|
|
|
|
|
- 714 (* bind the receiver: bare
|
|
|
|
|
- 715 field names resolve
|
|
|
|
|
- 716 against THIS *)
|
|
|
|
|
- 717 QbeGen.ThisBase(thisQ);
|
|
|
|
|
- 718 QbeGen.PushWith(thisQ); .)
|
|
|
|
|
- 719 Block<pn> (. QbeGen.PopWith;
|
|
|
|
|
- 720 methRes := SymTab.CurRes();
|
|
|
|
|
- 721 SymTab.CloseProc;
|
|
|
|
|
- 722 QbeGen.EndFunc(methRes); .) ) .
|
|
|
|
|
- 723 ConstBlock
|
|
|
|
|
- 724 = "CONST" { ConstDecl ";" } .
|
|
|
|
|
- 725 ConstDecl (. VAR n: SymTab.Name;
|
|
|
|
|
- 726 t: SymTab.TypeIndex;
|
|
|
|
|
- 727 qv: QbeGen.QVal;
|
|
|
|
|
- 728 cls: INTEGER; .)
|
|
|
|
|
- 729 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 730 SymTab.KindConst) THEN
|
|
|
|
|
- 731 SemError(200) END; .)
|
|
|
|
|
- 732 "="
|
|
|
|
|
- 733 Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
|
|
- 734 cls := SymTab.ClassOf(t);
|
|
|
|
|
- 735 IF (cls = SymTab.ClArray)
|
|
|
|
|
- 736 OR (cls = SymTab.ClRecord)
|
|
|
|
|
- 737 OR (cls = SymTab.ClClass)
|
|
|
|
|
- 738 OR (cls = SymTab.ClStr)
|
|
|
|
|
- 739 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
- 740 (* an aggregate/string
|
|
|
|
|
- 741 constant: qv is its
|
|
|
|
|
- 742 descriptor address; no
|
|
|
|
|
- 743 scalar data *)
|
|
|
|
|
- 744 SymTab.SetSymVal(n, qv)
|
|
|
|
|
- 745 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
|
|
- 746 SemError(230)
|
|
|
|
|
- 747 ELSE
|
|
|
|
|
- 748 SymTab.SetSymVal(n, qv);
|
|
|
|
|
- 749 QbeGen.DeclConst(n, qv, t)
|
|
|
|
|
- 750 END; .) .
|
|
|
|
|
- 751 VarBlock
|
|
|
|
|
- 752 = "VAR" { VarDecl ";" } .
|
|
|
|
|
- 753 VarDecl (. VAR nm: SymTab.Name;
|
|
|
|
|
- 754 t: SymTab.TypeIndex;
|
|
|
|
|
- 755 i: CARDINAL;
|
|
|
|
|
- 756 cls: INTEGER; .)
|
|
|
|
|
- 757 = VarIdents ":"
|
|
|
|
|
- 758 Type<t, FALSE> (. cls := SymTab.ClassOf(t);
|
|
|
|
|
- 759 IF (t # SymTab.InvalidType)
|
|
|
|
|
- 760 AND NOT SymTab.IsUnresolved(t)
|
|
|
|
|
- 761 AND (cls # SymTab.ClInt)
|
|
|
|
|
- 762 AND (cls # SymTab.ClBool)
|
|
|
|
|
- 763 AND (cls # SymTab.ClChar)
|
|
|
|
|
- 764 AND (cls # SymTab.ClReal)
|
|
|
|
|
- 765 AND (cls # SymTab.ClArray)
|
|
|
|
|
- 766 AND (cls # SymTab.ClSet)
|
|
|
|
|
- 767 AND (cls # SymTab.ClRecord)
|
|
|
|
|
- 768 AND (cls # SymTab.ClPtr)
|
|
|
|
|
- 769 AND (cls # SymTab.ClLong)
|
|
|
|
|
- 770 AND (cls # SymTab.ClProc)
|
|
|
|
|
- 771 AND (cls # SymTab.ClUChar)
|
|
|
|
|
- 772 AND (cls # SymTab.ClUStr)
|
|
|
|
|
- 773 AND (cls # SymTab.ClEnum)
|
|
|
|
|
- 774 AND (cls # SymTab.ClClass) THEN
|
|
|
|
|
- 775 SemError(230) END;
|
|
|
|
|
- 776 IF QbeGen.LocFull() THEN
|
|
|
|
|
- 777 SemError(233) END;
|
|
|
|
|
- 778 i := 0;
|
|
|
|
|
- 779 IF SymTab.IsUnresolved(t)
|
|
|
|
|
- 780 AND NOT SymTab.InProc() THEN
|
|
|
|
|
- 781 (* a forward-typed global:
|
|
|
|
|
- 782 defer emission until the
|
|
|
|
|
- 783 TYPE block completes *)
|
|
|
|
|
- 784 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
- 785 SymTab.PendName(i, nm);
|
|
|
|
|
- 786 IF nPendVar <=
|
|
|
|
|
- 787 HIGH(pendVarName) THEN
|
|
|
|
|
- 788 pendVarName[nPendVar] := nm;
|
|
|
|
|
- 789 pendVarT[nPendVar] := t;
|
|
|
|
|
- 790 INC(nPendVar)
|
|
|
|
|
- 791 END;
|
|
|
|
|
- 792 INC(i)
|
|
|
|
|
- 793 END
|
|
|
|
|
- 794 ELSE
|
|
|
|
|
- 795 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
- 796 SymTab.PendName(i, nm);
|
|
|
|
|
- 797 QbeGen.DeclVar(nm, t);
|
|
|
|
|
- 798 INC(i)
|
|
|
|
|
- 799 END
|
|
|
|
|
- 800 END;
|
|
|
|
|
- 801 (* a plain VAR list, not a
|
|
|
|
|
- 802 heading: the signature
|
|
|
|
|
- 803 result is discarded *)
|
|
|
|
|
- 804 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
- 805 END; .) .
|
|
|
|
|
- 806 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 807 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
- 808 SymTab.KindVar) THEN
|
|
|
|
|
- 809 SemError(200) END; .)
|
|
|
|
|
- 810 { ","
|
|
|
|
|
- 811 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
- 812 SymTab.KindVar) THEN
|
|
|
|
|
- 813 SemError(200) END; .) } .
|
|
|
|
|
- 814 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 815 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
- 816 SemError(200) END; .)
|
|
|
|
|
- 817 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
- 818 SemError(200) END; .) } .
|
|
|
|
|
- 819 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
|
|
- 820 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
|
|
- 821 FORWARD marks; the body heading re-enters (signature compare
|
|
|
|
|
- 822 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
|
|
- 823 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
|
|
- 824 (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 825 mg: QbeGen.QVal; .)
|
|
|
|
|
- 826 = "PROCEDURE"
|
|
|
|
|
- 827 GetIdent<pn> (. IF methCls #
|
|
|
|
|
- 828 SymTab.InvalidType THEN
|
|
|
|
|
- 829 (* a method: resume the
|
|
|
|
|
- 830 declared symbol (reuse
|
|
|
|
|
- 831 its uid) *)
|
|
|
|
|
- 832 IF NOT SymTab.ResumeMethod(
|
|
|
|
|
- 833 methCls, pn) THEN
|
|
|
|
|
- 834 SemError(200) END
|
|
|
|
|
- 835 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
|
|
- 836 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
|
|
- 837 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
|
|
- 838 SemError(200) END
|
|
|
|
|
- 839 END
|
|
|
|
|
- 840 END;
|
|
|
|
|
- 841 IF methCls #
|
|
|
|
|
- 842 SymTab.InvalidType THEN
|
|
|
|
|
- 843 QbeGen.Mangled(pn,
|
|
|
|
|
- 844 SymTab.MethUid(), mg)
|
|
|
|
|
- 845 ELSE
|
|
|
|
|
- 846 QbeGen.Mangled(pn,
|
|
|
|
|
- 847 SymTab.ProcUid(pn), mg)
|
|
|
|
|
- 848 END;
|
|
|
|
|
- 849 QbeGen.BeginFunc(mg);
|
|
|
|
|
- 850 IF methCls #
|
|
|
|
|
- 851 SymTab.InvalidType THEN
|
|
|
|
|
- 852 (* hidden THIS receiver:
|
|
|
|
|
- 853 a VAR param of the
|
|
|
|
|
- 854 class type, pushed as
|
|
|
|
|
- 855 the WITH base *)
|
|
|
|
|
- 856 IF NOT SymTab.EnterThisParam(
|
|
|
|
|
- 857 methCls) THEN
|
|
|
|
|
- 858 SemError(200) END;
|
|
|
|
|
- 859 IF NOT QbeGen.FuncParam(
|
|
|
|
|
- 860 "THIS", TRUE,
|
|
|
|
|
- 861 methCls) THEN
|
|
|
|
|
- 862 SemError(233) END
|
|
|
|
|
- 863 END; .)
|
|
|
|
|
- 864 [ FormalParams ]
|
|
|
|
|
- 865 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
|
|
- 866 SemError(235) END;
|
|
|
|
|
- 867 QbeGen.SetFuncRes(t);
|
|
|
|
|
- 868 IF (t #
|
|
|
|
|
- 869 SymTab.InvalidType)
|
|
|
|
|
- 870 AND ((SymTab.ClassOf(t)
|
|
|
|
|
- 871 = SymTab.ClArray)
|
|
|
|
|
- 872 OR (SymTab.ClassOf(t)
|
|
|
|
|
- 873 = SymTab.ClRecord)
|
|
|
|
|
- 874 OR (SymTab.ClassOf(t)
|
|
|
|
|
- 875 = SymTab.ClSet)
|
|
|
|
|
- 876 OR (SymTab.ClassOf(t)
|
|
|
|
|
- 877 = SymTab.ClClass)) THEN
|
|
|
|
|
- 878 SemError(230) END; .) ] .
|
|
|
|
|
- 879 FormalParams
|
|
|
|
|
- 880 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
|
|
- 881 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 882 nm: SymTab.Name;
|
|
|
|
|
- 883 i: CARDINAL;
|
|
|
|
|
- 884 isV: BOOLEAN; .)
|
|
|
|
|
- 885 = (. isV := FALSE; .)
|
|
|
|
|
- 886 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
- 887 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
|
|
- 888 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
- 889 SymTab.PendName(i, nm);
|
|
|
|
|
- 890 (* value open arrays are
|
|
|
|
|
- 891 passed as descriptor
|
|
|
|
|
- 892 addresses (no copy):
|
|
|
|
|
- 893 same representation as
|
|
|
|
|
- 894 VAR formals *)
|
|
|
|
|
- 895 IF NOT QbeGen.FuncParam(nm,
|
|
|
|
|
- 896 isV
|
|
|
|
|
- 897 OR SymTab.IsOpenArray(t),
|
|
|
|
|
- 898 t) THEN
|
|
|
|
|
- 899 SemError(233) END;
|
|
|
|
|
- 900 INC(i)
|
|
|
|
|
- 901 END;
|
|
|
|
|
- 902 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
- 903 SemError(235) END; .) .
|
|
|
|
|
- 904 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
|
|
- 905 static link gives them their parent's frame. Methods keep
|
|
|
|
|
- 906 parse-now/230-later. *)
|
|
|
|
|
- 907 ProcDecl (. VAR pn: SymTab.Name; .)
|
|
|
|
|
- 908 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
- 909 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
|
|
- 910 SymTab.CloseProc;
|
|
|
|
|
- 911 QbeGen.AbortFunc; .)
|
|
|
|
|
- 912 | "EXTERNAL" (. SymTab.MarkExternal("");
|
|
|
|
|
- 913 SymTab.CloseProc;
|
|
|
|
|
- 914 QbeGen.AbortFunc; .)
|
|
|
|
|
- 915 | (. QbeGen.EndFuncHeader; .)
|
|
|
|
|
- 916 Block<pn> (. SymTab.CloseProc;
|
|
|
|
|
- 917 QbeGen.EndFunc(
|
|
|
|
|
- 918 SymTab.ProcRes(pn)); .) ) .
|
|
|
|
|
- 919 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
|
|
- 920 = DeclSeq
|
|
|
|
|
- 921 [ "BEGIN"
|
|
|
|
|
- 922 [ StatSeq ] ]
|
|
|
|
|
- 923 "END"
|
|
|
|
|
- 924 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
|
|
- 925 SemError(202) END; .) .
|
|
|
|
|
- 926 StatSeq
|
|
|
|
|
- 927 = Statement { ";" [ Statement ] } .
|
|
|
|
|
- 928 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
|
|
- 929 are accepted: the statement after ';' is optional. *)
|
|
|
|
|
- 930 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
|
|
- 931 = AssOrCall
|
|
|
|
|
- 932 | IfStat
|
|
|
|
|
- 933 | WhileStat
|
|
|
|
|
- 934 | RepeatStat
|
|
|
|
|
- 935 | LoopStat
|
|
|
|
|
- 936 | ForStat
|
|
|
|
|
- 937 | CaseStat
|
|
|
|
|
- 938 | WithStat
|
|
|
|
|
- 939 | ReturnStat
|
|
|
|
|
- 940 | HaltStat
|
|
|
|
|
- 941 | NewStat
|
|
|
|
|
- 942 | DisposeStat
|
|
|
|
|
- 943 | IncDecStat
|
|
|
|
|
- 944 | InclExclStat
|
|
|
|
|
- 945 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
|
|
- 946 QbeGen.Jmp(lx)
|
|
|
|
|
- 947 ELSE SemError(230) END; .) .
|
|
|
|
|
- 948 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
|
|
- 949 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
|
|
- 950 dk: INTEGER;
|
|
|
|
|
- 951 qd, qe: QbeGen.QVal;
|
|
|
|
|
- 952 qn: SymTab.Name;
|
|
|
|
|
- 953 sfx, isInc: BOOLEAN; .)
|
|
|
|
|
- 954 = ( "INCL" (. isInc := TRUE; .)
|
|
|
|
|
- 955 | "EXCL" (. isInc := FALSE; .) )
|
|
|
|
|
- 956 "(" Design<at, dk, qd, qn, sfx> ","
|
|
|
|
|
- 957 Expr<et2, qe> ")"
|
|
|
|
|
- 958 (. IF at = SymTab.InvalidType THEN
|
|
|
|
|
- 959 ELSIF SymTab.ClassOf(at) #
|
|
|
|
|
- 960 SymTab.ClSet THEN
|
|
|
|
|
- 961 SemError(222)
|
|
|
|
|
- 962 ELSE
|
|
|
|
|
- 963 IF isInc THEN
|
|
|
|
|
- 964 QbeGen.SetBit(qd, qe,
|
|
|
|
|
- 965 SymTab.SetBaseLo(at),
|
|
|
|
|
- 966 SymTab.SetCount(at))
|
|
|
|
|
- 967 ELSE
|
|
|
|
|
- 968 QbeGen.SetClearBit(qd, qe,
|
|
|
|
|
- 969 SymTab.SetBaseLo(at),
|
|
|
|
|
- 970 SymTab.SetCount(at))
|
|
|
|
|
- 971 END
|
|
|
|
|
- 972 END; .) .
|
|
|
|
|
- 973 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
|
|
- 974 integer designator. *)
|
|
|
|
|
- 975 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
|
|
- 976 dk: INTEGER;
|
|
|
|
|
- 977 qd, qv, qn2, qstep:
|
|
|
|
|
- 978 QbeGen.QVal;
|
|
|
|
|
- 979 qn: SymTab.Name;
|
|
|
|
|
- 980 sfx, isInc: BOOLEAN; .)
|
|
|
|
|
- 981 = (. isInc := TRUE; .)
|
|
|
|
|
- 982 ( "INC" (. isInc := TRUE; .)
|
|
|
|
|
- 983 | "DEC" (. isInc := FALSE; .) )
|
|
|
|
|
- 984 "(" (. QbeGen.CopyOp("1", qstep); .)
|
|
|
|
|
- 985 Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
- 986 [ "," Expr<et2, qstep> ]
|
|
|
|
|
- 987 ")" (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 988 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
- 989 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 990 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 991 SemError(210)
|
|
|
|
|
- 992 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
|
|
- 993 SemError(211)
|
|
|
|
|
- 994 ELSE
|
|
|
|
|
- 995 IF sfx
|
|
|
|
|
- 996 OR (dk = SymTab.KindField) THEN
|
|
|
|
|
- 997 QbeGen.ElemLoad(qd, dt, qv)
|
|
|
|
|
- 998 ELSE QbeGen.LoadVar(qn,
|
|
|
|
|
- 999 FALSE, qv)
|
|
|
|
|
- 1000 END;
|
|
|
|
|
- 1001 QbeGen.NewTemp(qn2);
|
|
|
|
|
- 1002 IF isInc THEN
|
|
|
|
|
- 1003 QbeGen.Op3("add", qn2, qv,
|
|
|
|
|
- 1004 qstep, FALSE)
|
|
|
|
|
- 1005 ELSE QbeGen.Op3("sub", qn2, qv,
|
|
|
|
|
- 1006 qstep, FALSE)
|
|
|
|
|
- 1007 END;
|
|
|
|
|
- 1008 IF sfx
|
|
|
|
|
- 1009 OR (dk = SymTab.KindField) THEN
|
|
|
|
|
- 1010 QbeGen.ElemStore(qd, qn2,
|
|
|
|
|
- 1011 dt)
|
|
|
|
|
- 1012 ELSE QbeGen.StoreVar(qn,
|
|
|
|
|
- 1013 qn2, FALSE)
|
|
|
|
|
- 1014 END
|
|
|
|
|
- 1015 END; .) .
|
|
|
|
|
- 1016 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
|
|
- 1017 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
|
|
- 1018 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
|
|
- 1019 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
- 1020 dk: INTEGER;
|
|
|
|
|
- 1021 qd, qm: QbeGen.QVal;
|
|
|
|
|
- 1022 qn: SymTab.Name;
|
|
|
|
|
- 1023 sfx: BOOLEAN;
|
|
|
|
|
- 1024 bt: SymTab.TypeIndex; .)
|
|
|
|
|
- 1025 = "NEW" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 1026 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 1027 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
- 1028 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 1029 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 1030 SemError(210)
|
|
|
|
|
- 1031 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
- 1032 SymTab.ClPtr THEN
|
|
|
|
|
- 1033 SemError(219)
|
|
|
|
|
- 1034 ELSE bt := SymTab.PtrBase(dt);
|
|
|
|
|
- 1035 IF bt #
|
|
|
|
|
- 1036 SymTab.InvalidType THEN
|
|
|
|
|
- 1037 QbeGen.NewHeap(bt, qm);
|
|
|
|
|
- 1038 QbeGen.InitHeap(qm, bt);
|
|
|
|
|
- 1039 IF sfx
|
|
|
|
|
- 1040 OR (dk =
|
|
|
|
|
- 1041 SymTab.KindField) THEN
|
|
|
|
|
- 1042 QbeGen.ElemStore(qd, qm,
|
|
|
|
|
- 1043 dt)
|
|
|
|
|
- 1044 ELSE QbeGen.StorePtr(qn,
|
|
|
|
|
- 1045 qm)
|
|
|
|
|
- 1046 END
|
|
|
|
|
- 1047 END
|
|
|
|
|
- 1048 END; .) .
|
|
|
|
|
- 1049 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
- 1050 dk: INTEGER;
|
|
|
|
|
- 1051 qd, qv: QbeGen.QVal;
|
|
|
|
|
- 1052 qn: SymTab.Name;
|
|
|
|
|
- 1053 sfx: BOOLEAN; .)
|
|
|
|
|
- 1054 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 1055 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 1056 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
- 1057 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 1058 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 1059 SemError(210)
|
|
|
|
|
- 1060 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
- 1061 SymTab.ClPtr THEN
|
|
|
|
|
- 1062 SemError(219)
|
|
|
|
|
- 1063 ELSE
|
|
|
|
|
- 1064 IF sfx
|
|
|
|
|
- 1065 OR (dk =
|
|
|
|
|
- 1066 SymTab.KindField) THEN
|
|
|
|
|
- 1067 QbeGen.ElemLoad(qd, dt,
|
|
|
|
|
- 1068 qv)
|
|
|
|
|
- 1069 ELSE QbeGen.LoadPtr(qn, qv)
|
|
|
|
|
- 1070 END;
|
|
|
|
|
- 1071 QbeGen.FreeHeap(qv);
|
|
|
|
|
- 1072 IF sfx
|
|
|
|
|
- 1073 OR (dk =
|
|
|
|
|
- 1074 SymTab.KindField) THEN
|
|
|
|
|
- 1075 QbeGen.ElemStore(qd, "0",
|
|
|
|
|
- 1076 dt)
|
|
|
|
|
- 1077 ELSE QbeGen.StorePtr(qn,
|
|
|
|
|
- 1078 "0")
|
|
|
|
|
- 1079 END
|
|
|
|
|
- 1080 END; .) .
|
|
|
|
|
- 1081 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
|
|
- 1082 address; field designators resolve through both stacks. *)
|
|
|
|
|
- 1083 WithStat (. VAR nW: CARDINAL; .)
|
|
|
|
|
- 1084 = "WITH" (. nW := 0; .)
|
|
|
|
|
- 1085 WithItem<nW> { "," WithItem<nW> }
|
|
|
|
|
- 1086 "DO" [ StatSeq ] "END"
|
|
|
|
|
- 1087 (. WHILE nW > 0 DO
|
|
|
|
|
- 1088 SymTab.PopScope;
|
|
|
|
|
- 1089 QbeGen.PopWith;
|
|
|
|
|
- 1090 DEC(nW)
|
|
|
|
|
- 1091 END; .) .
|
|
|
|
|
- 1092 WithItem<VAR nW: CARDINAL> (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
- 1093 dk: INTEGER;
|
|
|
|
|
- 1094 qd, qe: QbeGen.QVal;
|
|
|
|
|
- 1095 qn: SymTab.Name;
|
|
|
|
|
- 1096 sfx: BOOLEAN; .)
|
|
|
|
|
- 1097 = Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
- 1098 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 1099 ELSIF (SymTab.ClassOf(dt) #
|
|
|
|
|
- 1100 SymTab.ClRecord)
|
|
|
|
|
- 1101 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
- 1102 SymTab.ClClass) THEN
|
|
|
|
|
- 1103 SemError(215)
|
|
|
|
|
- 1104 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
|
|
- 1105 QbeGen.PushWith(qd);
|
|
|
|
|
- 1106 INC(nW)
|
|
|
|
|
- 1107 END; .) .
|
|
|
|
|
- 1108 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
|
|
- 1109 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
|
|
- 1110 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
|
|
- 1111 dk: INTEGER;
|
|
|
|
|
- 1112 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
|
|
- 1113 qn: SymTab.Name;
|
|
|
|
|
- 1114 ct2, res0: SymTab.TypeIndex;
|
|
|
|
|
- 1115 q2, mg0: QbeGen.QVal;
|
|
|
|
|
- 1116 isR, conv, wconv: BOOLEAN;
|
|
|
|
|
- 1117 called, sfx: BOOLEAN; .)
|
|
|
|
|
- 1118 = Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
- 1119 ( ":="
|
|
|
|
|
- 1120 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
|
|
- 1121 AND (dk # SymTab.KindVar)
|
|
|
|
|
- 1122 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 1123 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 1124 SemError(210)
|
|
|
|
|
- 1125 ELSIF NOT SymTab.Assignable(et,
|
|
|
|
|
- 1126 dt) THEN
|
|
|
|
|
- 1127 SemError(210)
|
|
|
|
|
- 1128 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
- 1129 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
- 1130 SymTab.ClClass) THEN
|
|
|
|
|
- 1131 SemError(230) END;
|
|
|
|
|
- 1132 isR := (dt #
|
|
|
|
|
- 1133 SymTab.InvalidType)
|
|
|
|
|
- 1134 AND (SymTab.ClassOf(dt)
|
|
|
|
|
- 1135 = SymTab.ClReal);
|
|
|
|
|
- 1136 conv := isR
|
|
|
|
|
- 1137 AND SymTab.IsIntFamily(et);
|
|
|
|
|
- 1138 wconv := (dt #
|
|
|
|
|
- 1139 SymTab.InvalidType)
|
|
|
|
|
- 1140 AND SymTab.IsLongFamily(dt)
|
|
|
|
|
- 1141 AND SymTab.IsIntFamily(et);
|
|
|
|
|
- 1142 IF ((dk = SymTab.KindVar)
|
|
|
|
|
- 1143 OR (dk = SymTab.KindParam)
|
|
|
|
|
- 1144 OR (dk = SymTab.KindField))
|
|
|
|
|
- 1145 AND (dt # SymTab.InvalidType)
|
|
|
|
|
- 1146 AND (et # SymTab.InvalidType)
|
|
|
|
|
- 1147 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
- 1148 SymTab.ClClass) THEN
|
|
|
|
|
- 1149 IF sfx
|
|
|
|
|
- 1150 OR (dk = SymTab.KindField) THEN
|
|
|
|
|
- 1151 IF SymTab.ClassOf(dt) =
|
|
|
|
|
- 1152 SymTab.ClArray THEN
|
|
|
|
|
- 1153 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 1154 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
|
|
- 1155 AND SymTab.IsUCharArray(dt) THEN
|
|
|
|
|
- 1156 QbeGen.UAssign(qd, qe)
|
|
|
|
|
- 1157 ELSIF SymTab.StrCompat(dt,
|
|
|
|
|
- 1158 et) THEN
|
|
|
|
|
- 1159 QbeGen.StrAssign(qd,
|
|
|
|
|
- 1160 qe)
|
|
|
|
|
- 1161 ELSE
|
|
|
|
|
- 1162 QbeGen.CopyArray(qd,
|
|
|
|
|
- 1163 qe, dt)
|
|
|
|
|
- 1164 END
|
|
|
|
|
- 1165 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
- 1166 SymTab.ClSet THEN
|
|
|
|
|
- 1167 QbeGen.CopySet(qd, qe,
|
|
|
|
|
- 1168 SymTab.SetWords(dt),
|
|
|
|
|
- 1169 SymTab.SetWords(et))
|
|
|
|
|
- 1170 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
- 1171 SymTab.ClRecord THEN
|
|
|
|
|
- 1172 QbeGen.CopyRecord(qd, qe,
|
|
|
|
|
- 1173 dt)
|
|
|
|
|
- 1174 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
|
|
- 1175 IF wconv THEN
|
|
|
|
|
- 1176 QbeGen.WidenLong(qe, ql);
|
|
|
|
|
- 1177 QbeGen.ElemStore(qd, ql,
|
|
|
|
|
- 1178 dt)
|
|
|
|
|
- 1179 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
|
|
- 1180 dt)
|
|
|
|
|
- 1181 END
|
|
|
|
|
- 1182 ELSIF conv THEN
|
|
|
|
|
- 1183 QbeGen.ConvIR(qe, qt);
|
|
|
|
|
- 1184 QbeGen.ElemStore(qd, qt,
|
|
|
|
|
- 1185 dt)
|
|
|
|
|
- 1186 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
|
|
- 1187 dt)
|
|
|
|
|
- 1188 END
|
|
|
|
|
- 1189 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
- 1190 SymTab.ClArray THEN
|
|
|
|
|
- 1191 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 1192 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
|
|
- 1193 AND SymTab.IsUCharArray(dt) THEN
|
|
|
|
|
- 1194 QbeGen.UAssign(qd, qe)
|
|
|
|
|
- 1195 ELSIF SymTab.StrCompat(dt,
|
|
|
|
|
- 1196 et) THEN
|
|
|
|
|
- 1197 QbeGen.StrAssign(qd, qe)
|
|
|
|
|
- 1198 ELSE
|
|
|
|
|
- 1199 QbeGen.CopyArray(qd, qe,
|
|
|
|
|
- 1200 dt)
|
|
|
|
|
- 1201 END
|
|
|
|
|
- 1202 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
- 1203 SymTab.ClSet THEN
|
|
|
|
|
- 1204 QbeGen.CopySet(qd, qe,
|
|
|
|
|
- 1205 SymTab.SetWords(dt),
|
|
|
|
|
- 1206 SymTab.SetWords(et))
|
|
|
|
|
- 1207 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
- 1208 SymTab.ClRecord THEN
|
|
|
|
|
- 1209 QbeGen.CopyRecord(qd, qe, dt)
|
|
|
|
|
- 1210 ELSIF (SymTab.ClassOf(dt) =
|
|
|
|
|
- 1211 SymTab.ClPtr)
|
|
|
|
|
- 1212 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
- 1213 SymTab.ClProc) THEN
|
|
|
|
|
- 1214 QbeGen.StorePtr(qn, qe)
|
|
|
|
|
- 1215 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
|
|
- 1216 IF wconv THEN
|
|
|
|
|
- 1217 QbeGen.WidenLong(qe, ql);
|
|
|
|
|
- 1218 QbeGen.StoreLong(qn, ql)
|
|
|
|
|
- 1219 ELSE QbeGen.StoreLong(qn, qe)
|
|
|
|
|
- 1220 END
|
|
|
|
|
- 1221 ELSIF conv THEN
|
|
|
|
|
- 1222 QbeGen.ConvIR(qe, qt);
|
|
|
|
|
- 1223 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
|
|
- 1224 ELSE
|
|
|
|
|
- 1225 QbeGen.StoreVar(qn, qe, isR)
|
|
|
|
|
- 1226 END
|
|
|
|
|
- 1227 END; .)
|
|
|
|
|
- 1228 | ArgList<qn, dt, qd, FALSE, methCls, ct2, q2, called>
|
|
|
|
|
- 1229 | (* bare `P;`: proper parameterless
|
|
|
|
|
- 1230 procedure call; anything else
|
|
|
|
|
- 1231 here is 233 (was a bare syntax
|
|
|
|
|
- 1232 error before 4.2) *)
|
|
|
|
|
- 1233 (. IF (dk = SymTab.KindProc)
|
|
|
|
|
- 1234 AND NOT sfx THEN
|
|
|
|
|
- 1235 res0 := SymTab.ProcRes(qn);
|
|
|
|
|
- 1236 IF res0 #
|
|
|
|
|
- 1237 SymTab.InvalidType THEN
|
|
|
|
|
- 1238 SemError(233)
|
|
|
|
|
- 1239 ELSIF SymTab.ProcNPar(qn) #
|
|
|
|
|
- 1240 0 THEN
|
|
|
|
|
- 1241 SemError(233)
|
|
|
|
|
- 1242 ELSE QbeGen.Mangled(qn,
|
|
|
|
|
- 1243 SymTab.ProcUid(qn), mg0);
|
|
|
|
|
- 1244 QbeGen.CallBegin(mg0,
|
|
|
|
|
- 1245 res0,
|
|
|
|
|
- 1246 SymTab.ProcDepthOf(qn),
|
|
|
|
|
- 1247 SymTab.IsExternal(qn));
|
|
|
|
|
- 1248 QbeGen.CallEnd(FALSE, q2)
|
|
|
|
|
- 1249 END
|
|
|
|
|
- 1250 ELSE SemError(233)
|
|
|
|
|
- 1251 END; .) ) .
|
|
|
|
|
- 1252 (* Actual-parameter list shared by statement and expression calls.
|
|
|
|
|
- 1253 want selects CallEnd's result handling; t/q carry the call
|
|
|
|
|
- 1254 value (statement calls discard). Arity/type failures are 233;
|
|
|
|
|
- 1255 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
|
|
- 1256 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
|
|
- 1257 want: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
|
|
- 1258 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
- 1259 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
|
|
- 1260 vs: INTEGER;
|
|
|
|
|
- 1261 res: SymTab.TypeIndex;
|
|
|
|
|
- 1262 mg: QbeGen.QVal;
|
|
|
|
|
- 1263 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
|
|
- 1264 = "(" (. called := TRUE;
|
|
|
|
|
- 1265 ok := TRUE;
|
|
|
|
|
- 1266 ind := FALSE;
|
|
|
|
|
- 1267 isMeth := methCls #
|
|
|
|
|
- 1268 SymTab.InvalidType;
|
|
|
|
|
- 1269 IF isMeth THEN
|
|
|
|
|
- 1270 (* class method: the
|
|
|
|
|
- 1271 receiver is armed.
|
|
|
|
|
- 1272 Virtual -> dispatch
|
|
|
|
|
- 1273 through the vtable;
|
|
|
|
|
- 1274 otherwise a static
|
|
|
|
|
- 1275 call. *)
|
|
|
|
|
- 1276 res := SymTab.ClassMethodRes(
|
|
|
|
|
- 1277 methCls, pn);
|
|
|
|
|
- 1278 vs := SymTab.VirtSlot(
|
|
|
|
|
- 1279 methCls, pn);
|
|
|
|
|
- 1280 IF vs >= 0 THEN
|
|
|
|
|
- 1281 QbeGen.VirtCallBegin(
|
|
|
|
|
- 1282 callee, vs, res)
|
|
|
|
|
- 1283 ELSE
|
|
|
|
|
- 1284 QbeGen.Mangled(pn,
|
|
|
|
|
- 1285 SymTab.ClassMethodUid(
|
|
|
|
|
- 1286 methCls, pn), mg);
|
|
|
|
|
- 1287 QbeGen.CallBegin(mg, res, 0,
|
|
|
|
|
- 1288 FALSE)
|
|
|
|
|
- 1289 END
|
|
|
|
|
- 1290 ELSIF SymTab.SymKind(pn) =
|
|
|
|
|
- 1291 SymTab.KindProc THEN
|
|
|
|
|
- 1292 res := SymTab.ProcRes(pn);
|
|
|
|
|
- 1293 QbeGen.Mangled(pn,
|
|
|
|
|
- 1294 SymTab.ProcUid(pn), mg);
|
|
|
|
|
- 1295 QbeGen.CallBegin(mg, res,
|
|
|
|
|
- 1296 SymTab.ProcDepthOf(pn),
|
|
|
|
|
- 1297 SymTab.IsExternal(pn))
|
|
|
|
|
- 1298 ELSIF (pt # SymTab.InvalidType)
|
|
|
|
|
- 1299 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
|
|
- 1300 ind := TRUE;
|
|
|
|
|
- 1301 res :=
|
|
|
|
|
- 1302 SymTab.ProcTypeRes(pt);
|
|
|
|
|
- 1303 QbeGen.CallBeginInd(callee,
|
|
|
|
|
- 1304 res, FALSE)
|
|
|
|
|
- 1305 ELSE SemError(233);
|
|
|
|
|
- 1306 ok := FALSE;
|
|
|
|
|
- 1307 res := SymTab.InvalidType
|
|
|
|
|
- 1308 END;
|
|
|
|
|
- 1309 i := 0; .)
|
|
|
|
|
- 1310 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
|
|
- 1311 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
|
|
- 1312 ")" (. IF ok THEN
|
|
|
|
|
- 1313 IF isMeth THEN
|
|
|
|
|
- 1314 np := SymTab.ClassMethodNPar(
|
|
|
|
|
- 1315 methCls, pn)
|
|
|
|
|
- 1316 ELSIF ind THEN
|
|
|
|
|
- 1317 np := SymTab.ProcTypeNPar(pt)
|
|
|
|
|
- 1318 ELSE np := SymTab.ProcNPar(pn)
|
|
|
|
|
- 1319 END;
|
|
|
|
|
- 1320 va := (NOT isMeth) AND (NOT ind)
|
|
|
|
|
- 1321 AND (SymTab.SymKind(pn) =
|
|
|
|
|
- 1322 SymTab.KindProc)
|
|
|
|
|
- 1323 AND SymTab.Varargs(pn);
|
|
|
|
|
- 1324 IF (i # np) AND NOT va THEN
|
|
|
|
|
- 1325 SemError(233); ok := FALSE
|
|
|
|
|
- 1326 END
|
|
|
|
|
- 1327 END;
|
|
|
|
|
- 1328 IF NOT ok THEN
|
|
|
|
|
- 1329 t := SymTab.InvalidType;
|
|
|
|
|
- 1330 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1331 ELSIF want THEN
|
|
|
|
|
- 1332 IF res =
|
|
|
|
|
- 1333 SymTab.InvalidType THEN
|
|
|
|
|
- 1334 SemError(233);
|
|
|
|
|
- 1335 t := SymTab.InvalidType;
|
|
|
|
|
- 1336 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1337 ELSE t := res;
|
|
|
|
|
- 1338 QbeGen.CallEnd(TRUE, q)
|
|
|
|
|
- 1339 END
|
|
|
|
|
- 1340 ELSE
|
|
|
|
|
- 1341 IF res #
|
|
|
|
|
- 1342 SymTab.InvalidType THEN
|
|
|
|
|
- 1343 SemError(233)
|
|
|
|
|
- 1344 END;
|
|
|
|
|
- 1345 t := SymTab.InvalidType;
|
|
|
|
|
- 1346 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 1347 QbeGen.CallEnd(FALSE, q)
|
|
|
|
|
- 1348 END; .) .
|
|
|
|
|
- 1349 (* One actual: VAR formals take recorded designator addresses
|
|
|
|
|
- 1350 (233 otherwise); value formals take converted expressions. *)
|
|
|
|
|
- 1351 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
|
|
- 1352 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
|
|
- 1353 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
|
|
- 1354 qe, qa, qt: QbeGen.QVal;
|
|
|
|
|
- 1355 isV, conv, va: BOOLEAN;
|
|
|
|
|
- 1356 cl: CHAR; .)
|
|
|
|
|
- 1357 = Expr<at, qe> (. va := (NOT ind)
|
|
|
|
|
- 1358 AND (methCls =
|
|
|
|
|
- 1359 SymTab.InvalidType)
|
|
|
|
|
- 1360 AND (SymTab.SymKind(pn) =
|
|
|
|
|
- 1361 SymTab.KindProc)
|
|
|
|
|
- 1362 AND SymTab.Varargs(pn);
|
|
|
|
|
- 1363 IF ind THEN
|
|
|
|
|
- 1364 ft :=
|
|
|
|
|
- 1365 SymTab.ProcTypeParamType(pt,
|
|
|
|
|
- 1366 i);
|
|
|
|
|
- 1367 isV :=
|
|
|
|
|
- 1368 SymTab.ProcTypeParamIsVar(pt,
|
|
|
|
|
- 1369 i)
|
|
|
|
|
- 1370 ELSIF methCls #
|
|
|
|
|
- 1371 SymTab.InvalidType THEN
|
|
|
|
|
- 1372 ft :=
|
|
|
|
|
- 1373 SymTab.ClassMethodParamType(
|
|
|
|
|
- 1374 methCls, pn, i);
|
|
|
|
|
- 1375 isV :=
|
|
|
|
|
- 1376 SymTab.ClassMethodParamIsVar(
|
|
|
|
|
- 1377 methCls, pn, i)
|
|
|
|
|
- 1378 ELSE
|
|
|
|
|
- 1379 ft := SymTab.ParamType(pn, i);
|
|
|
|
|
- 1380 isV := SymTab.ParamIsVar(pn, i)
|
|
|
|
|
- 1381 END;
|
|
|
|
|
- 1382 IF (at = SymTab.InvalidType) THEN
|
|
|
|
|
- 1383 ELSIF ft = SymTab.InvalidType THEN
|
|
|
|
|
- 1384 IF va THEN
|
|
|
|
|
- 1385 QbeGen.CArgAdd(qe, at, qa, cl)
|
|
|
|
|
- 1386 END
|
|
|
|
|
- 1387 ELSIF isV THEN
|
|
|
|
|
- 1388 IF (SymTab.ClassOf(at)
|
|
|
|
|
- 1389 = SymTab.ClChar)
|
|
|
|
|
- 1390 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
- 1391 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
|
|
- 1392 = SymTab.ClChar)
|
|
|
|
|
- 1393 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
- 1394 (* 1-char string
|
|
|
|
|
- 1395 literal passed to
|
|
|
|
|
- 1396 a VAR ARRAY OF CHAR *)
|
|
|
|
|
- 1397 QbeGen.DeclCharStr(qe,
|
|
|
|
|
- 1398 qa);
|
|
|
|
|
- 1399 IF NOT QbeGen.CallArg(qa,
|
|
|
|
|
- 1400 "l") THEN
|
|
|
|
|
- 1401 SemError(233)
|
|
|
|
|
- 1402 END
|
|
|
|
|
- 1403 ELSIF NOT QbeGen.AddrOfVal(qe,
|
|
|
|
|
- 1404 qa) THEN
|
|
|
|
|
- 1405 SemError(233)
|
|
|
|
|
- 1406 ELSIF NOT SymTab.VarParamOk(at,
|
|
|
|
|
- 1407 ft) THEN
|
|
|
|
|
- 1408 SemError(233)
|
|
|
|
|
- 1409 ELSIF NOT QbeGen.CallArg(qa,
|
|
|
|
|
- 1410 "l") THEN
|
|
|
|
|
- 1411 SemError(233)
|
|
|
|
|
- 1412 END
|
|
|
|
|
- 1413 ELSE
|
|
|
|
|
- 1414 IF (SymTab.ClassOf(at)
|
|
|
|
|
- 1415 = SymTab.ClChar)
|
|
|
|
|
- 1416 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
- 1417 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
|
|
- 1418 = SymTab.ClChar)
|
|
|
|
|
- 1419 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
- 1420 (* 1-char string
|
|
|
|
|
- 1421 literal passed to
|
|
|
|
|
- 1422 ARRAY OF CHAR *)
|
|
|
|
|
- 1423 QbeGen.DeclCharStr(qe,
|
|
|
|
|
- 1424 qa);
|
|
|
|
|
- 1425 IF NOT QbeGen.CallArg(qa,
|
|
|
|
|
- 1426 "l") THEN
|
|
|
|
|
- 1427 SemError(233)
|
|
|
|
|
- 1428 END
|
|
|
|
|
- 1429 ELSIF NOT SymTab.Assignable(at,
|
|
|
|
|
- 1430 ft) THEN
|
|
|
|
|
- 1431 SemError(233)
|
|
|
|
|
- 1432 ELSE
|
|
|
|
|
- 1433 conv := (SymTab.ClassOf(
|
|
|
|
|
- 1434 ft) = SymTab.ClReal)
|
|
|
|
|
- 1435 AND SymTab.IsIntFamily(at);
|
|
|
|
|
- 1436 IF conv THEN
|
|
|
|
|
- 1437 QbeGen.ConvIR(qe, qt);
|
|
|
|
|
- 1438 IF NOT QbeGen.CallArg(qt,
|
|
|
|
|
- 1439 "d") THEN
|
|
|
|
|
- 1440 SemError(233)
|
|
|
|
|
- 1441 END
|
|
|
|
|
- 1442 ELSIF NOT QbeGen.CallArg(qe,
|
|
|
|
|
- 1443 QbeGen.ArgClass(ft)) THEN
|
|
|
|
|
- 1444 SemError(233)
|
|
|
|
|
- 1445 END
|
|
|
|
|
- 1446 END
|
|
|
|
|
- 1447 END; .) .
|
|
|
|
|
- 1448 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 1449 q, lThen, lElse, lEnd:
|
|
|
|
|
- 1450 QbeGen.QVal;
|
|
|
|
|
- 1451 hasElse: BOOLEAN; .)
|
|
|
|
|
- 1452 = "IF" (. hasElse := FALSE; .)
|
|
|
|
|
- 1453 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 1454 SemError(214) END;
|
|
|
|
|
- 1455 QbeGen.NewLabel(lThen);
|
|
|
|
|
- 1456 QbeGen.NewLabel(lElse);
|
|
|
|
|
- 1457 QbeGen.NewLabel(lEnd);
|
|
|
|
|
- 1458 QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
- 1459 QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
- 1460 "THEN" [ StatSeq ] (. QbeGen.Jmp(lEnd); .)
|
|
|
|
|
- 1461 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
- 1462 QbeGen.NewLabel(lElse); .)
|
|
|
|
|
- 1463 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 1464 SemError(214) END;
|
|
|
|
|
- 1465 QbeGen.NewLabel(lThen);
|
|
|
|
|
- 1466 QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
- 1467 QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
- 1468 "THEN" [ StatSeq ] (. QbeGen.Jmp(lEnd); .) }
|
|
|
|
|
- 1469 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
- 1470 hasElse := TRUE; .)
|
|
|
|
|
- 1471 [ StatSeq ] ]
|
|
|
|
|
- 1472 "END" (. IF hasElse THEN
|
|
|
|
|
- 1473 QbeGen.EmitLabel(lEnd)
|
|
|
|
|
- 1474 ELSE QbeGen.EmitLabel(lElse);
|
|
|
|
|
- 1475 QbeGen.EmitLabel(lEnd)
|
|
|
|
|
- 1476 END; .) .
|
|
|
|
|
- 1477 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 1478 q, lTop, lBody, lEnd:
|
|
|
|
|
- 1479 QbeGen.QVal; .)
|
|
|
|
|
- 1480 = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
- 1481 QbeGen.NewLabel(lBody);
|
|
|
|
|
- 1482 QbeGen.NewLabel(lEnd);
|
|
|
|
|
- 1483 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
- 1484 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 1485 SemError(214) END;
|
|
|
|
|
- 1486 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
|
|
- 1487 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
- 1488 "DO" [ StatSeq ] (. QbeGen.Jmp(lTop); .)
|
|
|
|
|
- 1489 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
- 1490 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 1491 q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
- 1492 = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
- 1493 QbeGen.NewLabel(lEnd);
|
|
|
|
|
- 1494 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
- 1495 [ StatSeq ]
|
|
|
|
|
- 1496 "UNTIL" Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 1497 SemError(214) END;
|
|
|
|
|
- 1498 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
|
|
- 1499 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
- 1500 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
- 1501 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
|
|
+ 389 | (. (* type-only parameter list:
|
|
|
|
|
+ 390 each name is a type (GNU
|
|
|
|
|
+ 391 shorthand used by the
|
|
|
|
|
+ 392 Coco/R scanner frame) *)
|
|
|
|
|
+ 393 k := 0;
|
|
|
|
|
+ 394 WHILE k < cnt DO
|
|
|
|
|
+ 395 IF SymTab.Lookup(names[k])
|
|
|
|
|
+ 396 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
|
|
+ 397 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
|
|
+ 398 pt := SymTab.SymType(names[k])
|
|
|
|
|
+ 399 ELSE SemError(201);
|
|
|
|
|
+ 400 pt := SymTab.InvalidType
|
|
|
|
|
+ 401 END;
|
|
|
|
|
+ 402 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
+ 403 INC(k)
|
|
|
|
|
+ 404 END; .) )
|
|
|
|
|
+ 405 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
|
|
+ 406 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
|
|
+ 407 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
|
|
+ 408 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
|
|
+ 409 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
|
|
+ 410 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
|
|
+ 411 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
|
|
+ 412 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
+ 413 (. VAR elem: SymTab.TypeIndex;
|
|
|
|
|
+ 414 ok: BOOLEAN;
|
|
|
|
|
+ 415 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
|
|
+ 416 nb, k: CARDINAL;
|
|
|
|
|
+ 417 idx: SymTab.TypeIndex;
|
|
|
|
|
+ 418 ilo, ihi: INTEGER; .)
|
|
|
|
|
+ 419 = "ARRAY"
|
|
|
|
|
+ 420 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
|
|
+ 421 SemError(230) END;
|
|
|
|
|
+ 422 t := SymTab.NewOpenArray(elem); .)
|
|
|
|
|
+ 423 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
|
|
+ 424 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
|
|
+ 425 type's ordinal bounds give the
|
|
|
|
|
+ 426 [lo..hi] pair *)
|
|
|
|
|
+ 427 IF SymTab.TypeBounds(idx, ilo,
|
|
|
|
|
+ 428 ihi)
|
|
|
|
|
+ 429 THEN t := SymTab.NewArrayB(elem,
|
|
|
|
|
+ 430 ilo, ihi)
|
|
|
|
|
+ 431 ELSE SemError(230);
|
|
|
|
|
+ 432 t := SymTab.InvalidType
|
|
|
|
|
+ 433 END; .)
|
|
|
|
|
+ 434 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
|
|
+ 435 BoundPair<ok>
|
|
|
|
|
+ 436 { "," BoundPair<ok> }
|
|
|
|
|
+ 437 "]" (. (* snapshot before the element
|
|
|
|
|
+ 438 type, which reuses the bound
|
|
|
|
|
+ 439 buffer for a nested ARRAY *)
|
|
|
|
|
+ 440 nb := SymTab.BoundCount();
|
|
|
|
|
+ 441 k := 0;
|
|
|
|
|
+ 442 WHILE k < nb DO
|
|
|
|
|
+ 443 bnds[k] := SymTab.BoundLo(k);
|
|
|
|
|
+ 444 bndh[k] := SymTab.BoundHi(k);
|
|
|
|
|
+ 445 INC(k)
|
|
|
|
|
+ 446 END; .)
|
|
|
|
|
+ 447 "OF" Type<elem, FALSE>
|
|
|
|
|
+ 448 (. IF ok THEN
|
|
|
|
|
+ 449 k := nb;
|
|
|
|
|
+ 450 WHILE k > 0 DO
|
|
|
|
|
+ 451 DEC(k);
|
|
|
|
|
+ 452 elem := SymTab.NewArrayB(
|
|
|
|
|
+ 453 elem, bnds[k], bndh[k])
|
|
|
|
|
+ 454 END;
|
|
|
|
|
+ 455 t := elem
|
|
|
|
|
+ 456 ELSE t := SymTab.InvalidType
|
|
|
|
|
+ 457 END; .) ) .
|
|
|
|
|
+ 458 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
+ 459 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
+ 460 lo, hi: INTEGER;
|
|
|
|
|
+ 461 cl, cl2: INTEGER; .)
|
|
|
|
|
+ 462 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
+ 463 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
+ 464 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
+ 465 ok := FALSE
|
|
|
|
|
+ 466 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
|
|
+ 467 cl2 := SymTab.ClassOf(thi);
|
|
|
|
|
+ 468 IF ((cl # SymTab.ClInt)
|
|
|
|
|
+ 469 AND (cl # SymTab.ClChar))
|
|
|
|
|
+ 470 OR ((cl2 # SymTab.ClInt)
|
|
|
|
|
+ 471 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
|
|
+ 472 SemError(230); ok := FALSE
|
|
|
|
|
+ 473 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
+ 474 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
+ 475 OR (lo > hi) THEN
|
|
|
|
|
+ 476 SemError(230); ok := FALSE
|
|
|
|
|
+ 477 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
|
|
+ 478 SemError(230); ok := FALSE
|
|
|
|
|
+ 479 END;
|
|
|
|
|
+ 480 END; .) .
|
|
|
|
|
+ 481 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
|
|
+ 482 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
|
|
+ 483 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
|
|
+ 484 comparison across suitable bases are lenient (masks over min
|
|
|
|
|
+ 485 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
|
|
+ 486 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
|
|
+ 487 blo, bhi, bspan: INTEGER;
|
|
|
|
|
+ 488 bcls: INTEGER; .)
|
|
|
|
|
+ 489 = "SET" "OF" Type<base, FALSE>
|
|
|
|
|
+ 490 (. IF base = SymTab.InvalidType THEN
|
|
|
|
|
+ 491 t := SymTab.InvalidType
|
|
|
|
|
+ 492 ELSE bcls :=
|
|
|
|
|
+ 493 SymTab.ClassOf(base);
|
|
|
|
|
+ 494 IF bcls = SymTab.ClBool THEN
|
|
|
|
|
+ 495 blo := 0; bspan := 2
|
|
|
|
|
+ 496 ELSIF bcls = SymTab.ClChar THEN
|
|
|
|
|
+ 497 blo := 0; bspan := 256
|
|
|
|
|
+ 498 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
|
|
+ 499 blo := 0;
|
|
|
|
|
+ 500 bspan := VAL(INTEGER,
|
|
|
|
|
+ 501 SymTab.EnumCount(base))
|
|
|
|
|
+ 502 ELSIF SymTab.SubBounds(base,
|
|
|
|
|
+ 503 blo, bhi) THEN
|
|
|
|
|
+ 504 bspan := bhi - blo + 1
|
|
|
|
|
+ 505 ELSE bspan := 0 END;
|
|
|
|
|
+ 506 IF (bspan <= 0)
|
|
|
|
|
+ 507 OR (bspan > 65536) THEN
|
|
|
|
|
+ 508 SemError(230);
|
|
|
|
|
+ 509 t := SymTab.InvalidType
|
|
|
|
|
+ 510 ELSE t := SymTab.NewSet(base)
|
|
|
|
|
+ 511 END
|
|
|
|
|
+ 512 END; .) .
|
|
|
|
|
+ 513 (* Records: flat blobs; array fields are pointers to static
|
|
|
|
|
+ 514 descriptors (locked amendment), nested records inline. Field
|
|
|
|
|
+ 515 offsets static and declaration-ordered. *)
|
|
|
|
|
+ 516 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
|
|
+ 517 variant part is a `CASE ... END` item; because it starts with the
|
|
|
|
|
+ 518 CASE keyword it is unambiguously distinguishable from a field
|
|
|
|
|
+ 519 (which starts with an identifier). *)
|
|
|
|
|
+ 520 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
+ 521 tagOk: BOOLEAN; .)
|
|
|
|
|
+ 522 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
|
|
+ 523 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
|
|
+ 524 "END" .
|
|
|
|
|
+ 525 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
|
|
+ 526 = RecField<rec>
|
|
|
|
|
+ 527 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
|
|
+ 528 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
|
|
+ 529 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
|
|
+ 530 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
|
|
+ 531 tagN: SymTab.Name; .)
|
|
|
|
|
+ 532 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
+ 533 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
+ 534 tagN) THEN
|
|
|
|
|
+ 535 SemError(200) END; .)
|
|
|
|
|
+ 536 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
|
|
+ 537 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
|
|
+ 538 SemError(224)
|
|
|
|
|
+ 539 END;
|
|
|
|
|
+ 540 SymTab.FixPendingF(rec, tagT);
|
|
|
|
|
+ 541 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
|
|
+ 542 "OF"
|
|
|
|
|
+ 543 RecFieldList<rec>
|
|
|
|
|
+ 544 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
+ 545 RecFieldList<rec> }
|
|
|
|
|
+ 546 "END" .
|
|
|
|
|
+ 547 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
|
|
+ 548 lv1, lv2: QbeGen.QVal; .)
|
|
|
|
|
+ 549 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
|
|
+ 550 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
|
|
+ 551 (* Variant case label: a constant (or a constant range). Values are
|
|
|
|
|
+ 552 not interpreted (the layout overlays regardless). *)
|
|
|
|
|
+ 553 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 554 (. VAR lname: SymTab.Name; .)
|
|
|
|
|
+ 555 = ( ident (. LexName(lname);
|
|
|
|
|
+ 556 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 557 t := SymTab.IntType(); .)
|
|
|
|
|
+ 558 | integer (. LexString(lname);
|
|
|
|
|
+ 559 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 560 t := SymTab.IntType(); .)
|
|
|
|
|
+ 561 | charConst (. LexString(lname);
|
|
|
|
|
+ 562 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 563 t := SymTab.CharType(); .) ) .
|
|
|
|
|
+ 564 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 565 t2: SymTab.TypeIndex; .)
|
|
|
|
|
+ 566 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
|
|
+ 567 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 568 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
+ 569 n) THEN
|
|
|
|
|
+ 570 SemError(200) END; .)
|
|
|
|
|
+ 571 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
+ 572 n) THEN
|
|
|
|
|
+ 573 SemError(200) END; .) } .
|
|
|
|
|
+ 574 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
|
|
+ 575 k: INTEGER;
|
|
|
|
|
+ 576 dotted: BOOLEAN; .)
|
|
|
|
|
+ 577 = GetIdent<n> (. dotted := FALSE;
|
|
|
|
|
+ 578 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
+ 579 k := -1;
|
|
|
|
|
+ 580 t := SymTab.ForwardType(n);
|
|
|
|
|
+ 581 IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 582 SemError(201)
|
|
|
|
|
+ 583 END
|
|
|
|
|
+ 584 ELSE k := SymTab.SymKind(n);
|
|
|
|
|
+ 585 IF (k = SymTab.KindType)
|
|
|
|
|
+ 586 OR (k = SymTab.KindPredef) THEN
|
|
|
|
|
+ 587 t := SymTab.SymType(n)
|
|
|
|
|
+ 588 ELSE t := SymTab.InvalidType
|
|
|
|
|
+ 589 END
|
|
|
|
|
+ 590 END; .)
|
|
|
|
|
+ 591 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
|
|
+ 592 IF k = SymTab.KindModule THEN
|
|
|
|
|
+ 593 t := SymTab.QualType(n, qid);
|
|
|
|
|
+ 594 IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 595 SemError(201)
|
|
|
|
|
+ 596 END
|
|
|
|
|
+ 597 ELSE SemError(221);
|
|
|
|
|
+ 598 t := SymTab.InvalidType
|
|
|
|
|
+ 599 END; .) ]
|
|
|
|
|
+ 600 (. IF NOT dotted THEN
|
|
|
|
|
+ 601 IF (k = SymTab.KindModule)
|
|
|
|
|
+ 602 OR ((k # SymTab.KindType)
|
|
|
|
|
+ 603 AND (k # SymTab.KindPredef)
|
|
|
|
|
+ 604 AND (k # SymTab.KindImport)
|
|
|
|
|
+ 605 AND (k # -1)) THEN
|
|
|
|
|
+ 606 SemError(221)
|
|
|
|
|
+ 607 END
|
|
|
|
|
+ 608 END; .) .
|
|
|
|
|
+ 609 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
+ 610 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
+ 611 lo, hi: INTEGER; .)
|
|
|
|
|
+ 612 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
+ 613 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
+ 614 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
+ 615 t := SymTab.InvalidType
|
|
|
|
|
+ 616 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
|
|
+ 617 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
|
|
+ 618 SemError(230);
|
|
|
|
|
+ 619 t := SymTab.InvalidType
|
|
|
|
|
+ 620 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
+ 621 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
+ 622 OR (lo > hi) THEN
|
|
|
|
|
+ 623 SemError(230);
|
|
|
|
|
+ 624 t := SymTab.InvalidType
|
|
|
|
|
+ 625 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
|
|
+ 626 END; .)
|
|
|
|
|
+ 627 "]" .
|
|
|
|
|
+ 628 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 629 ord: INTEGER;
|
|
|
|
|
+ 630 qv: QbeGen.QVal; .)
|
|
|
|
|
+ 631 = "(" (. t := SymTab.NewEnum();
|
|
|
|
|
+ 632 ord := 0; .)
|
|
|
|
|
+ 633 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 634 SymTab.KindConst) THEN
|
|
|
|
|
+ 635 SemError(200) END;
|
|
|
|
|
+ 636 SymTab.SetSymType(n, t);
|
|
|
|
|
+ 637 QbeGen.IntStr(ord, qv);
|
|
|
|
|
+ 638 SymTab.SetSymVal(n, qv);
|
|
|
|
|
+ 639 INC(ord); .)
|
|
|
|
|
+ 640 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 641 SymTab.KindConst) THEN
|
|
|
|
|
+ 642 SemError(200) END;
|
|
|
|
|
+ 643 SymTab.SetSymType(n, t);
|
|
|
|
|
+ 644 QbeGen.IntStr(ord, qv);
|
|
|
|
|
+ 645 SymTab.SetSymVal(n, qv);
|
|
|
|
|
+ 646 INC(ord); .) }
|
|
|
|
|
+ 647 ")" (. SymTab.SetEnumCount(t,
|
|
|
|
|
+ 648 VAL(CARDINAL, ord)); .) .
|
|
|
|
|
+ 649 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
|
|
+ 650 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
|
|
+ 651 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
|
|
+ 652 class/impl block. Methods end with ";" per the Table example
|
|
|
|
|
+ 653 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
|
|
+ 654 (* Single CLASS item in both loops: separating declaration from
|
|
|
|
|
+ 655 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
|
|
+ 656 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
|
|
+ 657 The second token decides after CLASS is consumed. A misplaced
|
|
|
|
|
+ 658 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
|
|
+ 659 whole unit ends 230 until lowering). *)
|
|
|
|
|
+ 660 ClassItem
|
|
|
|
|
+ 661 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
|
|
+ 662 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
|
|
+ 663 ct: SymTab.TypeIndex; .)
|
|
|
|
|
+ 664 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
|
|
+ 665 SymTab.KindType) THEN
|
|
|
|
|
+ 666 SemError(200) END;
|
|
|
|
|
+ 667 ct := SymTab.NewClass();
|
|
|
|
|
+ 668 SymTab.SetSymType(cn, ct);
|
|
|
|
|
+ 669 SymTab.PushClassScope(ct); .)
|
|
|
|
|
+ 670 [ Parents<ct> ]
|
|
|
|
|
+ 671 ";"
|
|
|
|
|
+ 672 { ClassField<ct> ";" }
|
|
|
|
|
+ 673 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
+ 674 (. SymTab.CloseProc;
|
|
|
|
|
+ 675 QbeGen.AbortFunc; .) }
|
|
|
|
|
+ 676 "END"
|
|
|
|
|
+ 677 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
+ 678 SemError(202) END;
|
|
|
|
|
+ 679 SymTab.LayoutClass(ct);
|
|
|
|
|
+ 680 SymTab.PopScope; .) .
|
|
|
|
|
+ 681 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
|
|
+ 682 = "(" Parent1<ct>
|
|
|
|
|
+ 683 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
|
|
+ 684 ")" .
|
|
|
|
|
+ 685 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
|
|
+ 686 pt: SymTab.TypeIndex; .)
|
|
|
|
|
+ 687 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
|
|
+ 688 SemError(201)
|
|
|
|
|
+ 689 ELSE pt := SymTab.SymType(p);
|
|
|
|
|
+ 690 IF SymTab.ClassOf(pt) #
|
|
|
|
|
+ 691 SymTab.ClClass THEN
|
|
|
|
|
+ 692 SemError(230)
|
|
|
|
|
+ 693 ELSE SymTab.SetParent(ct, pt)
|
|
|
|
|
+ 694 END
|
|
|
|
|
+ 695 END; .) .
|
|
|
|
|
+ 696 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
|
|
+ 697 t: SymTab.TypeIndex; .)
|
|
|
|
|
+ 698 = GetIdent<n>
|
|
|
|
|
+ 699 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 700 SymTab.KindConst) THEN
|
|
|
|
|
+ 701 SemError(200) END;
|
|
|
|
|
+ 702 IF SymTab.Lookup(rhs) THEN
|
|
|
|
|
+ 703 SymTab.SetSymType(n,
|
|
|
|
|
+ 704 SymTab.SymType(rhs))
|
|
|
|
|
+ 705 END; .)
|
|
|
|
|
+ 706 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
+ 707 n) THEN
|
|
|
|
|
+ 708 SemError(200) END; .)
|
|
|
|
|
+ 709 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
+ 710 n) THEN
|
|
|
|
|
+ 711 SemError(200) END; .) }
|
|
|
|
|
+ 712 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
|
|
+ 713 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
|
|
+ 714 (. VAR wantVirt: BOOLEAN; .)
|
|
|
|
|
+ 715 = (. wantVirt := FALSE; .)
|
|
|
|
|
+ 716 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
|
|
+ 717 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
|
|
+ 718 SymTab.MarkVirtual END; .) .
|
|
|
|
|
+ 719 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
|
|
+ 720 ct: SymTab.TypeIndex; .)
|
|
|
|
|
+ 721 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
|
|
+ 722 SemError(201);
|
|
|
|
|
+ 723 ct := SymTab.InvalidType
|
|
|
|
|
+ 724 ELSE ct := SymTab.SymType(cn);
|
|
|
|
|
+ 725 IF SymTab.ClassOf(ct) #
|
|
|
|
|
+ 726 SymTab.ClClass THEN
|
|
|
|
|
+ 727 SemError(230);
|
|
|
|
|
+ 728 ct := SymTab.InvalidType
|
|
|
|
|
+ 729 END
|
|
|
|
|
+ 730 END;
|
|
|
|
|
+ 731 IF ct #
|
|
|
|
|
+ 732 SymTab.InvalidType THEN
|
|
|
|
|
+ 733 IF NOT SymTab.PushClassMembers(
|
|
|
|
|
+ 734 ct) THEN
|
|
|
|
|
+ 735 SemError(230) END;
|
|
|
|
|
+ 736 SymTab.PushImplClass(ct)
|
|
|
|
|
+ 737 END; .)
|
|
|
|
|
+ 738 ";" { MethodImpl<ct> ";" }
|
|
|
|
|
+ 739 [ "BEGIN" (. QbeGen.BeginInit(cn); .)
|
|
|
|
|
+ 740 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
|
|
+ 741 "END"
|
|
|
|
|
+ 742 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
+ 743 SemError(202) END;
|
|
|
|
|
+ 744 SymTab.PopImplClass;
|
|
|
|
|
+ 745 SymTab.PopScope; .) .
|
|
|
|
|
+ 746 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
|
|
+ 747 thisQ: QbeGen.QVal;
|
|
|
|
|
+ 748 methRes: SymTab.TypeIndex; .)
|
|
|
|
|
+ 749 = MethodHeading<pn, ct> ";"
|
|
|
|
|
+ 750 (. IF (ct #
|
|
|
|
|
+ 751 SymTab.InvalidType)
|
|
|
|
|
+ 752 AND NOT SymTab.MethodExists(ct,
|
|
|
|
|
+ 753 pn) THEN
|
|
|
|
|
+ 754 SemError(201) END; .)
|
|
|
|
|
+ 755 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
|
|
+ 756 QbeGen.AbortFunc;
|
|
|
|
|
+ 757 SymTab.CloseProc; .)
|
|
|
|
|
+ 758 | (. QbeGen.EndFuncHeader;
|
|
|
|
|
+ 759 (* bind the receiver: bare
|
|
|
|
|
+ 760 field names resolve
|
|
|
|
|
+ 761 against THIS *)
|
|
|
|
|
+ 762 QbeGen.ThisBase(thisQ);
|
|
|
|
|
+ 763 QbeGen.PushWith(thisQ); .)
|
|
|
|
|
+ 764 Block<pn> (. QbeGen.PopWith;
|
|
|
|
|
+ 765 methRes := SymTab.CurRes();
|
|
|
|
|
+ 766 SymTab.CloseProc;
|
|
|
|
|
+ 767 QbeGen.EndFunc(methRes); .) ) .
|
|
|
|
|
+ 768 ConstBlock
|
|
|
|
|
+ 769 = "CONST" { ConstDecl ";" } .
|
|
|
|
|
+ 770 ConstDecl (. VAR n: SymTab.Name;
|
|
|
|
|
+ 771 t: SymTab.TypeIndex;
|
|
|
|
|
+ 772 qv: QbeGen.QVal;
|
|
|
|
|
+ 773 cls: INTEGER; .)
|
|
|
|
|
+ 774 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 775 SymTab.KindConst) THEN
|
|
|
|
|
+ 776 SemError(200) END; .)
|
|
|
|
|
+ 777 "="
|
|
|
|
|
+ 778 Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
|
|
+ 779 cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 780 IF (cls = SymTab.ClArray)
|
|
|
|
|
+ 781 OR (cls = SymTab.ClRecord)
|
|
|
|
|
+ 782 OR (cls = SymTab.ClClass)
|
|
|
|
|
+ 783 OR (cls = SymTab.ClStr)
|
|
|
|
|
+ 784 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
+ 785 (* an aggregate/string
|
|
|
|
|
+ 786 constant: qv is its
|
|
|
|
|
+ 787 descriptor address; no
|
|
|
|
|
+ 788 scalar data *)
|
|
|
|
|
+ 789 SymTab.SetSymVal(n, qv)
|
|
|
|
|
+ 790 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
|
|
+ 791 SemError(230)
|
|
|
|
|
+ 792 ELSE
|
|
|
|
|
+ 793 SymTab.SetSymVal(n, qv);
|
|
|
|
|
+ 794 QbeGen.DeclConst(n, qv, t)
|
|
|
|
|
+ 795 END; .) .
|
|
|
|
|
+ 796 VarBlock
|
|
|
|
|
+ 797 = "VAR" { VarDecl ";" } .
|
|
|
|
|
+ 798 VarDecl (. VAR nm: SymTab.Name;
|
|
|
|
|
+ 799 t: SymTab.TypeIndex;
|
|
|
|
|
+ 800 i: CARDINAL;
|
|
|
|
|
+ 801 cls: INTEGER; .)
|
|
|
|
|
+ 802 = VarIdents ":"
|
|
|
|
|
+ 803 Type<t, FALSE> (. cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 804 IF (t # SymTab.InvalidType)
|
|
|
|
|
+ 805 AND NOT SymTab.IsUnresolved(t)
|
|
|
|
|
+ 806 AND (cls # SymTab.ClInt)
|
|
|
|
|
+ 807 AND (cls # SymTab.ClBool)
|
|
|
|
|
+ 808 AND (cls # SymTab.ClChar)
|
|
|
|
|
+ 809 AND (cls # SymTab.ClReal)
|
|
|
|
|
+ 810 AND (cls # SymTab.ClArray)
|
|
|
|
|
+ 811 AND (cls # SymTab.ClSet)
|
|
|
|
|
+ 812 AND (cls # SymTab.ClRecord)
|
|
|
|
|
+ 813 AND (cls # SymTab.ClPtr)
|
|
|
|
|
+ 814 AND (cls # SymTab.ClLong)
|
|
|
|
|
+ 815 AND (cls # SymTab.ClProc)
|
|
|
|
|
+ 816 AND (cls # SymTab.ClUChar)
|
|
|
|
|
+ 817 AND (cls # SymTab.ClUStr)
|
|
|
|
|
+ 818 AND (cls # SymTab.ClEnum)
|
|
|
|
|
+ 819 AND (cls # SymTab.ClClass) THEN
|
|
|
|
|
+ 820 SemError(230) END;
|
|
|
|
|
+ 821 IF QbeGen.LocFull() THEN
|
|
|
|
|
+ 822 SemError(233) END;
|
|
|
|
|
+ 823 i := 0;
|
|
|
|
|
+ 824 IF SymTab.IsUnresolved(t)
|
|
|
|
|
+ 825 AND NOT SymTab.InProc() THEN
|
|
|
|
|
+ 826 (* a forward-typed global:
|
|
|
|
|
+ 827 defer emission until the
|
|
|
|
|
+ 828 TYPE block completes *)
|
|
|
|
|
+ 829 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 830 SymTab.PendName(i, nm);
|
|
|
|
|
+ 831 IF nPendVar <=
|
|
|
|
|
+ 832 HIGH(pendVarName) THEN
|
|
|
|
|
+ 833 pendVarName[nPendVar] := nm;
|
|
|
|
|
+ 834 pendVarT[nPendVar] := t;
|
|
|
|
|
+ 835 INC(nPendVar)
|
|
|
|
|
+ 836 END;
|
|
|
|
|
+ 837 INC(i)
|
|
|
|
|
+ 838 END
|
|
|
|
|
+ 839 ELSE
|
|
|
|
|
+ 840 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 841 SymTab.PendName(i, nm);
|
|
|
|
|
+ 842 QbeGen.DeclVar(nm, t);
|
|
|
|
|
+ 843 INC(i)
|
|
|
|
|
+ 844 END
|
|
|
|
|
+ 845 END;
|
|
|
|
|
+ 846 (* a plain VAR list, not a
|
|
|
|
|
+ 847 heading: the signature
|
|
|
|
|
+ 848 result is discarded *)
|
|
|
|
|
+ 849 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
+ 850 END; .) .
|
|
|
|
|
+ 851 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 852 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
+ 853 SymTab.KindVar) THEN
|
|
|
|
|
+ 854 SemError(200) END; .)
|
|
|
|
|
+ 855 { ","
|
|
|
|
|
+ 856 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
+ 857 SymTab.KindVar) THEN
|
|
|
|
|
+ 858 SemError(200) END; .) } .
|
|
|
|
|
+ 859 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 860 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
+ 861 SemError(200) END; .)
|
|
|
|
|
+ 862 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
+ 863 SemError(200) END; .) } .
|
|
|
|
|
+ 864 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
|
|
+ 865 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
|
|
+ 866 FORWARD marks; the body heading re-enters (signature compare
|
|
|
|
|
+ 867 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
|
|
+ 868 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
|
|
+ 869 (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 870 mg: QbeGen.QVal; .)
|
|
|
|
|
+ 871 = "PROCEDURE"
|
|
|
|
|
+ 872 GetIdent<pn> (. IF methCls #
|
|
|
|
|
+ 873 SymTab.InvalidType THEN
|
|
|
|
|
+ 874 (* a method: resume the
|
|
|
|
|
+ 875 declared symbol (reuse
|
|
|
|
|
+ 876 its uid) *)
|
|
|
|
|
+ 877 IF NOT SymTab.ResumeMethod(
|
|
|
|
|
+ 878 methCls, pn) THEN
|
|
|
|
|
+ 879 SemError(200) END
|
|
|
|
|
+ 880 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
|
|
+ 881 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
|
|
+ 882 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
|
|
+ 883 SemError(200) END
|
|
|
|
|
+ 884 END
|
|
|
|
|
+ 885 END;
|
|
|
|
|
+ 886 IF methCls #
|
|
|
|
|
+ 887 SymTab.InvalidType THEN
|
|
|
|
|
+ 888 QbeGen.Mangled(pn,
|
|
|
|
|
+ 889 SymTab.MethUid(), mg)
|
|
|
|
|
+ 890 ELSE
|
|
|
|
|
+ 891 QbeGen.Mangled(pn,
|
|
|
|
|
+ 892 SymTab.ProcUid(pn), mg)
|
|
|
|
|
+ 893 END;
|
|
|
|
|
+ 894 QbeGen.BeginFunc(mg);
|
|
|
|
|
+ 895 IF methCls #
|
|
|
|
|
+ 896 SymTab.InvalidType THEN
|
|
|
|
|
+ 897 (* hidden THIS receiver:
|
|
|
|
|
+ 898 a VAR param of the
|
|
|
|
|
+ 899 class type, pushed as
|
|
|
|
|
+ 900 the WITH base *)
|
|
|
|
|
+ 901 IF NOT SymTab.EnterThisParam(
|
|
|
|
|
+ 902 methCls) THEN
|
|
|
|
|
+ 903 SemError(200) END;
|
|
|
|
|
+ 904 IF NOT QbeGen.FuncParam(
|
|
|
|
|
+ 905 "THIS", TRUE,
|
|
|
|
|
+ 906 methCls) THEN
|
|
|
|
|
+ 907 SemError(233) END
|
|
|
|
|
+ 908 END; .)
|
|
|
|
|
+ 909 [ FormalParams ]
|
|
|
|
|
+ 910 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
|
|
+ 911 SemError(235) END;
|
|
|
|
|
+ 912 QbeGen.SetFuncRes(t);
|
|
|
|
|
+ 913 IF (t #
|
|
|
|
|
+ 914 SymTab.InvalidType)
|
|
|
|
|
+ 915 AND ((SymTab.ClassOf(t)
|
|
|
|
|
+ 916 = SymTab.ClArray)
|
|
|
|
|
+ 917 OR (SymTab.ClassOf(t)
|
|
|
|
|
+ 918 = SymTab.ClRecord)
|
|
|
|
|
+ 919 OR (SymTab.ClassOf(t)
|
|
|
|
|
+ 920 = SymTab.ClSet)
|
|
|
|
|
+ 921 OR (SymTab.ClassOf(t)
|
|
|
|
|
+ 922 = SymTab.ClClass)) THEN
|
|
|
|
|
+ 923 SemError(230) END; .) ] .
|
|
|
|
|
+ 924 FormalParams
|
|
|
|
|
+ 925 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
|
|
+ 926 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 927 nm: SymTab.Name;
|
|
|
|
|
+ 928 i: CARDINAL;
|
|
|
|
|
+ 929 isV: BOOLEAN; .)
|
|
|
|
|
+ 930 = (. isV := FALSE; .)
|
|
|
|
|
+ 931 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
+ 932 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
|
|
+ 933 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 934 SymTab.PendName(i, nm);
|
|
|
|
|
+ 935 (* value open arrays are
|
|
|
|
|
+ 936 passed as descriptor
|
|
|
|
|
+ 937 addresses (no copy):
|
|
|
|
|
+ 938 same representation as
|
|
|
|
|
+ 939 VAR formals *)
|
|
|
|
|
+ 940 IF NOT QbeGen.FuncParam(nm,
|
|
|
|
|
+ 941 isV
|
|
|
|
|
+ 942 OR SymTab.IsOpenArray(t),
|
|
|
|
|
+ 943 t) THEN
|
|
|
|
|
+ 944 SemError(233) END;
|
|
|
|
|
+ 945 INC(i)
|
|
|
|
|
+ 946 END;
|
|
|
|
|
+ 947 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
+ 948 SemError(235) END; .) .
|
|
|
|
|
+ 949 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
|
|
+ 950 static link gives them their parent's frame. Methods keep
|
|
|
|
|
+ 951 parse-now/230-later. *)
|
|
|
|
|
+ 952 ProcDecl (. VAR pn: SymTab.Name; .)
|
|
|
|
|
+ 953 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
+ 954 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
|
|
+ 955 SymTab.CloseProc;
|
|
|
|
|
+ 956 QbeGen.AbortFunc; .)
|
|
|
|
|
+ 957 | "EXTERNAL" (. SymTab.MarkExternal("");
|
|
|
|
|
+ 958 SymTab.CloseProc;
|
|
|
|
|
+ 959 QbeGen.AbortFunc; .)
|
|
|
|
|
+ 960 | (. QbeGen.EndFuncHeader; .)
|
|
|
|
|
+ 961 Block<pn> (. SymTab.CloseProc;
|
|
|
|
|
+ 962 QbeGen.EndFunc(
|
|
|
|
|
+ 963 SymTab.ProcRes(pn)); .) ) .
|
|
|
|
|
+ 964 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
|
|
+ 965 = DeclSeq
|
|
|
|
|
+ 966 [ "BEGIN"
|
|
|
|
|
+ 967 [ StatSeq ] ]
|
|
|
|
|
+ 968 "END"
|
|
|
|
|
+ 969 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
|
|
+ 970 SemError(202) END; .) .
|
|
|
|
|
+ 971 StatSeq
|
|
|
|
|
+ 972 = Statement { ";" [ Statement ] } .
|
|
|
|
|
+ 973 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
|
|
+ 974 are accepted: the statement after ';' is optional. *)
|
|
|
|
|
+ 975 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
|
|
+ 976 = AssOrCall
|
|
|
|
|
+ 977 | IfStat
|
|
|
|
|
+ 978 | WhileStat
|
|
|
|
|
+ 979 | RepeatStat
|
|
|
|
|
+ 980 | LoopStat
|
|
|
|
|
+ 981 | ForStat
|
|
|
|
|
+ 982 | CaseStat
|
|
|
|
|
+ 983 | WithStat
|
|
|
|
|
+ 984 | ReturnStat
|
|
|
|
|
+ 985 | HaltStat
|
|
|
|
|
+ 986 | NewStat
|
|
|
|
|
+ 987 | DisposeStat
|
|
|
|
|
+ 988 | IncDecStat
|
|
|
|
|
+ 989 | InclExclStat
|
|
|
|
|
+ 990 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
|
|
+ 991 QbeGen.Jmp(lx)
|
|
|
|
|
+ 992 ELSE SemError(230) END; .) .
|
|
|
|
|
+ 993 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
|
|
+ 994 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 995 dk: INTEGER;
|
|
|
|
|
+ 996 qd, qe: QbeGen.QVal;
|
|
|
|
|
+ 997 qn: SymTab.Name;
|
|
|
|
|
+ 998 sfx, isInc: BOOLEAN; .)
|
|
|
|
|
+ 999 = ( "INCL" (. isInc := TRUE; .)
|
|
|
|
|
+ 1000 | "EXCL" (. isInc := FALSE; .) )
|
|
|
|
|
+ 1001 "(" Design<at, dk, qd, qn, sfx> ","
|
|
|
|
|
+ 1002 Expr<et2, qe> ")"
|
|
|
|
|
+ 1003 (. IF at = SymTab.InvalidType THEN
|
|
|
|
|
+ 1004 ELSIF SymTab.ClassOf(at) #
|
|
|
|
|
+ 1005 SymTab.ClSet THEN
|
|
|
|
|
+ 1006 SemError(222)
|
|
|
|
|
+ 1007 ELSE
|
|
|
|
|
+ 1008 IF isInc THEN
|
|
|
|
|
+ 1009 QbeGen.SetBit(qd, qe,
|
|
|
|
|
+ 1010 SymTab.SetBaseLo(at),
|
|
|
|
|
+ 1011 SymTab.SetCount(at))
|
|
|
|
|
+ 1012 ELSE
|
|
|
|
|
+ 1013 QbeGen.SetClearBit(qd, qe,
|
|
|
|
|
+ 1014 SymTab.SetBaseLo(at),
|
|
|
|
|
+ 1015 SymTab.SetCount(at))
|
|
|
|
|
+ 1016 END
|
|
|
|
|
+ 1017 END; .) .
|
|
|
|
|
+ 1018 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
|
|
+ 1019 integer designator. *)
|
|
|
|
|
+ 1020 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 1021 dk: INTEGER;
|
|
|
|
|
+ 1022 qd, qv, qn2, qstep:
|
|
|
|
|
+ 1023 QbeGen.QVal;
|
|
|
|
|
+ 1024 qn: SymTab.Name;
|
|
|
|
|
+ 1025 sfx, isInc: BOOLEAN; .)
|
|
|
|
|
+ 1026 = (. isInc := TRUE; .)
|
|
|
|
|
+ 1027 ( "INC" (. isInc := TRUE; .)
|
|
|
|
|
+ 1028 | "DEC" (. isInc := FALSE; .) )
|
|
|
|
|
+ 1029 "(" (. QbeGen.CopyOp("1", qstep); .)
|
|
|
|
|
+ 1030 Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
+ 1031 [ "," Expr<et2, qstep> ]
|
|
|
|
|
+ 1032 ")" (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1033 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
+ 1034 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1035 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1036 SemError(210)
|
|
|
|
|
+ 1037 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
|
|
+ 1038 SemError(211)
|
|
|
|
|
+ 1039 ELSE
|
|
|
|
|
+ 1040 IF sfx
|
|
|
|
|
+ 1041 OR (dk = SymTab.KindField) THEN
|
|
|
|
|
+ 1042 QbeGen.ElemLoad(qd, dt, qv)
|
|
|
|
|
+ 1043 ELSE QbeGen.LoadVar(qn,
|
|
|
|
|
+ 1044 FALSE, qv)
|
|
|
|
|
+ 1045 END;
|
|
|
|
|
+ 1046 QbeGen.NewTemp(qn2);
|
|
|
|
|
+ 1047 IF isInc THEN
|
|
|
|
|
+ 1048 QbeGen.Op3("add", qn2, qv,
|
|
|
|
|
+ 1049 qstep, FALSE)
|
|
|
|
|
+ 1050 ELSE QbeGen.Op3("sub", qn2, qv,
|
|
|
|
|
+ 1051 qstep, FALSE)
|
|
|
|
|
+ 1052 END;
|
|
|
|
|
+ 1053 IF sfx
|
|
|
|
|
+ 1054 OR (dk = SymTab.KindField) THEN
|
|
|
|
|
+ 1055 QbeGen.ElemStore(qd, qn2,
|
|
|
|
|
+ 1056 dt)
|
|
|
|
|
+ 1057 ELSE QbeGen.StoreVar(qn,
|
|
|
|
|
+ 1058 qn2, FALSE)
|
|
|
|
|
+ 1059 END
|
|
|
|
|
+ 1060 END; .) .
|
|
|
|
|
+ 1061 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
|
|
+ 1062 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
|
|
+ 1063 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
|
|
+ 1064 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
+ 1065 dk: INTEGER;
|
|
|
|
|
+ 1066 qd, qm: QbeGen.QVal;
|
|
|
|
|
+ 1067 qn: SymTab.Name;
|
|
|
|
|
+ 1068 sfx: BOOLEAN;
|
|
|
|
|
+ 1069 bt: SymTab.TypeIndex; .)
|
|
|
|
|
+ 1070 = "NEW" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 1071 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1072 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
+ 1073 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1074 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1075 SemError(210)
|
|
|
|
|
+ 1076 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1077 SymTab.ClPtr THEN
|
|
|
|
|
+ 1078 SemError(219)
|
|
|
|
|
+ 1079 ELSE bt := SymTab.PtrBase(dt);
|
|
|
|
|
+ 1080 IF bt #
|
|
|
|
|
+ 1081 SymTab.InvalidType THEN
|
|
|
|
|
+ 1082 QbeGen.NewHeap(bt, qm);
|
|
|
|
|
+ 1083 QbeGen.InitHeap(qm, bt);
|
|
|
|
|
+ 1084 IF sfx
|
|
|
|
|
+ 1085 OR (dk =
|
|
|
|
|
+ 1086 SymTab.KindField) THEN
|
|
|
|
|
+ 1087 QbeGen.ElemStore(qd, qm,
|
|
|
|
|
+ 1088 dt)
|
|
|
|
|
+ 1089 ELSE QbeGen.StorePtr(qn,
|
|
|
|
|
+ 1090 qm)
|
|
|
|
|
+ 1091 END
|
|
|
|
|
+ 1092 END
|
|
|
|
|
+ 1093 END; .) .
|
|
|
|
|
+ 1094 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
+ 1095 dk: INTEGER;
|
|
|
|
|
+ 1096 qd, qv: QbeGen.QVal;
|
|
|
|
|
+ 1097 qn: SymTab.Name;
|
|
|
|
|
+ 1098 sfx: BOOLEAN; .)
|
|
|
|
|
+ 1099 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 1100 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1101 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
+ 1102 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1103 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1104 SemError(210)
|
|
|
|
|
+ 1105 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1106 SymTab.ClPtr THEN
|
|
|
|
|
+ 1107 SemError(219)
|
|
|
|
|
+ 1108 ELSE
|
|
|
|
|
+ 1109 IF sfx
|
|
|
|
|
+ 1110 OR (dk =
|
|
|
|
|
+ 1111 SymTab.KindField) THEN
|
|
|
|
|
+ 1112 QbeGen.ElemLoad(qd, dt,
|
|
|
|
|
+ 1113 qv)
|
|
|
|
|
+ 1114 ELSE QbeGen.LoadPtr(qn, qv)
|
|
|
|
|
+ 1115 END;
|
|
|
|
|
+ 1116 QbeGen.FreeHeap(qv);
|
|
|
|
|
+ 1117 IF sfx
|
|
|
|
|
+ 1118 OR (dk =
|
|
|
|
|
+ 1119 SymTab.KindField) THEN
|
|
|
|
|
+ 1120 QbeGen.ElemStore(qd, "0",
|
|
|
|
|
+ 1121 dt)
|
|
|
|
|
+ 1122 ELSE QbeGen.StorePtr(qn,
|
|
|
|
|
+ 1123 "0")
|
|
|
|
|
+ 1124 END
|
|
|
|
|
+ 1125 END; .) .
|
|
|
|
|
+ 1126 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
|
|
+ 1127 address; field designators resolve through both stacks. *)
|
|
|
|
|
+ 1128 WithStat (. VAR nW: CARDINAL; .)
|
|
|
|
|
+ 1129 = "WITH" (. nW := 0; .)
|
|
|
|
|
+ 1130 WithItem<nW> { "," WithItem<nW> }
|
|
|
|
|
+ 1131 "DO" [ StatSeq ] "END"
|
|
|
|
|
+ 1132 (. WHILE nW > 0 DO
|
|
|
|
|
+ 1133 SymTab.PopScope;
|
|
|
|
|
+ 1134 QbeGen.PopWith;
|
|
|
|
|
+ 1135 DEC(nW)
|
|
|
|
|
+ 1136 END; .) .
|
|
|
|
|
+ 1137 WithItem<VAR nW: CARDINAL> (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
+ 1138 dk: INTEGER;
|
|
|
|
|
+ 1139 qd, qe: QbeGen.QVal;
|
|
|
|
|
+ 1140 qn: SymTab.Name;
|
|
|
|
|
+ 1141 sfx: BOOLEAN; .)
|
|
|
|
|
+ 1142 = Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
+ 1143 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1144 ELSIF (SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1145 SymTab.ClRecord)
|
|
|
|
|
+ 1146 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1147 SymTab.ClClass) THEN
|
|
|
|
|
+ 1148 SemError(215)
|
|
|
|
|
+ 1149 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
|
|
+ 1150 QbeGen.PushWith(qd);
|
|
|
|
|
+ 1151 INC(nW)
|
|
|
|
|
+ 1152 END; .) .
|
|
|
|
|
+ 1153 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
|
|
+ 1154 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
|
|
+ 1155 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
|
|
+ 1156 dk: INTEGER;
|
|
|
|
|
+ 1157 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
|
|
+ 1158 qn: SymTab.Name;
|
|
|
|
|
+ 1159 ct2, res0: SymTab.TypeIndex;
|
|
|
|
|
+ 1160 q2, mg0: QbeGen.QVal;
|
|
|
|
|
+ 1161 isR, conv, wconv: BOOLEAN;
|
|
|
|
|
+ 1162 called, sfx: BOOLEAN; .)
|
|
|
|
|
+ 1163 = Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
+ 1164 ( ":="
|
|
|
|
|
+ 1165 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 1166 AND (dk # SymTab.KindVar)
|
|
|
|
|
+ 1167 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1168 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1169 SemError(210)
|
|
|
|
|
+ 1170 ELSIF NOT SymTab.Assignable(et,
|
|
|
|
|
+ 1171 dt) THEN
|
|
|
|
|
+ 1172 SemError(210)
|
|
|
|
|
+ 1173 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 1174 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1175 SymTab.ClClass) THEN
|
|
|
|
|
+ 1176 SemError(230) END;
|
|
|
|
|
+ 1177 isR := (dt #
|
|
|
|
|
+ 1178 SymTab.InvalidType)
|
|
|
|
|
+ 1179 AND (SymTab.ClassOf(dt)
|
|
|
|
|
+ 1180 = SymTab.ClReal);
|
|
|
|
|
+ 1181 conv := isR
|
|
|
|
|
+ 1182 AND SymTab.IsIntFamily(et);
|
|
|
|
|
+ 1183 wconv := (dt #
|
|
|
|
|
+ 1184 SymTab.InvalidType)
|
|
|
|
|
+ 1185 AND SymTab.IsLongFamily(dt)
|
|
|
|
|
+ 1186 AND SymTab.IsIntFamily(et);
|
|
|
|
|
+ 1187 IF ((dk = SymTab.KindVar)
|
|
|
|
|
+ 1188 OR (dk = SymTab.KindParam)
|
|
|
|
|
+ 1189 OR (dk = SymTab.KindField))
|
|
|
|
|
+ 1190 AND (dt # SymTab.InvalidType)
|
|
|
|
|
+ 1191 AND (et # SymTab.InvalidType)
|
|
|
|
|
+ 1192 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1193 SymTab.ClClass) THEN
|
|
|
|
|
+ 1194 IF sfx
|
|
|
|
|
+ 1195 OR (dk = SymTab.KindField) THEN
|
|
|
|
|
+ 1196 IF SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1197 SymTab.ClArray THEN
|
|
|
|
|
+ 1198 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 1199 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
|
|
+ 1200 AND SymTab.IsUCharArray(dt) THEN
|
|
|
|
|
+ 1201 QbeGen.UAssign(qd, qe)
|
|
|
|
|
+ 1202 ELSIF SymTab.StrCompat(dt,
|
|
|
|
|
+ 1203 et) THEN
|
|
|
|
|
+ 1204 QbeGen.StrAssign(qd,
|
|
|
|
|
+ 1205 qe)
|
|
|
|
|
+ 1206 ELSE
|
|
|
|
|
+ 1207 QbeGen.CopyArray(qd,
|
|
|
|
|
+ 1208 qe, dt)
|
|
|
|
|
+ 1209 END
|
|
|
|
|
+ 1210 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1211 SymTab.ClSet THEN
|
|
|
|
|
+ 1212 QbeGen.CopySet(qd, qe,
|
|
|
|
|
+ 1213 SymTab.SetWords(dt),
|
|
|
|
|
+ 1214 SymTab.SetWords(et))
|
|
|
|
|
+ 1215 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1216 SymTab.ClRecord THEN
|
|
|
|
|
+ 1217 QbeGen.CopyRecord(qd, qe,
|
|
|
|
|
+ 1218 dt)
|
|
|
|
|
+ 1219 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
|
|
+ 1220 IF wconv THEN
|
|
|
|
|
+ 1221 QbeGen.WidenLong(qe, ql);
|
|
|
|
|
+ 1222 QbeGen.ElemStore(qd, ql,
|
|
|
|
|
+ 1223 dt)
|
|
|
|
|
+ 1224 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
|
|
+ 1225 dt)
|
|
|
|
|
+ 1226 END
|
|
|
|
|
+ 1227 ELSIF conv THEN
|
|
|
|
|
+ 1228 QbeGen.ConvIR(qe, qt);
|
|
|
|
|
+ 1229 QbeGen.ElemStore(qd, qt,
|
|
|
|
|
+ 1230 dt)
|
|
|
|
|
+ 1231 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
|
|
+ 1232 dt)
|
|
|
|
|
+ 1233 END
|
|
|
|
|
+ 1234 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1235 SymTab.ClArray THEN
|
|
|
|
|
+ 1236 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 1237 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
|
|
+ 1238 AND SymTab.IsUCharArray(dt) THEN
|
|
|
|
|
+ 1239 QbeGen.UAssign(qd, qe)
|
|
|
|
|
+ 1240 ELSIF SymTab.StrCompat(dt,
|
|
|
|
|
+ 1241 et) THEN
|
|
|
|
|
+ 1242 QbeGen.StrAssign(qd, qe)
|
|
|
|
|
+ 1243 ELSE
|
|
|
|
|
+ 1244 QbeGen.CopyArray(qd, qe,
|
|
|
|
|
+ 1245 dt)
|
|
|
|
|
+ 1246 END
|
|
|
|
|
+ 1247 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1248 SymTab.ClSet THEN
|
|
|
|
|
+ 1249 QbeGen.CopySet(qd, qe,
|
|
|
|
|
+ 1250 SymTab.SetWords(dt),
|
|
|
|
|
+ 1251 SymTab.SetWords(et))
|
|
|
|
|
+ 1252 ELSIF SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1253 SymTab.ClRecord THEN
|
|
|
|
|
+ 1254 QbeGen.CopyRecord(qd, qe, dt)
|
|
|
|
|
+ 1255 ELSIF (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1256 SymTab.ClPtr)
|
|
|
|
|
+ 1257 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1258 SymTab.ClProc) THEN
|
|
|
|
|
+ 1259 QbeGen.StorePtr(qn, qe)
|
|
|
|
|
+ 1260 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
|
|
+ 1261 IF wconv THEN
|
|
|
|
|
+ 1262 QbeGen.WidenLong(qe, ql);
|
|
|
|
|
+ 1263 QbeGen.StoreLong(qn, ql)
|
|
|
|
|
+ 1264 ELSE QbeGen.StoreLong(qn, qe)
|
|
|
|
|
+ 1265 END
|
|
|
|
|
+ 1266 ELSIF conv THEN
|
|
|
|
|
+ 1267 QbeGen.ConvIR(qe, qt);
|
|
|
|
|
+ 1268 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
|
|
+ 1269 ELSE
|
|
|
|
|
+ 1270 QbeGen.StoreVar(qn, qe, isR)
|
|
|
|
|
+ 1271 END
|
|
|
|
|
+ 1272 END; .)
|
|
|
|
|
+ 1273 | ArgList<qn, dt, qd, FALSE, FALSE, methCls, ct2, q2, called>
|
|
|
|
|
+ 1274 | (* bare `P;`: proper parameterless
|
|
|
|
|
+ 1275 procedure call; anything else
|
|
|
|
|
+ 1276 here is 233 (was a bare syntax
|
|
|
|
|
+ 1277 error before 4.2) *)
|
|
|
|
|
+ 1278 (. IF (dk = SymTab.KindProc)
|
|
|
|
|
+ 1279 AND NOT sfx THEN
|
|
|
|
|
+ 1280 res0 := SymTab.ProcRes(qn);
|
|
|
|
|
+ 1281 IF res0 #
|
|
|
|
|
+ 1282 SymTab.InvalidType THEN
|
|
|
|
|
+ 1283 SemError(233)
|
|
|
|
|
+ 1284 ELSIF SymTab.ProcNPar(qn) #
|
|
|
|
|
+ 1285 0 THEN
|
|
|
|
|
+ 1286 SemError(233)
|
|
|
|
|
+ 1287 ELSE QbeGen.Mangled(qn,
|
|
|
|
|
+ 1288 SymTab.ProcUid(qn), mg0);
|
|
|
|
|
+ 1289 QbeGen.CallBegin(mg0,
|
|
|
|
|
+ 1290 res0,
|
|
|
|
|
+ 1291 SymTab.ProcDepthOf(qn),
|
|
|
|
|
+ 1292 SymTab.IsExternal(qn));
|
|
|
|
|
+ 1293 QbeGen.CallEnd(FALSE, q2)
|
|
|
|
|
+ 1294 END
|
|
|
|
|
+ 1295 ELSE SemError(233)
|
|
|
|
|
+ 1296 END; .) ) .
|
|
|
|
|
+ 1297 (* Actual-parameter list shared by statement and expression calls.
|
|
|
|
|
+ 1298 want selects CallEnd's result handling; t/q carry the call
|
|
|
|
|
+ 1299 value (statement calls discard). Arity/type failures are 233;
|
|
|
|
|
+ 1300 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
|
|
+ 1301 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
|
|
+ 1302 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
|
|
+ 1303 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
+ 1304 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
|
|
+ 1305 vs: INTEGER;
|
|
|
|
|
+ 1306 res: SymTab.TypeIndex;
|
|
|
|
|
+ 1307 mg: QbeGen.QVal;
|
|
|
|
|
+ 1308 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
|
|
+ 1309 = "(" (. called := TRUE;
|
|
|
|
|
+ 1310 ok := TRUE;
|
|
|
|
|
+ 1311 ind := FALSE;
|
|
|
|
|
+ 1312 isMeth := methCls #
|
|
|
|
|
+ 1313 SymTab.InvalidType;
|
|
|
|
|
+ 1314 IF isMeth THEN
|
|
|
|
|
+ 1315 (* class method: the
|
|
|
|
|
+ 1316 receiver is armed.
|
|
|
|
|
+ 1317 Virtual -> dispatch
|
|
|
|
|
+ 1318 through the vtable;
|
|
|
|
|
+ 1319 otherwise a static
|
|
|
|
|
+ 1320 call. *)
|
|
|
|
|
+ 1321 res := SymTab.ClassMethodRes(
|
|
|
|
|
+ 1322 methCls, pn);
|
|
|
|
|
+ 1323 vs := SymTab.VirtSlot(
|
|
|
|
|
+ 1324 methCls, pn);
|
|
|
|
|
+ 1325 IF vs >= 0 THEN
|
|
|
|
|
+ 1326 QbeGen.VirtCallBegin(
|
|
|
|
|
+ 1327 callee, vs, res)
|
|
|
|
|
+ 1328 ELSE
|
|
|
|
|
+ 1329 QbeGen.Mangled(pn,
|
|
|
|
|
+ 1330 SymTab.ClassMethodUid(
|
|
|
|
|
+ 1331 methCls, pn), mg);
|
|
|
|
|
+ 1332 QbeGen.CallBegin(mg, res, 0,
|
|
|
|
|
+ 1333 FALSE)
|
|
|
|
|
+ 1334 END
|
|
|
|
|
+ 1335 ELSIF SymTab.SymKind(pn) =
|
|
|
|
|
+ 1336 SymTab.KindProc THEN
|
|
|
|
|
+ 1337 res := SymTab.ProcRes(pn);
|
|
|
|
|
+ 1338 QbeGen.Mangled(pn,
|
|
|
|
|
+ 1339 SymTab.ProcUid(pn), mg);
|
|
|
|
|
+ 1340 QbeGen.CallBegin(mg, res,
|
|
|
|
|
+ 1341 SymTab.ProcDepthOf(pn),
|
|
|
|
|
+ 1342 SymTab.IsExternal(pn))
|
|
|
|
|
+ 1343 ELSIF (pt # SymTab.InvalidType)
|
|
|
|
|
+ 1344 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
|
|
+ 1345 ind := TRUE;
|
|
|
|
|
+ 1346 res :=
|
|
|
|
|
+ 1347 SymTab.ProcTypeRes(pt);
|
|
|
|
|
+ 1348 QbeGen.CallBeginInd(callee,
|
|
|
|
|
+ 1349 res, FALSE)
|
|
|
|
|
+ 1350 ELSE SemError(233);
|
|
|
|
|
+ 1351 ok := FALSE;
|
|
|
|
|
+ 1352 res := SymTab.InvalidType
|
|
|
|
|
+ 1353 END;
|
|
|
|
|
+ 1354 i := 0; .)
|
|
|
|
|
+ 1355 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
|
|
+ 1356 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
|
|
+ 1357 ")" (. IF ok THEN
|
|
|
|
|
+ 1358 IF isMeth THEN
|
|
|
|
|
+ 1359 np := SymTab.ClassMethodNPar(
|
|
|
|
|
+ 1360 methCls, pn)
|
|
|
|
|
+ 1361 ELSIF ind THEN
|
|
|
|
|
+ 1362 np := SymTab.ProcTypeNPar(pt)
|
|
|
|
|
+ 1363 ELSE np := SymTab.ProcNPar(pn)
|
|
|
|
|
+ 1364 END;
|
|
|
|
|
+ 1365 va := (NOT isMeth) AND (NOT ind)
|
|
|
|
|
+ 1366 AND (SymTab.SymKind(pn) =
|
|
|
|
|
+ 1367 SymTab.KindProc)
|
|
|
|
|
+ 1368 AND SymTab.Varargs(pn);
|
|
|
|
|
+ 1369 IF (i # np) AND NOT va THEN
|
|
|
|
|
+ 1370 SemError(233); ok := FALSE
|
|
|
|
|
+ 1371 END
|
|
|
|
|
+ 1372 END;
|
|
|
|
|
+ 1373 IF NOT ok THEN
|
|
|
|
|
+ 1374 t := SymTab.InvalidType;
|
|
|
|
|
+ 1375 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1376 ELSIF want THEN
|
|
|
|
|
+ 1377 IF res =
|
|
|
|
|
+ 1378 SymTab.InvalidType THEN
|
|
|
|
|
+ 1379 SemError(233);
|
|
|
|
|
+ 1380 t := SymTab.InvalidType;
|
|
|
|
|
+ 1381 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1382 ELSE t := res;
|
|
|
|
|
+ 1383 QbeGen.CallEnd(TRUE, q)
|
|
|
|
|
+ 1384 END
|
|
|
|
|
+ 1385 ELSE
|
|
|
|
|
+ 1386 IF res #
|
|
|
|
|
+ 1387 SymTab.InvalidType THEN
|
|
|
|
|
+ 1388 SemError(233)
|
|
|
|
|
+ 1389 END;
|
|
|
|
|
+ 1390 t := SymTab.InvalidType;
|
|
|
|
|
+ 1391 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 1392 QbeGen.CallEnd(FALSE, q)
|
|
|
|
|
+ 1393 END; .) .
|
|
|
|
|
+ 1394 (* One actual: VAR formals take recorded designator addresses
|
|
|
|
|
+ 1395 (233 otherwise); value formals take converted expressions. *)
|
|
|
|
|
+ 1396 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
|
|
+ 1397 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
|
|
+ 1398 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
|
|
+ 1399 qe, qa, qt: QbeGen.QVal;
|
|
|
|
|
+ 1400 isV, conv, va: BOOLEAN;
|
|
|
|
|
+ 1401 cl: CHAR; .)
|
|
|
|
|
+ 1402 = Expr<at, qe> (. va := (NOT ind)
|
|
|
|
|
+ 1403 AND (methCls =
|
|
|
|
|
+ 1404 SymTab.InvalidType)
|
|
|
|
|
+ 1405 AND (SymTab.SymKind(pn) =
|
|
|
|
|
+ 1406 SymTab.KindProc)
|
|
|
|
|
+ 1407 AND SymTab.Varargs(pn);
|
|
|
|
|
+ 1408 IF ind THEN
|
|
|
|
|
+ 1409 ft :=
|
|
|
|
|
+ 1410 SymTab.ProcTypeParamType(pt,
|
|
|
|
|
+ 1411 i);
|
|
|
|
|
+ 1412 isV :=
|
|
|
|
|
+ 1413 SymTab.ProcTypeParamIsVar(pt,
|
|
|
|
|
+ 1414 i)
|
|
|
|
|
+ 1415 ELSIF methCls #
|
|
|
|
|
+ 1416 SymTab.InvalidType THEN
|
|
|
|
|
+ 1417 ft :=
|
|
|
|
|
+ 1418 SymTab.ClassMethodParamType(
|
|
|
|
|
+ 1419 methCls, pn, i);
|
|
|
|
|
+ 1420 isV :=
|
|
|
|
|
+ 1421 SymTab.ClassMethodParamIsVar(
|
|
|
|
|
+ 1422 methCls, pn, i)
|
|
|
|
|
+ 1423 ELSE
|
|
|
|
|
+ 1424 ft := SymTab.ParamType(pn, i);
|
|
|
|
|
+ 1425 isV := SymTab.ParamIsVar(pn, i)
|
|
|
|
|
+ 1426 END;
|
|
|
|
|
+ 1427 IF (at = SymTab.InvalidType) THEN
|
|
|
|
|
+ 1428 ELSIF ft = SymTab.InvalidType THEN
|
|
|
|
|
+ 1429 IF va THEN
|
|
|
|
|
+ 1430 QbeGen.CArgAdd(qe, at, qa, cl)
|
|
|
|
|
+ 1431 END
|
|
|
|
|
+ 1432 ELSIF isV THEN
|
|
|
|
|
+ 1433 IF (SymTab.ClassOf(at)
|
|
|
|
|
+ 1434 = SymTab.ClChar)
|
|
|
|
|
+ 1435 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
+ 1436 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
|
|
+ 1437 = SymTab.ClChar)
|
|
|
|
|
+ 1438 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
+ 1439 (* 1-char string
|
|
|
|
|
+ 1440 literal passed to
|
|
|
|
|
+ 1441 a VAR ARRAY OF CHAR *)
|
|
|
|
|
+ 1442 QbeGen.DeclCharStr(qe,
|
|
|
|
|
+ 1443 qa);
|
|
|
|
|
+ 1444 IF NOT QbeGen.CallArg(qa,
|
|
|
|
|
+ 1445 "l") THEN
|
|
|
|
|
+ 1446 SemError(233)
|
|
|
|
|
+ 1447 END
|
|
|
|
|
+ 1448 ELSIF NOT QbeGen.AddrOfVal(qe,
|
|
|
|
|
+ 1449 qa) THEN
|
|
|
|
|
+ 1450 SemError(233)
|
|
|
|
|
+ 1451 ELSIF NOT SymTab.VarParamOk(at,
|
|
|
|
|
+ 1452 ft) THEN
|
|
|
|
|
+ 1453 SemError(233)
|
|
|
|
|
+ 1454 ELSIF NOT QbeGen.CallArg(qa,
|
|
|
|
|
+ 1455 "l") THEN
|
|
|
|
|
+ 1456 SemError(233)
|
|
|
|
|
+ 1457 END
|
|
|
|
|
+ 1458 ELSE
|
|
|
|
|
+ 1459 IF (SymTab.ClassOf(at)
|
|
|
|
|
+ 1460 = SymTab.ClChar)
|
|
|
|
|
+ 1461 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
+ 1462 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
|
|
+ 1463 = SymTab.ClChar)
|
|
|
|
|
+ 1464 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
+ 1465 (* 1-char string
|
|
|
|
|
+ 1466 literal passed to
|
|
|
|
|
+ 1467 ARRAY OF CHAR *)
|
|
|
|
|
+ 1468 QbeGen.DeclCharStr(qe,
|
|
|
|
|
+ 1469 qa);
|
|
|
|
|
+ 1470 IF NOT QbeGen.CallArg(qa,
|
|
|
|
|
+ 1471 "l") THEN
|
|
|
|
|
+ 1472 SemError(233)
|
|
|
|
|
+ 1473 END
|
|
|
|
|
+ 1474 ELSIF NOT SymTab.Assignable(at,
|
|
|
|
|
+ 1475 ft) THEN
|
|
|
|
|
+ 1476 SemError(233)
|
|
|
|
|
+ 1477 ELSE
|
|
|
|
|
+ 1478 conv := (SymTab.ClassOf(
|
|
|
|
|
+ 1479 ft) = SymTab.ClReal)
|
|
|
|
|
+ 1480 AND SymTab.IsIntFamily(at);
|
|
|
|
|
+ 1481 IF conv THEN
|
|
|
|
|
+ 1482 QbeGen.ConvIR(qe, qt);
|
|
|
|
|
+ 1483 IF NOT QbeGen.CallArg(qt,
|
|
|
|
|
+ 1484 "d") THEN
|
|
|
|
|
+ 1485 SemError(233)
|
|
|
|
|
+ 1486 END
|
|
|
|
|
+ 1487 ELSIF NOT QbeGen.CallArg(qe,
|
|
|
|
|
+ 1488 QbeGen.ArgClass(ft)) THEN
|
|
|
|
|
+ 1489 SemError(233)
|
|
|
|
|
+ 1490 END
|
|
|
|
|
+ 1491 END
|
|
|
|
|
+ 1492 END; .) .
|
|
|
|
|
+ 1493 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 1494 q, lThen, lElse, lEnd:
|
|
|
|
|
+ 1495 QbeGen.QVal;
|
|
|
|
|
+ 1496 hasElse: BOOLEAN; .)
|
|
|
|
|
+ 1497 = "IF" (. hasElse := FALSE; .)
|
|
|
|
|
+ 1498 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 1499 SemError(214) END;
|
|
|
|
|
+ 1500 QbeGen.NewLabel(lThen);
|
|
|
|
|
+ 1501 QbeGen.NewLabel(lElse);
|
|
|
1502 QbeGen.NewLabel(lEnd);
|
|
1502 QbeGen.NewLabel(lEnd);
|
|
|
- 1503 QbeGen.PushLoop(lEnd);
|
|
|
|
|
- 1504 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
- 1505 [ StatSeq ]
|
|
|
|
|
- 1506 "END" (. QbeGen.Jmp(lTop);
|
|
|
|
|
- 1507 QbeGen.PopLoop;
|
|
|
|
|
- 1508 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
- 1509 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
|
|
- 1510 Runtime direction would need a compare-select; the literal
|
|
|
|
|
- 1511 sign picks cslew/csegew at "DO" time. *)
|
|
|
|
|
- 1512 ForStat (. VAR lv: SymTab.Name;
|
|
|
|
|
- 1513 tlo, thi, tby:
|
|
|
|
|
- 1514 SymTab.TypeIndex;
|
|
|
|
|
- 1515 qlo, qhi, qby, qt, qk, qb:
|
|
|
|
|
- 1516 QbeGen.QVal;
|
|
|
|
|
- 1517 lTop, lBody, lEnd:
|
|
|
|
|
- 1518 QbeGen.QVal;
|
|
|
|
|
- 1519 by: INTEGER;
|
|
|
|
|
- 1520 ok: BOOLEAN; .)
|
|
|
|
|
- 1521 = "FOR" (. by := 1; .)
|
|
|
|
|
- 1522 GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
|
|
- 1523 IF NOT ok THEN
|
|
|
|
|
- 1524 SemError(201)
|
|
|
|
|
- 1525 ELSIF (SymTab.SymKind(lv) #
|
|
|
|
|
- 1526 SymTab.KindVar)
|
|
|
|
|
- 1527 AND (SymTab.SymKind(lv) #
|
|
|
|
|
- 1528 SymTab.KindParam) THEN
|
|
|
|
|
- 1529 SemError(220); ok := FALSE
|
|
|
|
|
- 1530 ELSIF NOT SymTab.IsIntFamily(
|
|
|
|
|
- 1531 SymTab.SymType(lv)) THEN
|
|
|
|
|
- 1532 SemError(220); ok := FALSE
|
|
|
|
|
- 1533 END; .)
|
|
|
|
|
- 1534 ":=" Expr<tlo, qlo> (. IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
|
|
- 1535 SemError(220); ok := FALSE
|
|
|
|
|
- 1536 END; .)
|
|
|
|
|
- 1537 "TO" Expr<thi, qhi> (. IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
|
|
- 1538 SemError(220); ok := FALSE
|
|
|
|
|
- 1539 END; .)
|
|
|
|
|
- 1540 [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
|
|
- 1541 SymTab.InvalidType)
|
|
|
|
|
- 1542 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
|
|
- 1543 SemError(220); ok := FALSE
|
|
|
|
|
- 1544 END;
|
|
|
|
|
- 1545 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
|
|
- 1546 SemError(230); by := 1
|
|
|
|
|
- 1547 ELSIF by = 0 THEN
|
|
|
|
|
- 1548 SemError(220); by := 1
|
|
|
|
|
- 1549 END; .) ]
|
|
|
|
|
- 1550 "DO" (. IF ok THEN
|
|
|
|
|
- 1551 QbeGen.StoreVar(lv, qlo,
|
|
|
|
|
- 1552 FALSE) END;
|
|
|
|
|
- 1553 QbeGen.NewLabel(lTop);
|
|
|
|
|
- 1554 QbeGen.NewLabel(lBody);
|
|
|
|
|
- 1555 QbeGen.NewLabel(lEnd);
|
|
|
|
|
- 1556 QbeGen.EmitLabel(lTop);
|
|
|
|
|
- 1557 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
|
|
- 1558 QbeGen.NewTemp(qk);
|
|
|
|
|
- 1559 IF by > 0 THEN
|
|
|
|
|
- 1560 QbeGen.Op3("cslew", qk,
|
|
|
|
|
- 1561 qt, qhi, FALSE)
|
|
|
|
|
- 1562 ELSE QbeGen.Op3("csgew", qk,
|
|
|
|
|
- 1563 qt, qhi, FALSE)
|
|
|
|
|
- 1564 END;
|
|
|
|
|
- 1565 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
|
|
- 1566 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
- 1567 [ StatSeq ]
|
|
|
|
|
- 1568 "END" (. IF ok THEN
|
|
|
|
|
- 1569 QbeGen.LoadVar(lv, FALSE,
|
|
|
|
|
- 1570 qt);
|
|
|
|
|
- 1571 QbeGen.IntStr(by, qb);
|
|
|
|
|
- 1572 QbeGen.NewTemp(qk);
|
|
|
|
|
- 1573 QbeGen.Op3("add", qk,
|
|
|
|
|
- 1574 qt, qb, FALSE);
|
|
|
|
|
- 1575 QbeGen.StoreVar(lv, qk,
|
|
|
|
|
- 1576 FALSE) END;
|
|
|
|
|
- 1577 QbeGen.Jmp(lTop);
|
|
|
|
|
- 1578 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
- 1579 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
|
|
- 1580 qsel, lEnd: QbeGen.QVal; .)
|
|
|
|
|
- 1581 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
|
|
- 1582 "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
|
|
- 1583 { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
|
|
- 1584 [ "ELSE" [ StatSeq ] ]
|
|
|
|
|
- 1585 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
- 1586 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
|
|
- 1587 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
|
|
- 1588 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
|
|
- 1589 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
|
|
- 1590 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
- 1591 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
|
|
- 1592 = (. QbeGen.NewLabel(lBody);
|
|
|
|
|
- 1593 QbeGen.NewLabel(lAfter); .)
|
|
|
|
|
- 1594 CaseLabel<tsel, qsel, lBody>
|
|
|
|
|
- 1595 { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
|
|
- 1596 ":" (. QbeGen.Jmp(lAfter);
|
|
|
|
|
- 1597 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
- 1598 [ StatSeq ] (. QbeGen.Jmp(lEnd);
|
|
|
|
|
- 1599 QbeGen.EmitLabel(lAfter); .) .
|
|
|
|
|
- 1600 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
- 1601 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
|
|
- 1602 q2, q3, qc, qd, qe:
|
|
|
|
|
- 1603 QbeGen.QVal;
|
|
|
|
|
- 1604 lNext: QbeGen.QVal; .)
|
|
|
|
|
- 1605 = Expr<t2, q2> (. IF (t2 #
|
|
|
|
|
- 1606 SymTab.InvalidType)
|
|
|
|
|
- 1607 AND (tsel #
|
|
|
|
|
- 1608 SymTab.InvalidType)
|
|
|
|
|
- 1609 AND ((SymTab.ClassOf(t2) =
|
|
|
|
|
- 1610 SymTab.ClSet)
|
|
|
|
|
- 1611 OR (SymTab.ClassOf(tsel) =
|
|
|
|
|
- 1612 SymTab.ClSet)) THEN
|
|
|
|
|
- 1613 SemError(230)
|
|
|
|
|
- 1614 ELSIF (t2 #
|
|
|
|
|
- 1615 SymTab.InvalidType)
|
|
|
|
|
- 1616 AND (tsel #
|
|
|
|
|
- 1617 SymTab.InvalidType)
|
|
|
|
|
- 1618 AND NOT SymTab.EqCheck(t2,
|
|
|
|
|
- 1619 tsel) THEN
|
|
|
|
|
- 1620 SemError(213) END;
|
|
|
|
|
- 1621 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
|
|
- 1622 SemError(230);
|
|
|
|
|
- 1623 QbeGen.CopyOp("0", q2)
|
|
|
|
|
- 1624 END;
|
|
|
|
|
- 1625 QbeGen.NewLabel(lNext);
|
|
|
|
|
- 1626 QbeGen.Cmp(SymTab.OpEq,
|
|
|
|
|
- 1627 qsel, q2, qc, FALSE);
|
|
|
|
|
- 1628 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
|
|
- 1629 QbeGen.EmitLabel(lNext); .)
|
|
|
|
|
- 1630 [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
|
|
- 1631 SymTab.InvalidType)
|
|
|
|
|
- 1632 AND (tsel #
|
|
|
|
|
- 1633 SymTab.InvalidType)
|
|
|
|
|
- 1634 AND NOT SymTab.EqCheck(t3,
|
|
|
|
|
- 1635 tsel) THEN
|
|
|
|
|
- 1636 SemError(213) END;
|
|
|
|
|
- 1637 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
|
|
- 1638 SemError(230);
|
|
|
|
|
- 1639 QbeGen.CopyOp("0", q3)
|
|
|
|
|
- 1640 END;
|
|
|
|
|
- 1641 QbeGen.Cmp(SymTab.OpGe,
|
|
|
|
|
- 1642 qsel, q2, qc, FALSE);
|
|
|
|
|
- 1643 QbeGen.Cmp(SymTab.OpLe,
|
|
|
|
|
- 1644 qsel, q3, qd, FALSE);
|
|
|
|
|
- 1645 QbeGen.NewTemp(qe);
|
|
|
|
|
- 1646 QbeGen.Op3("and", qe, qc, qd,
|
|
|
|
|
- 1647 FALSE);
|
|
|
|
|
- 1648 QbeGen.NewLabel(lNext);
|
|
|
|
|
- 1649 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
|
|
- 1650 QbeGen.EmitLabel(lNext); .) ] .
|
|
|
|
|
- 1651 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 1652 q, qt: QbeGen.QVal;
|
|
|
|
|
- 1653 res: SymTab.TypeIndex;
|
|
|
|
|
- 1654 hadE, conv: BOOLEAN; .)
|
|
|
|
|
- 1655 = "RETURN" (. hadE := FALSE; .)
|
|
|
|
|
- 1656 [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
|
|
- 1657 (. conv := FALSE;
|
|
|
|
|
- 1658 IF NOT SymTab.InProc() THEN
|
|
|
|
|
- 1659 SemError(232)
|
|
|
|
|
- 1660 ELSE res := SymTab.CurRes();
|
|
|
|
|
- 1661 IF NOT hadE THEN
|
|
|
|
|
- 1662 IF res #
|
|
|
|
|
- 1663 SymTab.InvalidType THEN
|
|
|
|
|
- 1664 SemError(232)
|
|
|
|
|
- 1665 ELSE QbeGen.EmitRet(q,
|
|
|
|
|
- 1666 FALSE)
|
|
|
|
|
- 1667 END
|
|
|
|
|
- 1668 ELSIF (res =
|
|
|
|
|
- 1669 SymTab.InvalidType)
|
|
|
|
|
- 1670 OR (t #
|
|
|
|
|
- 1671 SymTab.InvalidType)
|
|
|
|
|
- 1672 AND NOT SymTab.Assignable(t,
|
|
|
|
|
- 1673 res) THEN
|
|
|
|
|
- 1674 SemError(232)
|
|
|
|
|
- 1675 ELSE
|
|
|
|
|
- 1676 conv := (SymTab.ClassOf(
|
|
|
|
|
- 1677 res) = SymTab.ClReal)
|
|
|
|
|
- 1678 AND SymTab.IsIntFamily(t);
|
|
|
|
|
- 1679 IF conv THEN
|
|
|
|
|
- 1680 QbeGen.ConvIR(q, qt);
|
|
|
|
|
- 1681 QbeGen.EmitRet(qt, TRUE)
|
|
|
|
|
- 1682 ELSE QbeGen.EmitRet(q, TRUE)
|
|
|
|
|
- 1683 END
|
|
|
|
|
- 1684 END
|
|
|
|
|
- 1685 END; .) .
|
|
|
|
|
- 1686 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 1687 q: QbeGen.QVal; .)
|
|
|
|
|
- 1688 = "HALT" [ "(" Expr<t, q> ")" ] (. QbeGen.HaltQ; .) .
|
|
|
|
|
- 1689 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
|
|
- 1690 Each index descends one level (bounds-checked, trap on breach);
|
|
|
|
|
- 1691 nested levels reload the inner descriptor address. q ends as the
|
|
|
|
|
- 1692 value (scalars), the descriptor address (plain arrays), or the
|
|
|
|
|
- 1693 element address (indexed); sfx marks the indexed form. *)
|
|
|
|
|
- 1694 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
- 1695 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
|
|
- 1696 (. VAR n, fn, mal: SymTab.Name;
|
|
|
|
|
- 1697 cls: INTEGER;
|
|
|
|
|
- 1698 ic: SymTab.TypeIndex;
|
|
|
|
|
- 1699 curT, it, eT, bt:
|
|
|
|
|
- 1700 SymTab.TypeIndex;
|
|
|
|
|
- 1701 iq, ql, qlo, qhi, qe:
|
|
|
|
|
- 1702 QbeGen.QVal;
|
|
|
|
|
- 1703 lo, hi: INTEGER;
|
|
|
|
|
- 1704 fo: INTEGER;
|
|
|
|
|
- 1705 isOpen: BOOLEAN;
|
|
|
|
|
- 1706 qb, cv: QbeGen.QVal; .)
|
|
|
|
|
- 1707 = GetIdent<n> (. methCls := SymTab.InvalidType;
|
|
|
|
|
- 1708 QbeGen.CopyOp(n, qn);
|
|
|
|
|
- 1709 sfx := FALSE;
|
|
|
|
|
- 1710 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
- 1711 (* a bare method name inside
|
|
|
|
|
- 1712 a CLASS IMPLEMENTATION
|
|
|
|
|
- 1713 is a sibling call on
|
|
|
|
|
- 1714 THIS *)
|
|
|
|
|
- 1715 ic := SymTab.CurImplClass();
|
|
|
|
|
- 1716 IF (ic #
|
|
|
|
|
- 1717 SymTab.InvalidType)
|
|
|
|
|
- 1718 AND SymTab.MethodExists(ic, n) THEN
|
|
|
|
|
- 1719 sfx := FALSE;
|
|
|
|
|
- 1720 QbeGen.ThisBase(q);
|
|
|
|
|
- 1721 QbeGen.ArmRecv(q);
|
|
|
|
|
- 1722 methCls := ic;
|
|
|
|
|
- 1723 k := SymTab.KindProc;
|
|
|
|
|
- 1724 t := SymTab.InvalidType
|
|
|
|
|
- 1725 ELSE
|
|
|
|
|
- 1726 SemError(201);
|
|
|
|
|
- 1727 t :=
|
|
|
|
|
- 1728 SymTab.InvalidType;
|
|
|
|
|
- 1729 k := -1;
|
|
|
|
|
- 1730 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1731 END
|
|
|
|
|
- 1732 ELSE
|
|
|
|
|
- 1733 t := SymTab.SymType(n);
|
|
|
|
|
- 1734 k := SymTab.SymKind(n);
|
|
|
|
|
- 1735 IF k = SymTab.KindConst THEN
|
|
|
|
|
- 1736 IF SymTab.Equal(n,
|
|
|
|
|
- 1737 "TRUE") THEN
|
|
|
|
|
- 1738 t := SymTab.BoolType();
|
|
|
|
|
- 1739 QbeGen.CopyOp("1", q)
|
|
|
|
|
- 1740 ELSIF SymTab.Equal(n,
|
|
|
|
|
- 1741 "FALSE") THEN
|
|
|
|
|
- 1742 t := SymTab.BoolType();
|
|
|
|
|
- 1743 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1744 ELSIF SymTab.Equal(n,
|
|
|
|
|
- 1745 "NIL") THEN
|
|
|
|
|
- 1746 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1747 ELSE
|
|
|
|
|
- 1748 cls :=
|
|
|
|
|
- 1749 SymTab.ClassOf(t);
|
|
|
|
|
- 1750 IF (t #
|
|
|
|
|
- 1751 SymTab.InvalidType)
|
|
|
|
|
- 1752 AND ((cls = SymTab.ClInt)
|
|
|
|
|
- 1753 OR (cls
|
|
|
|
|
- 1754 = SymTab.ClChar)
|
|
|
|
|
- 1755 OR (cls
|
|
|
|
|
- 1756 = SymTab.ClEnum)
|
|
|
|
|
- 1757 OR (cls
|
|
|
|
|
- 1758 = SymTab.ClReal)
|
|
|
|
|
- 1759 OR (cls
|
|
|
|
|
- 1760 = SymTab.ClLong)
|
|
|
|
|
- 1761 OR (cls
|
|
|
|
|
- 1762 = SymTab.ClNil)) THEN
|
|
|
|
|
- 1763 IF cls = SymTab.ClNil THEN
|
|
|
|
|
- 1764 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1765 ELSIF ((cls
|
|
|
|
|
- 1766 = SymTab.ClInt)
|
|
|
|
|
- 1767 OR (cls
|
|
|
|
|
- 1768 = SymTab.ClChar)
|
|
|
|
|
- 1769 OR (cls
|
|
|
|
|
- 1770 = SymTab.ClEnum)
|
|
|
|
|
- 1771 OR (cls
|
|
|
|
|
- 1772 = SymTab.ClLong))
|
|
|
|
|
- 1773 AND SymTab.GetSymVal(n, cv)
|
|
|
|
|
- 1774 AND QbeGen.IsImm(cv) THEN
|
|
|
|
|
- 1775 QbeGen.CopyOp(cv, q)
|
|
|
|
|
- 1776 ELSE
|
|
|
|
|
- 1777 QbeGen.LoadVar(n,
|
|
|
|
|
- 1778 cls = SymTab.ClReal,
|
|
|
|
|
- 1779 q)
|
|
|
|
|
- 1780 END
|
|
|
|
|
- 1781 ELSIF (cls = SymTab.ClArray)
|
|
|
|
|
- 1782 OR (cls = SymTab.ClRecord)
|
|
|
|
|
- 1783 OR (cls = SymTab.ClClass)
|
|
|
|
|
- 1784 OR (cls = SymTab.ClStr)
|
|
|
|
|
- 1785 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
- 1786 (* aggregate constant:
|
|
|
|
|
- 1787 its value IS the
|
|
|
|
|
- 1788 descriptor address *)
|
|
|
|
|
- 1789 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
|
|
- 1790 QbeGen.CopyOp(cv, q)
|
|
|
|
|
- 1791 ELSE
|
|
|
|
|
- 1792 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1793 END
|
|
|
|
|
- 1794 ELSE
|
|
|
|
|
- 1795 IF t #
|
|
|
|
|
- 1796 SymTab.InvalidType THEN
|
|
|
|
|
- 1797 SemError(230)
|
|
|
|
|
- 1798 END;
|
|
|
|
|
- 1799 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1800 END
|
|
|
|
|
- 1801 END
|
|
|
|
|
- 1802 ELSIF (k = SymTab.KindVar)
|
|
|
|
|
- 1803 OR (k = SymTab.KindParam) THEN
|
|
|
|
|
- 1804 cls :=
|
|
|
|
|
- 1805 SymTab.ClassOf(t);
|
|
|
|
|
- 1806 IF (cls = SymTab.ClInt)
|
|
|
|
|
- 1807 OR (cls = SymTab.ClBool)
|
|
|
|
|
- 1808 OR (cls = SymTab.ClChar)
|
|
|
|
|
- 1809 OR (cls = SymTab.ClUChar)
|
|
|
|
|
- 1810 OR (cls = SymTab.ClEnum)
|
|
|
|
|
- 1811 OR (cls
|
|
|
|
|
- 1812 = SymTab.ClReal) THEN
|
|
|
|
|
- 1813 QbeGen.LoadVar(n,
|
|
|
|
|
- 1814 cls = SymTab.ClReal, q)
|
|
|
|
|
- 1815 ELSIF (cls = SymTab.ClPtr)
|
|
|
|
|
- 1816 OR (cls = SymTab.ClProc) THEN
|
|
|
|
|
- 1817 QbeGen.LoadPtr(n, q)
|
|
|
|
|
- 1818 ELSIF cls = SymTab.ClLong THEN
|
|
|
|
|
- 1819 QbeGen.LoadLong(n, q)
|
|
|
|
|
- 1820 ELSIF (cls
|
|
|
|
|
- 1821 = SymTab.ClArray)
|
|
|
|
|
- 1822 OR (cls
|
|
|
|
|
- 1823 = SymTab.ClSet)
|
|
|
|
|
- 1824 OR (cls
|
|
|
|
|
- 1825 = SymTab.ClRecord)
|
|
|
|
|
- 1826 OR (cls
|
|
|
|
|
- 1827 = SymTab.ClUStr)
|
|
|
|
|
- 1828 OR (cls
|
|
|
|
|
- 1829 = SymTab.ClClass) THEN
|
|
|
|
|
- 1830 QbeGen.AddrOf(n, q)
|
|
|
|
|
- 1831 ELSE SemError(230);
|
|
|
|
|
- 1832 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1833 END
|
|
|
|
|
- 1834 ELSE QbeGen.CopyOp("0", q);
|
|
|
|
|
- 1835 IF k = SymTab.KindImport THEN
|
|
|
|
|
- 1836 SemError(230)
|
|
|
|
|
- 1837 ELSIF k =
|
|
|
|
|
- 1838 SymTab.KindProc THEN
|
|
|
|
|
- 1839 (* bare procedure name:
|
|
|
|
|
- 1840 a following ArgList
|
|
|
|
|
- 1841 makes it a call;
|
|
|
|
|
- 1842 otherwise Fact
|
|
|
|
|
- 1843 reports 230 *)
|
|
|
|
|
- 1844 ELSE
|
|
|
|
|
- 1845 IF k = SymTab.KindField THEN
|
|
|
|
|
- 1846 IF QbeGen.TopWith(qb) THEN
|
|
|
|
|
- 1847 fo :=
|
|
|
|
|
- 1848 SymTab.FieldOffset(
|
|
|
|
|
- 1849 SymTab.FieldOwner(n),
|
|
|
|
|
- 1850 n);
|
|
|
|
|
- 1851 QbeGen.FieldAddr(qb,
|
|
|
|
|
- 1852 fo, q);
|
|
|
|
|
- 1853 sfx := TRUE
|
|
|
|
|
- 1854 ELSE SemError(230);
|
|
|
|
|
- 1855 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1856 END
|
|
|
|
|
- 1857 END
|
|
|
|
|
- 1858 END
|
|
|
|
|
- 1859 END
|
|
|
|
|
- 1860 END; .)
|
|
|
|
|
- 1861 { "[" Expr<it, iq>
|
|
|
|
|
- 1862 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 1863 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 1864 SymTab.ClArray THEN
|
|
|
|
|
- 1865 SemError(217);
|
|
|
|
|
- 1866 t := SymTab.InvalidType
|
|
|
|
|
- 1867 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
- 1868 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 1869 SymTab.ClChar)
|
|
|
|
|
- 1870 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 1871 SymTab.ClEnum) THEN
|
|
|
|
|
- 1872 SemError(218);
|
|
|
|
|
- 1873 t := SymTab.InvalidType
|
|
|
|
|
- 1874 ELSE
|
|
|
|
|
- 1875 QbeGen.WidenIndex(iq, ql);
|
|
|
|
|
- 1876 isOpen :=
|
|
|
|
|
- 1877 SymTab.IsOpenArray(t);
|
|
|
|
|
- 1878 IF isOpen THEN
|
|
|
|
|
- 1879 QbeGen.CopyOp("0", qlo);
|
|
|
|
|
- 1880 IF SymTab.IsCharArray(t)
|
|
|
|
|
- 1881 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
- 1882 QbeGen.OpenHiChar(q, qhi)
|
|
|
|
|
- 1883 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
|
|
- 1884 END
|
|
|
|
|
- 1885 ELSE
|
|
|
|
|
- 1886 lo := SymTab.ArrayLo(t);
|
|
|
|
|
- 1887 hi := SymTab.ArrayHi(t);
|
|
|
|
|
- 1888 IF SymTab.IsCharArray(t)
|
|
|
|
|
- 1889 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
- 1890 hi := hi + 1
|
|
|
|
|
- 1891 END;
|
|
|
|
|
- 1892 QbeGen.IntStr(lo, qlo);
|
|
|
|
|
- 1893 QbeGen.IntStr(hi, qhi)
|
|
|
|
|
- 1894 END;
|
|
|
|
|
- 1895 QbeGen.CheckRange(ql, qlo,
|
|
|
|
|
- 1896 qhi);
|
|
|
|
|
- 1897 eT := SymTab.ArrayElem(t);
|
|
|
|
|
- 1898 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
|
|
- 1899 t, qe);
|
|
|
|
|
- 1900 IF SymTab.ClassOf(eT) =
|
|
|
|
|
- 1901 SymTab.ClArray THEN
|
|
|
|
|
- 1902 QbeGen.ElemLoad(qe, eT, q)
|
|
|
|
|
- 1903 ELSE QbeGen.CopyOp(qe, q)
|
|
|
|
|
- 1904 END;
|
|
|
|
|
- 1905 t := eT; sfx := TRUE
|
|
|
|
|
- 1906 END; .)
|
|
|
|
|
- 1907 { "," Expr<it, iq>
|
|
|
|
|
- 1908 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 1909 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 1910 SymTab.ClArray THEN
|
|
|
|
|
- 1911 SemError(217);
|
|
|
|
|
- 1912 t := SymTab.InvalidType
|
|
|
|
|
- 1913 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
- 1914 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 1915 SymTab.ClChar)
|
|
|
|
|
- 1916 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 1917 SymTab.ClEnum) THEN
|
|
|
|
|
- 1918 SemError(218);
|
|
|
|
|
- 1919 t := SymTab.InvalidType
|
|
|
|
|
- 1920 ELSE
|
|
|
|
|
- 1921 QbeGen.WidenIndex(iq, ql);
|
|
|
|
|
- 1922 isOpen :=
|
|
|
|
|
- 1923 SymTab.IsOpenArray(t);
|
|
|
|
|
- 1924 IF isOpen THEN
|
|
|
|
|
- 1925 QbeGen.CopyOp("0", qlo);
|
|
|
|
|
- 1926 IF SymTab.IsCharArray(t)
|
|
|
|
|
- 1927 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
- 1928 QbeGen.OpenHiChar(q, qhi)
|
|
|
|
|
- 1929 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
|
|
- 1930 END
|
|
|
|
|
- 1931 ELSE
|
|
|
|
|
- 1932 lo := SymTab.ArrayLo(t);
|
|
|
|
|
- 1933 hi := SymTab.ArrayHi(t);
|
|
|
|
|
- 1934 IF SymTab.IsCharArray(t)
|
|
|
|
|
- 1935 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
- 1936 hi := hi + 1
|
|
|
|
|
- 1937 END;
|
|
|
|
|
- 1938 QbeGen.IntStr(lo, qlo);
|
|
|
|
|
- 1939 QbeGen.IntStr(hi, qhi)
|
|
|
|
|
- 1940 END;
|
|
|
|
|
- 1941 QbeGen.CheckRange(ql, qlo,
|
|
|
|
|
- 1942 qhi);
|
|
|
|
|
- 1943 eT := SymTab.ArrayElem(t);
|
|
|
|
|
- 1944 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
|
|
- 1945 t, qe);
|
|
|
|
|
- 1946 IF SymTab.ClassOf(eT) =
|
|
|
|
|
- 1947 SymTab.ClArray THEN
|
|
|
|
|
- 1948 QbeGen.ElemLoad(qe, eT, q)
|
|
|
|
|
- 1949 ELSE QbeGen.CopyOp(qe, q)
|
|
|
|
|
- 1950 END;
|
|
|
|
|
- 1951 t := eT; sfx := TRUE
|
|
|
|
|
- 1952 END; .) }
|
|
|
|
|
- 1953 "]"
|
|
|
|
|
- 1954 | "." GetIdent<fn>
|
|
|
|
|
- 1955 (. IF k = SymTab.KindModule THEN
|
|
|
|
|
- 1956 (* qualified L.x: materialize
|
|
|
|
|
- 1957 the export, then load it *)
|
|
|
|
|
- 1958 IF NOT SymTab.MaterializeAlias(n,
|
|
|
|
|
- 1959 fn, mal) THEN
|
|
|
|
|
- 1960 SemError(201);
|
|
|
|
|
- 1961 t := SymTab.InvalidType;
|
|
|
|
|
- 1962 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1963 ELSE
|
|
|
|
|
- 1964 QbeGen.CopyOp(mal, qn);
|
|
|
|
|
- 1965 t := SymTab.SymType(mal);
|
|
|
|
|
- 1966 k := SymTab.SymKind(mal);
|
|
|
|
|
- 1967 sfx := FALSE;
|
|
|
|
|
- 1968 IF k = SymTab.KindProc THEN
|
|
|
|
|
- 1969 (* call: ArgList supplies
|
|
|
|
|
- 1970 the value *)
|
|
|
|
|
- 1971 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1972 ELSIF NOT QbeGen.LoadDesignator(
|
|
|
|
|
- 1973 mal, t, k, q) THEN
|
|
|
|
|
- 1974 SemError(230);
|
|
|
|
|
- 1975 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 1976 END
|
|
|
|
|
- 1977 END
|
|
|
|
|
- 1978 ELSIF t = SymTab.InvalidType THEN
|
|
|
|
|
- 1979 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
- 1980 SymTab.ClRecord)
|
|
|
|
|
- 1981 AND (SymTab.ClassOf(t) #
|
|
|
|
|
- 1982 SymTab.ClClass) THEN
|
|
|
|
|
- 1983 SemError(215);
|
|
|
|
|
- 1984 t := SymTab.InvalidType
|
|
|
|
|
- 1985 ELSIF (SymTab.ClassOf(t) =
|
|
|
|
|
- 1986 SymTab.ClClass)
|
|
|
|
|
- 1987 AND SymTab.MethodExists(t, fn) THEN
|
|
|
|
|
- 1988 (* obj.Method: bind the
|
|
|
|
|
- 1989 method and pass obj as
|
|
|
|
|
- 1990 the hidden receiver; q
|
|
|
|
|
- 1991 already holds the
|
|
|
|
|
- 1992 object's address *)
|
|
|
|
|
- 1993 QbeGen.ArmRecv(q);
|
|
|
|
|
- 1994 QbeGen.CopyOp(fn, n);
|
|
|
|
|
- 1995 QbeGen.CopyOp(fn, qn);
|
|
|
|
|
- 1996 methCls := t;
|
|
|
|
|
- 1997 k := SymTab.KindProc;
|
|
|
|
|
- 1998 t := SymTab.InvalidType
|
|
|
|
|
- 1999 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
- 2000 fn) THEN
|
|
|
|
|
- 2001 SemError(216);
|
|
|
|
|
- 2002 t := SymTab.InvalidType
|
|
|
|
|
- 2003 ELSE
|
|
|
|
|
- 2004 fo := SymTab.FieldOffset(t,
|
|
|
|
|
- 2005 fn);
|
|
|
|
|
- 2006 t := SymTab.FieldType(t, fn);
|
|
|
|
|
- 2007 QbeGen.FieldAddr(q, fo, qe);
|
|
|
|
|
- 2008 (* array fields are inline:
|
|
|
|
|
- 2009 the field address is the
|
|
|
|
|
- 2010 descriptor, like records *)
|
|
|
|
|
- 2011 QbeGen.CopyOp(qe, q);
|
|
|
|
|
- 2012 sfx := TRUE
|
|
|
|
|
- 2013 END; .)
|
|
|
|
|
- 2014 | "^"
|
|
|
|
|
- 2015 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2016 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2017 SymTab.ClPtr THEN
|
|
|
|
|
- 2018 SemError(219);
|
|
|
|
|
- 2019 t := SymTab.InvalidType
|
|
|
|
|
- 2020 ELSE
|
|
|
|
|
- 2021 bt := SymTab.PtrBase(t);
|
|
|
|
|
- 2022 IF bt = SymTab.InvalidType THEN
|
|
|
|
|
- 2023 ELSE
|
|
|
|
|
- 2024 IF sfx THEN
|
|
|
|
|
- 2025 QbeGen.ElemLoad(q, t,
|
|
|
|
|
- 2026 qb);
|
|
|
|
|
- 2027 QbeGen.CopyOp(qb, q)
|
|
|
|
|
- 2028 END;
|
|
|
|
|
- 2029 t := bt;
|
|
|
|
|
- 2030 (* q holds the pointee
|
|
|
|
|
- 2031 address: Fact loads
|
|
|
|
|
- 2032 scalars/pointers and uses
|
|
|
|
|
- 2033 the address for
|
|
|
|
|
- 2034 aggregates; the VAR-actual
|
|
|
|
|
- 2035 note is q itself. *)
|
|
|
|
|
- 2036 sfx := TRUE
|
|
|
|
|
- 2037 END
|
|
|
|
|
- 2038 END; .) } .
|
|
|
|
|
- 2039 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
|
|
- 2040 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
|
|
- 2041 (a value, or a descriptor address for aggregates); each component
|
|
|
|
|
- 2042 descends one level exactly like the Design components. *)
|
|
|
|
|
- 2043 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
- 2044 VAR sfx: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
|
|
- 2045 iq, ql, qlo, qhi, qe, qb:
|
|
|
|
|
- 2046 QbeGen.QVal;
|
|
|
|
|
- 2047 lo, hi, fo: INTEGER;
|
|
|
|
|
- 2048 isOpen: BOOLEAN;
|
|
|
|
|
- 2049 fname: SymTab.Name; .)
|
|
|
|
|
- 2050 = "[" Expr<it, iq>
|
|
|
|
|
- 2051 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2052 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2053 SymTab.ClArray THEN
|
|
|
|
|
- 2054 SemError(217);
|
|
|
|
|
- 2055 t := SymTab.InvalidType
|
|
|
|
|
- 2056 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
- 2057 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
|
|
- 2058 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
|
|
- 2059 SemError(218);
|
|
|
|
|
- 2060 t := SymTab.InvalidType
|
|
|
|
|
- 2061 ELSE
|
|
|
|
|
- 2062 QbeGen.WidenIndex(iq, ql);
|
|
|
|
|
- 2063 isOpen :=
|
|
|
|
|
- 2064 SymTab.IsOpenArray(t);
|
|
|
|
|
- 2065 IF isOpen THEN
|
|
|
|
|
- 2066 QbeGen.CopyOp("0", qlo);
|
|
|
|
|
- 2067 IF SymTab.IsCharArray(t)
|
|
|
|
|
- 2068 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
- 2069 QbeGen.OpenHiChar(q, qhi)
|
|
|
|
|
- 2070 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
|
|
- 2071 END
|
|
|
|
|
- 2072 ELSE
|
|
|
|
|
- 2073 lo := SymTab.ArrayLo(t);
|
|
|
|
|
- 2074 hi := SymTab.ArrayHi(t);
|
|
|
|
|
- 2075 IF SymTab.IsCharArray(t)
|
|
|
|
|
- 2076 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
- 2077 hi := hi + 1
|
|
|
|
|
- 2078 END;
|
|
|
|
|
- 2079 QbeGen.IntStr(lo, qlo);
|
|
|
|
|
- 2080 QbeGen.IntStr(hi, qhi)
|
|
|
|
|
- 2081 END;
|
|
|
|
|
- 2082 QbeGen.CheckRange(ql, qlo,
|
|
|
|
|
- 2083 qhi);
|
|
|
|
|
- 2084 eT := SymTab.ArrayElem(t);
|
|
|
|
|
- 2085 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
|
|
- 2086 t, qe);
|
|
|
|
|
- 2087 IF SymTab.ClassOf(eT) =
|
|
|
|
|
- 2088 SymTab.ClArray THEN
|
|
|
|
|
- 2089 QbeGen.ElemLoad(qe, eT, q)
|
|
|
|
|
- 2090 ELSE QbeGen.CopyOp(qe, q)
|
|
|
|
|
- 2091 END;
|
|
|
|
|
- 2092 t := eT; sfx := TRUE
|
|
|
|
|
- 2093 END; .)
|
|
|
|
|
- 2094 "]"
|
|
|
|
|
- 2095 | "." GetIdent<fname>
|
|
|
|
|
- 2096 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2097 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
- 2098 SymTab.ClRecord)
|
|
|
|
|
- 2099 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
- 2100 SemError(215);
|
|
|
|
|
- 2101 t := SymTab.InvalidType
|
|
|
|
|
- 2102 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
- 2103 fname) THEN
|
|
|
|
|
- 2104 SemError(216);
|
|
|
|
|
- 2105 t := SymTab.InvalidType
|
|
|
|
|
- 2106 ELSE
|
|
|
|
|
- 2107 fo := SymTab.FieldOffset(t,
|
|
|
|
|
- 2108 fname);
|
|
|
|
|
- 2109 t := SymTab.FieldType(t, fname);
|
|
|
|
|
- 2110 QbeGen.FieldAddr(q, fo, qe);
|
|
|
|
|
- 2111 QbeGen.CopyOp(qe, q);
|
|
|
|
|
- 2112 sfx := TRUE
|
|
|
|
|
- 2113 END; .)
|
|
|
|
|
- 2114 | "^" (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2115 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2116 SymTab.ClPtr THEN
|
|
|
|
|
- 2117 SemError(219);
|
|
|
|
|
- 2118 t := SymTab.InvalidType
|
|
|
|
|
- 2119 ELSE
|
|
|
|
|
- 2120 bt := SymTab.PtrBase(t);
|
|
|
|
|
- 2121 IF bt # SymTab.InvalidType THEN
|
|
|
|
|
- 2122 IF sfx THEN
|
|
|
|
|
- 2123 QbeGen.ElemLoad(q, t, qb);
|
|
|
|
|
- 2124 QbeGen.CopyOp(qb, q)
|
|
|
|
|
- 2125 END;
|
|
|
|
|
- 2126 t := bt; sfx := TRUE
|
|
|
|
|
- 2127 END
|
|
|
|
|
- 2128 END; .) .
|
|
|
|
|
- 2129 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2130 (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
- 2131 op: INTEGER;
|
|
|
|
|
- 2132 q2, qt, wl: QbeGen.QVal;
|
|
|
|
|
- 2133 isR: BOOLEAN; .)
|
|
|
|
|
- 2134 = SimExpr<t, q>
|
|
|
|
|
- 2135 [ Rel<op> SimExpr<t2, q2>
|
|
|
|
|
- 2136 (. IF op = SymTab.OpIn THEN
|
|
|
|
|
- 2137 IF SymTab.InCheck(t, t2) THEN
|
|
|
|
|
- 2138 IF (t = SymTab.InvalidType)
|
|
|
|
|
- 2139 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
- 2140 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2141 ELSE
|
|
|
|
|
- 2142 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
|
|
|
|
|
- 2143 SymTab.SetCount(t2), qt);
|
|
|
|
|
- 2144 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2145 END
|
|
|
|
|
- 2146 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
|
|
- 2147 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2148 END
|
|
|
|
|
- 2149 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
|
|
- 2150 IF (t = SymTab.InvalidType)
|
|
|
|
|
- 2151 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
- 2152 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2153 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
|
|
- 2154 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
|
|
- 2155 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
|
|
- 2156 AND (op # SymTab.OpNeq2) THEN
|
|
|
|
|
- 2157 SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
- 2158 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2159 ELSE
|
|
|
|
|
- 2160 QbeGen.CmpL(op, q, q2, qt);
|
|
|
|
|
- 2161 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2162 END
|
|
|
|
|
- 2163 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
- 2164 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
- 2165 QbeGen.CmpSet(op, q, q2,
|
|
|
|
|
- 2166 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
|
|
|
|
|
- 2167 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2168 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
|
|
- 2169 QbeGen.StrEq(op, q, q2, qt);
|
|
|
|
|
- 2170 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2171 ELSIF SymTab.IsLongFamily(t)
|
|
|
|
|
- 2172 OR SymTab.IsLongFamily(t2) THEN
|
|
|
|
|
- 2173 IF SymTab.IsIntFamily(t) THEN
|
|
|
|
|
- 2174 QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
|
|
|
|
|
- 2175 END;
|
|
|
|
|
- 2176 IF SymTab.IsIntFamily(t2) THEN
|
|
|
|
|
- 2177 QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
|
|
|
|
|
- 2178 END;
|
|
|
|
|
- 2179 QbeGen.CmpLong(op, q, q2, qt);
|
|
|
|
|
- 2180 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2181 ELSE
|
|
|
|
|
- 2182 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
- 2183 t := SymTab.BoolType();
|
|
|
|
|
- 2184 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
|
|
- 2185 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2186 END
|
|
|
|
|
- 2187 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
- 2188 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2189 END; .) ] .
|
|
|
|
|
- 2190 Rel<VAR op: INTEGER>
|
|
|
|
|
- 2191 = "=" (. op := SymTab.OpEq; .)
|
|
|
|
|
- 2192 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
|
|
- 2193 | "<" (. op := SymTab.OpLt; .)
|
|
|
|
|
- 2194 | "<=" (. op := SymTab.OpLe; .)
|
|
|
|
|
- 2195 | ">" (. op := SymTab.OpGt; .)
|
|
|
|
|
- 2196 | ">=" (. op := SymTab.OpGe; .)
|
|
|
|
|
- 2197 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
|
|
- 2198 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2199 (. VAR t2, res2, lt, rt:
|
|
|
|
|
- 2200 SymTab.TypeIndex;
|
|
|
|
|
- 2201 op: INTEGER;
|
|
|
|
|
- 2202 q2, qt, wq, qf, q2a, q2b:
|
|
|
|
|
- 2203 QbeGen.QVal;
|
|
|
|
|
- 2204 neg, isR, isL, folded:
|
|
|
|
|
- 2205 BOOLEAN;
|
|
|
|
|
- 2206 fok: BOOLEAN;
|
|
|
|
|
- 2207 lw, rw, mw: CARDINAL;
|
|
|
|
|
- 2208 lTrue, lNext, lDone, qr, qs:
|
|
|
|
|
- 2209 QbeGen.QVal; .)
|
|
|
|
|
- 2210 = (. neg := FALSE; .)
|
|
|
|
|
- 2211 [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
|
|
- 2212 Term<t, q> (. IF neg THEN
|
|
|
|
|
- 2213 IF QbeGen.IsImm(q) THEN
|
|
|
|
|
- 2214 QbeGen.NegFold(q, q)
|
|
|
|
|
- 2215 ELSE QbeGen.NewTemp(qt);
|
|
|
|
|
- 2216 QbeGen.NegQ(q, qt,
|
|
|
|
|
- 2217 SymTab.ClassOf(t)
|
|
|
|
|
- 2218 = SymTab.ClReal);
|
|
|
|
|
- 2219 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2220 END
|
|
|
|
|
- 2221 END; .)
|
|
|
|
|
- 2222 { AddOp<op> (. IF op = SymTab.OpOr THEN
|
|
|
|
|
- 2223 QbeGen.DelayBegin END; .)
|
|
|
|
|
- 2224 Term<t2, q2> (. IF op = SymTab.OpOr THEN
|
|
|
|
|
- 2225 QbeGen.DelayEnd END; .)
|
|
|
|
|
- 2226 (. IF op = SymTab.OpOr THEN
|
|
|
|
|
- 2227 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
|
|
- 2228 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
- 2229 t := SymTab.BoolType()
|
|
|
|
|
- 2230 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
- 2231 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2232 QbeGen.Slot4(qs);
|
|
|
|
|
- 2233 QbeGen.NewLabel(lTrue);
|
|
|
|
|
- 2234 QbeGen.NewLabel(lNext);
|
|
|
|
|
- 2235 QbeGen.NewLabel(lDone);
|
|
|
|
|
- 2236 QbeGen.Jnz(q, lTrue, lNext);
|
|
|
|
|
- 2237 QbeGen.EmitLabel(lTrue);
|
|
|
|
|
- 2238 QbeGen.StoreW(qs, "1");
|
|
|
|
|
- 2239 QbeGen.Jmp(lDone);
|
|
|
|
|
- 2240 QbeGen.EmitLabel(lNext);
|
|
|
|
|
- 2241 QbeGen.DelayFlush;
|
|
|
|
|
- 2242 QbeGen.StoreW(qs, q2);
|
|
|
|
|
- 2243 QbeGen.Jmp(lDone);
|
|
|
|
|
- 2244 QbeGen.EmitLabel(lDone);
|
|
|
|
|
- 2245 QbeGen.LoadW(qs, qr);
|
|
|
|
|
- 2246 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 2247 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2248 END
|
|
|
|
|
- 2249 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
- 2250 AND (SymTab.UStrCompat(t, t2)
|
|
|
|
|
- 2251 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
- 2252 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
|
|
- 2253 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
|
|
- 2254 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
|
|
- 2255 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
- 2256 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
|
|
- 2257 (* UString concatenation: a UCHAR operand becomes a
|
|
|
|
|
- 2258 1-codepoint UString; the result is a descriptor in the
|
|
|
|
|
- 2259 shim's concat buffer. Work on copies so neither
|
|
|
|
|
- 2260 operand is clobbered. *)
|
|
|
|
|
- 2261 IF SymTab.ClassOf(t) = SymTab.ClUStr THEN
|
|
|
|
|
- 2262 QbeGen.CopyOp(q, q2a)
|
|
|
|
|
- 2263 ELSE
|
|
|
|
|
- 2264 QbeGen.UStrFrom(q, q2a)
|
|
|
|
|
- 2265 END;
|
|
|
|
|
- 2266 IF SymTab.ClassOf(t2) = SymTab.ClUStr THEN
|
|
|
|
|
- 2267 QbeGen.UStrCat(q2a, q2, qt)
|
|
|
|
|
- 2268 ELSE
|
|
|
|
|
- 2269 QbeGen.UStrFrom(q2, q2b);
|
|
|
|
|
- 2270 QbeGen.UStrCat(q2a, q2b, qt)
|
|
|
|
|
- 2271 END;
|
|
|
|
|
- 2272 t := SymTab.NewUStr();
|
|
|
|
|
- 2273 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2274 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
- 2275 AND (SymTab.StrCompat(t, t2)
|
|
|
|
|
- 2276 OR (SymTab.IsStrType(t)
|
|
|
|
|
- 2277 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
|
|
- 2278 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
|
|
- 2279 AND SymTab.IsStrType(t2))) THEN
|
|
|
|
|
- 2280 (* string concatenation; a CHAR operand becomes a
|
|
|
|
|
- 2281 1-character string literal. When both operands are
|
|
|
|
|
- 2282 constants, fold to a single string literal so a
|
|
|
|
|
- 2283 constructor element stays compile-time. *)
|
|
|
|
|
- 2284 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
|
|
- 2285 qt, fok);
|
|
|
|
|
- 2286 IF NOT fok THEN
|
|
|
|
|
- 2287 IF SymTab.StrCompat(t, t2) THEN
|
|
|
|
|
- 2288 QbeGen.StrCat(q, q2, qt)
|
|
|
|
|
- 2289 ELSIF SymTab.IsStrType(t) THEN
|
|
|
|
|
- 2290 QbeGen.DeclCharStr(q2, qs);
|
|
|
|
|
- 2291 QbeGen.StrCat(q, qs, qt)
|
|
|
|
|
- 2292 ELSE
|
|
|
|
|
- 2293 QbeGen.DeclCharStr(q, qs);
|
|
|
|
|
- 2294 QbeGen.StrCat(qs, q2, qt)
|
|
|
|
|
- 2295 END
|
|
|
|
|
- 2296 END;
|
|
|
|
|
- 2297 t := SymTab.NewStr();
|
|
|
|
|
- 2298 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2299 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
- 2300 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
- 2301 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
- 2302 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
- 2303 mw := lw;
|
|
|
|
|
- 2304 IF rw > mw THEN mw := rw END;
|
|
|
|
|
- 2305 IF op = SymTab.OpAdd THEN
|
|
|
|
|
- 2306 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
|
|
|
|
|
- 2307 ELSE
|
|
|
|
|
- 2308 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
|
|
|
|
|
- 2309 END;
|
|
|
|
|
- 2310 t := SymTab.NewSet(
|
|
|
|
|
- 2311 SymTab.NewSubR(0,
|
|
|
|
|
- 2312 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
- 2313 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2314 ELSE
|
|
|
|
|
- 2315 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
|
|
- 2316 lt := t; rt := t2; t := res2
|
|
|
|
|
- 2317 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
- 2318 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2319 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
- 2320 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
- 2321 folded := FALSE;
|
|
|
|
|
- 2322 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
- 2323 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
- 2324 IF op = SymTab.OpAdd THEN
|
|
|
|
|
- 2325 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
|
|
- 2326 ELSE
|
|
|
|
|
- 2327 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
|
|
- 2328 END
|
|
|
|
|
- 2329 END;
|
|
|
|
|
- 2330 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
- 2331 ELSE
|
|
|
|
|
- 2332 IF isL THEN
|
|
|
|
|
- 2333 IF SymTab.IsIntFamily(lt) THEN
|
|
|
|
|
- 2334 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
|
|
- 2335 END;
|
|
|
|
|
- 2336 IF SymTab.IsIntFamily(rt) THEN
|
|
|
|
|
- 2337 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
|
|
- 2338 END;
|
|
|
|
|
- 2339 QbeGen.NewTemp(qt);
|
|
|
|
|
- 2340 IF op = SymTab.OpAdd THEN
|
|
|
|
|
- 2341 QbeGen.Op3L("add", qt, q, q2)
|
|
|
|
|
- 2342 ELSE
|
|
|
|
|
- 2343 QbeGen.Op3L("sub", qt, q, q2)
|
|
|
|
|
- 2344 END
|
|
|
|
|
- 2345 ELSE
|
|
|
|
|
- 2346 QbeGen.NewTemp(qt);
|
|
|
|
|
- 2347 IF op = SymTab.OpAdd THEN
|
|
|
|
|
- 2348 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
|
|
- 2349 ELSE
|
|
|
|
|
- 2350 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
|
|
- 2351 END
|
|
|
|
|
- 2352 END;
|
|
|
|
|
- 2353 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2354 END
|
|
|
|
|
- 2355 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2356 END
|
|
|
|
|
- 2357 END; .) } .
|
|
|
|
|
- 2358 AddOp<VAR op: INTEGER>
|
|
|
|
|
- 2359 = "+" (. op := SymTab.OpAdd; .)
|
|
|
|
|
- 2360 | "-" (. op := SymTab.OpSub; .)
|
|
|
|
|
- 2361 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
|
|
- 2362 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2363 (. VAR t2, res2, lt, rt:
|
|
|
|
|
- 2364 SymTab.TypeIndex;
|
|
|
|
|
- 2365 op: INTEGER;
|
|
|
|
|
- 2366 q2, qt, wq, qf:
|
|
|
|
|
- 2367 QbeGen.QVal;
|
|
|
|
|
- 2368 isR, isL, folded: BOOLEAN;
|
|
|
|
|
- 2369 lw, rw, mw: CARDINAL;
|
|
|
|
|
- 2370 lNext, lFalse, lDone, qr, qs:
|
|
|
|
|
- 2371 QbeGen.QVal; .)
|
|
|
|
|
- 2372 = Fact<t, q> { MulOp<op> (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
- 2373 QbeGen.DelayBegin END; .)
|
|
|
|
|
- 2374 Fact<t2, q2> (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
- 2375 QbeGen.DelayEnd END; .)
|
|
|
|
|
- 2376 (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
- 2377 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
|
|
- 2378 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
- 2379 t := SymTab.BoolType()
|
|
|
|
|
- 2380 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
- 2381 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2382 QbeGen.Slot4(qs);
|
|
|
|
|
- 2383 QbeGen.NewLabel(lNext);
|
|
|
|
|
- 2384 QbeGen.NewLabel(lFalse);
|
|
|
|
|
- 2385 QbeGen.NewLabel(lDone);
|
|
|
|
|
- 2386 QbeGen.Jnz(q, lNext, lFalse);
|
|
|
|
|
- 2387 QbeGen.EmitLabel(lNext);
|
|
|
|
|
- 2388 QbeGen.DelayFlush;
|
|
|
|
|
- 2389 QbeGen.StoreW(qs, q2);
|
|
|
|
|
- 2390 QbeGen.Jmp(lDone);
|
|
|
|
|
- 2391 QbeGen.EmitLabel(lFalse);
|
|
|
|
|
- 2392 QbeGen.StoreW(qs, "0");
|
|
|
|
|
- 2393 QbeGen.Jmp(lDone);
|
|
|
|
|
- 2394 QbeGen.EmitLabel(lDone);
|
|
|
|
|
- 2395 QbeGen.LoadW(qs, qr);
|
|
|
|
|
- 2396 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 2397 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2398 END
|
|
|
|
|
- 2399 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
- 2400 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
- 2401 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
- 2402 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
- 2403 mw := lw;
|
|
|
|
|
- 2404 IF rw > mw THEN mw := rw END;
|
|
|
|
|
- 2405 IF op = SymTab.OpTimes THEN
|
|
|
|
|
- 2406 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
|
|
|
|
|
- 2407 ELSE
|
|
|
|
|
- 2408 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
|
|
|
|
|
- 2409 END;
|
|
|
|
|
- 2410 t := SymTab.NewSet(
|
|
|
|
|
- 2411 SymTab.NewSubR(0,
|
|
|
|
|
- 2412 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
- 2413 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2414 ELSE
|
|
|
|
|
- 2415 IF SymTab.ArithCheck(t, t2,
|
|
|
|
|
- 2416 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
|
|
- 2417 res2) THEN
|
|
|
|
|
- 2418 lt := t; rt := t2; t := res2
|
|
|
|
|
- 2419 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
- 2420 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2421 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
- 2422 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
- 2423 folded := FALSE;
|
|
|
|
|
- 2424 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
- 2425 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
- 2426 IF op = SymTab.OpTimes THEN
|
|
|
|
|
- 2427 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
|
|
- 2428 ELSIF op = SymTab.OpDiv THEN
|
|
|
|
|
- 2429 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
|
|
- 2430 ELSIF op = SymTab.OpMod THEN
|
|
|
|
|
- 2431 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
|
|
- 2432 END
|
|
|
|
|
- 2433 END;
|
|
|
|
|
- 2434 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
- 2435 ELSE
|
|
|
|
|
- 2436 IF isL THEN
|
|
|
|
|
- 2437 IF SymTab.IsIntFamily(lt) THEN
|
|
|
|
|
- 2438 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
|
|
- 2439 END;
|
|
|
|
|
- 2440 IF SymTab.IsIntFamily(rt) THEN
|
|
|
|
|
- 2441 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
|
|
- 2442 END;
|
|
|
|
|
- 2443 QbeGen.NewTemp(qt);
|
|
|
|
|
- 2444 IF op = SymTab.OpTimes THEN
|
|
|
|
|
- 2445 QbeGen.Op3L("mul", qt, q, q2)
|
|
|
|
|
- 2446 ELSIF (op = SymTab.OpDiv)
|
|
|
|
|
- 2447 OR (op = SymTab.OpSlash) THEN
|
|
|
|
|
- 2448 QbeGen.Op3L("div", qt, q, q2)
|
|
|
|
|
- 2449 ELSE
|
|
|
|
|
- 2450 QbeGen.Op3L("rem", qt, q, q2)
|
|
|
|
|
- 2451 END
|
|
|
|
|
- 2452 ELSE
|
|
|
|
|
- 2453 QbeGen.NewTemp(qt);
|
|
|
|
|
- 2454 IF op = SymTab.OpTimes THEN
|
|
|
|
|
- 2455 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
|
|
- 2456 ELSIF (op = SymTab.OpDiv)
|
|
|
|
|
- 2457 OR (op = SymTab.OpSlash) THEN
|
|
|
|
|
- 2458 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
|
|
- 2459 ELSE
|
|
|
|
|
- 2460 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
|
|
- 2461 END
|
|
|
|
|
- 2462 END;
|
|
|
|
|
- 2463 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2464 END
|
|
|
|
|
- 2465 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2466 END
|
|
|
|
|
- 2467 END; .) } .
|
|
|
|
|
- 2468 MulOp<VAR op: INTEGER>
|
|
|
|
|
- 2469 = "*" (. op := SymTab.OpTimes; .)
|
|
|
|
|
- 2470 | "/" (. op := SymTab.OpSlash; .)
|
|
|
|
|
- 2471 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
|
|
- 2472 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
|
|
- 2473 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
|
|
- 2474 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2475 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
|
|
- 2476 et, dt, t2, st, ct2, et2:
|
|
|
|
|
- 2477 SymTab.TypeIndex;
|
|
|
|
|
- 2478 dk: INTEGER;
|
|
|
|
|
- 2479 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
|
|
- 2480 QbeGen.QVal;
|
|
|
|
|
- 2481 qn, vn: SymTab.Name;
|
|
|
|
|
- 2482 vt: SymTab.TypeIndex;
|
|
|
|
|
- 2483 c1, c2: INTEGER;
|
|
|
|
|
- 2484 lo, hi: INTEGER;
|
|
|
|
|
- 2485 isMax: BOOLEAN;
|
|
|
|
|
- 2486 called, isHigh, sfx, isCh,
|
|
|
|
|
- 2487 isU, uok, isStr: BOOLEAN;
|
|
|
|
|
- 2488 ucp: INTEGER; .)
|
|
|
|
|
- 2489 = integer (. LexString(s);
|
|
|
|
|
- 2490 QbeGen.NormInt(s, q);
|
|
|
|
|
- 2491 t := SymTab.IntType(); .)
|
|
|
|
|
- 2492 | charConst (. LexString(s);
|
|
|
|
|
- 2493 QbeGen.NormLit(s, q, isCh);
|
|
|
|
|
- 2494 t := SymTab.CharType(); .)
|
|
|
|
|
- 2495 | real (. LexString(s);
|
|
|
|
|
- 2496 QbeGen.NormReal(s, q);
|
|
|
|
|
- 2497 t := SymTab.RealType(); .)
|
|
|
|
|
- 2498 | string (. LexString(s);
|
|
|
|
|
- 2499 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
- 2500 t := SymTab.CharType();
|
|
|
|
|
- 2501 QbeGen.IntStr(
|
|
|
|
|
- 2502 QbeGen.CharVal(s), q)
|
|
|
|
|
- 2503 ELSE t := SymTab.NewStr();
|
|
|
|
|
- 2504 QbeGen.DeclStr(s, q);
|
|
|
|
|
- 2505 (* a literal's value IS its
|
|
|
|
|
- 2506 static descriptor address *)
|
|
|
|
|
- 2507 QbeGen.NoteAddr(q, q)
|
|
|
|
|
- 2508 END; .)
|
|
|
|
|
- 2509 | ustring (. LexString(s);
|
|
|
|
|
- 2510 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
|
|
- 2511 uok);
|
|
|
|
|
- 2512 IF NOT uok THEN
|
|
|
|
|
- 2513 SemError(234);
|
|
|
|
|
- 2514 t := SymTab.InvalidType
|
|
|
|
|
- 2515 ELSIF isU THEN
|
|
|
|
|
- 2516 t := SymTab.UCharType();
|
|
|
|
|
- 2517 QbeGen.IntStr(ucp, q)
|
|
|
|
|
- 2518 ELSE
|
|
|
|
|
- 2519 t := SymTab.NewUStr();
|
|
|
|
|
- 2520 QbeGen.NoteAddr(q, q)
|
|
|
|
|
- 2521 END; .)
|
|
|
|
|
- 2522 | Design<dt, dk, qd, qn, sfx> (. called := FALSE;
|
|
|
|
|
- 2523 t := dt;
|
|
|
|
|
- 2524 IF sfx THEN
|
|
|
|
|
- 2525 IF dt =
|
|
|
|
|
- 2526 SymTab.InvalidType THEN
|
|
|
|
|
- 2527 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2528 ELSIF (SymTab.ClassOf(dt) =
|
|
|
|
|
- 2529 SymTab.ClRecord)
|
|
|
|
|
- 2530 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
- 2531 SymTab.ClSet)
|
|
|
|
|
- 2532 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
- 2533 SymTab.ClArray)
|
|
|
|
|
- 2534 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
- 2535 SymTab.ClClass) THEN
|
|
|
|
|
- 2536 QbeGen.CopyOp(qd, q)
|
|
|
|
|
- 2537 ELSE QbeGen.ElemLoad(qd, dt,
|
|
|
|
|
- 2538 q)
|
|
|
|
|
- 2539 END
|
|
|
|
|
- 2540 ELSE QbeGen.CopyOp(qd, q)
|
|
|
|
|
- 2541 END;
|
|
|
|
|
- 2542 IF (dk = SymTab.KindVar)
|
|
|
|
|
- 2543 OR (dk = SymTab.KindParam)
|
|
|
|
|
- 2544 OR (dk =
|
|
|
|
|
- 2545 SymTab.KindField) THEN
|
|
|
|
|
- 2546 IF sfx THEN
|
|
|
|
|
- 2547 QbeGen.NoteAddr(q, qd)
|
|
|
|
|
- 2548 ELSE
|
|
|
|
|
- 2549 QbeGen.AddrOf(qn, qa);
|
|
|
|
|
- 2550 QbeGen.NoteAddr(q, qa)
|
|
|
|
|
- 2551 END
|
|
|
|
|
- 2552 ELSIF sfx
|
|
|
|
|
- 2553 AND (dt #
|
|
|
|
|
- 2554 SymTab.InvalidType)
|
|
|
|
|
- 2555 AND ((SymTab.ClassOf(dt) =
|
|
|
|
|
- 2556 SymTab.ClArray)
|
|
|
|
|
- 2557 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
- 2558 SymTab.ClSet)
|
|
|
|
|
- 2559 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
- 2560 SymTab.ClRecord)) THEN
|
|
|
|
|
- 2561 QbeGen.NoteAddr(qd, qd)
|
|
|
|
|
- 2562 END; .)
|
|
|
|
|
- 2563 [ TypedBraceLit<dt, q> (. t := dt; .) ]
|
|
|
|
|
- 2564 [ ArgList<qn, dt, qd, TRUE, methCls, ct2, q2, called>
|
|
|
|
|
- 2565 (. t := ct2;
|
|
|
|
|
- 2566 QbeGen.CopyOp(q2, q);
|
|
|
|
|
- 2567 sfx := FALSE; .)
|
|
|
|
|
- 2568 { ResultComp<t, q, sfx> }
|
|
|
|
|
- 2569 (. IF sfx THEN
|
|
|
|
|
- 2570 IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2571 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2572 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
- 2573 SymTab.ClRecord)
|
|
|
|
|
- 2574 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
|
|
- 2575 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
|
|
- 2576 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
- 2577 QbeGen.ElemLoad(q, t, q2);
|
|
|
|
|
- 2578 QbeGen.CopyOp(q2, q)
|
|
|
|
|
- 2579 END
|
|
|
|
|
- 2580 END; .) ]
|
|
|
|
|
- 2581 (. IF NOT called
|
|
|
|
|
- 2582 AND (dk = SymTab.KindProc) THEN
|
|
|
|
|
- 2583 (* bare zero-arg function
|
|
|
|
|
- 2584 call (parentheses may be
|
|
|
|
|
- 2585 omitted); a proper or
|
|
|
|
|
- 2586 parameterised proc here
|
|
|
|
|
- 2587 is 230 *)
|
|
|
|
|
- 2588 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
|
|
- 2589 AND (SymTab.ProcRes(qn) #
|
|
|
|
|
- 2590 SymTab.InvalidType) THEN
|
|
|
|
|
- 2591 QbeGen.Mangled(qn,
|
|
|
|
|
- 2592 SymTab.ProcUid(qn), qm0);
|
|
|
|
|
- 2593 QbeGen.CallBegin(qm0,
|
|
|
|
|
- 2594 SymTab.ProcRes(qn),
|
|
|
|
|
- 2595 SymTab.ProcDepthOf(qn),
|
|
|
|
|
- 2596 SymTab.IsExternal(qn));
|
|
|
|
|
- 2597 QbeGen.CallEnd(TRUE, q);
|
|
|
|
|
- 2598 t := SymTab.ProcRes(qn)
|
|
|
|
|
- 2599 ELSE
|
|
|
|
|
- 2600 (* procedure used as a
|
|
|
|
|
- 2601 value (assign to a
|
|
|
|
|
- 2602 procedure variable):
|
|
|
|
|
- 2603 its code address *)
|
|
|
|
|
- 2604 t := SymTab.ProcTypeOf(qn);
|
|
|
|
|
- 2605 QbeGen.Mangled(qn,
|
|
|
|
|
- 2606 SymTab.ProcUid(qn), qm0);
|
|
|
|
|
- 2607 QbeGen.ProcAddr(qm0, q)
|
|
|
|
|
- 2608 END
|
|
|
|
|
- 2609 END; .)
|
|
|
|
|
- 2610 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
|
|
- 2611 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
|
|
- 2612 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
|
|
- 2613 isU := FALSE; .)
|
|
|
|
|
- 2614 | string (. LexString(s);
|
|
|
|
|
- 2615 isStr := TRUE;
|
|
|
|
|
- 2616 isU := FALSE;
|
|
|
|
|
- 2617 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
- 2618 dt := SymTab.CharType();
|
|
|
|
|
- 2619 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
|
|
- 2620 qd)
|
|
|
|
|
- 2621 ELSE
|
|
|
|
|
- 2622 dt := SymTab.NewStr();
|
|
|
|
|
- 2623 QbeGen.DeclStr(s, qd);
|
|
|
|
|
- 2624 QbeGen.NoteAddr(qd, qd)
|
|
|
|
|
- 2625 END;
|
|
|
|
|
- 2626 dk := -1;
|
|
|
|
|
- 2627 qn[0] := CHR(0); .)
|
|
|
|
|
- 2628 | ustring (. LexString(s);
|
|
|
|
|
- 2629 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
|
|
- 2630 uok);
|
|
|
|
|
- 2631 isStr := FALSE;
|
|
|
|
|
- 2632 IF NOT uok THEN
|
|
|
|
|
- 2633 SemError(234);
|
|
|
|
|
- 2634 dt := SymTab.InvalidType
|
|
|
|
|
- 2635 ELSIF isU THEN
|
|
|
|
|
- 2636 (* one codepoint: a UCHAR;
|
|
|
|
|
- 2637 LEN is 1, HIGH is 0 *)
|
|
|
|
|
- 2638 dt := SymTab.UCharType();
|
|
|
|
|
- 2639 QbeGen.IntStr(ucp, qd)
|
|
|
|
|
- 2640 ELSE
|
|
|
|
|
- 2641 dt := SymTab.NewUStr();
|
|
|
|
|
- 2642 QbeGen.NoteAddr(qd, qd)
|
|
|
|
|
- 2643 END;
|
|
|
|
|
- 2644 dk := -1;
|
|
|
|
|
- 2645 qn[0] := CHR(0); .) )
|
|
|
|
|
- 2646 ")"
|
|
|
|
|
- 2647 (. IF (dt # SymTab.InvalidType)
|
|
|
|
|
- 2648 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
|
|
- 2649 (* UString: the count is
|
|
|
|
|
- 2650 the descriptor header *)
|
|
|
|
|
- 2651 IF isHigh THEN
|
|
|
|
|
- 2652 QbeGen.UStrLen(qd, qr);
|
|
|
|
|
- 2653 QbeGen.DecQ(qr)
|
|
|
|
|
- 2654 ELSE
|
|
|
|
|
- 2655 QbeGen.UStrLen(qd, qr)
|
|
|
|
|
- 2656 END;
|
|
|
|
|
- 2657 t := SymTab.IntType();
|
|
|
|
|
- 2658 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 2659 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
- 2660 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
|
|
- 2661 (* single UCHAR codepoint *)
|
|
|
|
|
- 2662 IF isHigh THEN
|
|
|
|
|
- 2663 QbeGen.CopyOp("0", qr)
|
|
|
|
|
- 2664 ELSE
|
|
|
|
|
- 2665 QbeGen.CopyOp("1", qr)
|
|
|
|
|
- 2666 END;
|
|
|
|
|
- 2667 t := SymTab.IntType();
|
|
|
|
|
- 2668 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 2669 ELSIF isStr THEN
|
|
|
|
|
- 2670 (* fold: content length at
|
|
|
|
|
- 2671 compile time *)
|
|
|
|
|
- 2672 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
- 2673 c1 := 1
|
|
|
|
|
- 2674 ELSE
|
|
|
|
|
- 2675 c1 :=
|
|
|
|
|
- 2676 SymTab.StrLen(s) - 2
|
|
|
|
|
- 2677 END;
|
|
|
|
|
- 2678 IF isHigh THEN
|
|
|
|
|
- 2679 DEC(c1)
|
|
|
|
|
- 2680 END;
|
|
|
|
|
- 2681 QbeGen.IntStr(c1, qr);
|
|
|
|
|
- 2682 t := SymTab.IntType();
|
|
|
|
|
- 2683 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 2684 ELSIF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 2685 t := SymTab.InvalidType;
|
|
|
|
|
- 2686 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2687 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
- 2688 SymTab.ClArray THEN
|
|
|
|
|
- 2689 SemError(217);
|
|
|
|
|
- 2690 t := SymTab.InvalidType;
|
|
|
|
|
- 2691 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2692 ELSE
|
|
|
|
|
- 2693 IF isHigh THEN
|
|
|
|
|
- 2694 IF SymTab.IsOpenArray(dt) THEN
|
|
|
|
|
- 2695 QbeGen.OpenHi(qd, qr)
|
|
|
|
|
- 2696 ELSE
|
|
|
|
|
- 2697 QbeGen.IntStr(
|
|
|
|
|
- 2698 SymTab.ArrayHi(dt), qr)
|
|
|
|
|
- 2699 END
|
|
|
|
|
- 2700 ELSE
|
|
|
|
|
- 2701 IF SymTab.IsOpenArray(dt) THEN
|
|
|
|
|
- 2702 QbeGen.LoadCount(qd, qr)
|
|
|
|
|
- 2703 ELSE
|
|
|
|
|
- 2704 QbeGen.IntStr(VAL(
|
|
|
|
|
- 2705 INTEGER,
|
|
|
|
|
- 2706 SymTab.ArrayLen(dt)),
|
|
|
|
|
- 2707 qr)
|
|
|
|
|
- 2708 END
|
|
|
|
|
- 2709 END;
|
|
|
|
|
- 2710 t := SymTab.IntType();
|
|
|
|
|
- 2711 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 2712 END; .)
|
|
|
|
|
- 2713 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 2714 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 2715 t := SymTab.InvalidType;
|
|
|
|
|
- 2716 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2717 ELSE
|
|
|
|
|
- 2718 QbeGen.IntStr(VAL(INTEGER,
|
|
|
|
|
- 2719 SymTab.ObjectSize(dt)), q);
|
|
|
|
|
- 2720 t := SymTab.IntType()
|
|
|
|
|
- 2721 END; .)
|
|
|
|
|
- 2722 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
|
|
- 2723 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
|
|
- 2724 "(" Expr<et, q> "," Expr<et2, q2> ")"
|
|
|
|
|
- 2725 (. (* set shift/rotate: isMax
|
|
|
|
|
- 2726 doubles as "rotate" *)
|
|
|
|
|
- 2727 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 2728 AND (SymTab.ClassOf(et) =
|
|
|
|
|
- 2729 SymTab.ClSet) THEN
|
|
|
|
|
- 2730 QbeGen.SetShift(q, q2,
|
|
|
|
|
- 2731 SymTab.SetWords(et),
|
|
|
|
|
- 2732 SymTab.SetCount(et), isMax,
|
|
|
|
|
- 2733 qt);
|
|
|
|
|
- 2734 t := et;
|
|
|
|
|
- 2735 QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2736 ELSE SemError(230);
|
|
|
|
|
- 2737 t := SymTab.InvalidType;
|
|
|
|
|
- 2738 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2739 END; .)
|
|
|
|
|
- 2740 | ( "MIN" (. isMax := FALSE; .)
|
|
|
|
|
- 2741 | "MAX" (. isMax := TRUE; .) )
|
|
|
|
|
- 2742 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 2743 (. IF (dt # SymTab.InvalidType)
|
|
|
|
|
- 2744 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
|
|
- 2745 (* REAL/LONGREAL: the
|
|
|
|
|
- 2746 implementation bounds *)
|
|
|
|
|
- 2747 IF isMax THEN
|
|
|
|
|
- 2748 QbeGen.NormReal(
|
|
|
|
|
- 2749 "3.402823e38", q)
|
|
|
|
|
- 2750 ELSE QbeGen.NormReal(
|
|
|
|
|
- 2751 "-3.402823e38", q)
|
|
|
|
|
- 2752 END;
|
|
|
|
|
- 2753 t := SymTab.RealType()
|
|
|
|
|
- 2754 ELSIF (dt #
|
|
|
|
|
- 2755 SymTab.InvalidType)
|
|
|
|
|
- 2756 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
- 2757 SymTab.ClLong) THEN
|
|
|
|
|
- 2758 IF isMax THEN
|
|
|
|
|
- 2759 QbeGen.CopyOp(
|
|
|
|
|
- 2760 "9223372036854775807", q)
|
|
|
|
|
- 2761 ELSE QbeGen.CopyOp(
|
|
|
|
|
- 2762 "-9223372036854775808", q)
|
|
|
|
|
- 2763 END;
|
|
|
|
|
- 2764 t := SymTab.LongType()
|
|
|
|
|
- 2765 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
|
|
- 2766 hi) THEN
|
|
|
|
|
- 2767 IF isMax THEN
|
|
|
|
|
- 2768 QbeGen.IntStr(hi, q)
|
|
|
|
|
- 2769 ELSE QbeGen.IntStr(lo, q)
|
|
|
|
|
- 2770 END;
|
|
|
|
|
- 2771 t := SymTab.IntType()
|
|
|
|
|
- 2772 ELSE SemError(230);
|
|
|
|
|
- 2773 t := SymTab.InvalidType;
|
|
|
|
|
- 2774 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2775 END; .)
|
|
|
|
|
- 2776 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 2777 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 2778 t := SymTab.InvalidType;
|
|
|
|
|
- 2779 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2780 ELSE
|
|
|
|
|
- 2781 IF sfx THEN
|
|
|
|
|
- 2782 QbeGen.CopyOp(qd, q)
|
|
|
|
|
- 2783 ELSIF (dk = SymTab.KindVar)
|
|
|
|
|
- 2784 OR (dk = SymTab.KindParam) THEN
|
|
|
|
|
- 2785 QbeGen.AddrOf(qn, q)
|
|
|
|
|
- 2786 ELSE SemError(230);
|
|
|
|
|
- 2787 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2788 END;
|
|
|
|
|
- 2789 t := SymTab.AddrType()
|
|
|
|
|
- 2790 END; .)
|
|
|
|
|
- 2791 | "CHR" "(" Expr<et, q> ")"
|
|
|
|
|
- 2792 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
- 2793 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
- 2794 SemError(211) END;
|
|
|
|
|
- 2795 t := SymTab.CharType(); .)
|
|
|
|
|
- 2796 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
|
|
- 2797 (. IF et # SymTab.InvalidType THEN
|
|
|
|
|
- 2798 IF (SymTab.ClassOf(et) #
|
|
|
|
|
- 2799 SymTab.ClChar)
|
|
|
|
|
- 2800 AND (SymTab.ClassOf(et) #
|
|
|
|
|
- 2801 SymTab.ClBool)
|
|
|
|
|
- 2802 AND (SymTab.ClassOf(et) #
|
|
|
|
|
- 2803 SymTab.ClEnum)
|
|
|
|
|
- 2804 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
- 2805 SemError(211) END
|
|
|
|
|
- 2806 END;
|
|
|
|
|
- 2807 t := SymTab.IntType(); .)
|
|
|
|
|
- 2808 | "CAP" "(" Expr<et, q> ")"
|
|
|
|
|
- 2809 (. QbeGen.CapQ(q, qa);
|
|
|
|
|
- 2810 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 2811 t := SymTab.CharType(); .)
|
|
|
|
|
- 2812 | "UCHR" "(" Expr<et, q> ")"
|
|
|
|
|
- 2813 (. (* UCHR: the UCHAR constructor.
|
|
|
|
|
- 2814 CHAR -> UCHAR (identity);
|
|
|
|
|
- 2815 INTEGER familly -> UCHAR
|
|
|
|
|
- 2816 (codepoint value). *)
|
|
|
|
|
- 2817 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 2818 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
|
|
- 2819 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
- 2820 SemError(211) END;
|
|
|
|
|
- 2821 t := SymTab.UCharType(); .)
|
|
|
|
|
- 2822 | "CHR8" "(" Expr<et, q> ")"
|
|
|
|
|
- 2823 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
- 2824 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
- 2825 SemError(211) END;
|
|
|
|
|
- 2826 QbeGen.WidenLong(q, qa);
|
|
|
|
|
- 2827 QbeGen.CheckRange(qa, "0", "255");
|
|
|
|
|
- 2828 t := SymTab.CharType(); .)
|
|
|
|
|
- 2829 | "UORD" "(" Expr<et, q> ")"
|
|
|
|
|
- 2830 (. (* UORD(u): the codepoint as a
|
|
|
|
|
- 2831 32-bit ordinal (INTEGER),
|
|
|
|
|
- 2832 cf. ORD for CHAR. *)
|
|
|
|
|
- 2833 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 2834 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
- 2835 SemError(211) END;
|
|
|
|
|
- 2836 t := SymTab.IntType(); .)
|
|
|
|
|
- 2837 | "ABS" "(" Expr<et, q> ")"
|
|
|
|
|
- 2838 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
- 2839 AND NOT SymTab.IsIntFamily(et)
|
|
|
|
|
- 2840 AND (SymTab.ClassOf(et) #
|
|
|
|
|
- 2841 SymTab.ClReal) THEN
|
|
|
|
|
- 2842 SemError(211)
|
|
|
|
|
- 2843 ELSE QbeGen.AbsQ(q, qa,
|
|
|
|
|
- 2844 SymTab.ClassOf(et) =
|
|
|
|
|
- 2845 SymTab.ClReal);
|
|
|
|
|
- 2846 QbeGen.CopyOp(qa, q)
|
|
|
|
|
- 2847 END;
|
|
|
|
|
- 2848 t := et; .)
|
|
|
|
|
- 2849 | "VAL" "(" GetIdent<vn> "," Expr<et, q> ")"
|
|
|
|
|
- 2850 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
|
|
- 2851 SemError(201);
|
|
|
|
|
- 2852 t := SymTab.InvalidType
|
|
|
|
|
- 2853 ELSE vt := SymTab.SymType(vn);
|
|
|
|
|
- 2854 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
- 2855 t := SymTab.InvalidType
|
|
|
|
|
- 2856 ELSIF et =
|
|
|
|
|
- 2857 SymTab.InvalidType THEN
|
|
|
|
|
- 2858 t := vt
|
|
|
|
|
- 2859 ELSE
|
|
|
|
|
- 2860 c1 := SymTab.ClassOf(et);
|
|
|
|
|
- 2861 c2 := SymTab.ClassOf(vt);
|
|
|
|
|
- 2862 IF (c1 = SymTab.ClInt)
|
|
|
|
|
- 2863 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
- 2864 QbeGen.WidenLong(q, qa);
|
|
|
|
|
- 2865 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 2866 t := vt
|
|
|
|
|
- 2867 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
- 2868 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
- 2869 QbeGen.NarrowLong(q, qa);
|
|
|
|
|
- 2870 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 2871 t := vt
|
|
|
|
|
- 2872 ELSIF (c1 = SymTab.ClInt)
|
|
|
|
|
- 2873 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
- 2874 QbeGen.ConvIR(q, qa);
|
|
|
|
|
- 2875 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 2876 t := vt
|
|
|
|
|
- 2877 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
- 2878 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
- 2879 QbeGen.ConvLR(q, qa);
|
|
|
|
|
- 2880 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 2881 t := vt
|
|
|
|
|
- 2882 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
- 2883 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
- 2884 QbeGen.ConvRI(q, qa);
|
|
|
|
|
- 2885 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 2886 t := vt
|
|
|
|
|
- 2887 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
- 2888 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
- 2889 QbeGen.ConvRL(q, qa);
|
|
|
|
|
- 2890 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 2891 t := vt
|
|
|
|
|
- 2892 ELSIF ((c1 = SymTab.ClInt)
|
|
|
|
|
- 2893 OR (c1 =
|
|
|
|
|
- 2894 SymTab.ClChar)
|
|
|
|
|
- 2895 OR (c1 =
|
|
|
|
|
- 2896 SymTab.ClBool)
|
|
|
|
|
- 2897 OR (c1 =
|
|
|
|
|
- 2898 SymTab.ClEnum))
|
|
|
|
|
- 2899 AND ((c2 = SymTab.ClInt)
|
|
|
|
|
- 2900 OR (c2 =
|
|
|
|
|
- 2901 SymTab.ClChar)
|
|
|
|
|
- 2902 OR (c2 =
|
|
|
|
|
- 2903 SymTab.ClBool)
|
|
|
|
|
- 2904 OR (c2 =
|
|
|
|
|
- 2905 SymTab.ClEnum)) THEN
|
|
|
|
|
- 2906 t := vt
|
|
|
|
|
- 2907 ELSIF (c1 = SymTab.ClPtr)
|
|
|
|
|
- 2908 AND (c2 = SymTab.ClPtr) THEN
|
|
|
|
|
- 2909 t := vt
|
|
|
|
|
- 2910 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
- 2911 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
- 2912 t := vt
|
|
|
|
|
- 2913 ELSE SemError(230);
|
|
|
|
|
- 2914 t := SymTab.InvalidType
|
|
|
|
|
- 2915 END
|
|
|
|
|
- 2916 END
|
|
|
|
|
- 2917 END; .)
|
|
|
|
|
- 2918 | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
|
|
- 2919 | SetLit<st, sq> (. t := st;
|
|
|
|
|
- 2920 QbeGen.CopyOp(sq, q); .)
|
|
|
|
|
- 2921 | ( "NOT" | "~" ) Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
|
|
- 2922 t := SymTab.BoolType()
|
|
|
|
|
- 2923 ELSE SemError(212);
|
|
|
|
|
- 2924 t := SymTab.InvalidType END;
|
|
|
|
|
- 2925 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2926 QbeGen.NotQ(q2, q)
|
|
|
|
|
- 2927 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2928 END; .) .
|
|
|
|
|
- 2929 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
|
|
- 2930 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
|
|
- 2931 for computed elements. Ranges always lower via SetRange. *)
|
|
|
|
|
- 2932 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2933 = "{" (. t := SymTab.NewSet(
|
|
|
|
|
- 2934 SymTab.NewSubR(0, 255));
|
|
|
|
|
- 2935 QbeGen.NewSetTemp(8, q);
|
|
|
|
|
- 2936 QbeGen.SetZero(q, 8); .)
|
|
|
|
|
- 2937 [ SetElem<t, q> { "," SetElem<t, q> } ]
|
|
|
|
|
- 2938 "}" .
|
|
|
|
|
- 2939 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
|
|
- 2940 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
|
|
- 2941 declared type sets the width (set) or element type (array). *)
|
|
|
|
|
- 2942 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2943 (. VAR nw: CARDINAL;
|
|
|
|
|
- 2944 savedCls: INTEGER; .)
|
|
|
|
|
- 2945 = "{" (. savedCls := braceCls;
|
|
|
|
|
- 2946 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
- 2947 braceCls := -1
|
|
|
|
|
- 2948 ELSE braceCls :=
|
|
|
|
|
- 2949 SymTab.ClassOf(vt)
|
|
|
|
|
- 2950 END;
|
|
|
|
|
- 2951 IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
- 2952 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
- 2953 nw := 8
|
|
|
|
|
- 2954 ELSE nw := SymTab.SetWords(vt);
|
|
|
|
|
- 2955 IF nw = 0 THEN nw := 8 END
|
|
|
|
|
- 2956 END;
|
|
|
|
|
- 2957 QbeGen.NewSetTemp(nw, q);
|
|
|
|
|
- 2958 QbeGen.SetZero(q, nw)
|
|
|
|
|
- 2959 ELSIF (braceCls =
|
|
|
|
|
- 2960 SymTab.ClArray)
|
|
|
|
|
- 2961 OR (braceCls =
|
|
|
|
|
- 2962 SymTab.ClRecord)
|
|
|
|
|
- 2963 OR (braceCls =
|
|
|
|
|
- 2964 SymTab.ClClass) THEN
|
|
|
|
|
- 2965 QbeGen.CtorBegin(vt)
|
|
|
|
|
- 2966 ELSE
|
|
|
|
|
- 2967 IF vt # SymTab.InvalidType THEN
|
|
|
|
|
- 2968 SemError(230) END;
|
|
|
|
|
- 2969 braceCls := -1
|
|
|
|
|
- 2970 END; .)
|
|
|
|
|
- 2971 [ BraceElem<vt, q> { "," BraceElem<vt, q> } ]
|
|
|
|
|
- 2972 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
|
|
- 2973 OR (braceCls =
|
|
|
|
|
- 2974 SymTab.ClRecord)
|
|
|
|
|
- 2975 OR (braceCls =
|
|
|
|
|
- 2976 SymTab.ClClass) THEN
|
|
|
|
|
- 2977 QbeGen.CtorEnd(q)
|
|
|
|
|
- 2978 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
|
|
- 2979 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2980 END;
|
|
|
|
|
- 2981 braceCls := savedCls; .) .
|
|
|
|
|
- 2982 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal>
|
|
|
|
|
- 2983 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
- 2984 qe, q2: QbeGen.QVal;
|
|
|
|
|
- 2985 v, v2, reps, k: INTEGER;
|
|
|
|
|
- 2986 elem: SymTab.TypeIndex;
|
|
|
|
|
- 2987 lo: INTEGER;
|
|
|
|
|
- 2988 span: CARDINAL;
|
|
|
|
|
- 2989 cl, cl2: INTEGER;
|
|
|
|
|
- 2990 hasR, hasB: BOOLEAN; .)
|
|
|
|
|
- 2991 = (. hasR := FALSE; hasB := FALSE; .)
|
|
|
|
|
- 2992 Expr<et, qe>
|
|
|
|
|
- 2993 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
|
|
- 2994 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
|
|
- 2995 (. IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
- 2996 IF hasB THEN SemError(230) END;
|
|
|
|
|
- 2997 lo := SymTab.SetBaseLo(vt);
|
|
|
|
|
- 2998 span := SymTab.SetCount(vt);
|
|
|
|
|
- 2999 IF (et = SymTab.InvalidType)
|
|
|
|
|
- 3000 OR (hasR AND (et2 =
|
|
|
|
|
- 3001 SymTab.InvalidType)) THEN
|
|
|
|
|
- 3002 ELSE cl :=
|
|
|
|
|
- 3003 SymTab.ClassOf(et);
|
|
|
|
|
- 3004 IF hasR THEN
|
|
|
|
|
- 3005 cl2 :=
|
|
|
|
|
- 3006 SymTab.ClassOf(et2)
|
|
|
|
|
- 3007 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
- 3008 END;
|
|
|
|
|
- 3009 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
- 3010 OR (hasR AND NOT
|
|
|
|
|
- 3011 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
- 3012 THEN
|
|
|
|
|
- 3013 SemError(222)
|
|
|
|
|
- 3014 ELSIF hasR
|
|
|
|
|
- 3015 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
- 3016 AND SymTab.ConstInt(q2,
|
|
|
|
|
- 3017 v2)
|
|
|
|
|
- 3018 AND ((v < lo)
|
|
|
|
|
- 3019 OR (v2 < lo)
|
|
|
|
|
- 3020 OR (v >= lo +
|
|
|
|
|
- 3021 VAL(INTEGER, span))
|
|
|
|
|
- 3022 OR (v2 >= lo +
|
|
|
|
|
- 3023 VAL(INTEGER, span))
|
|
|
|
|
- 3024 OR (v > v2)) THEN
|
|
|
|
|
- 3025 SemError(222)
|
|
|
|
|
- 3026 ELSIF hasR THEN
|
|
|
|
|
- 3027 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
- 3028 lo, span)
|
|
|
|
|
- 3029 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
- 3030 v)
|
|
|
|
|
- 3031 AND ((v < lo)
|
|
|
|
|
- 3032 OR (v >= lo +
|
|
|
|
|
- 3033 VAL(INTEGER,
|
|
|
|
|
- 3034 span))) THEN
|
|
|
|
|
- 3035 SemError(222)
|
|
|
|
|
- 3036 ELSE QbeGen.SetBit(sq, qe,
|
|
|
|
|
- 3037 lo, span)
|
|
|
|
|
- 3038 END
|
|
|
|
|
- 3039 END
|
|
|
|
|
- 3040 ELSIF (braceCls = SymTab.ClArray)
|
|
|
|
|
- 3041 OR (braceCls =
|
|
|
|
|
- 3042 SymTab.ClRecord)
|
|
|
|
|
- 3043 OR (braceCls =
|
|
|
|
|
- 3044 SymTab.ClClass) THEN
|
|
|
|
|
- 3045 IF hasR THEN SemError(230) END;
|
|
|
|
|
- 3046 reps := 1;
|
|
|
|
|
- 3047 IF hasB THEN
|
|
|
|
|
- 3048 IF SymTab.ConstInt(q2, v2)
|
|
|
|
|
- 3049 AND (v2 >= 1) THEN
|
|
|
|
|
- 3050 reps := v2
|
|
|
|
|
- 3051 ELSE SemError(230)
|
|
|
|
|
- 3052 END
|
|
|
|
|
- 3053 END;
|
|
|
|
|
- 3054 k := 0;
|
|
|
|
|
- 3055 WHILE k < reps DO
|
|
|
|
|
- 3056 QbeGen.CtorElem(qe);
|
|
|
|
|
- 3057 INC(k)
|
|
|
|
|
- 3058 END
|
|
|
|
|
- 3059 END; .) .
|
|
|
|
|
- 3060 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
- 3061 qe, q2: QbeGen.QVal;
|
|
|
|
|
- 3062 v, v2: INTEGER;
|
|
|
|
|
- 3063 lo: INTEGER;
|
|
|
|
|
- 3064 span: CARDINAL;
|
|
|
|
|
- 3065 cl, cl2: INTEGER;
|
|
|
|
|
- 3066 hasR: BOOLEAN; .)
|
|
|
|
|
- 3067 = (. hasR := FALSE; .)
|
|
|
|
|
- 3068 Expr<et, qe>
|
|
|
|
|
- 3069 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
|
|
- 3070 (. lo := SymTab.SetBaseLo(st);
|
|
|
|
|
- 3071 span := SymTab.SetCount(st);
|
|
|
|
|
- 3072 IF (et = SymTab.InvalidType)
|
|
|
|
|
- 3073 OR (hasR AND (et2 =
|
|
|
|
|
- 3074 SymTab.InvalidType)) THEN
|
|
|
|
|
- 3075 ELSE cl :=
|
|
|
|
|
- 3076 SymTab.ClassOf(et);
|
|
|
|
|
- 3077 IF hasR THEN
|
|
|
|
|
- 3078 cl2 :=
|
|
|
|
|
- 3079 SymTab.ClassOf(et2)
|
|
|
|
|
- 3080 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
- 3081 END;
|
|
|
|
|
- 3082 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
- 3083 OR (hasR AND NOT
|
|
|
|
|
- 3084 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
- 3085 THEN
|
|
|
|
|
- 3086 SemError(222)
|
|
|
|
|
- 3087 ELSIF hasR
|
|
|
|
|
- 3088 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
- 3089 AND SymTab.ConstInt(q2,
|
|
|
|
|
- 3090 v2)
|
|
|
|
|
- 3091 AND ((v < lo)
|
|
|
|
|
- 3092 OR (v2 < lo)
|
|
|
|
|
- 3093 OR (v >= lo +
|
|
|
|
|
- 3094 VAL(INTEGER, span))
|
|
|
|
|
- 3095 OR (v2 >= lo +
|
|
|
|
|
- 3096 VAL(INTEGER, span))
|
|
|
|
|
- 3097 OR (v > v2)) THEN
|
|
|
|
|
- 3098 SemError(222)
|
|
|
|
|
- 3099 ELSIF hasR THEN
|
|
|
|
|
- 3100 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
|
|
+ 1503 QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
+ 1504 QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
+ 1505 "THEN" [ StatSeq ] (. QbeGen.Jmp(lEnd); .)
|
|
|
|
|
+ 1506 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ 1507 QbeGen.NewLabel(lElse); .)
|
|
|
|
|
+ 1508 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 1509 SemError(214) END;
|
|
|
|
|
+ 1510 QbeGen.NewLabel(lThen);
|
|
|
|
|
+ 1511 QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
+ 1512 QbeGen.EmitLabel(lThen); .)
|
|
|
|
|
+ 1513 "THEN" [ StatSeq ] (. QbeGen.Jmp(lEnd); .) }
|
|
|
|
|
+ 1514 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ 1515 hasElse := TRUE; .)
|
|
|
|
|
+ 1516 [ StatSeq ] ]
|
|
|
|
|
+ 1517 "END" (. IF hasElse THEN
|
|
|
|
|
+ 1518 QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ 1519 ELSE QbeGen.EmitLabel(lElse);
|
|
|
|
|
+ 1520 QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ 1521 END; .) .
|
|
|
|
|
+ 1522 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 1523 q, lTop, lBody, lEnd:
|
|
|
|
|
+ 1524 QbeGen.QVal; .)
|
|
|
|
|
+ 1525 = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 1526 QbeGen.NewLabel(lBody);
|
|
|
|
|
+ 1527 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 1528 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ 1529 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 1530 SemError(214) END;
|
|
|
|
|
+ 1531 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
|
|
+ 1532 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ 1533 "DO" [ StatSeq ] (. QbeGen.Jmp(lTop); .)
|
|
|
|
|
+ 1534 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 1535 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 1536 q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ 1537 = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 1538 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 1539 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ 1540 [ StatSeq ]
|
|
|
|
|
+ 1541 "UNTIL" Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 1542 SemError(214) END;
|
|
|
|
|
+ 1543 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
|
|
+ 1544 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 1545 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ 1546 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 1547 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 1548 QbeGen.PushLoop(lEnd);
|
|
|
|
|
+ 1549 QbeGen.EmitLabel(lTop); .)
|
|
|
|
|
+ 1550 [ StatSeq ]
|
|
|
|
|
+ 1551 "END" (. QbeGen.Jmp(lTop);
|
|
|
|
|
+ 1552 QbeGen.PopLoop;
|
|
|
|
|
+ 1553 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 1554 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
|
|
+ 1555 Runtime direction would need a compare-select; the literal
|
|
|
|
|
+ 1556 sign picks cslew/csegew at "DO" time. *)
|
|
|
|
|
+ 1557 ForStat (. VAR lv: SymTab.Name;
|
|
|
|
|
+ 1558 tlo, thi, tby:
|
|
|
|
|
+ 1559 SymTab.TypeIndex;
|
|
|
|
|
+ 1560 qlo, qhi, qby, qt, qk, qb:
|
|
|
|
|
+ 1561 QbeGen.QVal;
|
|
|
|
|
+ 1562 lTop, lBody, lEnd:
|
|
|
|
|
+ 1563 QbeGen.QVal;
|
|
|
|
|
+ 1564 by: INTEGER;
|
|
|
|
|
+ 1565 ok: BOOLEAN; .)
|
|
|
|
|
+ 1566 = "FOR" (. by := 1; .)
|
|
|
|
|
+ 1567 GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
|
|
+ 1568 IF NOT ok THEN
|
|
|
|
|
+ 1569 SemError(201)
|
|
|
|
|
+ 1570 ELSIF (SymTab.SymKind(lv) #
|
|
|
|
|
+ 1571 SymTab.KindVar)
|
|
|
|
|
+ 1572 AND (SymTab.SymKind(lv) #
|
|
|
|
|
+ 1573 SymTab.KindParam) THEN
|
|
|
|
|
+ 1574 SemError(220); ok := FALSE
|
|
|
|
|
+ 1575 ELSIF NOT SymTab.IsIntFamily(
|
|
|
|
|
+ 1576 SymTab.SymType(lv)) THEN
|
|
|
|
|
+ 1577 SemError(220); ok := FALSE
|
|
|
|
|
+ 1578 END; .)
|
|
|
|
|
+ 1579 ":=" Expr<tlo, qlo> (. IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
|
|
+ 1580 SemError(220); ok := FALSE
|
|
|
|
|
+ 1581 END; .)
|
|
|
|
|
+ 1582 "TO" Expr<thi, qhi> (. IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
|
|
+ 1583 SemError(220); ok := FALSE
|
|
|
|
|
+ 1584 END; .)
|
|
|
|
|
+ 1585 [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
|
|
+ 1586 SymTab.InvalidType)
|
|
|
|
|
+ 1587 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
|
|
+ 1588 SemError(220); ok := FALSE
|
|
|
|
|
+ 1589 END;
|
|
|
|
|
+ 1590 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
|
|
+ 1591 SemError(230); by := 1
|
|
|
|
|
+ 1592 ELSIF by = 0 THEN
|
|
|
|
|
+ 1593 SemError(220); by := 1
|
|
|
|
|
+ 1594 END; .) ]
|
|
|
|
|
+ 1595 "DO" (. IF ok THEN
|
|
|
|
|
+ 1596 QbeGen.StoreVar(lv, qlo,
|
|
|
|
|
+ 1597 FALSE) END;
|
|
|
|
|
+ 1598 QbeGen.NewLabel(lTop);
|
|
|
|
|
+ 1599 QbeGen.NewLabel(lBody);
|
|
|
|
|
+ 1600 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 1601 QbeGen.EmitLabel(lTop);
|
|
|
|
|
+ 1602 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
|
|
+ 1603 QbeGen.NewTemp(qk);
|
|
|
|
|
+ 1604 IF by > 0 THEN
|
|
|
|
|
+ 1605 QbeGen.Op3("cslew", qk,
|
|
|
|
|
+ 1606 qt, qhi, FALSE)
|
|
|
|
|
+ 1607 ELSE QbeGen.Op3("csgew", qk,
|
|
|
|
|
+ 1608 qt, qhi, FALSE)
|
|
|
|
|
+ 1609 END;
|
|
|
|
|
+ 1610 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
|
|
+ 1611 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ 1612 [ StatSeq ]
|
|
|
|
|
+ 1613 "END" (. IF ok THEN
|
|
|
|
|
+ 1614 QbeGen.LoadVar(lv, FALSE,
|
|
|
|
|
+ 1615 qt);
|
|
|
|
|
+ 1616 QbeGen.IntStr(by, qb);
|
|
|
|
|
+ 1617 QbeGen.NewTemp(qk);
|
|
|
|
|
+ 1618 QbeGen.Op3("add", qk,
|
|
|
|
|
+ 1619 qt, qb, FALSE);
|
|
|
|
|
+ 1620 QbeGen.StoreVar(lv, qk,
|
|
|
|
|
+ 1621 FALSE) END;
|
|
|
|
|
+ 1622 QbeGen.Jmp(lTop);
|
|
|
|
|
+ 1623 QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 1624 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
|
|
+ 1625 qsel, lEnd: QbeGen.QVal; .)
|
|
|
|
|
+ 1626 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
|
|
+ 1627 "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
|
|
+ 1628 { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
|
|
+ 1629 [ "ELSE" [ StatSeq ] ]
|
|
|
|
|
+ 1630 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
|
|
+ 1631 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
|
|
+ 1632 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
|
|
+ 1633 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
|
|
+ 1634 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
|
|
+ 1635 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ 1636 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
|
|
+ 1637 = (. QbeGen.NewLabel(lBody);
|
|
|
|
|
+ 1638 QbeGen.NewLabel(lAfter); .)
|
|
|
|
|
+ 1639 CaseLabel<tsel, qsel, lBody>
|
|
|
|
|
+ 1640 { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
|
|
+ 1641 ":" (. QbeGen.Jmp(lAfter);
|
|
|
|
|
+ 1642 QbeGen.EmitLabel(lBody); .)
|
|
|
|
|
+ 1643 [ StatSeq ] (. QbeGen.Jmp(lEnd);
|
|
|
|
|
+ 1644 QbeGen.EmitLabel(lAfter); .) .
|
|
|
|
|
+ 1645 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ 1646 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
|
|
+ 1647 q2, q3, qc, qd, qe:
|
|
|
|
|
+ 1648 QbeGen.QVal;
|
|
|
|
|
+ 1649 lNext: QbeGen.QVal; .)
|
|
|
|
|
+ 1650 = Expr<t2, q2> (. IF (t2 #
|
|
|
|
|
+ 1651 SymTab.InvalidType)
|
|
|
|
|
+ 1652 AND (tsel #
|
|
|
|
|
+ 1653 SymTab.InvalidType)
|
|
|
|
|
+ 1654 AND ((SymTab.ClassOf(t2) =
|
|
|
|
|
+ 1655 SymTab.ClSet)
|
|
|
|
|
+ 1656 OR (SymTab.ClassOf(tsel) =
|
|
|
|
|
+ 1657 SymTab.ClSet)) THEN
|
|
|
|
|
+ 1658 SemError(230)
|
|
|
|
|
+ 1659 ELSIF (t2 #
|
|
|
|
|
+ 1660 SymTab.InvalidType)
|
|
|
|
|
+ 1661 AND (tsel #
|
|
|
|
|
+ 1662 SymTab.InvalidType)
|
|
|
|
|
+ 1663 AND NOT SymTab.EqCheck(t2,
|
|
|
|
|
+ 1664 tsel) THEN
|
|
|
|
|
+ 1665 SemError(213) END;
|
|
|
|
|
+ 1666 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ 1667 SemError(230);
|
|
|
|
|
+ 1668 QbeGen.CopyOp("0", q2)
|
|
|
|
|
+ 1669 END;
|
|
|
|
|
+ 1670 QbeGen.NewLabel(lNext);
|
|
|
|
|
+ 1671 QbeGen.Cmp(SymTab.OpEq,
|
|
|
|
|
+ 1672 qsel, q2, qc, FALSE);
|
|
|
|
|
+ 1673 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
|
|
+ 1674 QbeGen.EmitLabel(lNext); .)
|
|
|
|
|
+ 1675 [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
|
|
+ 1676 SymTab.InvalidType)
|
|
|
|
|
+ 1677 AND (tsel #
|
|
|
|
|
+ 1678 SymTab.InvalidType)
|
|
|
|
|
+ 1679 AND NOT SymTab.EqCheck(t3,
|
|
|
|
|
+ 1680 tsel) THEN
|
|
|
|
|
+ 1681 SemError(213) END;
|
|
|
|
|
+ 1682 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
|
|
+ 1683 SemError(230);
|
|
|
|
|
+ 1684 QbeGen.CopyOp("0", q3)
|
|
|
|
|
+ 1685 END;
|
|
|
|
|
+ 1686 QbeGen.Cmp(SymTab.OpGe,
|
|
|
|
|
+ 1687 qsel, q2, qc, FALSE);
|
|
|
|
|
+ 1688 QbeGen.Cmp(SymTab.OpLe,
|
|
|
|
|
+ 1689 qsel, q3, qd, FALSE);
|
|
|
|
|
+ 1690 QbeGen.NewTemp(qe);
|
|
|
|
|
+ 1691 QbeGen.Op3("and", qe, qc, qd,
|
|
|
|
|
+ 1692 FALSE);
|
|
|
|
|
+ 1693 QbeGen.NewLabel(lNext);
|
|
|
|
|
+ 1694 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
|
|
+ 1695 QbeGen.EmitLabel(lNext); .) ] .
|
|
|
|
|
+ 1696 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 1697 q, qt: QbeGen.QVal;
|
|
|
|
|
+ 1698 res: SymTab.TypeIndex;
|
|
|
|
|
+ 1699 hadE, conv: BOOLEAN; .)
|
|
|
|
|
+ 1700 = "RETURN" (. hadE := FALSE; .)
|
|
|
|
|
+ 1701 [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
|
|
+ 1702 (. conv := FALSE;
|
|
|
|
|
+ 1703 IF NOT SymTab.InProc() THEN
|
|
|
|
|
+ 1704 SemError(232)
|
|
|
|
|
+ 1705 ELSE res := SymTab.CurRes();
|
|
|
|
|
+ 1706 IF NOT hadE THEN
|
|
|
|
|
+ 1707 IF res #
|
|
|
|
|
+ 1708 SymTab.InvalidType THEN
|
|
|
|
|
+ 1709 SemError(232)
|
|
|
|
|
+ 1710 ELSE QbeGen.EmitRet(q,
|
|
|
|
|
+ 1711 FALSE)
|
|
|
|
|
+ 1712 END
|
|
|
|
|
+ 1713 ELSIF (res =
|
|
|
|
|
+ 1714 SymTab.InvalidType)
|
|
|
|
|
+ 1715 OR (t #
|
|
|
|
|
+ 1716 SymTab.InvalidType)
|
|
|
|
|
+ 1717 AND NOT SymTab.Assignable(t,
|
|
|
|
|
+ 1718 res) THEN
|
|
|
|
|
+ 1719 SemError(232)
|
|
|
|
|
+ 1720 ELSE
|
|
|
|
|
+ 1721 conv := (SymTab.ClassOf(
|
|
|
|
|
+ 1722 res) = SymTab.ClReal)
|
|
|
|
|
+ 1723 AND SymTab.IsIntFamily(t);
|
|
|
|
|
+ 1724 IF conv THEN
|
|
|
|
|
+ 1725 QbeGen.ConvIR(q, qt);
|
|
|
|
|
+ 1726 QbeGen.EmitRet(qt, TRUE)
|
|
|
|
|
+ 1727 ELSE QbeGen.EmitRet(q, TRUE)
|
|
|
|
|
+ 1728 END
|
|
|
|
|
+ 1729 END
|
|
|
|
|
+ 1730 END; .) .
|
|
|
|
|
+ 1731 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 1732 q: QbeGen.QVal; .)
|
|
|
|
|
+ 1733 = "HALT" [ "(" Expr<t, q> ")" ] (. QbeGen.HaltQ; .) .
|
|
|
|
|
+ 1734 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
|
|
+ 1735 Each index descends one level (bounds-checked, trap on breach);
|
|
|
|
|
+ 1736 nested levels reload the inner descriptor address. q ends as the
|
|
|
|
|
+ 1737 value (scalars), the descriptor address (plain arrays), or the
|
|
|
|
|
+ 1738 element address (indexed); sfx marks the indexed form. *)
|
|
|
|
|
+ 1739 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
+ 1740 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
|
|
+ 1741 (. VAR n, fn, mal: SymTab.Name;
|
|
|
|
|
+ 1742 cls: INTEGER;
|
|
|
|
|
+ 1743 ic: SymTab.TypeIndex;
|
|
|
|
|
+ 1744 curT, it, eT, bt:
|
|
|
|
|
+ 1745 SymTab.TypeIndex;
|
|
|
|
|
+ 1746 iq, ql, qlo, qhi, qe:
|
|
|
|
|
+ 1747 QbeGen.QVal;
|
|
|
|
|
+ 1748 lo, hi: INTEGER;
|
|
|
|
|
+ 1749 fo: INTEGER;
|
|
|
|
|
+ 1750 isOpen: BOOLEAN;
|
|
|
|
|
+ 1751 qb, cv: QbeGen.QVal;
|
|
|
|
|
+ 1752 fid, fref, slot: INTEGER;
|
|
|
|
|
+ 1753 r: BOOLEAN; .)
|
|
|
|
|
+ 1754 = GetIdent<n> (. methCls := SymTab.InvalidType;
|
|
|
|
|
+ 1755 QbeGen.CopyOp(n, qn);
|
|
|
|
|
+ 1756 sfx := FALSE;
|
|
|
|
|
+ 1757 fid := 0; fref := 0; slot := 0;
|
|
|
|
|
+ 1758 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
+ 1759 (* a bare method name inside
|
|
|
|
|
+ 1760 a CLASS IMPLEMENTATION
|
|
|
|
|
+ 1761 is a sibling call on
|
|
|
|
|
+ 1762 THIS *)
|
|
|
|
|
+ 1763 ic := SymTab.CurImplClass();
|
|
|
|
|
+ 1764 IF (ic #
|
|
|
|
|
+ 1765 SymTab.InvalidType)
|
|
|
|
|
+ 1766 AND SymTab.MethodExists(ic, n) THEN
|
|
|
|
|
+ 1767 sfx := FALSE;
|
|
|
|
|
+ 1768 QbeGen.ThisBase(q);
|
|
|
|
|
+ 1769 QbeGen.ArmRecv(q);
|
|
|
|
|
+ 1770 methCls := ic;
|
|
|
|
|
+ 1771 k := SymTab.KindProc;
|
|
|
|
|
+ 1772 t := SymTab.InvalidType
|
|
|
|
|
+ 1773 ELSIF SymTab.InProc() THEN
|
|
|
|
|
+ 1774 (* not declared yet: a
|
|
|
|
|
+ 1775 forward reference to a
|
|
|
|
|
+ 1776 module-level variable
|
|
|
|
|
+ 1777 declared further down. *)
|
|
|
|
|
+ 1778 k := SymTab.KindVar;
|
|
|
|
|
+ 1779 r := SymTab.FwdVarRef(n, k,
|
|
|
|
|
+ 1780 fref, t);
|
|
|
|
|
+ 1781 slot := QbeGen.FwdDesignator();
|
|
|
|
|
+ 1782 FwdVarNote(fref, slot);
|
|
|
|
|
+ 1783 fid := slot;
|
|
|
|
|
+ 1784 QbeGen.FwdAddrOper(fid, q);
|
|
|
|
|
+ 1785 sfx := TRUE
|
|
|
|
|
+ 1786 ELSE
|
|
|
|
|
+ 1787 SemError(201);
|
|
|
|
|
+ 1788 t :=
|
|
|
|
|
+ 1789 SymTab.InvalidType;
|
|
|
|
|
+ 1790 k := -1;
|
|
|
|
|
+ 1791 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1792 END
|
|
|
|
|
+ 1793 ELSE
|
|
|
|
|
+ 1794 t := SymTab.SymType(n);
|
|
|
|
|
+ 1795 k := SymTab.SymKind(n);
|
|
|
|
|
+ 1796 IF k = SymTab.KindConst THEN
|
|
|
|
|
+ 1797 IF SymTab.Equal(n,
|
|
|
|
|
+ 1798 "TRUE") THEN
|
|
|
|
|
+ 1799 t := SymTab.BoolType();
|
|
|
|
|
+ 1800 QbeGen.CopyOp("1", q)
|
|
|
|
|
+ 1801 ELSIF SymTab.Equal(n,
|
|
|
|
|
+ 1802 "FALSE") THEN
|
|
|
|
|
+ 1803 t := SymTab.BoolType();
|
|
|
|
|
+ 1804 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1805 ELSIF SymTab.Equal(n,
|
|
|
|
|
+ 1806 "NIL") THEN
|
|
|
|
|
+ 1807 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1808 ELSE
|
|
|
|
|
+ 1809 cls :=
|
|
|
|
|
+ 1810 SymTab.ClassOf(t);
|
|
|
|
|
+ 1811 IF (t #
|
|
|
|
|
+ 1812 SymTab.InvalidType)
|
|
|
|
|
+ 1813 AND ((cls = SymTab.ClInt)
|
|
|
|
|
+ 1814 OR (cls
|
|
|
|
|
+ 1815 = SymTab.ClChar)
|
|
|
|
|
+ 1816 OR (cls
|
|
|
|
|
+ 1817 = SymTab.ClEnum)
|
|
|
|
|
+ 1818 OR (cls
|
|
|
|
|
+ 1819 = SymTab.ClReal)
|
|
|
|
|
+ 1820 OR (cls
|
|
|
|
|
+ 1821 = SymTab.ClLong)
|
|
|
|
|
+ 1822 OR (cls
|
|
|
|
|
+ 1823 = SymTab.ClNil)) THEN
|
|
|
|
|
+ 1824 IF cls = SymTab.ClNil THEN
|
|
|
|
|
+ 1825 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1826 ELSIF ((cls
|
|
|
|
|
+ 1827 = SymTab.ClInt)
|
|
|
|
|
+ 1828 OR (cls
|
|
|
|
|
+ 1829 = SymTab.ClChar)
|
|
|
|
|
+ 1830 OR (cls
|
|
|
|
|
+ 1831 = SymTab.ClEnum)
|
|
|
|
|
+ 1832 OR (cls
|
|
|
|
|
+ 1833 = SymTab.ClLong))
|
|
|
|
|
+ 1834 AND SymTab.GetSymVal(n, cv)
|
|
|
|
|
+ 1835 AND QbeGen.IsImm(cv) THEN
|
|
|
|
|
+ 1836 QbeGen.CopyOp(cv, q)
|
|
|
|
|
+ 1837 ELSE
|
|
|
|
|
+ 1838 QbeGen.LoadVar(n,
|
|
|
|
|
+ 1839 cls = SymTab.ClReal,
|
|
|
|
|
+ 1840 q)
|
|
|
|
|
+ 1841 END
|
|
|
|
|
+ 1842 ELSIF (cls = SymTab.ClArray)
|
|
|
|
|
+ 1843 OR (cls = SymTab.ClRecord)
|
|
|
|
|
+ 1844 OR (cls = SymTab.ClClass)
|
|
|
|
|
+ 1845 OR (cls = SymTab.ClStr)
|
|
|
|
|
+ 1846 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
+ 1847 (* aggregate constant:
|
|
|
|
|
+ 1848 its value IS the
|
|
|
|
|
+ 1849 descriptor address *)
|
|
|
|
|
+ 1850 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
|
|
+ 1851 QbeGen.CopyOp(cv, q)
|
|
|
|
|
+ 1852 ELSE
|
|
|
|
|
+ 1853 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1854 END
|
|
|
|
|
+ 1855 ELSE
|
|
|
|
|
+ 1856 IF t #
|
|
|
|
|
+ 1857 SymTab.InvalidType THEN
|
|
|
|
|
+ 1858 SemError(230)
|
|
|
|
|
+ 1859 END;
|
|
|
|
|
+ 1860 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1861 END
|
|
|
|
|
+ 1862 END
|
|
|
|
|
+ 1863 ELSIF (k = SymTab.KindVar)
|
|
|
|
|
+ 1864 OR (k = SymTab.KindParam) THEN
|
|
|
|
|
+ 1865 cls :=
|
|
|
|
|
+ 1866 SymTab.ClassOf(t);
|
|
|
|
|
+ 1867 IF (cls = SymTab.ClInt)
|
|
|
|
|
+ 1868 OR (cls = SymTab.ClBool)
|
|
|
|
|
+ 1869 OR (cls = SymTab.ClChar)
|
|
|
|
|
+ 1870 OR (cls = SymTab.ClUChar)
|
|
|
|
|
+ 1871 OR (cls = SymTab.ClEnum)
|
|
|
|
|
+ 1872 OR (cls
|
|
|
|
|
+ 1873 = SymTab.ClReal) THEN
|
|
|
|
|
+ 1874 QbeGen.LoadVar(n,
|
|
|
|
|
+ 1875 cls = SymTab.ClReal, q)
|
|
|
|
|
+ 1876 ELSIF (cls = SymTab.ClPtr)
|
|
|
|
|
+ 1877 OR (cls = SymTab.ClProc) THEN
|
|
|
|
|
+ 1878 QbeGen.LoadPtr(n, q)
|
|
|
|
|
+ 1879 ELSIF cls = SymTab.ClLong THEN
|
|
|
|
|
+ 1880 QbeGen.LoadLong(n, q)
|
|
|
|
|
+ 1881 ELSIF (cls
|
|
|
|
|
+ 1882 = SymTab.ClArray)
|
|
|
|
|
+ 1883 OR (cls
|
|
|
|
|
+ 1884 = SymTab.ClSet)
|
|
|
|
|
+ 1885 OR (cls
|
|
|
|
|
+ 1886 = SymTab.ClRecord)
|
|
|
|
|
+ 1887 OR (cls
|
|
|
|
|
+ 1888 = SymTab.ClUStr)
|
|
|
|
|
+ 1889 OR (cls
|
|
|
|
|
+ 1890 = SymTab.ClClass) THEN
|
|
|
|
|
+ 1891 QbeGen.AddrOf(n, q)
|
|
|
|
|
+ 1892 ELSE SemError(230);
|
|
|
|
|
+ 1893 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1894 END
|
|
|
|
|
+ 1895 ELSE QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 1896 IF k = SymTab.KindImport THEN
|
|
|
|
|
+ 1897 SemError(230)
|
|
|
|
|
+ 1898 ELSIF k =
|
|
|
|
|
+ 1899 SymTab.KindProc THEN
|
|
|
|
|
+ 1900 (* bare procedure name:
|
|
|
|
|
+ 1901 a following ArgList
|
|
|
|
|
+ 1902 makes it a call;
|
|
|
|
|
+ 1903 otherwise Fact
|
|
|
|
|
+ 1904 reports 230 *)
|
|
|
|
|
+ 1905 ELSE
|
|
|
|
|
+ 1906 IF k = SymTab.KindField THEN
|
|
|
|
|
+ 1907 IF QbeGen.TopWith(qb) THEN
|
|
|
|
|
+ 1908 fo :=
|
|
|
|
|
+ 1909 SymTab.FieldOffset(
|
|
|
|
|
+ 1910 SymTab.FieldOwner(n),
|
|
|
|
|
+ 1911 n);
|
|
|
|
|
+ 1912 QbeGen.FieldAddr(qb,
|
|
|
|
|
+ 1913 fo, q);
|
|
|
|
|
+ 1914 sfx := TRUE
|
|
|
|
|
+ 1915 ELSE SemError(230);
|
|
|
|
|
+ 1916 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 1917 END
|
|
|
|
|
+ 1918 END
|
|
|
|
|
+ 1919 END
|
|
|
|
|
+ 1920 END
|
|
|
|
|
+ 1921 END; .)
|
|
|
|
|
+ 1922 { "[" Expr<it, iq>
|
|
|
|
|
+ 1923 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 1924 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 1925 SymTab.ClArray THEN
|
|
|
|
|
+ 1926 SemError(217);
|
|
|
|
|
+ 1927 t := SymTab.InvalidType
|
|
|
|
|
+ 1928 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
+ 1929 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 1930 SymTab.ClChar)
|
|
|
|
|
+ 1931 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 1932 SymTab.ClEnum) THEN
|
|
|
|
|
+ 1933 SemError(218);
|
|
|
|
|
+ 1934 t := SymTab.InvalidType
|
|
|
|
|
+ 1935 ELSE
|
|
|
|
|
+ 1936 QbeGen.WidenIndex(iq, ql);
|
|
|
|
|
+ 1937 isOpen :=
|
|
|
|
|
+ 1938 SymTab.IsOpenArray(t);
|
|
|
|
|
+ 1939 IF isOpen THEN
|
|
|
|
|
+ 1940 QbeGen.CopyOp("0", qlo);
|
|
|
|
|
+ 1941 IF SymTab.IsCharArray(t)
|
|
|
|
|
+ 1942 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
+ 1943 QbeGen.OpenHiChar(q, qhi)
|
|
|
|
|
+ 1944 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
|
|
+ 1945 END
|
|
|
|
|
+ 1946 ELSE
|
|
|
|
|
+ 1947 lo := SymTab.ArrayLo(t);
|
|
|
|
|
+ 1948 hi := SymTab.ArrayHi(t);
|
|
|
|
|
+ 1949 IF SymTab.IsCharArray(t)
|
|
|
|
|
+ 1950 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
+ 1951 hi := hi + 1
|
|
|
|
|
+ 1952 END;
|
|
|
|
|
+ 1953 QbeGen.IntStr(lo, qlo);
|
|
|
|
|
+ 1954 QbeGen.IntStr(hi, qhi)
|
|
|
|
|
+ 1955 END;
|
|
|
|
|
+ 1956 QbeGen.CheckRange(ql, qlo,
|
|
|
|
|
+ 1957 qhi);
|
|
|
|
|
+ 1958 eT := SymTab.ArrayElem(t);
|
|
|
|
|
+ 1959 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
|
|
+ 1960 t, qe);
|
|
|
|
|
+ 1961 IF SymTab.ClassOf(eT) =
|
|
|
|
|
+ 1962 SymTab.ClArray THEN
|
|
|
|
|
+ 1963 QbeGen.ElemLoad(qe, eT, q)
|
|
|
|
|
+ 1964 ELSE QbeGen.CopyOp(qe, q)
|
|
|
|
|
+ 1965 END;
|
|
|
|
|
+ 1966 t := eT; sfx := TRUE
|
|
|
|
|
+ 1967 END; .)
|
|
|
|
|
+ 1968 { "," Expr<it, iq>
|
|
|
|
|
+ 1969 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 1970 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 1971 SymTab.ClArray THEN
|
|
|
|
|
+ 1972 SemError(217);
|
|
|
|
|
+ 1973 t := SymTab.InvalidType
|
|
|
|
|
+ 1974 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
+ 1975 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 1976 SymTab.ClChar)
|
|
|
|
|
+ 1977 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 1978 SymTab.ClEnum) THEN
|
|
|
|
|
+ 1979 SemError(218);
|
|
|
|
|
+ 1980 t := SymTab.InvalidType
|
|
|
|
|
+ 1981 ELSE
|
|
|
|
|
+ 1982 QbeGen.WidenIndex(iq, ql);
|
|
|
|
|
+ 1983 isOpen :=
|
|
|
|
|
+ 1984 SymTab.IsOpenArray(t);
|
|
|
|
|
+ 1985 IF isOpen THEN
|
|
|
|
|
+ 1986 QbeGen.CopyOp("0", qlo);
|
|
|
|
|
+ 1987 IF SymTab.IsCharArray(t)
|
|
|
|
|
+ 1988 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
+ 1989 QbeGen.OpenHiChar(q, qhi)
|
|
|
|
|
+ 1990 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
|
|
+ 1991 END
|
|
|
|
|
+ 1992 ELSE
|
|
|
|
|
+ 1993 lo := SymTab.ArrayLo(t);
|
|
|
|
|
+ 1994 hi := SymTab.ArrayHi(t);
|
|
|
|
|
+ 1995 IF SymTab.IsCharArray(t)
|
|
|
|
|
+ 1996 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
+ 1997 hi := hi + 1
|
|
|
|
|
+ 1998 END;
|
|
|
|
|
+ 1999 QbeGen.IntStr(lo, qlo);
|
|
|
|
|
+ 2000 QbeGen.IntStr(hi, qhi)
|
|
|
|
|
+ 2001 END;
|
|
|
|
|
+ 2002 QbeGen.CheckRange(ql, qlo,
|
|
|
|
|
+ 2003 qhi);
|
|
|
|
|
+ 2004 eT := SymTab.ArrayElem(t);
|
|
|
|
|
+ 2005 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
|
|
+ 2006 t, qe);
|
|
|
|
|
+ 2007 IF SymTab.ClassOf(eT) =
|
|
|
|
|
+ 2008 SymTab.ClArray THEN
|
|
|
|
|
+ 2009 QbeGen.ElemLoad(qe, eT, q)
|
|
|
|
|
+ 2010 ELSE QbeGen.CopyOp(qe, q)
|
|
|
|
|
+ 2011 END;
|
|
|
|
|
+ 2012 t := eT; sfx := TRUE
|
|
|
|
|
+ 2013 END; .) }
|
|
|
|
|
+ 2014 "]"
|
|
|
|
|
+ 2015 | "." GetIdent<fn>
|
|
|
|
|
+ 2016 (. IF k = SymTab.KindModule THEN
|
|
|
|
|
+ 2017 (* qualified L.x: materialize
|
|
|
|
|
+ 2018 the export, then load it *)
|
|
|
|
|
+ 2019 IF NOT SymTab.MaterializeAlias(n,
|
|
|
|
|
+ 2020 fn, mal) THEN
|
|
|
|
|
+ 2021 SemError(201);
|
|
|
|
|
+ 2022 t := SymTab.InvalidType;
|
|
|
|
|
+ 2023 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2024 ELSE
|
|
|
|
|
+ 2025 QbeGen.CopyOp(mal, qn);
|
|
|
|
|
+ 2026 t := SymTab.SymType(mal);
|
|
|
|
|
+ 2027 k := SymTab.SymKind(mal);
|
|
|
|
|
+ 2028 sfx := FALSE;
|
|
|
|
|
+ 2029 IF k = SymTab.KindProc THEN
|
|
|
|
|
+ 2030 (* call: ArgList supplies
|
|
|
|
|
+ 2031 the value *)
|
|
|
|
|
+ 2032 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2033 ELSIF NOT QbeGen.LoadDesignator(
|
|
|
|
|
+ 2034 mal, t, k, q) THEN
|
|
|
|
|
+ 2035 SemError(230);
|
|
|
|
|
+ 2036 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2037 END
|
|
|
|
|
+ 2038 END
|
|
|
|
|
+ 2039 ELSIF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2040 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
+ 2041 SymTab.ClRecord)
|
|
|
|
|
+ 2042 AND (SymTab.ClassOf(t) #
|
|
|
|
|
+ 2043 SymTab.ClClass) THEN
|
|
|
|
|
+ 2044 SemError(215);
|
|
|
|
|
+ 2045 t := SymTab.InvalidType
|
|
|
|
|
+ 2046 ELSIF (SymTab.ClassOf(t) =
|
|
|
|
|
+ 2047 SymTab.ClClass)
|
|
|
|
|
+ 2048 AND SymTab.MethodExists(t, fn) THEN
|
|
|
|
|
+ 2049 (* obj.Method: bind the
|
|
|
|
|
+ 2050 method and pass obj as
|
|
|
|
|
+ 2051 the hidden receiver; q
|
|
|
|
|
+ 2052 already holds the
|
|
|
|
|
+ 2053 object's address *)
|
|
|
|
|
+ 2054 QbeGen.ArmRecv(q);
|
|
|
|
|
+ 2055 QbeGen.CopyOp(fn, n);
|
|
|
|
|
+ 2056 QbeGen.CopyOp(fn, qn);
|
|
|
|
|
+ 2057 methCls := t;
|
|
|
|
|
+ 2058 k := SymTab.KindProc;
|
|
|
|
|
+ 2059 t := SymTab.InvalidType
|
|
|
|
|
+ 2060 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
+ 2061 fn) THEN
|
|
|
|
|
+ 2062 SemError(216);
|
|
|
|
|
+ 2063 t := SymTab.InvalidType
|
|
|
|
|
+ 2064 ELSE
|
|
|
|
|
+ 2065 fo := SymTab.FieldOffset(t,
|
|
|
|
|
+ 2066 fn);
|
|
|
|
|
+ 2067 t := SymTab.FieldType(t, fn);
|
|
|
|
|
+ 2068 QbeGen.FieldAddr(q, fo, qe);
|
|
|
|
|
+ 2069 (* array fields are inline:
|
|
|
|
|
+ 2070 the field address is the
|
|
|
|
|
+ 2071 descriptor, like records *)
|
|
|
|
|
+ 2072 QbeGen.CopyOp(qe, q);
|
|
|
|
|
+ 2073 sfx := TRUE
|
|
|
|
|
+ 2074 END; .)
|
|
|
|
|
+ 2075 | "^"
|
|
|
|
|
+ 2076 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2077 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2078 SymTab.ClPtr THEN
|
|
|
|
|
+ 2079 SemError(219);
|
|
|
|
|
+ 2080 t := SymTab.InvalidType
|
|
|
|
|
+ 2081 ELSE
|
|
|
|
|
+ 2082 bt := SymTab.PtrBase(t);
|
|
|
|
|
+ 2083 IF bt = SymTab.InvalidType THEN
|
|
|
|
|
+ 2084 ELSE
|
|
|
|
|
+ 2085 IF sfx THEN
|
|
|
|
|
+ 2086 QbeGen.ElemLoad(q, t,
|
|
|
|
|
+ 2087 qb);
|
|
|
|
|
+ 2088 QbeGen.CopyOp(qb, q)
|
|
|
|
|
+ 2089 END;
|
|
|
|
|
+ 2090 t := bt;
|
|
|
|
|
+ 2091 (* q holds the pointee
|
|
|
|
|
+ 2092 address: Fact loads
|
|
|
|
|
+ 2093 scalars/pointers and uses
|
|
|
|
|
+ 2094 the address for
|
|
|
|
|
+ 2095 aggregates; the VAR-actual
|
|
|
|
|
+ 2096 note is q itself. *)
|
|
|
|
|
+ 2097 sfx := TRUE
|
|
|
|
|
+ 2098 END
|
|
|
|
|
+ 2099 END; .) } .
|
|
|
|
|
+ 2100 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
|
|
+ 2101 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
|
|
+ 2102 (a value, or a descriptor address for aggregates); each component
|
|
|
|
|
+ 2103 descends one level exactly like the Design components. *)
|
|
|
|
|
+ 2104 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
+ 2105 VAR sfx: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
|
|
+ 2106 iq, ql, qlo, qhi, qe, qb:
|
|
|
|
|
+ 2107 QbeGen.QVal;
|
|
|
|
|
+ 2108 lo, hi, fo: INTEGER;
|
|
|
|
|
+ 2109 isOpen: BOOLEAN;
|
|
|
|
|
+ 2110 fname: SymTab.Name; .)
|
|
|
|
|
+ 2111 = "[" Expr<it, iq>
|
|
|
|
|
+ 2112 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2113 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2114 SymTab.ClArray THEN
|
|
|
|
|
+ 2115 SemError(217);
|
|
|
|
|
+ 2116 t := SymTab.InvalidType
|
|
|
|
|
+ 2117 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
+ 2118 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
|
|
+ 2119 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
|
|
+ 2120 SemError(218);
|
|
|
|
|
+ 2121 t := SymTab.InvalidType
|
|
|
|
|
+ 2122 ELSE
|
|
|
|
|
+ 2123 QbeGen.WidenIndex(iq, ql);
|
|
|
|
|
+ 2124 isOpen :=
|
|
|
|
|
+ 2125 SymTab.IsOpenArray(t);
|
|
|
|
|
+ 2126 IF isOpen THEN
|
|
|
|
|
+ 2127 QbeGen.CopyOp("0", qlo);
|
|
|
|
|
+ 2128 IF SymTab.IsCharArray(t)
|
|
|
|
|
+ 2129 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
+ 2130 QbeGen.OpenHiChar(q, qhi)
|
|
|
|
|
+ 2131 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
|
|
+ 2132 END
|
|
|
|
|
+ 2133 ELSE
|
|
|
|
|
+ 2134 lo := SymTab.ArrayLo(t);
|
|
|
|
|
+ 2135 hi := SymTab.ArrayHi(t);
|
|
|
|
|
+ 2136 IF SymTab.IsCharArray(t)
|
|
|
|
|
+ 2137 OR SymTab.IsUCharArray(t) THEN
|
|
|
|
|
+ 2138 hi := hi + 1
|
|
|
|
|
+ 2139 END;
|
|
|
|
|
+ 2140 QbeGen.IntStr(lo, qlo);
|
|
|
|
|
+ 2141 QbeGen.IntStr(hi, qhi)
|
|
|
|
|
+ 2142 END;
|
|
|
|
|
+ 2143 QbeGen.CheckRange(ql, qlo,
|
|
|
|
|
+ 2144 qhi);
|
|
|
|
|
+ 2145 eT := SymTab.ArrayElem(t);
|
|
|
|
|
+ 2146 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
|
|
+ 2147 t, qe);
|
|
|
|
|
+ 2148 IF SymTab.ClassOf(eT) =
|
|
|
|
|
+ 2149 SymTab.ClArray THEN
|
|
|
|
|
+ 2150 QbeGen.ElemLoad(qe, eT, q)
|
|
|
|
|
+ 2151 ELSE QbeGen.CopyOp(qe, q)
|
|
|
|
|
+ 2152 END;
|
|
|
|
|
+ 2153 t := eT; sfx := TRUE
|
|
|
|
|
+ 2154 END; .)
|
|
|
|
|
+ 2155 "]"
|
|
|
|
|
+ 2156 | "." GetIdent<fname>
|
|
|
|
|
+ 2157 (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2158 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
+ 2159 SymTab.ClRecord)
|
|
|
|
|
+ 2160 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
+ 2161 SemError(215);
|
|
|
|
|
+ 2162 t := SymTab.InvalidType
|
|
|
|
|
+ 2163 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
+ 2164 fname) THEN
|
|
|
|
|
+ 2165 SemError(216);
|
|
|
|
|
+ 2166 t := SymTab.InvalidType
|
|
|
|
|
+ 2167 ELSE
|
|
|
|
|
+ 2168 fo := SymTab.FieldOffset(t,
|
|
|
|
|
+ 2169 fname);
|
|
|
|
|
+ 2170 t := SymTab.FieldType(t, fname);
|
|
|
|
|
+ 2171 QbeGen.FieldAddr(q, fo, qe);
|
|
|
|
|
+ 2172 QbeGen.CopyOp(qe, q);
|
|
|
|
|
+ 2173 sfx := TRUE
|
|
|
|
|
+ 2174 END; .)
|
|
|
|
|
+ 2175 | "^" (. IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2176 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2177 SymTab.ClPtr THEN
|
|
|
|
|
+ 2178 SemError(219);
|
|
|
|
|
+ 2179 t := SymTab.InvalidType
|
|
|
|
|
+ 2180 ELSE
|
|
|
|
|
+ 2181 bt := SymTab.PtrBase(t);
|
|
|
|
|
+ 2182 IF bt # SymTab.InvalidType THEN
|
|
|
|
|
+ 2183 IF sfx THEN
|
|
|
|
|
+ 2184 QbeGen.ElemLoad(q, t, qb);
|
|
|
|
|
+ 2185 QbeGen.CopyOp(qb, q)
|
|
|
|
|
+ 2186 END;
|
|
|
|
|
+ 2187 t := bt; sfx := TRUE
|
|
|
|
|
+ 2188 END
|
|
|
|
|
+ 2189 END; .) .
|
|
|
|
|
+ 2190 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2191 (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
+ 2192 op: INTEGER;
|
|
|
|
|
+ 2193 q2, qt, wl: QbeGen.QVal;
|
|
|
|
|
+ 2194 isR: BOOLEAN; .)
|
|
|
|
|
+ 2195 = SimExpr<t, q>
|
|
|
|
|
+ 2196 [ Rel<op> SimExpr<t2, q2>
|
|
|
|
|
+ 2197 (. IF op = SymTab.OpIn THEN
|
|
|
|
|
+ 2198 IF SymTab.InCheck(t, t2) THEN
|
|
|
|
|
+ 2199 IF (t = SymTab.InvalidType)
|
|
|
|
|
+ 2200 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
+ 2201 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2202 ELSE
|
|
|
|
|
+ 2203 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
|
|
|
|
|
+ 2204 SymTab.SetCount(t2), qt);
|
|
|
|
|
+ 2205 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2206 END
|
|
|
|
|
+ 2207 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
|
|
+ 2208 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2209 END
|
|
|
|
|
+ 2210 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
|
|
+ 2211 IF (t = SymTab.InvalidType)
|
|
|
|
|
+ 2212 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
+ 2213 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2214 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
|
|
+ 2215 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
|
|
+ 2216 IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
|
|
|
|
|
+ 2217 QbeGen.Cmp(op, q, q2, qt, FALSE);
|
|
|
|
|
+ 2218 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2219 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
|
|
+ 2220 AND (op # SymTab.OpNeq2) THEN
|
|
|
|
|
+ 2221 SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
+ 2222 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2223 ELSE
|
|
|
|
|
+ 2224 QbeGen.CmpL(op, q, q2, qt);
|
|
|
|
|
+ 2225 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2226 END
|
|
|
|
|
+ 2227 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
+ 2228 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
+ 2229 QbeGen.CmpSet(op, q, q2,
|
|
|
|
|
+ 2230 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
|
|
|
|
|
+ 2231 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2232 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
|
|
+ 2233 QbeGen.StrEq(op, q, q2, qt);
|
|
|
|
|
+ 2234 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2235 ELSIF SymTab.IsLongFamily(t)
|
|
|
|
|
+ 2236 OR SymTab.IsLongFamily(t2) THEN
|
|
|
|
|
+ 2237 IF SymTab.IsIntFamily(t) THEN
|
|
|
|
|
+ 2238 QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
|
|
|
|
|
+ 2239 END;
|
|
|
|
|
+ 2240 IF SymTab.IsIntFamily(t2) THEN
|
|
|
|
|
+ 2241 QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
|
|
|
|
|
+ 2242 END;
|
|
|
|
|
+ 2243 QbeGen.CmpLong(op, q, q2, qt);
|
|
|
|
|
+ 2244 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2245 ELSE
|
|
|
|
|
+ 2246 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 2247 t := SymTab.BoolType();
|
|
|
|
|
+ 2248 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
|
|
+ 2249 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2250 END
|
|
|
|
|
+ 2251 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
+ 2252 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2253 END; .) ] .
|
|
|
|
|
+ 2254 Rel<VAR op: INTEGER>
|
|
|
|
|
+ 2255 = "=" (. op := SymTab.OpEq; .)
|
|
|
|
|
+ 2256 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
|
|
+ 2257 | "<" (. op := SymTab.OpLt; .)
|
|
|
|
|
+ 2258 | "<=" (. op := SymTab.OpLe; .)
|
|
|
|
|
+ 2259 | ">" (. op := SymTab.OpGt; .)
|
|
|
|
|
+ 2260 | ">=" (. op := SymTab.OpGe; .)
|
|
|
|
|
+ 2261 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
|
|
+ 2262 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2263 (. VAR t2, res2, lt, rt:
|
|
|
|
|
+ 2264 SymTab.TypeIndex;
|
|
|
|
|
+ 2265 op: INTEGER;
|
|
|
|
|
+ 2266 q2, qt, wq, qf, q2a, q2b:
|
|
|
|
|
+ 2267 QbeGen.QVal;
|
|
|
|
|
+ 2268 neg, isR, isL, folded:
|
|
|
|
|
+ 2269 BOOLEAN;
|
|
|
|
|
+ 2270 fok: BOOLEAN;
|
|
|
|
|
+ 2271 lw, rw, mw: CARDINAL;
|
|
|
|
|
+ 2272 lTrue, lNext, lDone, qr, qs:
|
|
|
|
|
+ 2273 QbeGen.QVal; .)
|
|
|
|
|
+ 2274 = (. neg := FALSE; .)
|
|
|
|
|
+ 2275 [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
|
|
+ 2276 Term<t, q> (. IF neg THEN
|
|
|
|
|
+ 2277 IF QbeGen.IsImm(q) THEN
|
|
|
|
|
+ 2278 QbeGen.NegFold(q, q)
|
|
|
|
|
+ 2279 ELSE QbeGen.NewTemp(qt);
|
|
|
|
|
+ 2280 QbeGen.NegQ(q, qt,
|
|
|
|
|
+ 2281 SymTab.ClassOf(t)
|
|
|
|
|
+ 2282 = SymTab.ClReal);
|
|
|
|
|
+ 2283 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2284 END
|
|
|
|
|
+ 2285 END; .)
|
|
|
|
|
+ 2286 { AddOp<op> (. IF op = SymTab.OpOr THEN
|
|
|
|
|
+ 2287 QbeGen.DelayBegin END; .)
|
|
|
|
|
+ 2288 Term<t2, q2> (. IF op = SymTab.OpOr THEN
|
|
|
|
|
+ 2289 QbeGen.DelayEnd END; .)
|
|
|
|
|
+ 2290 (. IF op = SymTab.OpOr THEN
|
|
|
|
|
+ 2291 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
|
|
+ 2292 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 2293 t := SymTab.BoolType()
|
|
|
|
|
+ 2294 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2295 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2296 QbeGen.Slot4(qs);
|
|
|
|
|
+ 2297 QbeGen.NewLabel(lTrue);
|
|
|
|
|
+ 2298 QbeGen.NewLabel(lNext);
|
|
|
|
|
+ 2299 QbeGen.NewLabel(lDone);
|
|
|
|
|
+ 2300 QbeGen.Jnz(q, lTrue, lNext);
|
|
|
|
|
+ 2301 QbeGen.EmitLabel(lTrue);
|
|
|
|
|
+ 2302 QbeGen.StoreW(qs, "1");
|
|
|
|
|
+ 2303 QbeGen.Jmp(lDone);
|
|
|
|
|
+ 2304 QbeGen.EmitLabel(lNext);
|
|
|
|
|
+ 2305 QbeGen.DelayFlush;
|
|
|
|
|
+ 2306 QbeGen.StoreW(qs, q2);
|
|
|
|
|
+ 2307 QbeGen.Jmp(lDone);
|
|
|
|
|
+ 2308 QbeGen.EmitLabel(lDone);
|
|
|
|
|
+ 2309 QbeGen.LoadW(qs, qr);
|
|
|
|
|
+ 2310 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 2311 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2312 END
|
|
|
|
|
+ 2313 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
+ 2314 AND (SymTab.UStrCompat(t, t2)
|
|
|
|
|
+ 2315 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
+ 2316 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
|
|
+ 2317 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
|
|
+ 2318 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
|
|
+ 2319 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
+ 2320 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
|
|
+ 2321 (* UString concatenation: a UCHAR operand becomes a
|
|
|
|
|
+ 2322 1-codepoint UString; the result is a descriptor in the
|
|
|
|
|
+ 2323 shim's concat buffer. Work on copies so neither
|
|
|
|
|
+ 2324 operand is clobbered. *)
|
|
|
|
|
+ 2325 IF SymTab.ClassOf(t) = SymTab.ClUStr THEN
|
|
|
|
|
+ 2326 QbeGen.CopyOp(q, q2a)
|
|
|
|
|
+ 2327 ELSE
|
|
|
|
|
+ 2328 QbeGen.UStrFrom(q, q2a)
|
|
|
|
|
+ 2329 END;
|
|
|
|
|
+ 2330 IF SymTab.ClassOf(t2) = SymTab.ClUStr THEN
|
|
|
|
|
+ 2331 QbeGen.UStrCat(q2a, q2, qt)
|
|
|
|
|
+ 2332 ELSE
|
|
|
|
|
+ 2333 QbeGen.UStrFrom(q2, q2b);
|
|
|
|
|
+ 2334 QbeGen.UStrCat(q2a, q2b, qt)
|
|
|
|
|
+ 2335 END;
|
|
|
|
|
+ 2336 t := SymTab.NewUStr();
|
|
|
|
|
+ 2337 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2338 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
+ 2339 AND (SymTab.StrCompat(t, t2)
|
|
|
|
|
+ 2340 OR (SymTab.IsStrType(t)
|
|
|
|
|
+ 2341 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
|
|
+ 2342 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
|
|
+ 2343 AND SymTab.IsStrType(t2))) THEN
|
|
|
|
|
+ 2344 (* string concatenation; a CHAR operand becomes a
|
|
|
|
|
+ 2345 1-character string literal. When both operands are
|
|
|
|
|
+ 2346 constants, fold to a single string literal so a
|
|
|
|
|
+ 2347 constructor element stays compile-time. *)
|
|
|
|
|
+ 2348 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
|
|
+ 2349 qt, fok);
|
|
|
|
|
+ 2350 IF NOT fok THEN
|
|
|
|
|
+ 2351 IF SymTab.StrCompat(t, t2) THEN
|
|
|
|
|
+ 2352 QbeGen.StrCat(q, q2, qt)
|
|
|
|
|
+ 2353 ELSIF SymTab.IsStrType(t) THEN
|
|
|
|
|
+ 2354 QbeGen.DeclCharStr(q2, qs);
|
|
|
|
|
+ 2355 QbeGen.StrCat(q, qs, qt)
|
|
|
|
|
+ 2356 ELSE
|
|
|
|
|
+ 2357 QbeGen.DeclCharStr(q, qs);
|
|
|
|
|
+ 2358 QbeGen.StrCat(qs, q2, qt)
|
|
|
|
|
+ 2359 END
|
|
|
|
|
+ 2360 END;
|
|
|
|
|
+ 2361 t := SymTab.NewStr();
|
|
|
|
|
+ 2362 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2363 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
+ 2364 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
+ 2365 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
+ 2366 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
+ 2367 mw := lw;
|
|
|
|
|
+ 2368 IF rw > mw THEN mw := rw END;
|
|
|
|
|
+ 2369 IF op = SymTab.OpAdd THEN
|
|
|
|
|
+ 2370 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
|
|
|
|
|
+ 2371 ELSE
|
|
|
|
|
+ 2372 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
|
|
|
|
|
+ 2373 END;
|
|
|
|
|
+ 2374 t := SymTab.NewSet(
|
|
|
|
|
+ 2375 SymTab.NewSubR(0,
|
|
|
|
|
+ 2376 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
+ 2377 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2378 ELSE
|
|
|
|
|
+ 2379 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
|
|
+ 2380 lt := t; rt := t2; t := res2
|
|
|
|
|
+ 2381 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2382 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2383 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
+ 2384 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 2385 folded := FALSE;
|
|
|
|
|
+ 2386 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
+ 2387 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ 2388 IF op = SymTab.OpAdd THEN
|
|
|
|
|
+ 2389 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
|
|
+ 2390 ELSE
|
|
|
|
|
+ 2391 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
|
|
+ 2392 END
|
|
|
|
|
+ 2393 END;
|
|
|
|
|
+ 2394 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
+ 2395 ELSE
|
|
|
|
|
+ 2396 IF isL THEN
|
|
|
|
|
+ 2397 IF SymTab.IsIntFamily(lt) THEN
|
|
|
|
|
+ 2398 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
|
|
+ 2399 END;
|
|
|
|
|
+ 2400 IF SymTab.IsIntFamily(rt) THEN
|
|
|
|
|
+ 2401 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
|
|
+ 2402 END;
|
|
|
|
|
+ 2403 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 2404 IF op = SymTab.OpAdd THEN
|
|
|
|
|
+ 2405 QbeGen.Op3L("add", qt, q, q2)
|
|
|
|
|
+ 2406 ELSE
|
|
|
|
|
+ 2407 QbeGen.Op3L("sub", qt, q, q2)
|
|
|
|
|
+ 2408 END
|
|
|
|
|
+ 2409 ELSE
|
|
|
|
|
+ 2410 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 2411 IF op = SymTab.OpAdd THEN
|
|
|
|
|
+ 2412 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
|
|
+ 2413 ELSE
|
|
|
|
|
+ 2414 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
|
|
+ 2415 END
|
|
|
|
|
+ 2416 END;
|
|
|
|
|
+ 2417 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2418 END
|
|
|
|
|
+ 2419 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2420 END
|
|
|
|
|
+ 2421 END; .) } .
|
|
|
|
|
+ 2422 AddOp<VAR op: INTEGER>
|
|
|
|
|
+ 2423 = "+" (. op := SymTab.OpAdd; .)
|
|
|
|
|
+ 2424 | "-" (. op := SymTab.OpSub; .)
|
|
|
|
|
+ 2425 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
|
|
+ 2426 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2427 (. VAR t2, res2, lt, rt:
|
|
|
|
|
+ 2428 SymTab.TypeIndex;
|
|
|
|
|
+ 2429 op: INTEGER;
|
|
|
|
|
+ 2430 q2, qt, wq, qf:
|
|
|
|
|
+ 2431 QbeGen.QVal;
|
|
|
|
|
+ 2432 isR, isL, folded: BOOLEAN;
|
|
|
|
|
+ 2433 lw, rw, mw: CARDINAL;
|
|
|
|
|
+ 2434 lNext, lFalse, lDone, qr, qs:
|
|
|
|
|
+ 2435 QbeGen.QVal; .)
|
|
|
|
|
+ 2436 = Fact<t, q> { MulOp<op> (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
+ 2437 QbeGen.DelayBegin END; .)
|
|
|
|
|
+ 2438 Fact<t2, q2> (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
+ 2439 QbeGen.DelayEnd END; .)
|
|
|
|
|
+ 2440 (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
+ 2441 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
|
|
+ 2442 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 2443 t := SymTab.BoolType()
|
|
|
|
|
+ 2444 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2445 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2446 QbeGen.Slot4(qs);
|
|
|
|
|
+ 2447 QbeGen.NewLabel(lNext);
|
|
|
|
|
+ 2448 QbeGen.NewLabel(lFalse);
|
|
|
|
|
+ 2449 QbeGen.NewLabel(lDone);
|
|
|
|
|
+ 2450 QbeGen.Jnz(q, lNext, lFalse);
|
|
|
|
|
+ 2451 QbeGen.EmitLabel(lNext);
|
|
|
|
|
+ 2452 QbeGen.DelayFlush;
|
|
|
|
|
+ 2453 QbeGen.StoreW(qs, q2);
|
|
|
|
|
+ 2454 QbeGen.Jmp(lDone);
|
|
|
|
|
+ 2455 QbeGen.EmitLabel(lFalse);
|
|
|
|
|
+ 2456 QbeGen.StoreW(qs, "0");
|
|
|
|
|
+ 2457 QbeGen.Jmp(lDone);
|
|
|
|
|
+ 2458 QbeGen.EmitLabel(lDone);
|
|
|
|
|
+ 2459 QbeGen.LoadW(qs, qr);
|
|
|
|
|
+ 2460 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 2461 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2462 END
|
|
|
|
|
+ 2463 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
+ 2464 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
+ 2465 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
+ 2466 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
+ 2467 mw := lw;
|
|
|
|
|
+ 2468 IF rw > mw THEN mw := rw END;
|
|
|
|
|
+ 2469 IF op = SymTab.OpTimes THEN
|
|
|
|
|
+ 2470 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
|
|
|
|
|
+ 2471 ELSE
|
|
|
|
|
+ 2472 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
|
|
|
|
|
+ 2473 END;
|
|
|
|
|
+ 2474 t := SymTab.NewSet(
|
|
|
|
|
+ 2475 SymTab.NewSubR(0,
|
|
|
|
|
+ 2476 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
+ 2477 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2478 ELSE
|
|
|
|
|
+ 2479 IF SymTab.ArithCheck(t, t2,
|
|
|
|
|
+ 2480 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
|
|
+ 2481 res2) THEN
|
|
|
|
|
+ 2482 lt := t; rt := t2; t := res2
|
|
|
|
|
+ 2483 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2484 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2485 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
+ 2486 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 2487 folded := FALSE;
|
|
|
|
|
+ 2488 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
+ 2489 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ 2490 IF op = SymTab.OpTimes THEN
|
|
|
|
|
+ 2491 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
|
|
+ 2492 ELSIF op = SymTab.OpDiv THEN
|
|
|
|
|
+ 2493 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
|
|
+ 2494 ELSIF op = SymTab.OpMod THEN
|
|
|
|
|
+ 2495 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
|
|
+ 2496 END
|
|
|
|
|
+ 2497 END;
|
|
|
|
|
+ 2498 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
+ 2499 ELSE
|
|
|
|
|
+ 2500 IF isL THEN
|
|
|
|
|
+ 2501 IF SymTab.IsIntFamily(lt) THEN
|
|
|
|
|
+ 2502 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
|
|
+ 2503 END;
|
|
|
|
|
+ 2504 IF SymTab.IsIntFamily(rt) THEN
|
|
|
|
|
+ 2505 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
|
|
+ 2506 END;
|
|
|
|
|
+ 2507 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 2508 IF op = SymTab.OpTimes THEN
|
|
|
|
|
+ 2509 QbeGen.Op3L("mul", qt, q, q2)
|
|
|
|
|
+ 2510 ELSIF (op = SymTab.OpDiv)
|
|
|
|
|
+ 2511 OR (op = SymTab.OpSlash) THEN
|
|
|
|
|
+ 2512 QbeGen.Op3L("div", qt, q, q2)
|
|
|
|
|
+ 2513 ELSE
|
|
|
|
|
+ 2514 QbeGen.Op3L("rem", qt, q, q2)
|
|
|
|
|
+ 2515 END
|
|
|
|
|
+ 2516 ELSE
|
|
|
|
|
+ 2517 QbeGen.NewTemp(qt);
|
|
|
|
|
+ 2518 IF op = SymTab.OpTimes THEN
|
|
|
|
|
+ 2519 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
|
|
+ 2520 ELSIF (op = SymTab.OpDiv)
|
|
|
|
|
+ 2521 OR (op = SymTab.OpSlash) THEN
|
|
|
|
|
+ 2522 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
|
|
+ 2523 ELSE
|
|
|
|
|
+ 2524 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
|
|
+ 2525 END
|
|
|
|
|
+ 2526 END;
|
|
|
|
|
+ 2527 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2528 END
|
|
|
|
|
+ 2529 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2530 END
|
|
|
|
|
+ 2531 END; .) } .
|
|
|
|
|
+ 2532 MulOp<VAR op: INTEGER>
|
|
|
|
|
+ 2533 = "*" (. op := SymTab.OpTimes; .)
|
|
|
|
|
+ 2534 | "/" (. op := SymTab.OpSlash; .)
|
|
|
|
|
+ 2535 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
|
|
+ 2536 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
|
|
+ 2537 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
|
|
+ 2538 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2539 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
|
|
+ 2540 et, dt, t2, st, ct2, et2:
|
|
|
|
|
+ 2541 SymTab.TypeIndex;
|
|
|
|
|
+ 2542 dk: INTEGER;
|
|
|
|
|
+ 2543 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
|
|
+ 2544 QbeGen.QVal;
|
|
|
|
|
+ 2545 qn, vn: SymTab.Name;
|
|
|
|
|
+ 2546 vt: SymTab.TypeIndex;
|
|
|
|
|
+ 2547 c1, c2: INTEGER;
|
|
|
|
|
+ 2548 lo, hi: INTEGER;
|
|
|
|
|
+ 2549 isMax: BOOLEAN;
|
|
|
|
|
+ 2550 called, isHigh, sfx, isCh,
|
|
|
|
|
+ 2551 isU, uok, isStr: BOOLEAN;
|
|
|
|
|
+ 2552 ucp: INTEGER; .)
|
|
|
|
|
+ 2553 = integer (. LexString(s);
|
|
|
|
|
+ 2554 QbeGen.NormInt(s, q);
|
|
|
|
|
+ 2555 t := SymTab.IntType(); .)
|
|
|
|
|
+ 2556 | charConst (. LexString(s);
|
|
|
|
|
+ 2557 QbeGen.NormLit(s, q, isCh);
|
|
|
|
|
+ 2558 t := SymTab.CharType(); .)
|
|
|
|
|
+ 2559 | real (. LexString(s);
|
|
|
|
|
+ 2560 QbeGen.NormReal(s, q);
|
|
|
|
|
+ 2561 t := SymTab.RealType(); .)
|
|
|
|
|
+ 2562 | string (. LexString(s);
|
|
|
|
|
+ 2563 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
+ 2564 t := SymTab.CharType();
|
|
|
|
|
+ 2565 QbeGen.IntStr(
|
|
|
|
|
+ 2566 QbeGen.CharVal(s), q)
|
|
|
|
|
+ 2567 ELSE t := SymTab.NewStr();
|
|
|
|
|
+ 2568 QbeGen.DeclStr(s, q);
|
|
|
|
|
+ 2569 (* a literal's value IS its
|
|
|
|
|
+ 2570 static descriptor address *)
|
|
|
|
|
+ 2571 QbeGen.NoteAddr(q, q)
|
|
|
|
|
+ 2572 END; .)
|
|
|
|
|
+ 2573 | ustring (. LexString(s);
|
|
|
|
|
+ 2574 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
|
|
+ 2575 uok);
|
|
|
|
|
+ 2576 IF NOT uok THEN
|
|
|
|
|
+ 2577 SemError(234);
|
|
|
|
|
+ 2578 t := SymTab.InvalidType
|
|
|
|
|
+ 2579 ELSIF isU THEN
|
|
|
|
|
+ 2580 t := SymTab.UCharType();
|
|
|
|
|
+ 2581 QbeGen.IntStr(ucp, q)
|
|
|
|
|
+ 2582 ELSE
|
|
|
|
|
+ 2583 t := SymTab.NewUStr();
|
|
|
|
|
+ 2584 QbeGen.NoteAddr(q, q)
|
|
|
|
|
+ 2585 END; .)
|
|
|
|
|
+ 2586 | Design<dt, dk, qd, qn, sfx> (. called := FALSE;
|
|
|
|
|
+ 2587 t := dt;
|
|
|
|
|
+ 2588 IF sfx THEN
|
|
|
|
|
+ 2589 IF dt =
|
|
|
|
|
+ 2590 SymTab.InvalidType THEN
|
|
|
|
|
+ 2591 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2592 ELSIF (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2593 SymTab.ClRecord)
|
|
|
|
|
+ 2594 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2595 SymTab.ClSet)
|
|
|
|
|
+ 2596 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2597 SymTab.ClArray)
|
|
|
|
|
+ 2598 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2599 SymTab.ClClass) THEN
|
|
|
|
|
+ 2600 QbeGen.CopyOp(qd, q)
|
|
|
|
|
+ 2601 ELSE QbeGen.ElemLoad(qd, dt,
|
|
|
|
|
+ 2602 q)
|
|
|
|
|
+ 2603 END
|
|
|
|
|
+ 2604 ELSE QbeGen.CopyOp(qd, q)
|
|
|
|
|
+ 2605 END;
|
|
|
|
|
+ 2606 IF (dk = SymTab.KindVar)
|
|
|
|
|
+ 2607 OR (dk = SymTab.KindParam)
|
|
|
|
|
+ 2608 OR (dk =
|
|
|
|
|
+ 2609 SymTab.KindField) THEN
|
|
|
|
|
+ 2610 IF sfx THEN
|
|
|
|
|
+ 2611 QbeGen.NoteAddr(q, qd)
|
|
|
|
|
+ 2612 ELSE
|
|
|
|
|
+ 2613 QbeGen.AddrOf(qn, qa);
|
|
|
|
|
+ 2614 QbeGen.NoteAddr(q, qa)
|
|
|
|
|
+ 2615 END
|
|
|
|
|
+ 2616 ELSIF sfx
|
|
|
|
|
+ 2617 AND (dt #
|
|
|
|
|
+ 2618 SymTab.InvalidType)
|
|
|
|
|
+ 2619 AND ((SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2620 SymTab.ClArray)
|
|
|
|
|
+ 2621 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2622 SymTab.ClSet)
|
|
|
|
|
+ 2623 OR (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2624 SymTab.ClRecord)) THEN
|
|
|
|
|
+ 2625 QbeGen.NoteAddr(qd, qd)
|
|
|
|
|
+ 2626 END; .)
|
|
|
|
|
+ 2627 [ TypedBraceLit<dt, q> (. t := dt; .) ]
|
|
|
|
|
+ 2628 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
|
|
+ 2629 (. t := ct2;
|
|
|
|
|
+ 2630 QbeGen.CopyOp(q2, q);
|
|
|
|
|
+ 2631 sfx := FALSE; .)
|
|
|
|
|
+ 2632 { ResultComp<t, q, sfx> }
|
|
|
|
|
+ 2633 (. IF sfx THEN
|
|
|
|
|
+ 2634 IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2635 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2636 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
+ 2637 SymTab.ClRecord)
|
|
|
|
|
+ 2638 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
|
|
+ 2639 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
|
|
+ 2640 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
+ 2641 QbeGen.ElemLoad(q, t, q2);
|
|
|
|
|
+ 2642 QbeGen.CopyOp(q2, q)
|
|
|
|
|
+ 2643 END
|
|
|
|
|
+ 2644 END; .) ]
|
|
|
|
|
+ 2645 (. IF NOT called
|
|
|
|
|
+ 2646 AND (dk = SymTab.KindProc) THEN
|
|
|
|
|
+ 2647 (* bare zero-arg function
|
|
|
|
|
+ 2648 call (parentheses may be
|
|
|
|
|
+ 2649 omitted); a proper or
|
|
|
|
|
+ 2650 parameterised proc here
|
|
|
|
|
+ 2651 is 230 *)
|
|
|
|
|
+ 2652 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
|
|
+ 2653 AND (SymTab.ProcRes(qn) #
|
|
|
|
|
+ 2654 SymTab.InvalidType) THEN
|
|
|
|
|
+ 2655 QbeGen.Mangled(qn,
|
|
|
|
|
+ 2656 SymTab.ProcUid(qn), qm0);
|
|
|
|
|
+ 2657 QbeGen.CallBegin(qm0,
|
|
|
|
|
+ 2658 SymTab.ProcRes(qn),
|
|
|
|
|
+ 2659 SymTab.ProcDepthOf(qn),
|
|
|
|
|
+ 2660 SymTab.IsExternal(qn));
|
|
|
|
|
+ 2661 QbeGen.CallEnd(TRUE, q);
|
|
|
|
|
+ 2662 t := SymTab.ProcRes(qn)
|
|
|
|
|
+ 2663 ELSE
|
|
|
|
|
+ 2664 (* procedure used as a
|
|
|
|
|
+ 2665 value (assign to a
|
|
|
|
|
+ 2666 procedure variable):
|
|
|
|
|
+ 2667 its code address *)
|
|
|
|
|
+ 2668 t := SymTab.ProcTypeOf(qn);
|
|
|
|
|
+ 2669 QbeGen.Mangled(qn,
|
|
|
|
|
+ 2670 SymTab.ProcUid(qn), qm0);
|
|
|
|
|
+ 2671 QbeGen.ProcAddr(qm0, q)
|
|
|
|
|
+ 2672 END
|
|
|
|
|
+ 2673 END; .)
|
|
|
|
|
+ 2674 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
|
|
+ 2675 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
|
|
+ 2676 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
|
|
+ 2677 isU := FALSE; .)
|
|
|
|
|
+ 2678 | string (. LexString(s);
|
|
|
|
|
+ 2679 isStr := TRUE;
|
|
|
|
|
+ 2680 isU := FALSE;
|
|
|
|
|
+ 2681 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
+ 2682 dt := SymTab.CharType();
|
|
|
|
|
+ 2683 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
|
|
+ 2684 qd)
|
|
|
|
|
+ 2685 ELSE
|
|
|
|
|
+ 2686 dt := SymTab.NewStr();
|
|
|
|
|
+ 2687 QbeGen.DeclStr(s, qd);
|
|
|
|
|
+ 2688 QbeGen.NoteAddr(qd, qd)
|
|
|
|
|
+ 2689 END;
|
|
|
|
|
+ 2690 dk := -1;
|
|
|
|
|
+ 2691 qn[0] := CHR(0); .)
|
|
|
|
|
+ 2692 | ustring (. LexString(s);
|
|
|
|
|
+ 2693 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
|
|
+ 2694 uok);
|
|
|
|
|
+ 2695 isStr := FALSE;
|
|
|
|
|
+ 2696 IF NOT uok THEN
|
|
|
|
|
+ 2697 SemError(234);
|
|
|
|
|
+ 2698 dt := SymTab.InvalidType
|
|
|
|
|
+ 2699 ELSIF isU THEN
|
|
|
|
|
+ 2700 (* one codepoint: a UCHAR;
|
|
|
|
|
+ 2701 LEN is 1, HIGH is 0 *)
|
|
|
|
|
+ 2702 dt := SymTab.UCharType();
|
|
|
|
|
+ 2703 QbeGen.IntStr(ucp, qd)
|
|
|
|
|
+ 2704 ELSE
|
|
|
|
|
+ 2705 dt := SymTab.NewUStr();
|
|
|
|
|
+ 2706 QbeGen.NoteAddr(qd, qd)
|
|
|
|
|
+ 2707 END;
|
|
|
|
|
+ 2708 dk := -1;
|
|
|
|
|
+ 2709 qn[0] := CHR(0); .) )
|
|
|
|
|
+ 2710 ")"
|
|
|
|
|
+ 2711 (. IF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 2712 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
|
|
+ 2713 (* UString: the count is
|
|
|
|
|
+ 2714 the descriptor header *)
|
|
|
|
|
+ 2715 IF isHigh THEN
|
|
|
|
|
+ 2716 QbeGen.UStrLen(qd, qr);
|
|
|
|
|
+ 2717 QbeGen.DecQ(qr)
|
|
|
|
|
+ 2718 ELSE
|
|
|
|
|
+ 2719 QbeGen.UStrLen(qd, qr)
|
|
|
|
|
+ 2720 END;
|
|
|
|
|
+ 2721 t := SymTab.IntType();
|
|
|
|
|
+ 2722 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 2723 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 2724 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
|
|
+ 2725 (* single UCHAR codepoint *)
|
|
|
|
|
+ 2726 IF isHigh THEN
|
|
|
|
|
+ 2727 QbeGen.CopyOp("0", qr)
|
|
|
|
|
+ 2728 ELSE
|
|
|
|
|
+ 2729 QbeGen.CopyOp("1", qr)
|
|
|
|
|
+ 2730 END;
|
|
|
|
|
+ 2731 t := SymTab.IntType();
|
|
|
|
|
+ 2732 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 2733 ELSIF isStr THEN
|
|
|
|
|
+ 2734 (* fold: content length at
|
|
|
|
|
+ 2735 compile time *)
|
|
|
|
|
+ 2736 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
+ 2737 c1 := 1
|
|
|
|
|
+ 2738 ELSE
|
|
|
|
|
+ 2739 c1 :=
|
|
|
|
|
+ 2740 SymTab.StrLen(s) - 2
|
|
|
|
|
+ 2741 END;
|
|
|
|
|
+ 2742 IF isHigh THEN
|
|
|
|
|
+ 2743 DEC(c1)
|
|
|
|
|
+ 2744 END;
|
|
|
|
|
+ 2745 QbeGen.IntStr(c1, qr);
|
|
|
|
|
+ 2746 t := SymTab.IntType();
|
|
|
|
|
+ 2747 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 2748 ELSIF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 2749 t := SymTab.InvalidType;
|
|
|
|
|
+ 2750 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2751 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
+ 2752 SymTab.ClArray THEN
|
|
|
|
|
+ 2753 SemError(217);
|
|
|
|
|
+ 2754 t := SymTab.InvalidType;
|
|
|
|
|
+ 2755 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2756 ELSE
|
|
|
|
|
+ 2757 IF isHigh THEN
|
|
|
|
|
+ 2758 IF SymTab.IsOpenArray(dt) THEN
|
|
|
|
|
+ 2759 QbeGen.OpenHi(qd, qr)
|
|
|
|
|
+ 2760 ELSE
|
|
|
|
|
+ 2761 QbeGen.IntStr(
|
|
|
|
|
+ 2762 SymTab.ArrayHi(dt), qr)
|
|
|
|
|
+ 2763 END
|
|
|
|
|
+ 2764 ELSE
|
|
|
|
|
+ 2765 IF SymTab.IsOpenArray(dt) THEN
|
|
|
|
|
+ 2766 QbeGen.LoadCount(qd, qr)
|
|
|
|
|
+ 2767 ELSE
|
|
|
|
|
+ 2768 QbeGen.IntStr(VAL(
|
|
|
|
|
+ 2769 INTEGER,
|
|
|
|
|
+ 2770 SymTab.ArrayLen(dt)),
|
|
|
|
|
+ 2771 qr)
|
|
|
|
|
+ 2772 END
|
|
|
|
|
+ 2773 END;
|
|
|
|
|
+ 2774 t := SymTab.IntType();
|
|
|
|
|
+ 2775 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 2776 END; .)
|
|
|
|
|
+ 2777 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 2778 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 2779 t := SymTab.InvalidType;
|
|
|
|
|
+ 2780 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2781 ELSE
|
|
|
|
|
+ 2782 QbeGen.IntStr(VAL(INTEGER,
|
|
|
|
|
+ 2783 SymTab.ObjectSize(dt)), q);
|
|
|
|
|
+ 2784 t := SymTab.IntType()
|
|
|
|
|
+ 2785 END; .)
|
|
|
|
|
+ 2786 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
|
|
+ 2787 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
|
|
+ 2788 "(" Expr<et, q> "," Expr<et2, q2> ")"
|
|
|
|
|
+ 2789 (. (* set shift/rotate: isMax
|
|
|
|
|
+ 2790 doubles as "rotate" *)
|
|
|
|
|
+ 2791 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 2792 AND (SymTab.ClassOf(et) =
|
|
|
|
|
+ 2793 SymTab.ClSet) THEN
|
|
|
|
|
+ 2794 QbeGen.SetShift(q, q2,
|
|
|
|
|
+ 2795 SymTab.SetWords(et),
|
|
|
|
|
+ 2796 SymTab.SetCount(et), isMax,
|
|
|
|
|
+ 2797 qt);
|
|
|
|
|
+ 2798 t := et;
|
|
|
|
|
+ 2799 QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2800 ELSE SemError(230);
|
|
|
|
|
+ 2801 t := SymTab.InvalidType;
|
|
|
|
|
+ 2802 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2803 END; .)
|
|
|
|
|
+ 2804 | ( "MIN" (. isMax := FALSE; .)
|
|
|
|
|
+ 2805 | "MAX" (. isMax := TRUE; .) )
|
|
|
|
|
+ 2806 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 2807 (. IF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 2808 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
|
|
+ 2809 (* REAL/LONGREAL: the
|
|
|
|
|
+ 2810 implementation bounds *)
|
|
|
|
|
+ 2811 IF isMax THEN
|
|
|
|
|
+ 2812 QbeGen.NormReal(
|
|
|
|
|
+ 2813 "3.402823e38", q)
|
|
|
|
|
+ 2814 ELSE QbeGen.NormReal(
|
|
|
|
|
+ 2815 "-3.402823e38", q)
|
|
|
|
|
+ 2816 END;
|
|
|
|
|
+ 2817 t := SymTab.RealType()
|
|
|
|
|
+ 2818 ELSIF (dt #
|
|
|
|
|
+ 2819 SymTab.InvalidType)
|
|
|
|
|
+ 2820 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 2821 SymTab.ClLong) THEN
|
|
|
|
|
+ 2822 IF isMax THEN
|
|
|
|
|
+ 2823 QbeGen.CopyOp(
|
|
|
|
|
+ 2824 "9223372036854775807", q)
|
|
|
|
|
+ 2825 ELSE QbeGen.CopyOp(
|
|
|
|
|
+ 2826 "-9223372036854775808", q)
|
|
|
|
|
+ 2827 END;
|
|
|
|
|
+ 2828 t := SymTab.LongType()
|
|
|
|
|
+ 2829 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
|
|
+ 2830 hi) THEN
|
|
|
|
|
+ 2831 IF isMax THEN
|
|
|
|
|
+ 2832 QbeGen.IntStr(hi, q)
|
|
|
|
|
+ 2833 ELSE QbeGen.IntStr(lo, q)
|
|
|
|
|
+ 2834 END;
|
|
|
|
|
+ 2835 t := SymTab.IntType()
|
|
|
|
|
+ 2836 ELSE SemError(230);
|
|
|
|
|
+ 2837 t := SymTab.InvalidType;
|
|
|
|
|
+ 2838 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2839 END; .)
|
|
|
|
|
+ 2840 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 2841 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 2842 t := SymTab.InvalidType;
|
|
|
|
|
+ 2843 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2844 ELSE
|
|
|
|
|
+ 2845 IF sfx THEN
|
|
|
|
|
+ 2846 QbeGen.CopyOp(qd, q)
|
|
|
|
|
+ 2847 ELSIF (dk = SymTab.KindVar)
|
|
|
|
|
+ 2848 OR (dk = SymTab.KindParam) THEN
|
|
|
|
|
+ 2849 QbeGen.AddrOf(qn, q)
|
|
|
|
|
+ 2850 ELSE SemError(230);
|
|
|
|
|
+ 2851 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2852 END;
|
|
|
|
|
+ 2853 t := SymTab.AddrType()
|
|
|
|
|
+ 2854 END; .)
|
|
|
|
|
+ 2855 | "CHR" "(" Expr<et, q> ")"
|
|
|
|
|
+ 2856 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 2857 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
+ 2858 SemError(211) END;
|
|
|
|
|
+ 2859 t := SymTab.CharType(); .)
|
|
|
|
|
+ 2860 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
|
|
+ 2861 (. IF et # SymTab.InvalidType THEN
|
|
|
|
|
+ 2862 IF (SymTab.ClassOf(et) #
|
|
|
|
|
+ 2863 SymTab.ClChar)
|
|
|
|
|
+ 2864 AND (SymTab.ClassOf(et) #
|
|
|
|
|
+ 2865 SymTab.ClBool)
|
|
|
|
|
+ 2866 AND (SymTab.ClassOf(et) #
|
|
|
|
|
+ 2867 SymTab.ClEnum)
|
|
|
|
|
+ 2868 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
+ 2869 SemError(211) END
|
|
|
|
|
+ 2870 END;
|
|
|
|
|
+ 2871 t := SymTab.IntType(); .)
|
|
|
|
|
+ 2872 | "CAP" "(" Expr<et, q> ")"
|
|
|
|
|
+ 2873 (. QbeGen.CapQ(q, qa);
|
|
|
|
|
+ 2874 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 2875 t := SymTab.CharType(); .)
|
|
|
|
|
+ 2876 | "UCHR" "(" Expr<et, q> ")"
|
|
|
|
|
+ 2877 (. (* UCHR: the UCHAR constructor.
|
|
|
|
|
+ 2878 CHAR -> UCHAR (identity);
|
|
|
|
|
+ 2879 INTEGER familly -> UCHAR
|
|
|
|
|
+ 2880 (codepoint value). *)
|
|
|
|
|
+ 2881 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 2882 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
|
|
+ 2883 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
+ 2884 SemError(211) END;
|
|
|
|
|
+ 2885 t := SymTab.UCharType(); .)
|
|
|
|
|
+ 2886 | "CHR8" "(" Expr<et, q> ")"
|
|
|
|
|
+ 2887 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 2888 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
+ 2889 SemError(211) END;
|
|
|
|
|
+ 2890 QbeGen.WidenLong(q, qa);
|
|
|
|
|
+ 2891 QbeGen.CheckRange(qa, "0", "255");
|
|
|
|
|
+ 2892 t := SymTab.CharType(); .)
|
|
|
|
|
+ 2893 | "UORD" "(" Expr<et, q> ")"
|
|
|
|
|
+ 2894 (. (* UORD(u): the codepoint as a
|
|
|
|
|
+ 2895 32-bit ordinal (INTEGER),
|
|
|
|
|
+ 2896 cf. ORD for CHAR. *)
|
|
|
|
|
+ 2897 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 2898 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
+ 2899 SemError(211) END;
|
|
|
|
|
+ 2900 t := SymTab.IntType(); .)
|
|
|
|
|
+ 2901 | "ABS" "(" Expr<et, q> ")"
|
|
|
|
|
+ 2902 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 2903 AND NOT SymTab.IsIntFamily(et)
|
|
|
|
|
+ 2904 AND (SymTab.ClassOf(et) #
|
|
|
|
|
+ 2905 SymTab.ClReal) THEN
|
|
|
|
|
+ 2906 SemError(211)
|
|
|
|
|
+ 2907 ELSE QbeGen.AbsQ(q, qa,
|
|
|
|
|
+ 2908 SymTab.ClassOf(et) =
|
|
|
|
|
+ 2909 SymTab.ClReal);
|
|
|
|
|
+ 2910 QbeGen.CopyOp(qa, q)
|
|
|
|
|
+ 2911 END;
|
|
|
|
|
+ 2912 t := et; .)
|
|
|
|
|
+ 2913 | "VAL" "(" GetIdent<vn> "," Expr<et, q> ")"
|
|
|
|
|
+ 2914 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
|
|
+ 2915 SemError(201);
|
|
|
|
|
+ 2916 t := SymTab.InvalidType
|
|
|
|
|
+ 2917 ELSE vt := SymTab.SymType(vn);
|
|
|
|
|
+ 2918 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
+ 2919 t := SymTab.InvalidType
|
|
|
|
|
+ 2920 ELSIF et =
|
|
|
|
|
+ 2921 SymTab.InvalidType THEN
|
|
|
|
|
+ 2922 t := vt
|
|
|
|
|
+ 2923 ELSE
|
|
|
|
|
+ 2924 c1 := SymTab.ClassOf(et);
|
|
|
|
|
+ 2925 c2 := SymTab.ClassOf(vt);
|
|
|
|
|
+ 2926 IF (c1 = SymTab.ClInt)
|
|
|
|
|
+ 2927 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
+ 2928 QbeGen.WidenLong(q, qa);
|
|
|
|
|
+ 2929 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 2930 t := vt
|
|
|
|
|
+ 2931 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
+ 2932 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
+ 2933 QbeGen.NarrowLong(q, qa);
|
|
|
|
|
+ 2934 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 2935 t := vt
|
|
|
|
|
+ 2936 ELSIF (c1 = SymTab.ClInt)
|
|
|
|
|
+ 2937 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
+ 2938 QbeGen.ConvIR(q, qa);
|
|
|
|
|
+ 2939 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 2940 t := vt
|
|
|
|
|
+ 2941 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
+ 2942 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
+ 2943 QbeGen.ConvLR(q, qa);
|
|
|
|
|
+ 2944 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 2945 t := vt
|
|
|
|
|
+ 2946 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
+ 2947 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
+ 2948 QbeGen.ConvRI(q, qa);
|
|
|
|
|
+ 2949 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 2950 t := vt
|
|
|
|
|
+ 2951 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
+ 2952 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
+ 2953 QbeGen.ConvRL(q, qa);
|
|
|
|
|
+ 2954 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 2955 t := vt
|
|
|
|
|
+ 2956 ELSIF ((c1 = SymTab.ClInt)
|
|
|
|
|
+ 2957 OR (c1 =
|
|
|
|
|
+ 2958 SymTab.ClChar)
|
|
|
|
|
+ 2959 OR (c1 =
|
|
|
|
|
+ 2960 SymTab.ClBool)
|
|
|
|
|
+ 2961 OR (c1 =
|
|
|
|
|
+ 2962 SymTab.ClEnum))
|
|
|
|
|
+ 2963 AND ((c2 = SymTab.ClInt)
|
|
|
|
|
+ 2964 OR (c2 =
|
|
|
|
|
+ 2965 SymTab.ClChar)
|
|
|
|
|
+ 2966 OR (c2 =
|
|
|
|
|
+ 2967 SymTab.ClBool)
|
|
|
|
|
+ 2968 OR (c2 =
|
|
|
|
|
+ 2969 SymTab.ClEnum)) THEN
|
|
|
|
|
+ 2970 t := vt
|
|
|
|
|
+ 2971 ELSIF (c1 = SymTab.ClPtr)
|
|
|
|
|
+ 2972 AND (c2 = SymTab.ClPtr) THEN
|
|
|
|
|
+ 2973 t := vt
|
|
|
|
|
+ 2974 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
+ 2975 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
+ 2976 t := vt
|
|
|
|
|
+ 2977 ELSE SemError(230);
|
|
|
|
|
+ 2978 t := SymTab.InvalidType
|
|
|
|
|
+ 2979 END
|
|
|
|
|
+ 2980 END
|
|
|
|
|
+ 2981 END; .)
|
|
|
|
|
+ 2982 | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
|
|
+ 2983 | SetLit<st, sq> (. t := st;
|
|
|
|
|
+ 2984 QbeGen.CopyOp(sq, q); .)
|
|
|
|
|
+ 2985 | ( "NOT" | "~" ) Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 2986 t := SymTab.BoolType()
|
|
|
|
|
+ 2987 ELSE SemError(212);
|
|
|
|
|
+ 2988 t := SymTab.InvalidType END;
|
|
|
|
|
+ 2989 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2990 QbeGen.NotQ(q2, q)
|
|
|
|
|
+ 2991 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2992 END; .) .
|
|
|
|
|
+ 2993 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
|
|
+ 2994 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
|
|
+ 2995 for computed elements. Ranges always lower via SetRange. *)
|
|
|
|
|
+ 2996 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2997 = "{" (. t := SymTab.NewSet(
|
|
|
|
|
+ 2998 SymTab.NewSubR(0, 255));
|
|
|
|
|
+ 2999 QbeGen.NewSetTemp(8, q);
|
|
|
|
|
+ 3000 QbeGen.SetZero(q, 8); .)
|
|
|
|
|
+ 3001 [ SetElem<t, q> { "," SetElem<t, q> } ]
|
|
|
|
|
+ 3002 "}" .
|
|
|
|
|
+ 3003 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
|
|
+ 3004 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
|
|
+ 3005 declared type sets the width (set) or element type (array). *)
|
|
|
|
|
+ 3006 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 3007 (. VAR nw: CARDINAL;
|
|
|
|
|
+ 3008 savedCls: INTEGER; .)
|
|
|
|
|
+ 3009 = "{" (. savedCls := braceCls;
|
|
|
|
|
+ 3010 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3011 braceCls := -1
|
|
|
|
|
+ 3012 ELSE braceCls :=
|
|
|
|
|
+ 3013 SymTab.ClassOf(vt)
|
|
|
|
|
+ 3014 END;
|
|
|
|
|
+ 3015 IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
+ 3016 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3017 nw := 8
|
|
|
|
|
+ 3018 ELSE nw := SymTab.SetWords(vt);
|
|
|
|
|
+ 3019 IF nw = 0 THEN nw := 8 END
|
|
|
|
|
+ 3020 END;
|
|
|
|
|
+ 3021 QbeGen.NewSetTemp(nw, q);
|
|
|
|
|
+ 3022 QbeGen.SetZero(q, nw)
|
|
|
|
|
+ 3023 ELSIF (braceCls =
|
|
|
|
|
+ 3024 SymTab.ClArray)
|
|
|
|
|
+ 3025 OR (braceCls =
|
|
|
|
|
+ 3026 SymTab.ClRecord)
|
|
|
|
|
+ 3027 OR (braceCls =
|
|
|
|
|
+ 3028 SymTab.ClClass) THEN
|
|
|
|
|
+ 3029 QbeGen.CtorBegin(vt)
|
|
|
|
|
+ 3030 ELSE
|
|
|
|
|
+ 3031 IF vt # SymTab.InvalidType THEN
|
|
|
|
|
+ 3032 SemError(230) END;
|
|
|
|
|
+ 3033 braceCls := -1
|
|
|
|
|
+ 3034 END; .)
|
|
|
|
|
+ 3035 [ BraceElem<vt, q> { "," BraceElem<vt, q> } ]
|
|
|
|
|
+ 3036 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
|
|
+ 3037 OR (braceCls =
|
|
|
|
|
+ 3038 SymTab.ClRecord)
|
|
|
|
|
+ 3039 OR (braceCls =
|
|
|
|
|
+ 3040 SymTab.ClClass) THEN
|
|
|
|
|
+ 3041 QbeGen.CtorEnd(q)
|
|
|
|
|
+ 3042 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
|
|
+ 3043 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3044 END;
|
|
|
|
|
+ 3045 braceCls := savedCls; .) .
|
|
|
|
|
+ 3046 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal>
|
|
|
|
|
+ 3047 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 3048 qe, q2: QbeGen.QVal;
|
|
|
|
|
+ 3049 v, v2, reps, k: INTEGER;
|
|
|
|
|
+ 3050 elem: SymTab.TypeIndex;
|
|
|
|
|
+ 3051 lo: INTEGER;
|
|
|
|
|
+ 3052 span: CARDINAL;
|
|
|
|
|
+ 3053 cl, cl2: INTEGER;
|
|
|
|
|
+ 3054 hasR, hasB: BOOLEAN; .)
|
|
|
|
|
+ 3055 = (. hasR := FALSE; hasB := FALSE; .)
|
|
|
|
|
+ 3056 Expr<et, qe>
|
|
|
|
|
+ 3057 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
|
|
+ 3058 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
|
|
+ 3059 (. IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
+ 3060 IF hasB THEN SemError(230) END;
|
|
|
|
|
+ 3061 lo := SymTab.SetBaseLo(vt);
|
|
|
|
|
+ 3062 span := SymTab.SetCount(vt);
|
|
|
|
|
+ 3063 IF (et = SymTab.InvalidType)
|
|
|
|
|
+ 3064 OR (hasR AND (et2 =
|
|
|
|
|
+ 3065 SymTab.InvalidType)) THEN
|
|
|
|
|
+ 3066 ELSE cl :=
|
|
|
|
|
+ 3067 SymTab.ClassOf(et);
|
|
|
|
|
+ 3068 IF hasR THEN
|
|
|
|
|
+ 3069 cl2 :=
|
|
|
|
|
+ 3070 SymTab.ClassOf(et2)
|
|
|
|
|
+ 3071 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
+ 3072 END;
|
|
|
|
|
+ 3073 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
+ 3074 OR (hasR AND NOT
|
|
|
|
|
+ 3075 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
+ 3076 THEN
|
|
|
|
|
+ 3077 SemError(222)
|
|
|
|
|
+ 3078 ELSIF hasR
|
|
|
|
|
+ 3079 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
+ 3080 AND SymTab.ConstInt(q2,
|
|
|
|
|
+ 3081 v2)
|
|
|
|
|
+ 3082 AND ((v < lo)
|
|
|
|
|
+ 3083 OR (v2 < lo)
|
|
|
|
|
+ 3084 OR (v >= lo +
|
|
|
|
|
+ 3085 VAL(INTEGER, span))
|
|
|
|
|
+ 3086 OR (v2 >= lo +
|
|
|
|
|
+ 3087 VAL(INTEGER, span))
|
|
|
|
|
+ 3088 OR (v > v2)) THEN
|
|
|
|
|
+ 3089 SemError(222)
|
|
|
|
|
+ 3090 ELSIF hasR THEN
|
|
|
|
|
+ 3091 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
+ 3092 lo, span)
|
|
|
|
|
+ 3093 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
+ 3094 v)
|
|
|
|
|
+ 3095 AND ((v < lo)
|
|
|
|
|
+ 3096 OR (v >= lo +
|
|
|
|
|
+ 3097 VAL(INTEGER,
|
|
|
|
|
+ 3098 span))) THEN
|
|
|
|
|
+ 3099 SemError(222)
|
|
|
|
|
+ 3100 ELSE QbeGen.SetBit(sq, qe,
|
|
|
3101 lo, span)
|
|
3101 lo, span)
|
|
|
- 3102 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
- 3103 v)
|
|
|
|
|
- 3104 AND ((v < lo)
|
|
|
|
|
- 3105 OR (v >= lo +
|
|
|
|
|
- 3106 VAL(INTEGER,
|
|
|
|
|
- 3107 span))) THEN
|
|
|
|
|
- 3108 SemError(222)
|
|
|
|
|
- 3109 ELSE QbeGen.SetBit(sq, qe,
|
|
|
|
|
- 3110 lo, span)
|
|
|
|
|
- 3111 END
|
|
|
|
|
- 3112 END; .) .
|
|
|
|
|
- 3113 GetIdent<VAR n: SymTab.Name>
|
|
|
|
|
- 3114 = ident (. LexName(n); .) .
|
|
|
|
|
- 3115
|
|
|
|
|
- 3116 END M2.
|
|
|
|
|
|
|
+ 3102 END
|
|
|
|
|
+ 3103 END
|
|
|
|
|
+ 3104 ELSIF (braceCls = SymTab.ClArray)
|
|
|
|
|
+ 3105 OR (braceCls =
|
|
|
|
|
+ 3106 SymTab.ClRecord)
|
|
|
|
|
+ 3107 OR (braceCls =
|
|
|
|
|
+ 3108 SymTab.ClClass) THEN
|
|
|
|
|
+ 3109 IF hasR THEN SemError(230) END;
|
|
|
|
|
+ 3110 reps := 1;
|
|
|
|
|
+ 3111 IF hasB THEN
|
|
|
|
|
+ 3112 IF SymTab.ConstInt(q2, v2)
|
|
|
|
|
+ 3113 AND (v2 >= 1) THEN
|
|
|
|
|
+ 3114 reps := v2
|
|
|
|
|
+ 3115 ELSE SemError(230)
|
|
|
|
|
+ 3116 END
|
|
|
|
|
+ 3117 END;
|
|
|
|
|
+ 3118 k := 0;
|
|
|
|
|
+ 3119 WHILE k < reps DO
|
|
|
|
|
+ 3120 QbeGen.CtorElem(qe);
|
|
|
|
|
+ 3121 INC(k)
|
|
|
|
|
+ 3122 END
|
|
|
|
|
+ 3123 END; .) .
|
|
|
|
|
+ 3124 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 3125 qe, q2: QbeGen.QVal;
|
|
|
|
|
+ 3126 v, v2: INTEGER;
|
|
|
|
|
+ 3127 lo: INTEGER;
|
|
|
|
|
+ 3128 span: CARDINAL;
|
|
|
|
|
+ 3129 cl, cl2: INTEGER;
|
|
|
|
|
+ 3130 hasR: BOOLEAN; .)
|
|
|
|
|
+ 3131 = (. hasR := FALSE; .)
|
|
|
|
|
+ 3132 Expr<et, qe>
|
|
|
|
|
+ 3133 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
|
|
+ 3134 (. lo := SymTab.SetBaseLo(st);
|
|
|
|
|
+ 3135 span := SymTab.SetCount(st);
|
|
|
|
|
+ 3136 IF (et = SymTab.InvalidType)
|
|
|
|
|
+ 3137 OR (hasR AND (et2 =
|
|
|
|
|
+ 3138 SymTab.InvalidType)) THEN
|
|
|
|
|
+ 3139 ELSE cl :=
|
|
|
|
|
+ 3140 SymTab.ClassOf(et);
|
|
|
|
|
+ 3141 IF hasR THEN
|
|
|
|
|
+ 3142 cl2 :=
|
|
|
|
|
+ 3143 SymTab.ClassOf(et2)
|
|
|
|
|
+ 3144 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
+ 3145 END;
|
|
|
|
|
+ 3146 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
+ 3147 OR (hasR AND NOT
|
|
|
|
|
+ 3148 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
+ 3149 THEN
|
|
|
|
|
+ 3150 SemError(222)
|
|
|
|
|
+ 3151 ELSIF hasR
|
|
|
|
|
+ 3152 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
+ 3153 AND SymTab.ConstInt(q2,
|
|
|
|
|
+ 3154 v2)
|
|
|
|
|
+ 3155 AND ((v < lo)
|
|
|
|
|
+ 3156 OR (v2 < lo)
|
|
|
|
|
+ 3157 OR (v >= lo +
|
|
|
|
|
+ 3158 VAL(INTEGER, span))
|
|
|
|
|
+ 3159 OR (v2 >= lo +
|
|
|
|
|
+ 3160 VAL(INTEGER, span))
|
|
|
|
|
+ 3161 OR (v > v2)) THEN
|
|
|
|
|
+ 3162 SemError(222)
|
|
|
|
|
+ 3163 ELSIF hasR THEN
|
|
|
|
|
+ 3164 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
+ 3165 lo, span)
|
|
|
|
|
+ 3166 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
+ 3167 v)
|
|
|
|
|
+ 3168 AND ((v < lo)
|
|
|
|
|
+ 3169 OR (v >= lo +
|
|
|
|
|
+ 3170 VAL(INTEGER,
|
|
|
|
|
+ 3171 span))) THEN
|
|
|
|
|
+ 3172 SemError(222)
|
|
|
|
|
+ 3173 ELSE QbeGen.SetBit(sq, qe,
|
|
|
|
|
+ 3174 lo, span)
|
|
|
|
|
+ 3175 END
|
|
|
|
|
+ 3176 END; .) .
|
|
|
|
|
+ 3177 GetIdent<VAR n: SymTab.Name>
|
|
|
|
|
+ 3178 = ident (. LexName(n); .) .
|
|
|
|
|
+ 3179
|
|
|
|
|
+ 3180 END M2.
|
|
|
|
|
|
|
|
0 errors
|
|
0 errors
|
|
|
|
|
|