فهرست منبع

lower L6: virtual dispatch, class pointers, empty class BEGIN

- IsMethodCall now walks the whole designator chain, so p^.Method (deref
  to a class) is recognised; obj.Method, p^.Method and bare sibling names
  all route through LowerMethodCall.
- Class BEGIN is marked with an empty NkBlock (M2.atg) so an empty class
  initialiser is distinguishable from 'no BEGIN' and <class>_init is
  emitted (and called from main).

lower_ok t_virtual / t_class / t_classinit byte-match (joining
t_classmethod / t_classinherit / t_classsibling).  Suite 200/200;
FIXPOINT OK (stage2 == stage3, 3,378,633 bytes).
Eric Streit 6 روز پیش
والد
کامیت
7aa21ff1ed
4فایلهای تغییر یافته به همراه36 افزوده شده و 10 حذف شده
  1. 3 0
      compiler/run_tests.sh
  2. 31 8
      compiler/src/Lower.mod
  3. 1 1
      compiler/src/M2.atg
  4. 1 1
      compiler/src/M2.lst

+ 3 - 0
compiler/run_tests.sh

@@ -475,6 +475,9 @@ lower_ok t_nestedmod.mod
 lower_ok t_classmethod.mod
 lower_ok t_classinherit.mod
 lower_ok t_classsibling.mod
+lower_ok t_class.mod
+lower_ok t_classinit.mod
+lower_ok t_virtual.mod
 lower_ok t_lower4.mod
 lower_ok t_lower4case.mod
 lower_ok t_lower4with.mod

+ 31 - 8
compiler/src/Lower.mod

@@ -396,8 +396,10 @@ PROCEDURE CanDesign (n: AST.Node): BOOLEAN;
   END CanDesign;
 
 PROCEDURE IsMethodCall (n: AST.Node): BOOLEAN;
-(* n is a call whose callee is `obj.Method` on a class receiver. *)
+(* n is a call whose callee resolves to a class method: `obj.Method`,
+   `p^.Method`, or a bare sibling name inside an implementation. *)
   VAR d, sel: AST.Node; nm, fn: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
+      i: CARDINAL;
   BEGIN
     IF (AST.Kind(n) # AST.NkCall) OR (AST.NChild(n) < 1) THEN RETURN FALSE END;
     d := AST.Child(n, 0);
@@ -408,15 +410,36 @@ PROCEDURE IsMethodCall (n: AST.Node): BOOLEAN;
       RETURN (curImplCls # SymTab.InvalidType)
              AND SymTab.MethodExists(curImplCls, nm)
     END;
-    IF AST.NChild(d) < 2 THEN RETURN FALSE END;
-    sel := AST.Child(d, AST.NChild(d) - 1);
-    IF AST.Op(sel) # AST.SelField THEN RETURN FALSE END;
     Name(AST.Child(d, 0), nm);
     IF NOT Resolve(nm, k, t) THEN RETURN FALSE END;
-    IF t = SymTab.InvalidType THEN RETURN FALSE END;
-    IF SymTab.ClassOf(t) # SymTab.ClClass THEN RETURN FALSE END;
-    Name(AST.Child(sel, 0), fn);
-    RETURN SymTab.MethodExists(t, fn)
+    i := 1;
+    WHILE i < AST.NChild(d) DO
+      sel := AST.Child(d, i);
+      IF AST.Op(sel) = AST.SelField THEN
+        Name(AST.Child(sel, 0), fn);
+        IF (t # SymTab.InvalidType) AND (SymTab.ClassOf(t) = SymTab.ClClass)
+           AND SymTab.MethodExists(t, fn) THEN
+          RETURN i = AST.NChild(d) - 1
+        END;
+        IF (t = SymTab.InvalidType) OR NOT SymTab.FieldExists(t, fn) THEN
+          RETURN FALSE
+        END;
+        t := SymTab.FieldType(t, fn)
+      ELSIF AST.Op(sel) = AST.SelIndex THEN
+        IF (t = SymTab.InvalidType) OR (SymTab.ClassOf(t) # SymTab.ClArray) THEN
+          RETURN FALSE
+        END;
+        t := SymTab.ArrayElem(t)
+      ELSIF AST.Op(sel) = AST.SelDeref THEN
+        IF (t = SymTab.InvalidType) OR (SymTab.ClassOf(t) # SymTab.ClPtr) THEN
+          RETURN FALSE
+        END;
+        t := SymTab.PtrBase(t)
+      ELSE RETURN FALSE
+      END;
+      INC(i)
+    END;
+    RETURN FALSE
   END IsMethodCall;
 
 PROCEDURE CanMethodCall (n: AST.Node): BOOLEAN;

+ 1 - 1
compiler/src/M2.atg

@@ -962,7 +962,7 @@ PRODUCTIONS
                                            END; .)
       ";" { MethodImpl<ct> ";" }
                                         (. astStmt := AST.NoNode; .)
-      [ "BEGIN"                         (. astStmt := AST.NoNode;
+      [ "BEGIN"                         (. astStmt := AST.MakeNode(AST.NkBlock);
                                            QbeGen.BeginInit(cn); .)
         [ StatSeq ]                     (. QbeGen.EndInit; .) ]
       "END"

+ 1 - 1
compiler/src/M2.lst

@@ -980,7 +980,7 @@ Listing:
   962                                             END; .)
   963        ";" { MethodImpl<ct> ";" }
   964                                          (. astStmt := AST.NoNode; .)
-  965        [ "BEGIN"                         (. astStmt := AST.NoNode;
+  965        [ "BEGIN"                         (. astStmt := AST.MakeNode(AST.NkBlock);
   966                                             QbeGen.BeginInit(cn); .)
   967          [ StatSeq ]                     (. QbeGen.EndInit; .) ]
   968        "END"