|
|
@@ -42,6 +42,9 @@ VAR
|
|
|
modScanned: ARRAY [0..255] OF BOOLEAN;
|
|
|
modExternal: ARRAY [0..255] OF BOOLEAN;
|
|
|
modIsMain: ARRAY [0..255] OF BOOLEAN;
|
|
|
+ modIsGeneric: ARRAY [0..255] OF BOOLEAN;
|
|
|
+ modIsInstance: ARRAY [0..255] OF BOOLEAN;
|
|
|
+ modInstGen: ARRAY [0..255] OF Name;
|
|
|
nDep: ARRAY [0..255] OF CARDINAL;
|
|
|
depTab: ARRAY [0..16383] OF INTEGER;
|
|
|
state: ARRAY [0..255] OF CARDINAL;
|
|
|
@@ -60,6 +63,9 @@ VAR
|
|
|
mainIdx: INTEGER;
|
|
|
inComment: CARDINAL;
|
|
|
gPendingFrom, gInImport, gSawHead, gWantName, gFromSeen: BOOLEAN;
|
|
|
+ gGenericNext, gHeadWasSaw, gAfterName, gWantGen: BOOLEAN;
|
|
|
+ gInInstActuals: BOOLEAN;
|
|
|
+ gLastActual: Name;
|
|
|
tmpA, tmpB: Path;
|
|
|
tmpN: Name;
|
|
|
tmpP, tmpQ: Path;
|
|
|
@@ -315,6 +321,9 @@ BEGIN
|
|
|
modScanned[nMods] := FALSE;
|
|
|
modExternal[nMods] := FALSE;
|
|
|
modIsMain[nMods] := FALSE;
|
|
|
+ modIsGeneric[nMods] := FALSE;
|
|
|
+ modIsInstance[nMods] := FALSE;
|
|
|
+ modInstGen[nMods][0] := CHR(0);
|
|
|
nDep[nMods] := 0;
|
|
|
INC(nMods);
|
|
|
RETURN VAL(INTEGER, nMods - 1)
|
|
|
@@ -417,76 +426,79 @@ END ResolveModule;
|
|
|
|
|
|
PROCEDURE HandleTok(tok: ARRAY OF CHAR; midx: INTEGER);
|
|
|
BEGIN
|
|
|
+ IF Cmp(tok, "GENERIC") = 0 THEN
|
|
|
+ gGenericNext := TRUE;
|
|
|
+ gPendingFrom := FALSE; gInImport := FALSE;
|
|
|
+ gSawHead := FALSE; gWantName := FALSE; gFromSeen := FALSE;
|
|
|
+ RETURN
|
|
|
+ END;
|
|
|
IF Cmp(tok, "FROM") = 0 THEN
|
|
|
gPendingFrom := TRUE;
|
|
|
gInImport := FALSE;
|
|
|
- gSawHead := FALSE;
|
|
|
- gWantName := FALSE;
|
|
|
- gFromSeen := FALSE;
|
|
|
+ gSawHead := FALSE; gWantName := FALSE; gFromSeen := FALSE;
|
|
|
+ gAfterName := FALSE; gWantGen := FALSE;
|
|
|
RETURN
|
|
|
END;
|
|
|
IF Cmp(tok, "IMPORT") = 0 THEN
|
|
|
IF gPendingFrom OR gFromSeen THEN
|
|
|
- (* FROM M IMPORT ... : following names are items, not modules *)
|
|
|
- gPendingFrom := FALSE;
|
|
|
- gFromSeen := FALSE
|
|
|
+ gPendingFrom := FALSE; gFromSeen := FALSE
|
|
|
ELSE gInImport := TRUE
|
|
|
END;
|
|
|
- gSawHead := FALSE;
|
|
|
- gWantName := FALSE;
|
|
|
+ gSawHead := FALSE; gWantName := FALSE;
|
|
|
RETURN
|
|
|
END;
|
|
|
- IF Cmp(tok, "DEFINITION") = 0 THEN
|
|
|
- gSawHead := TRUE;
|
|
|
- gPendingFrom := FALSE;
|
|
|
- gInImport := FALSE;
|
|
|
- gWantName := FALSE;
|
|
|
- gFromSeen := FALSE;
|
|
|
- RETURN
|
|
|
- END;
|
|
|
- IF Cmp(tok, "IMPLEMENTATION") = 0 THEN
|
|
|
- gSawHead := TRUE;
|
|
|
- gPendingFrom := FALSE;
|
|
|
- gInImport := FALSE;
|
|
|
- gWantName := FALSE;
|
|
|
- gFromSeen := FALSE;
|
|
|
+ IF (Cmp(tok, "DEFINITION") = 0) OR (Cmp(tok, "IMPLEMENTATION") = 0) THEN
|
|
|
+ gSawHead := TRUE; gHeadWasSaw := TRUE;
|
|
|
+ gPendingFrom := FALSE; gInImport := FALSE;
|
|
|
+ gWantName := FALSE; gFromSeen := FALSE;
|
|
|
RETURN
|
|
|
END;
|
|
|
IF Cmp(tok, "MODULE") = 0 THEN
|
|
|
- IF gSawHead THEN gWantName := FALSE
|
|
|
- ELSE gWantName := TRUE
|
|
|
- END;
|
|
|
+ gWantName := TRUE;
|
|
|
gSawHead := FALSE;
|
|
|
- gPendingFrom := FALSE;
|
|
|
- gInImport := FALSE;
|
|
|
- gFromSeen := FALSE;
|
|
|
+ gPendingFrom := FALSE; gInImport := FALSE; gFromSeen := FALSE;
|
|
|
+ gAfterName := FALSE; gWantGen := FALSE;
|
|
|
RETURN
|
|
|
END;
|
|
|
IF gPendingFrom THEN
|
|
|
AddDepName(midx, tok);
|
|
|
- gPendingFrom := FALSE;
|
|
|
- gFromSeen := TRUE;
|
|
|
- gSawHead := FALSE;
|
|
|
+ gPendingFrom := FALSE; gFromSeen := TRUE; gSawHead := FALSE;
|
|
|
RETURN
|
|
|
END;
|
|
|
IF gInImport THEN
|
|
|
AddDepName(midx, tok);
|
|
|
- gSawHead := FALSE;
|
|
|
- gFromSeen := FALSE;
|
|
|
+ gSawHead := FALSE; gFromSeen := FALSE;
|
|
|
RETURN
|
|
|
END;
|
|
|
IF gWantName THEN
|
|
|
- gWantName := FALSE;
|
|
|
- IF wantProg AND (midx = mainIdx) THEN
|
|
|
- Copy(tok, progName);
|
|
|
- wantProg := FALSE
|
|
|
+ gWantName := FALSE; gAfterName := TRUE;
|
|
|
+ IF gGenericNext THEN
|
|
|
+ modIsGeneric[midx] := TRUE; gGenericNext := FALSE
|
|
|
END;
|
|
|
- gSawHead := FALSE;
|
|
|
- gFromSeen := FALSE;
|
|
|
+ IF (NOT gHeadWasSaw) AND wantProg AND (midx = mainIdx) THEN
|
|
|
+ Copy(tok, progName); wantProg := FALSE
|
|
|
+ END;
|
|
|
+ gHeadWasSaw := FALSE; gSawHead := FALSE; gFromSeen := FALSE;
|
|
|
RETURN
|
|
|
END;
|
|
|
- gSawHead := FALSE;
|
|
|
- gFromSeen := FALSE
|
|
|
+ IF gAfterName AND (Cmp(tok, "=") = 0) THEN
|
|
|
+ gAfterName := FALSE; gWantGen := TRUE;
|
|
|
+ gInInstActuals := FALSE; gLastActual[0] := CHR(0);
|
|
|
+ RETURN
|
|
|
+ END;
|
|
|
+ IF gWantGen THEN
|
|
|
+ AddDepName(midx, tok);
|
|
|
+ Copy(tok, modInstGen[midx]);
|
|
|
+ modIsInstance[midx] := TRUE;
|
|
|
+ gWantGen := FALSE; gAfterName := FALSE;
|
|
|
+ gInInstActuals := TRUE; gLastActual[0] := CHR(0);
|
|
|
+ RETURN
|
|
|
+ END;
|
|
|
+ IF gInInstActuals THEN
|
|
|
+ Copy(tok, gLastActual)
|
|
|
+ END;
|
|
|
+ gSawHead := FALSE; gFromSeen := FALSE;
|
|
|
+ gAfterName := FALSE
|
|
|
END HandleTok;
|
|
|
|
|
|
PROCEDURE ScanLine(line: ARRAY OF CHAR; midx: INTEGER);
|
|
|
@@ -520,12 +532,29 @@ BEGIN
|
|
|
i := n
|
|
|
ELSIF (ch = "'") OR (ch = '"') THEN
|
|
|
inStr := TRUE; qc := ch; INC(i)
|
|
|
+ ELSIF ch = "." THEN
|
|
|
+ IF gInInstActuals AND (gLastActual[0] # CHR(0)) THEN
|
|
|
+ AddDepName(midx, gLastActual);
|
|
|
+ gLastActual[0] := CHR(0)
|
|
|
+ END;
|
|
|
+ INC(i)
|
|
|
+ ELSIF ch = "=" THEN
|
|
|
+ IF gAfterName THEN
|
|
|
+ gAfterName := FALSE; gWantGen := TRUE
|
|
|
+ END;
|
|
|
+ INC(i)
|
|
|
ELSIF ch = ";" THEN
|
|
|
gPendingFrom := FALSE;
|
|
|
gInImport := FALSE;
|
|
|
gSawHead := FALSE;
|
|
|
gWantName := FALSE;
|
|
|
gFromSeen := FALSE;
|
|
|
+ gGenericNext := FALSE; gHeadWasSaw := FALSE;
|
|
|
+ gAfterName := FALSE; gWantGen := FALSE;
|
|
|
+ gInInstActuals := FALSE; gLastActual[0] := CHR(0);
|
|
|
+ gAfterName := FALSE;
|
|
|
+ gWantGen := FALSE;
|
|
|
+ gInInstActuals := FALSE; gLastActual[0] := CHR(0);
|
|
|
INC(i)
|
|
|
ELSIF IsLetter(ch) THEN
|
|
|
k := i;
|
|
|
@@ -863,6 +892,10 @@ BEGIN
|
|
|
WHILE k < nOrder DO
|
|
|
GetDef(order[k], tmpP);
|
|
|
IF SrcNewer(tmpP, ot) THEN RETURN TRUE END;
|
|
|
+ IF modIsGeneric[order[k]] THEN
|
|
|
+ GetSrc(order[k], tmpP);
|
|
|
+ IF SrcNewer(tmpP, ot) THEN RETURN TRUE END
|
|
|
+ END;
|
|
|
INC(k)
|
|
|
END;
|
|
|
RETURN FALSE
|
|
|
@@ -910,17 +943,25 @@ PROCEDURE BuildM2Separate(out: ARRAY OF CHAR);
|
|
|
object with main; every module object exports <mod>_init. *)
|
|
|
VAR cmd: Cmd; k, m: CARDINAL; rc: INTEGER;
|
|
|
obj, src, ssafile, sfile, flags: Path;
|
|
|
- outT: LONGINT; compiledAny, linkNeeded, abiOK: BOOLEAN;
|
|
|
+ outT: LONGINT; compiledAny, linkNeeded, abiOK, hasGeneric: BOOLEAN;
|
|
|
+ gi, k2: INTEGER;
|
|
|
BEGIN
|
|
|
Zero(cmd);
|
|
|
abiOK := AbiStampOK();
|
|
|
compiledAny := FALSE;
|
|
|
+ hasGeneric := FALSE;
|
|
|
+ k2 := 0;
|
|
|
+ WHILE k2 < nOrder DO
|
|
|
+ IF modIsGeneric[order[k2]] THEN hasGeneric := TRUE END;
|
|
|
+ INC(k2)
|
|
|
+ END;
|
|
|
k := 0;
|
|
|
WHILE k < nOrder DO
|
|
|
m := order[k];
|
|
|
GetSrc(m, src);
|
|
|
GetDef(m, tmpQ);
|
|
|
- IF (Len(src) > 0) OR ((NOT modIsMain[m]) AND (Len(tmpQ) > 0)) THEN
|
|
|
+ IF (NOT modIsGeneric[m]) AND
|
|
|
+ ((Len(src) > 0) OR ((NOT modIsMain[m]) AND (Len(tmpQ) > 0))) THEN
|
|
|
IF Len(src) = 0 THEN
|
|
|
(* A definition-only module still contributes exported data and
|
|
|
class vtables to the link. *)
|
|
|
@@ -939,13 +980,41 @@ BEGIN
|
|
|
AppendSeg(tmpCmd, " ");
|
|
|
AppendSeg(tmpCmd, m2Flags)
|
|
|
END;
|
|
|
- (* M2 resolves the target .def and all imported .defs from -I. *)
|
|
|
- IFlags(flags);
|
|
|
- IF Len(flags) > 0 THEN
|
|
|
- AppendSeg(tmpCmd, " ");
|
|
|
- AppendSeg(tmpCmd, flags)
|
|
|
+ IF hasGeneric THEN
|
|
|
+ (* A generic instance needs its template in the same session.
|
|
|
+ Keep the explicit closure small: all interfaces + generic
|
|
|
+ implementations + the target source. *)
|
|
|
+ k2 := 0;
|
|
|
+ WHILE k2 < nOrder DO
|
|
|
+ GetDef(order[k2], tmpP);
|
|
|
+ IF Len(tmpP) > 0 THEN AppendTok(tmpCmd, tmpP) END;
|
|
|
+ IF modIsGeneric[order[k2]] THEN
|
|
|
+ GetSrc(order[k2], tmpP);
|
|
|
+ IF Len(tmpP) > 0 THEN AppendTok(tmpCmd, tmpP) END
|
|
|
+ END;
|
|
|
+ INC(k2)
|
|
|
+ END;
|
|
|
+ AppendTok(tmpCmd, src)
|
|
|
+ ELSE
|
|
|
+ (* M2 resolves the target .def and all imported .defs from -I. *)
|
|
|
+ IFlags(flags);
|
|
|
+ IF Len(flags) > 0 THEN
|
|
|
+ AppendSeg(tmpCmd, " ");
|
|
|
+ AppendSeg(tmpCmd, flags)
|
|
|
+ END;
|
|
|
+ IF modIsInstance[m] THEN
|
|
|
+ gi := FindMod(modInstGen[m]);
|
|
|
+ IF gi >= 0 THEN
|
|
|
+ GetDef(VAL(CARDINAL, gi), tmpP);
|
|
|
+ IF Len(tmpP) > 0 THEN AppendTok(tmpCmd, tmpP) END;
|
|
|
+ GetSrc(VAL(CARDINAL, gi), tmpP);
|
|
|
+ IF Len(tmpP) > 0 THEN AppendTok(tmpCmd, tmpP) END
|
|
|
+ END;
|
|
|
+ GetDef(m, tmpP);
|
|
|
+ IF Len(tmpP) > 0 THEN AppendTok(tmpCmd, tmpP) END
|
|
|
+ END;
|
|
|
+ AppendTok(tmpCmd, src)
|
|
|
END;
|
|
|
- AppendTok(tmpCmd, src);
|
|
|
AppendSeg(tmpCmd, " 2>&1 | tee m2make.log | grep -q 'Parsed correctly'");
|
|
|
AppendSeg(tmpCmd, " && qbe -o ");
|
|
|
AppendTok(tmpCmd, sfile);
|
|
|
@@ -1005,7 +1074,8 @@ BEGIN
|
|
|
m := order[k];
|
|
|
GetSrc(m, src);
|
|
|
GetDef(m, tmpQ);
|
|
|
- IF (Len(src) > 0) OR ((NOT modIsMain[m]) AND (Len(tmpQ) > 0)) THEN
|
|
|
+ IF (NOT modIsGeneric[m]) AND
|
|
|
+ ((Len(src) > 0) OR ((NOT modIsMain[m]) AND (Len(tmpQ) > 0))) THEN
|
|
|
IF modIsMain[m] THEN Copy(progName, tmpN) ELSE GetName(m, tmpN) END;
|
|
|
Zero(obj); Cat("gen_ssa/", tmpN, tmpA); Cat(tmpA, ".o", obj);
|
|
|
AppendTok(tmpCmd, obj)
|