Browse Source

lower L6: qualified names (M.x / M.P) — prepared for the flip

- LowerDesign/CanDesign handle a module base: MaterializeAlias then
  LoadDesignator (values) / SymType+SymKind (gate).
- CalleeAlias/IsQualifiedCall/CanQualifiedCall and LowerCall resolve
  module-qualified calls through SymTab.Proc*/Param*.
- CanLower no longer rejects imports.

Not yet byte-verifiable: any multi-unit session contributes code/data and
consumes backend counters from the *earlier* units (a definition-module
CONST emits data; a def-module proc heading consumes a temp), and -lower
re-emits only the last unit.  Verification needs the per-unit mechanism
(the L7 flip).  Scratch cases in docs/wip/qualified/.

Suite 200/200; FIXPOINT OK (stage2 == stage3, 3,388,933 bytes).
Eric Streit 6 days ago
parent
commit
76048e09f0

+ 91 - 22
compiler/src/Lower.mod

@@ -346,7 +346,7 @@ PROCEDURE DesignTypeOf (n: AST.Node): SymTab.TypeIndex;
   END DesignTypeOf;
 
 PROCEDURE CanDesign (n: AST.Node): BOOLEAN;
-  VAR nm, fn: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
+  VAR nm, fn, mal: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
       i: CARDINAL; sel: AST.Node;
   BEGIN
     IF AST.Kind(n) # AST.NkDesignator THEN RETURN FALSE END;
@@ -361,23 +361,33 @@ PROCEDURE CanDesign (n: AST.Node): BOOLEAN;
       ELSE RETURN FALSE
       END
     END;
