Просмотр исходного кода

resolve-check step 4b: Check resolves a forward designator's type

Starting the designator resolver.  A forward-reference note now carries
its designator node; FlushForward resolves the name, applies the node's
selectors to the base type (field/index/deref) and stores the result via
AST.SetTy.  A forward designator finally has a real type on the AST
(Lower still re-derives its own for emission).

- SymTab.FwdVarResolve now also returns the resolved type.
- Check gains SelType (selector walk over SymTab.FieldType/ArrayElem/
  PtrBase) and LeafName.
- Design attaches the node to the forward note (fref + astDes).

Verified with a temporary differential instrument in LowerDesign (which
independently computes the same type): clean across the suite (incl.
t_fwdvar) and a forward-array test (FwdSel -> 7), and it fires (299) when
the resolver is deliberately broken.  The instrument was removed again.

Suite 190/190; fixpoint OK (3,474,750 bytes).
Eric Streit 1 день назад
Родитель
Сommit
192ad55812
6 измененных файлов с 187 добавлено и 142 удалено
  1. 4 3
      compiler/src/Check.def
  2. 49 7
      compiler/src/Check.mod
  3. 2 2
      compiler/src/M2.atg
  4. 125 125
      compiler/src/M2.lst
  5. 3 3
      compiler/src/SymTab.def
  6. 4 2
      compiler/src/SymTab.mod

+ 4 - 3
compiler/src/Check.def

@@ -13,9 +13,10 @@ PROCEDURE BeginSession (progName: ARRAY OF CHAR);
 PROCEDURE BeginUnit;
 (* Per-unit setup (called before Parse). *)
 
