|
|
@@ -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
|