-    IF (k # SymTab.KindVar) AND (k # SymTab.KindParam)
-       AND (k # SymTab.KindConst) AND (k # SymTab.KindField) THEN
-      RETURN FALSE
+    IF k = SymTab.KindModule THEN
+      (* qualified name: the first .field resolves the export *)
+    ELSE
+      IF (k # SymTab.KindVar) AND (k # SymTab.KindParam)
+         AND (k # SymTab.KindConst) AND (k # SymTab.KindField) THEN
+        RETURN FALSE
+      END;
+      IF NOT CanType(t) THEN RETURN FALSE END
     END;
-    IF NOT CanType(t) THEN RETURN FALSE END;
     i := 1;
     WHILE i < AST.NChild(n) DO
       sel := AST.Child(n, i);
       IF AST.Op(sel) = AST.SelField THEN
-        IF (t = SymTab.InvalidType)
-           OR ((SymTab.ClassOf(t) # SymTab.ClRecord)
-               AND (SymTab.ClassOf(t) # SymTab.ClClass)) THEN
-          RETURN FALSE
-        END;
         Name(AST.Child(sel, 0), fn);
-        IF NOT SymTab.FieldExists(t, fn) THEN RETURN FALSE END;
-        t := SymTab.FieldType(t, fn)
+        IF k = SymTab.KindModule THEN
+          IF NOT SymTab.MaterializeAlias(nm, fn, mal) THEN RETURN FALSE END;
+          t := SymTab.SymType(mal); k := SymTab.SymKind(mal)
+        ELSIF t = SymTab.InvalidType THEN RETURN FALSE
+        ELSIF (SymTab.ClassOf(t) = SymTab.ClClass)
+           AND SymTab.MethodExists(t, fn) THEN
+          k := SymTab.KindProc; t := SymTab.InvalidType
+        ELSIF (SymTab.ClassOf(t) # SymTab.ClRecord)
+           AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
+          RETURN FALSE
+        ELSIF NOT SymTab.FieldExists(t, fn) THEN RETURN FALSE
+        ELSE t := SymTab.FieldType(t, fn)
+        END
       ELSIF AST.Op(sel) = AST.SelIndex THEN
         IF (t = SymTab.InvalidType)
            OR (SymTab.ClassOf(t) # SymTab.ClArray) THEN RETURN FALSE END;
@@ -389,7 +399,7 @@ PROCEDURE CanDesign (n: AST.Node): BOOLEAN;
         t := SymTab.PtrBase(t)
       ELSE RETURN FALSE
       END;
-      IF NOT CanType(t) THEN RETURN FALSE END;
+      IF (k # SymTab.KindProc) AND NOT CanType(t) THEN RETURN FALSE END;
       INC(i)
     END;
     RETURN TRUE
@@ -454,6 +464,41 @@ PROCEDURE CanMethodCall (n: AST.Node): BOOLEAN;
     RETURN TRUE
   END CanMethodCall;
 
+PROCEDURE CalleeAlias (call: AST.Node; VAR mal: SymTab.Name): BOOLEAN;
+(* Callee is `M.P` (module-qualified): materialize the export alias. *)
+  VAR d, sel: AST.Node; nm, fn: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
+  BEGIN
+    d := AST.Child(call, 0);
+    IF (AST.Kind(d) # AST.NkDesignator) OR (AST.NChild(d) # 2) THEN
+      RETURN FALSE
+    END;
+    sel := AST.Child(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 k # SymTab.KindModule THEN RETURN FALSE END;
+    Name(AST.Child(sel, 0), fn);
+    RETURN SymTab.MaterializeAlias(nm, fn, mal)
+  END CalleeAlias;
+
+PROCEDURE IsQualifiedCall (n: AST.Node): BOOLEAN;
+  VAR mal: SymTab.Name;
+  BEGIN
+    IF AST.Kind(n) # AST.NkCall THEN RETURN FALSE END;
+    RETURN CalleeAlias(n, mal)
+  END IsQualifiedCall;
+
+PROCEDURE CanQualifiedCall (n: AST.Node): BOOLEAN;
+  VAR i: CARDINAL;
+  BEGIN
+    i := 1;
+    WHILE i < AST.NChild(n) DO
+      IF NOT CanExpr(AST.Child(n, i)) THEN RETURN FALSE END;
+      INC(i)
+    END;
+    RETURN TRUE
+  END CanQualifiedCall;
+
 PROCEDURE CanBuiltin (n: AST.Node): BOOLEAN;
   VAR i: CARDINAL;
   BEGIN
@@ -496,6 +541,7 @@ PROCEDURE CanExpr (n: AST.Node): BOOLEAN;
     IF AST.Kind(n) = AST.NkDesignator THEN RETURN CanDesign(n) END;
     IF AST.Kind(n) = AST.NkCall THEN
       IF IsMethodCall(n) THEN RETURN CanMethodCall(n) END;
+      IF IsQualifiedCall(n) THEN RETURN CanQualifiedCall(n) END;
       CalleeName(n, nm);
       IF IsBuiltin(nm) THEN RETURN CanBuiltin(n) END;
       RETURN IsCall(n) AND CanCallArgs(n)
@@ -599,6 +645,7 @@ PROCEDURE CanStmt (n: AST.Node): BOOLEAN;
     END;
     IF k = AST.NkCall THEN
       IF IsMethodCall(n) THEN RETURN CanMethodCall(n) END;
+      IF IsQualifiedCall(n) THEN RETURN CanQualifiedCall(n) END;
       CalleeName(n, nm);
       IF IsBuiltin(nm) THEN RETURN CanBuiltin(n) END;
       RETURN IsCall(n) AND CanCallArgs(n)
@@ -713,7 +760,6 @@ PROCEDURE CanLower (unit: AST.Node): BOOLEAN;
     curImplCls := SymTab.InvalidType;
     IF AST.Kind(unit) # AST.NkUnit THEN RETURN FALSE END;
     IF AST.Kind(AST.Child(unit, 0)) # AST.NkIdent THEN RETURN FALSE END;
-    IF AST.Child(unit, 3) # AST.NoNode THEN RETURN FALSE END;
     RETURN CanDecls(AST.Child(unit, 1)) AND CanStmt(AST.Child(unit, 2))
   END CanLower;
 
@@ -754,7 +800,7 @@ PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
                        VAR sfx: BOOLEAN);
 (* Base ident then selectors (mirrors the grammar's Design).  Leaves the
    address in q with sfx=TRUE for selectors; base vars/consts load. *)
-  VAR nm, fn: SymTab.Name; cv: QbeGen.QVal; cls, op: INTEGER;
+  VAR nm, fn, mal: SymTab.Name; cv: QbeGen.QVal; cls, op: INTEGER;
       i: CARDINAL; sel: AST.Node; eT, it: SymTab.TypeIndex;
       iq, ql, qlo, qhi, qe: QbeGen.QVal;
       lo, hi, fo: INTEGER; isOpen: BOOLEAN;
@@ -809,7 +855,18 @@ PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
       op := AST.Op(sel);
       IF op = AST.SelField THEN
         Name(AST.Child(sel, 0), fn);
-        IF t = SymTab.InvalidType THEN
+        IF k = SymTab.KindModule THEN
+          (* qualified L.x: materialize the export, then load it *)
+          IF SymTab.MaterializeAlias(nm, fn, mal) THEN
+            QbeGen.CopyOp(mal, qn);
+            t := SymTab.SymType(mal); k := SymTab.SymKind(mal); sfx := FALSE;
+            IF k = SymTab.KindProc THEN QbeGen.CopyOp("0", q)
+            ELSIF NOT QbeGen.LoadDesignator(mal, t, k, q) THEN
+              t := SymTab.InvalidType; QbeGen.CopyOp("0", q)
+            END
+          ELSE t := SymTab.InvalidType; QbeGen.CopyOp("0", q)
+          END
+        ELSIF t = SymTab.InvalidType THEN
         ELSIF (SymTab.ClassOf(t) = SymTab.ClClass)
            AND SymTab.MethodExists(t, fn) THEN
           (* obj.Method: bind the receiver; the call supplies the value *)
@@ -866,18 +923,30 @@ PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
 
 PROCEDURE LowerCall (n: AST.Node; VAR t: SymTab.TypeIndex;
                      VAR q: QbeGen.QVal; want: BOOLEAN);
-  VAR nm: SymTab.Name; i: CARDINAL; at, ft, res: SymTab.TypeIndex;
-      qa, qt, qe: QbeGen.QVal; mg: QbeGen.QVal; cls: CHAR; conv, isV: BOOLEAN;
-      uid, depth, np: CARDINAL; ext: BOOLEAN; pn: SymTab.Name;
+  VAR nm, pn: SymTab.Name; i: CARDINAL; at, ft, res: SymTab.TypeIndex;
+      qa, qt, qe, mg: QbeGen.QVal; conv, isV, qual: BOOLEAN;
+      uid, depth, np: CARDINAL; ext: BOOLEAN;
   BEGIN
-    CalleeName(n, nm);
-    IF NOT ProcInfo(nm, uid, res, depth, ext, np) THEN END;
+    qual := CalleeAlias(n, nm);
+    IF qual THEN
+      uid := SymTab.ProcUid(nm); res := SymTab.ProcRes(nm);
+      depth := SymTab.ProcDepthOf(nm); ext := SymTab.IsExternal(nm);
+      np := SymTab.ProcNPar(nm)
+    ELSE
+      CalleeName(n, nm);
+      IF NOT ProcInfo(nm, uid, res, depth, ext, np) THEN END
+    END;
     QbeGen.Mangled(nm, uid, mg);
     QbeGen.CallBegin(mg, res, depth, ext);
     i := 1;
     WHILE i < AST.NChild(n) DO
       LowerExpr(AST.Child(n, i), at, qe);
-      IF NOT ParamInfo(nm, i - 1, ft, isV, pn) THEN END;
+      IF qual THEN
+        ft := SymTab.ParamType(nm, i - 1);
+        isV := SymTab.ParamIsVar(nm, i - 1)
+      ELSE
+        IF NOT ParamInfo(nm, i - 1, ft, isV, pn) THEN END
+      END;
       IF isV THEN
         IF QbeGen.AddrOfVal(qe, qa) THEN
           IF NOT QbeGen.CallArg(qa, "l") THEN END

+ 4 - 0
docs/wip/qualified/d_libc.def

@@ -0,0 +1,4 @@
+DEFINITION MODULE DLibC;
+(* Qualified CONST access; definitions emit no code. *)
+CONST K = 42;
+END DLibC.

+ 3 - 0
docs/wip/qualified/d_qualp.def

@@ -0,0 +1,3 @@
+DEFINITION MODULE DQualP;
+PROCEDURE P;
+END DQualP.

+ 6 - 0
docs/wip/qualified/t_qual.mod

@@ -0,0 +1,6 @@
+MODULE TQual;
+IMPORT DLibC;
+VAR ExitCode : INTEGER;
+BEGIN
+  ExitCode := DLibC.K
+END TQual.

+ 7 - 0
docs/wip/qualified/t_qualp.mod

@@ -0,0 +1,7 @@
+MODULE TQualP;
+IMPORT DQualP;
+VAR ExitCode : INTEGER;
+BEGIN
+  DQualP.P;
+  ExitCode := 0
+END TQualP.