-PROCEDURE NoteForward (id: INTEGER);
-(* Records a forward module-level reference noted by the parser (Design);
-   FlushForward resolves it once the unit's declarations are complete. *)
+PROCEDURE NoteForward (id: INTEGER; node: AST.Node);
+(* Records a forward module-level reference noted by the parser (Design)
+   together with its designator node; FlushForward resolves the name and
+   stores the designator's type on that node. *)
 
 PROCEDURE FlushForward;
 (* Resolve every noted forward reference against the unit's declarations;

+ 49 - 7
compiler/src/Check.mod

@@ -3,8 +3,8 @@ IMPLEMENTATION MODULE Check;
 (* Resolve / check pass (two-phase, part 2).  Forward module-level
    references (a procedure body naming a variable declared further down)
    are resolved here, after the unit has been parsed and before Lower:
-   the placeholder recorded by Design is bound to the real symbol, so
-   resolution no longer depends on declaration order.  See
+   the designator's real type is computed from the now-visible symbol and
+   its selectors, and stored on the AST node.  See
    docs/plan-resolve-check.md. *)
 
 IMPORT AST, SymTab, M2S;
@@ -14,6 +14,40 @@ CONST MaxFwd = 256;
 VAR
   nFwd:  CARDINAL;
   fwdId: ARRAY [0 .. MaxFwd - 1] OF INTEGER;
+  fwdNd: ARRAY [0 .. MaxFwd - 1] OF AST.Node;
+
+PROCEDURE LeafName (n: AST.Node; VAR s: SymTab.Name);
+(* Text of an identifier leaf node (its child 0 is the text index). *)
+  BEGIN
+    s[0] := CHR(0);
+    IF n >= 0 THEN AST.Txt(AST.Child(n, 0), s) END
+  END LeafName;
+
+PROCEDURE SelType (n: AST.Node; VAR t: SymTab.TypeIndex);
+(* Applies a designator's selectors to its base type. *)
+  VAR i: CARDINAL; sel, leaf: AST.Node; op: INTEGER; fn: SymTab.Name;
+  BEGIN
+    IF n < 0 THEN RETURN END;
+    i := 1;
+    WHILE (i < AST.NChild(n)) AND (t # SymTab.InvalidType) DO
+      sel := AST.Child(n, i);
+      op := AST.Op(sel);
+      IF op = AST.SelField THEN
+        leaf := AST.Child(sel, 0);
+        LeafName(leaf, fn);
+        IF SymTab.FieldExists(t, fn) THEN t := SymTab.FieldType(t, fn)
+        ELSE t := SymTab.InvalidType
+        END
+      ELSIF op = AST.SelIndex THEN
+        t := SymTab.ArrayElem(t)
+      ELSIF op = AST.SelDeref THEN
+        IF SymTab.ClassOf(t) = SymTab.ClPtr THEN t := SymTab.PtrBase(t)
+        ELSE t := SymTab.InvalidType
+        END
+      END;
+      INC(i)
+    END
+  END SelType;
 
 PROCEDURE BeginSession (progName: ARRAY OF CHAR);
 BEGIN
@@ -24,25 +58,33 @@ PROCEDURE BeginUnit;
 BEGIN
 END BeginUnit;
 
-PROCEDURE NoteForward (id: INTEGER);
-(* Records a forward reference id noted during parse. *)
+PROCEDURE NoteForward (id: INTEGER; node: AST.Node);
+(* Records a forward reference id and its designator node. *)
 BEGIN
   IF nFwd <= HIGH(fwdId) THEN
     fwdId[nFwd] := id;
+    fwdNd[nFwd] := node;
     INC(nFwd)
   END
 END NoteForward;
 
 PROCEDURE FlushForward;
-(* Resolve every noted forward reference; an unresolved name is 201. *)
+(* Resolve every noted forward reference; store the designator's type on
+   its node; an unresolved name is 201. *)
   VAR k: CARDINAL;
       nm: SymTab.Name;
+      t: SymTab.TypeIndex;
 BEGIN
   k := 0;
   WHILE k < nFwd DO
     SymTab.FwdVarName(fwdId[k], nm);
-    IF (nm[0] # CHR(0)) AND (NOT SymTab.FwdVarResolve(fwdId[k])) THEN
-      M2S.Error(201, M2S.line, M2S.col, M2S.pos)
+    IF nm[0] # CHR(0) THEN
+      IF SymTab.FwdVarResolve(fwdId[k], t) THEN
+        SelType(fwdNd[k], t);
+        AST.SetTy(fwdNd[k], t)
+      ELSE
+        M2S.Error(201, M2S.line, M2S.col, M2S.pos)
+      END
     END;
     INC(k)
   END;

+ 2 - 2
compiler/src/M2.atg

@@ -2157,7 +2157,6 @@ PRODUCTIONS
                                                k := SymTab.KindVar;
                                                r := SymTab.FwdVarRef(n, k,
                                                  fref, t);
-                                                Check.NoteForward(fref);
                                                 QbeGen.CopyOp("@", q);
                                                sfx := TRUE; fwd := TRUE
                                              ELSE
@@ -2281,7 +2280,8 @@ PRODUCTIONS
                                            END; .)
       (. astDes := AST.MakeNode(AST.NkDesignator);
          AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
-         IF fwd THEN AST.SetOp(astDes, 1) END; .)
+         IF fwd THEN AST.SetOp(astDes, 1) END;
+          IF fwd THEN Check.NoteForward(fref, astDes) END; .)
       { "[" Expr<it, iq>
                                         (. AST.SetChild(astDes, AST.NChild(astDes),
              AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN

+ 125 - 125
compiler/src/M2.lst

@@ -2176,131 +2176,131 @@ Listing:
  2157                                                 k := SymTab.KindVar;
  2158                                                 r := SymTab.FwdVarRef(n, k,
  2159                                                   fref, t);
- 2160                                                  Check.NoteForward(fref);
- 2161                                                  QbeGen.CopyOp("@", q);
- 2162                                                 sfx := TRUE; fwd := TRUE
- 2163                                               ELSE
- 2164                                                 SemError(201);
- 2165                                                 t :=
- 2166                                                   SymTab.InvalidType;
- 2167                                                 k := -1;
- 2168                                                 QbeGen.CopyOp("0", q)
- 2169                                               END
- 2170                                             ELSE
- 2171                                               t := SymTab.SymType(n);
- 2172                                               k := SymTab.SymKind(n);
- 2173                                               IF k = SymTab.KindConst THEN
- 2174                                                 IF SymTab.Equal(n,
- 2175                                                    "TRUE") THEN
- 2176                                                   t := SymTab.BoolType();
- 2177                                                   QbeGen.CopyOp("1", q)
- 2178                                                 ELSIF SymTab.Equal(n,
- 2179                                                    "FALSE") THEN
- 2180                                                   t := SymTab.BoolType();
- 2181                                                   QbeGen.CopyOp("0", q)
- 2182                                                 ELSIF SymTab.Equal(n,
- 2183                                                    "NIL") THEN
- 2184                                                   QbeGen.CopyOp("0", q)
- 2185                                                 ELSE
- 2186                                                   cls :=
- 2187                                                     SymTab.ClassOf(t);
- 2188                                                   IF (t #
- 2189                                                       SymTab.InvalidType)
- 2190   AND ((cls = SymTab.ClInt)
- 2191                                                      OR (cls
- 2192                                                          = SymTab.ClChar)
- 2193                                                      OR (cls
- 2194                                                          = SymTab.ClEnum)
- 2195                                                      OR (cls
- 2196                                                          = SymTab.ClReal)
- 2197                                                      OR (cls
- 2198                                                          = SymTab.ClLong)
- 2199                                                      OR (cls
- 2200                                                          = SymTab.ClNil)) THEN
- 2201                                                     IF cls = SymTab.ClNil THEN
- 2202                                                       QbeGen.CopyOp("0", q)
- 2203                                                     ELSIF ((cls
- 2204                                                         = SymTab.ClInt)
- 2205                                                       OR (cls
- 2206                                                         = SymTab.ClChar)
- 2207                                                       OR (cls
- 2208                                                         = SymTab.ClEnum)
- 2209                                                       OR (cls
- 2210                                                         = SymTab.ClLong))
- 2211    AND SymTab.GetSymVal(n, cv)
- 2212    AND QbeGen.IsImm(cv) THEN
- 2213                                                       QbeGen.CopyOp(cv, q)
- 2214                                                     ELSE
- 2215                                                       QbeGen.LoadVar(n,
- 2216                                                         cls = SymTab.ClReal,
- 2217                                                         q)
- 2218                                                     END
- 2219                                                   ELSIF (cls = SymTab.ClArray)
- 2220                                                      OR (cls = SymTab.ClRecord)
- 2221                                                      OR (cls = SymTab.ClClass)
- 2222                                                      OR (cls = SymTab.ClStr)
- 2223                                                      OR (cls = SymTab.ClUStr) THEN
- 2224                                                     (* aggregate constant:
- 2225                                                        its value IS the
- 2226                                                        descriptor address *)
- 2227                                                     IF SymTab.GetSymVal(n, cv) THEN
- 2228                                                       QbeGen.CopyOp(cv, q)
- 2229                                                     ELSE
- 2230                                                       QbeGen.CopyOp("0", q)
- 2231                                                     END
- 2232                                                   ELSE
- 2233                                                     IF t #
- 2234                                                        SymTab.InvalidType THEN
- 2235                                                       SemError(230)
- 2236                                                     END;
- 2237                                                     QbeGen.CopyOp("0", q)
- 2238                                                   END
- 2239                                                 END
- 2240                                               ELSIF (k = SymTab.KindVar)
- 2241                                                  OR (k = SymTab.KindParam) THEN
- 2242                                                 cls := SymTab.ClassOf(t);
- 2243                                                 IF (cls # SymTab.ClInt)
- 2244                                                    AND (cls # SymTab.ClBool)
- 2245                                                    AND (cls # SymTab.ClChar)
- 2246                                                    AND (cls # SymTab.ClUChar)
- 2247                                                    AND (cls # SymTab.ClEnum)
- 2248                                                    AND (cls # SymTab.ClReal)
- 2249                                                    AND (cls # SymTab.ClPtr)
- 2250                                                    AND (cls # SymTab.ClProc)
- 2251                                                    AND (cls # SymTab.ClLong)
- 2252                                                    AND (cls # SymTab.ClArray)
- 2253                                                    AND (cls # SymTab.ClSet)
- 2254                                                    AND (cls # SymTab.ClRecord)
- 2255                                                    AND (cls # SymTab.ClUStr)
- 2256                                                    AND (cls # SymTab.ClClass) THEN
- 2257                                                   SemError(230);
- 2258                                                   QbeGen.CopyOp("0", q)
- 2259                                                 ELSE QbeGen.CopyOp("@", q)
- 2260                                                 END
- 2261                                               ELSE QbeGen.CopyOp("0", q);
- 2262                                                 IF k = SymTab.KindImport THEN
- 2263                                                   SemError(230)
- 2264                                                 ELSIF k =
- 2265                                                    SymTab.KindProc THEN
- 2266                                                   (* bare procedure name:
- 2267                                                      a following ArgList
- 2268                                                      makes it a call;
- 2269                                                      otherwise Fact
- 2270                                                      reports 230 *)
- 2271                                                 ELSE
- 2272                                                    IF k = SymTab.KindField THEN
- 2273                                                      IF QbeGen.TopWith(qb) THEN
- 2274                                                        sfx := TRUE
- 2275                                                      ELSE SemError(230);
- 2276                                                        QbeGen.CopyOp("0", q)
- 2277                                                      END
- 2278                                                    END
- 2279                                                 END
- 2280                                               END
- 2281                                             END; .)
- 2282        (. astDes := AST.MakeNode(AST.NkDesignator);
- 2283           AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
- 2284           IF fwd THEN AST.SetOp(astDes, 1) END; .)
+ 2160                                                  QbeGen.CopyOp("@", q);
+ 2161                                                 sfx := TRUE; fwd := TRUE
+ 2162                                               ELSE
+ 2163                                                 SemError(201);
+ 2164                                                 t :=
+ 2165                                                   SymTab.InvalidType;
+ 2166                                                 k := -1;
+ 2167                                                 QbeGen.CopyOp("0", q)
+ 2168                                               END
+ 2169                                             ELSE
+ 2170                                               t := SymTab.SymType(n);
+ 2171                                               k := SymTab.SymKind(n);
+ 2172                                               IF k = SymTab.KindConst THEN
+ 2173                                                 IF SymTab.Equal(n,
+ 2174                                                    "TRUE") THEN
+ 2175                                                   t := SymTab.BoolType();
+ 2176                                                   QbeGen.CopyOp("1", q)
+ 2177                                                 ELSIF SymTab.Equal(n,
+ 2178                                                    "FALSE") THEN
+ 2179                                                   t := SymTab.BoolType();
+ 2180                                                   QbeGen.CopyOp("0", q)
+ 2181                                                 ELSIF SymTab.Equal(n,
+ 2182                                                    "NIL") THEN
+ 2183                                                   QbeGen.CopyOp("0", q)
+ 2184                                                 ELSE
+ 2185                                                   cls :=
+ 2186                                                     SymTab.ClassOf(t);
+ 2187                                                   IF (t #
+ 2188                                                       SymTab.InvalidType)
+ 2189   AND ((cls = SymTab.ClInt)
+ 2190                                                      OR (cls
+ 2191                                                          = SymTab.ClChar)
+ 2192                                                      OR (cls
+ 2193                                                          = SymTab.ClEnum)
+ 2194                                                      OR (cls
+ 2195                                                          = SymTab.ClReal)
+ 2196                                                      OR (cls
+ 2197                                                          = SymTab.ClLong)
+ 2198                                                      OR (cls
+ 2199                                                          = SymTab.ClNil)) THEN
+ 2200                                                     IF cls = SymTab.ClNil THEN
+ 2201                                                       QbeGen.CopyOp("0", q)
+ 2202                                                     ELSIF ((cls
+ 2203                                                         = SymTab.ClInt)
+ 2204                                                       OR (cls
+ 2205                                                         = SymTab.ClChar)
+ 2206                                                       OR (cls
+ 2207                                                         = SymTab.ClEnum)
+ 2208                                                       OR (cls
+ 2209                                                         = SymTab.ClLong))
+ 2210    AND SymTab.GetSymVal(n, cv)
+ 2211    AND QbeGen.IsImm(cv) THEN
+ 2212                                                       QbeGen.CopyOp(cv, q)
+ 2213                                                     ELSE
+ 2214                                                       QbeGen.LoadVar(n,
+ 2215                                                         cls = SymTab.ClReal,
+ 2216                                                         q)
+ 2217                                                     END
+ 2218                                                   ELSIF (cls = SymTab.ClArray)
+ 2219                                                      OR (cls = SymTab.ClRecord)
+ 2220                                                      OR (cls = SymTab.ClClass)
+ 2221                                                      OR (cls = SymTab.ClStr)
+ 2222                                                      OR (cls = SymTab.ClUStr) THEN
+ 2223                                                     (* aggregate constant:
+ 2224                                                        its value IS the
+ 2225                                                        descriptor address *)
+ 2226                                                     IF SymTab.GetSymVal(n, cv) THEN
+ 2227                                                       QbeGen.CopyOp(cv, q)
+ 2228                                                     ELSE
+ 2229                                                       QbeGen.CopyOp("0", q)
+ 2230                                                     END
+ 2231                                                   ELSE
+ 2232                                                     IF t #
+ 2233                                                        SymTab.InvalidType THEN
+ 2234                                                       SemError(230)
+ 2235                                                     END;
+ 2236                                                     QbeGen.CopyOp("0", q)
+ 2237                                                   END
+ 2238                                                 END
+ 2239                                               ELSIF (k = SymTab.KindVar)
+ 2240                                                  OR (k = SymTab.KindParam) THEN
+ 2241                                                 cls := SymTab.ClassOf(t);
+ 2242                                                 IF (cls # SymTab.ClInt)
+ 2243                                                    AND (cls # SymTab.ClBool)
+ 2244                                                    AND (cls # SymTab.ClChar)
+ 2245                                                    AND (cls # SymTab.ClUChar)
+ 2246                                                    AND (cls # SymTab.ClEnum)
+ 2247                                                    AND (cls # SymTab.ClReal)
+ 2248                                                    AND (cls # SymTab.ClPtr)
+ 2249                                                    AND (cls # SymTab.ClProc)
+ 2250                                                    AND (cls # SymTab.ClLong)
+ 2251                                                    AND (cls # SymTab.ClArray)
+ 2252                                                    AND (cls # SymTab.ClSet)
+ 2253                                                    AND (cls # SymTab.ClRecord)
+ 2254                                                    AND (cls # SymTab.ClUStr)
+ 2255                                                    AND (cls # SymTab.ClClass) THEN
+ 2256                                                   SemError(230);
+ 2257                                                   QbeGen.CopyOp("0", q)
+ 2258                                                 ELSE QbeGen.CopyOp("@", q)
+ 2259                                                 END
+ 2260                                               ELSE QbeGen.CopyOp("0", q);
+ 2261                                                 IF k = SymTab.KindImport THEN
+ 2262                                                   SemError(230)
+ 2263                                                 ELSIF k =
+ 2264                                                    SymTab.KindProc THEN
+ 2265                                                   (* bare procedure name:
+ 2266                                                      a following ArgList
+ 2267                                                      makes it a call;
+ 2268                                                      otherwise Fact
+ 2269                                                      reports 230 *)
+ 2270                                                 ELSE
+ 2271                                                    IF k = SymTab.KindField THEN
+ 2272                                                      IF QbeGen.TopWith(qb) THEN
+ 2273                                                        sfx := TRUE
+ 2274                                                      ELSE SemError(230);
+ 2275                                                        QbeGen.CopyOp("0", q)
+ 2276                                                      END
+ 2277                                                    END
+ 2278                                                 END
+ 2279                                               END
+ 2280                                             END; .)
+ 2281        (. astDes := AST.MakeNode(AST.NkDesignator);
+ 2282           AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
+ 2283           IF fwd THEN AST.SetOp(astDes, 1) END;
+ 2284            IF fwd THEN Check.NoteForward(fref, astDes) END; .)
  2285        { "[" Expr<it, iq>
  2286                                          (. AST.SetChild(astDes, AST.NChild(astDes),
  2287               AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN

+ 3 - 3
compiler/src/SymTab.def

@@ -451,9 +451,9 @@ PROCEDURE FwdVarRef (name: ARRAY OF CHAR; kind: INTEGER;
 
 PROCEDURE FwdVarName (id: INTEGER; VAR name: Name);
 (* The identifier behind forward reference id (1-based). *)
-PROCEDURE FwdVarResolve (id: INTEGER): BOOLEAN;
-(* Resolves forward reference id against the module's declarations:
-   TRUE when the name now exists with the expected kind. *)
+PROCEDURE FwdVarResolve (id: INTEGER; VAR t: TypeIndex): BOOLEAN;
+(* Resolves forward reference id against the unit's declarations: TRUE
+   when the name now exists with the expected kind; t is its type. *)
 
 PROCEDURE IntType (): TypeIndex;
 PROCEDURE UCharType (): TypeIndex;

+ 4 - 2
compiler/src/SymTab.mod

@@ -2610,13 +2610,14 @@ PROCEDURE FwdVarRef (name: ARRAY OF CHAR; kind: INTEGER;
     RETURN TRUE
   END FwdVarRef;
 
-PROCEDURE FwdVarResolve (id: INTEGER): BOOLEAN;
+PROCEDURE FwdVarResolve (id: INTEGER; VAR t: TypeIndex): BOOLEAN;
 (* Resolves forward reference id against the unit's declarations.  The
    scope recorded at reference time is used, so this may run after the
    module scope has been popped (the resolve/check pass).
-   TRUE when the name now exists with the expected kind. *)
+   TRUE when the name now exists with the expected kind; t is its type. *)
   VAR node: SymPtr;
   BEGIN
+    t := InvalidType;
     IF (id < 1) OR (id > VAL(INTEGER, nFwdVar)) THEN RETURN TRUE END;
     node := FindScope(fwdVarName[id - 1], fwdVarScope[id - 1]);
     IF node = NIL THEN RETURN FALSE END;
@@ -2627,6 +2628,7 @@ PROCEDURE FwdVarResolve (id: INTEGER): BOOLEAN;
         RETURN FALSE
       END
     END;
+    t := node^.typ;
     RETURN TRUE
   END FwdVarResolve;