|
|
@@ -1,35 +1,41 @@
|
|
|
COMPILER M2c
|
|
|
-(* Modula-2 program modules without procedures, with an MC64 backend
|
|
|
+(* Modula-2 program modules with procedures, MC64 backend
|
|
|
(see MGen for details).
|
|
|
|
|
|
- program module only, no DEFINITION / IMPLEMENTATION split
|
|
|
- no local modules, no EXPORT, no PRIORITY
|
|
|
- - no ProcedureDeclaration, FormalParameters, ProcedureType,
|
|
|
- ProcedureCall, ActualParameters, FORWARD, RETURN
|
|
|
- - statements: assignment, IF, CASE, WHILE, REPEAT, LOOP/EXIT, FOR, WITH
|
|
|
+ - procedures: declarations (nested), value and VAR parameters,
|
|
|
+ functions with RETURN, recursion, FORWARD headings;
|
|
|
+ no procedure types/variables, no cones
|
|
|
+ - statements: assignment, procedure call, IF, CASE, WHILE,
|
|
|
+ REPEAT, LOOP/EXIT, FOR, WITH, RETURN
|
|
|
- symbol table (SymTab) with static type checking: error codes
|
|
|
- 200/201/202 and 210-224, same lenient rules as the reference
|
|
|
- implementation (single pass, declare-before-use; INTEGER,
|
|
|
- CARDINAL and subranges form one integer family; no mixed
|
|
|
- INTEGER/REAL arithmetic; INTEGER assigns to REAL; 1-character
|
|
|
- literal is CHAR; InvalidType suppresses follow-on errors)
|
|
|
- - backend (MGen): emits a single-module MC64 image <ModName>.MC4
|
|
|
- (current directory), runnable with mcint. Lowered: scalar
|
|
|
- globals, CONST literals (startup stores), SET OF ordinals
|
|
|
- (bit masks) with literals, IN, = and #; full scalar
|
|
|
- expressions on the stack machine; control flow via E0/E1 jumps.
|
|
|
- Everything else parses and type-checks but gets error 230
|
|
|
- (not supported in this phase): ARRAY/RECORD/POINTER variables,
|
|
|
- string variables, WITH, non-literal CONST expressions and BY
|
|
|
- steps, EXIT outside LOOP, imported names used as values.
|
|
|
+ 200/201/202 and 210-224 (as before), plus 231 (procedure
|
|
|
+ forward mismatch or missing body), 232 (bad RETURN), 233
|
|
|
+ (invalid procedure call); same lenient rules (single pass,
|
|
|
+ declare-before-use; INTEGER, CARDINAL and subranges form one
|
|
|
+ integer family; no mixed INTEGER/REAL arithmetic; INTEGER
|
|
|
+ assigns to REAL; 1-character literal is CHAR; InvalidType
|
|
|
+ suppresses follow-on errors)
|
|
|
+ - backend (MGen): single-module MC64 image <ModName>.MC4,
|
|
|
+ runnable with mcint. Procedures take table entries 1..N
|
|
|
+ (0 = module body), run with ENTER frames, called via ED
|
|
|
+ (global), EC (directly nested) or EE (display walk); actuals
|
|
|
+ evaluate left-to-right into temps, then push reversed.
|
|
|
+ Lowered: scalar globals and frame variables, CONST literals,
|
|
|
+ SET masks with literals/IN/=/#; full scalar expressions;
|
|
|
+ control flow via E0/E1 jumps. The rest parses and type-checks
|
|
|
+ but gets error 230: ARRAY/RECORD/POINTER variables, string
|
|
|
+ variables, WITH, non-literal CONST expressions and BY steps,
|
|
|
+ EXIT outside LOOP, imported names used as values.
|
|
|
- test convention (the language has no I/O): a global
|
|
|
VAR ExitCode : INTEGER;
|
|
|
is printed as decimal + CRLF through an embedded helper;
|
|
|
without it the program just ends.
|
|
|
- - known semantic edges: INTEGER DIV/MOD truncate toward zero
|
|
|
- (not Modula-2 floor); CARDINAL values past MAXINT compare as
|
|
|
- signed; AND/OR are eager (no short-circuit); REAL widens to
|
|
|
- binary64; assignment targets cost one dead load. *)
|
|
|
+ - known semantic edges: INTEGER DIV/MOD truncate toward zero;
|
|
|
+ CARDINAL past MAXINT compares as signed; AND/OR are eager;
|
|
|
+ REAL widens to binary64; at most 64 procedures, 64 actuals
|
|
|
+ per call, 16 names per FP-section, 8-deep nested calls. *)
|
|
|
|
|
|
IMPORT SymTab, MGen;
|
|
|
|
|
|
@@ -63,10 +69,14 @@ PRODUCTIONS
|
|
|
IF ~SymTab.Enter(m1, SymTab.KindModule)
|
|
|
THEN SemError(200) END .)
|
|
|
";"
|
|
|
- { Import } Block GetIdent<m2> (. IF ~SymTab.Equal(m1, m2)
|
|
|
+ { Import } Block<FALSE> GetIdent<m2>
|
|
|
+ (. IF ~SymTab.Equal(m1, m2)
|
|
|
THEN SemError(202) END .)
|
|
|
- "." (. MGen.EndModule;
|
|
|
- SymTab.PrintTable; .) .
|
|
|
+ "." (. IF SymTab.AnyForward() THEN
|
|
|
+ SemError(231)
|
|
|
+ END;
|
|
|
+ MGen.EndModule;
|
|
|
+ SymTab.PrintTable; .) .
|
|
|
Import (. VAR n: SymTab.Name; .)
|
|
|
= "FROM"
|
|
|
GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
|
|
|
@@ -81,10 +91,29 @@ PRODUCTIONS
|
|
|
{ ","
|
|
|
GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
|
|
|
THEN SemError(200) END .) } .
|
|
|
- Block = { Declaration }
|
|
|
- [ "BEGIN" (. MGen.BeginBody; .)
|
|
|
- StatSeq ]
|
|
|
- "END" .
|
|
|
+ Block <isProc: BOOLEAN> (. VAR began: BOOLEAN; .)
|
|
|
+ = (. began := FALSE; .)
|
|
|
+ { Declaration }
|
|
|
+ [ "BEGIN" (. began := TRUE;
|
|
|
+ IF isProc THEN
|
|
|
+ MGen.ProcEntry(
|
|
|
+ SymTab.CurProc(),
|
|
|
+ SymTab.ProcNLocals())
|
|
|
+ ELSE MGen.BeginBody
|
|
|
+ END; .)
|
|
|
+ StatSeq ]
|
|
|
+ "END" (. IF isProc THEN
|
|
|
+ IF ~began THEN
|
|
|
+ MGen.ProcEntry(
|
|
|
+ SymTab.CurProc(),
|
|
|
+ SymTab.ProcNLocals())
|
|
|
+ END;
|
|
|
+ IF SymTab.InFunction() THEN
|
|
|
+ MGen.PushInt(0)
|
|
|
+ END;
|
|
|
+ MGen.Leave(SymTab.CurNPar(),
|
|
|
+ SymTab.InFunction())
|
|
|
+ END; .) .
|
|
|
Declaration = "CONST"
|
|
|
{
|
|
|
ConstDecl ";" }
|
|
|
@@ -93,7 +122,8 @@ PRODUCTIONS
|
|
|
TypeDecl ";" }
|
|
|
| "VAR"
|
|
|
{
|
|
|
- VarDecl ";" } .
|
|
|
+ VarDecl ";" }
|
|
|
+ | ProcedureDecl ";" .
|
|
|
ConstDecl (. VAR n: SymTab.Name;
|
|
|
t: SymTab.TypeIndex;
|
|
|
lx: MGen.LitStr;
|
|
|
@@ -111,7 +141,9 @@ PRODUCTIONS
|
|
|
MGen.DeclConst(n, lx, t);
|
|
|
MGen.NoEmitExit; .) .
|
|
|
ConstExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
|
|
|
- = Expr<t, lx> .
|
|
|
+ (. VAR vD: BOOLEAN;
|
|
|
+ vnD: SymTab.Name; .)
|
|
|
+ = Expr<t, lx, vD, vnD> .
|
|
|
TypeDecl (. VAR n: SymTab.Name;
|
|
|
t0, t1: SymTab.TypeIndex; .)
|
|
|
= GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindType)
|
|
|
@@ -140,7 +172,9 @@ PRODUCTIONS
|
|
|
i := 0;
|
|
|
WHILE i < SymTab.PendCount() DO
|
|
|
SymTab.PendName(i, nm);
|
|
|
- MGen.DeclVar(nm);
|
|
|
+ IF SymTab.SymDepth(nm) = 0 THEN
|
|
|
+ MGen.DeclVar(nm)
|
|
|
+ END;
|
|
|
INC(i)
|
|
|
END;
|
|
|
SymTab.FixPending(t); .) .
|
|
|
@@ -152,6 +186,65 @@ PRODUCTIONS
|
|
|
GetIdent<n> (. IF ~SymTab.EnterPending(n,
|
|
|
SymTab.KindVar)
|
|
|
THEN SemError(200) END .) } .
|
|
|
+ ProcedureDecl (. VAR n, m: SymTab.Name;
|
|
|
+ rt: SymTab.TypeIndex;
|
|
|
+ hasR, ok: BOOLEAN;
|
|
|
+ endL: INTEGER; .)
|
|
|
+ = "PROCEDURE" (. hasR := FALSE; .)
|
|
|
+ GetIdent<n> (. IF SymTab.IsForward(n) THEN
|
|
|
+ SymTab.ReuseProc(n)
|
|
|
+ ELSIF ~SymTab.EnterProc(n) THEN
|
|
|
+ SemError(200)
|
|
|
+ END;
|
|
|
+ SymTab.OpenProcScope;
|
|
|
+ endL := MGen.NewLabel();
|
|
|
+ MGen.Jmp(endL); .)
|
|
|
+ [ "(" FormalParams ")" ]
|
|
|
+ [ ":" QualIdent<rt> (. hasR := TRUE; .) ]
|
|
|
+ (. IF hasR THEN
|
|
|
+ ok := SymTab.SetProcRet(rt)
|
|
|
+ ELSE
|
|
|
+ ok := SymTab.SetProcRet(
|
|
|
+ SymTab.InvalidType)
|
|
|
+ END;
|
|
|
+ IF ~ok THEN SemError(231) END;
|
|
|
+ IF ~SymTab.VerifyProc() THEN
|
|
|
+ SemError(231)
|
|
|
+ END; .)
|
|
|
+ ";"
|
|
|
+ ( Block<TRUE> GetIdent<m> (. IF ~SymTab.Equal(n, m) THEN
|
|
|
+ SemError(202) END;
|
|
|
+ MGen.DefLabel(endL);
|
|
|
+ SymTab.CloseProc; .)
|
|
|
+ | "FORWARD" (. SymTab.SetForward;
|
|
|
+ SymTab.CloseProc;
|
|
|
+ MGen.DefLabel(endL); .) ) .
|
|
|
+ FormalParams = FPSection { ";" FPSection } .
|
|
|
+ FPSection (. VAR isV: BOOLEAN;
|
|
|
+ nn, i: CARDINAL;
|
|
|
+ pn: ARRAY [0 .. 15] OF SymTab.Name;
|
|
|
+ n: SymTab.Name;
|
|
|
+ t: SymTab.TypeIndex; .)
|
|
|
+ = (. isV := FALSE; nn := 0; .)
|
|
|
+ [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ GetIdent<n> (. IF nn <= HIGH(pn) THEN
|
|
|
+ MGen.CopyName(n, pn[nn])
|
|
|
+ END;
|
|
|
+ INC(nn); .)
|
|
|
+ { "," GetIdent<n> (. IF nn <= HIGH(pn) THEN
|
|
|
+ MGen.CopyName(n, pn[nn])
|
|
|
+ END;
|
|
|
+ INC(nn); .) }
|
|
|
+ ":" Type<t> (. i := 0;
|
|
|
+ WHILE i < nn DO
|
|
|
+ IF i <= HIGH(pn) THEN
|
|
|
+ IF ~SymTab.EnterParam(
|
|
|
+ pn[i], isV, t) THEN
|
|
|
+ SemError(200)
|
|
|
+ END
|
|
|
+ END;
|
|
|
+ INC(i)
|
|
|
+ END; .) .
|
|
|
QualIdent <VAR t: SymTab.TypeIndex>
|
|
|
(. VAR n, m: SymTab.Name; .)
|
|
|
= GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
|
|
|
@@ -175,7 +268,9 @@ PRODUCTIONS
|
|
|
| SetType<t> | PointerType<t> .
|
|
|
SimpleType <VAR t: SymTab.TypeIndex>
|
|
|
(. VAR t1, t2: SymTab.TypeIndex;
|
|
|
- lx1, lx2: MGen.LitStr; .)
|
|
|
+ lx1, lx2: MGen.LitStr;
|
|
|
+ vD: BOOLEAN;
|
|
|
+ vnD: SymTab.Name; .)
|
|
|
= QualIdent<t> [ "["
|
|
|
(. MGen.NoEmitEnter; .)
|
|
|
ConstExpr<t1, lx1> (. IF (t1 # SymTab.InvalidType)
|
|
|
@@ -297,23 +392,39 @@ PRODUCTIONS
|
|
|
"TO"
|
|
|
Type<b> (. t := SymTab.NewPtr(b); .) .
|
|
|
|
|
|
- (* Statements: ProcedureCall and RETURN removed *)
|
|
|
+ (* Statements: RETURN added; calls via AssignOrCall *)
|
|
|
StatSeq = Stat { ";"
|
|
|
Stat } .
|
|
|
Stat (. VAR lx: INTEGER; .)
|
|
|
- = [ Assign | IfStat | CaseStat | WhileStat
|
|
|
- | RepeatStat | LoopStat | ForStat | WithStat
|
|
|
+ = [ AssignOrCall | IfStat | CaseStat | WhileStat
|
|
|
+ | RepeatStat | LoopStat | ForStat | WithStat | ReturnStat
|
|
|
| "EXIT" (. IF MGen.TopLoop(lx) THEN
|
|
|
MGen.Jmp(lx)
|
|
|
ELSE SemError(230) END; .) ] .
|
|
|
- Assign (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ AssignOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
dk: INTEGER;
|
|
|
bn: SymTab.Name;
|
|
|
- lxe, lxD: MGen.LitStr;
|
|
|
- isR, conv: BOOLEAN; .)
|
|
|
- = Design<dt, dk, bn, FALSE, lxD> ":="
|
|
|
- Expr<et, lxe> (. IF (dt # SymTab.InvalidType)
|
|
|
+ lxD, lxe: MGen.LitStr;
|
|
|
+ vE: BOOLEAN;
|
|
|
+ vnE: SymTab.Name;
|
|
|
+ sfx: BOOLEAN;
|
|
|
+ okC: BOOLEAN;
|
|
|
+ isR, conv,
|
|
|
+ storable: BOOLEAN; .)
|
|
|
+ = (. sfx := FALSE; .)
|
|
|
+ DesignHead<dt, dk, bn, FALSE, lxD>
|
|
|
+ ( DesignTail<dt, dk, bn, FALSE, lxD, sfx> ":="
|
|
|
+ (. storable :=
|
|
|
+ (dk = SymTab.KindVar)
|
|
|
+ OR (dk = SymTab.KindParam)
|
|
|
+ OR (dk = SymTab.KindVarPar);
|
|
|
+ IF storable THEN
|
|
|
+ MGen.StoreSetup(bn)
|
|
|
+ END; .)
|
|
|
+ Expr<et, lxe, vE, vnE> (. IF (dt # SymTab.InvalidType)
|
|
|
& (dk # SymTab.KindVar)
|
|
|
+ & (dk # SymTab.KindParam)
|
|
|
+ & (dk # SymTab.KindVarPar)
|
|
|
& (dk # SymTab.KindField)
|
|
|
& (dk # SymTab.KindImport) THEN
|
|
|
SemError(210)
|
|
|
@@ -327,19 +438,45 @@ PRODUCTIONS
|
|
|
= SymTab.ClReal);
|
|
|
conv := isR
|
|
|
& SymTab.IsIntFamily(et);
|
|
|
- IF dk = SymTab.KindVar THEN
|
|
|
+ IF storable THEN
|
|
|
IF conv THEN
|
|
|
- MGen.IntToReal;
|
|
|
+ MGen.IntToReal
|
|
|
END;
|
|
|
- MGen.StoreVar(bn)
|
|
|
+ MGen.StoreFinish(bn)
|
|
|
ELSE MGen.Drop
|
|
|
+ END; .)
|
|
|
+ | CallTail<bn, sfx, FALSE, okC, FALSE>
|
|
|
+ | (. MGen.ActBegin(bn);
|
|
|
+ IF MGen.ActEnd(bn, FALSE, FALSE) # 0 THEN
|
|
|
+ SemError(233)
|
|
|
+ END; .) ) .
|
|
|
+ CallTail <pn: SymTab.Name; sfx: BOOLEAN; inExpr: BOOLEAN;
|
|
|
+ VAR ok: BOOLEAN; hasDead: BOOLEAN>
|
|
|
+ (. VAR t: SymTab.TypeIndex;
|
|
|
+ lx: MGen.LitStr;
|
|
|
+ v: BOOLEAN;
|
|
|
+ vn: SymTab.Name; .)
|
|
|
+ = "(" (. ok := FALSE;
|
|
|
+ IF hasDead THEN MGen.Drop END;
|
|
|
+ MGen.ActBegin(pn); .)
|
|
|
+ [ Expr<t, lx, v, vn> (. IF MGen.ActValue(t, v, vn) # 0 THEN
|
|
|
+ SemError(233)
|
|
|
+ END; .)
|
|
|
+ { "," Expr<t, lx, v, vn> (. IF MGen.ActValue(t, v, vn) # 0 THEN
|
|
|
+ SemError(233)
|
|
|
+ END; .) } ]
|
|
|
+ ")" (. IF MGen.ActEnd(pn, sfx, inExpr) # 0
|
|
|
+ THEN SemError(233)
|
|
|
+ ELSE ok := TRUE
|
|
|
END; .) .
|
|
|
IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
lxC: MGen.LitStr;
|
|
|
+ vC: BOOLEAN;
|
|
|
+ vnC: SymTab.Name;
|
|
|
elseL, endL: INTEGER;
|
|
|
hasElse: BOOLEAN; .)
|
|
|
= "IF"
|
|
|
- Expr<t, lxC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
SemError(214) END;
|
|
|
elseL := MGen.NewLabel();
|
|
|
endL := MGen.NewLabel();
|
|
|
@@ -349,7 +486,7 @@ PRODUCTIONS
|
|
|
StatSeq
|
|
|
{ "ELSIF" (. MGen.Jmp(endL);
|
|
|
MGen.DefLabel(elseL); .)
|
|
|
- Expr<t, lxC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
SemError(214) END;
|
|
|
elseL := MGen.NewLabel();
|
|
|
MGen.Jz(elseL); .)
|
|
|
@@ -365,9 +502,11 @@ PRODUCTIONS
|
|
|
MGen.DefLabel(endL); .) .
|
|
|
CaseStat (. VAR st: SymTab.TypeIndex;
|
|
|
lxS: MGen.LitStr;
|
|
|
+ vS: BOOLEAN;
|
|
|
+ vnS: SymTab.Name;
|
|
|
tmp, endL: INTEGER; .)
|
|
|
= "CASE"
|
|
|
- Expr<st, lxS> (. tmp := MGen.TempGlobal();
|
|
|
+ Expr<st, lxS, vS, vnS> (. tmp := MGen.TempGlobal();
|
|
|
MGen.StoreTemp(tmp);
|
|
|
endL := MGen.NewLabel(); .)
|
|
|
"OF"
|
|
|
@@ -391,6 +530,8 @@ PRODUCTIONS
|
|
|
Labels <sel: SymTab.TypeIndex; tmp: INTEGER; bodyL: INTEGER>
|
|
|
(. VAR t, t2: SymTab.TypeIndex;
|
|
|
lx1, lx2: MGen.LitStr;
|
|
|
+ v1, v2: BOOLEAN;
|
|
|
+ vn1, vn2: SymTab.Name;
|
|
|
ta, tb, chunk: INTEGER;
|
|
|
r, hasRange: BOOLEAN; .)
|
|
|
= ConstExpr<t, lx1> (. IF ~SymTab.EqCheck(t, sel) THEN
|
|
|
@@ -430,11 +571,13 @@ PRODUCTIONS
|
|
|
MGen.DefLabel(chunk); .) .
|
|
|
WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
lxC: MGen.LitStr;
|
|
|
+ vC: BOOLEAN;
|
|
|
+ vnC: SymTab.Name;
|
|
|
topL, endL: INTEGER; .)
|
|
|
= "WHILE" (. topL := MGen.NewLabel();
|
|
|
endL := MGen.NewLabel();
|
|
|
MGen.DefLabel(topL); .)
|
|
|
- Expr<t, lxC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
SemError(214) END;
|
|
|
MGen.Jz(endL); .)
|
|
|
"DO"
|
|
|
@@ -443,12 +586,14 @@ PRODUCTIONS
|
|
|
MGen.DefLabel(endL); .) .
|
|
|
RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
lxC: MGen.LitStr;
|
|
|
+ vC: BOOLEAN;
|
|
|
+ vnC: SymTab.Name;
|
|
|
topL: INTEGER; .)
|
|
|
= "REPEAT" (. topL := MGen.NewLabel();
|
|
|
MGen.DefLabel(topL); .)
|
|
|
StatSeq
|
|
|
"UNTIL"
|
|
|
- Expr<t, lxC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
+ Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
|
|
|
SemError(214) END;
|
|
|
MGen.Jz(topL); .) .
|
|
|
LoopStat (. VAR topL, exitL: INTEGER; .)
|
|
|
@@ -461,32 +606,54 @@ PRODUCTIONS
|
|
|
MGen.DefLabel(exitL);
|
|
|
MGen.PopLoop; .) .
|
|
|
ForStat (. VAR n, lv: SymTab.Name;
|
|
|
+ fk: INTEGER;
|
|
|
lo, hi: SymTab.TypeIndex;
|
|
|
lxLo, lxHi: MGen.LitStr;
|
|
|
+ vLo, vHi: BOOLEAN;
|
|
|
+ vnLo, vnHi: SymTab.Name;
|
|
|
byV, ht: INTEGER;
|
|
|
lTop, lChk, lEnd: INTEGER;
|
|
|
- neg: BOOLEAN; .)
|
|
|
+ neg, storable: BOOLEAN; .)
|
|
|
= "FOR"
|
|
|
GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
|
|
|
- SemError(201)
|
|
|
+ SemError(201);
|
|
|
+ fk := -1
|
|
|
ELSIF (SymTab.SymKind(n) #
|
|
|
SymTab.KindVar)
|
|
|
+ & (SymTab.SymKind(n) #
|
|
|
+ SymTab.KindParam)
|
|
|
+ & (SymTab.SymKind(n) #
|
|
|
+ SymTab.KindVarPar)
|
|
|
& (SymTab.SymKind(n) #
|
|
|
SymTab.KindField) THEN
|
|
|
- SemError(220)
|
|
|
+ SemError(220);
|
|
|
+ fk := -1
|
|
|
ELSIF (SymTab.SymType(n) #
|
|
|
SymTab.InvalidType)
|
|
|
& ~SymTab.IsIntFamily(
|
|
|
SymTab.SymType(n)) THEN
|
|
|
- SemError(220) END;
|
|
|
- MGen.CopyName(n, lv); .)
|
|
|
+ SemError(220);
|
|
|
+ fk := -1
|
|
|
+ ELSE
|
|
|
+ fk := SymTab.SymKind(n)
|
|
|
+ END;
|
|
|
+ MGen.CopyName(n, lv);
|
|
|
+ storable := (fk = SymTab.KindVar)
|
|
|
+ OR (fk = SymTab.KindParam)
|
|
|
+ OR (fk = SymTab.KindVarPar);
|
|
|
+ IF storable THEN
|
|
|
+ MGen.StoreSetup(lv)
|
|
|
+ END; .)
|
|
|
":="
|
|
|
- Expr<lo, lxLo> (. IF (lo # SymTab.InvalidType)
|
|
|
+ Expr<lo, lxLo, vLo, vnLo> (. IF (lo # SymTab.InvalidType)
|
|
|
& ~SymTab.IsIntFamily(lo) THEN
|
|
|
SemError(220) END;
|
|
|
- MGen.StoreVar(lv); .)
|
|
|
+ IF storable THEN
|
|
|
+ MGen.StoreFinish(lv)
|
|
|
+ ELSE MGen.Drop
|
|
|
+ END; .)
|
|
|
"TO"
|
|
|
- Expr<hi, lxHi> (. IF (hi # SymTab.InvalidType)
|
|
|
+ Expr<hi, lxHi, vHi, vnHi> (. IF (hi # SymTab.InvalidType)
|
|
|
& ~SymTab.IsIntFamily(hi) THEN
|
|
|
SemError(220) END;
|
|
|
ht := MGen.TempGlobal();
|
|
|
@@ -500,12 +667,15 @@ PRODUCTIONS
|
|
|
MGen.Jmp(lChk);
|
|
|
MGen.DefLabel(lTop); .)
|
|
|
StatSeq
|
|
|
- "END" (. MGen.LoadVar(lv);
|
|
|
+ "END" (. MGen.PushVar(lv);
|
|
|
MGen.PushInt(byV);
|
|
|
MGen.Add;
|
|
|
- MGen.StoreVar(lv);
|
|
|
+ IF storable THEN
|
|
|
+ MGen.StoreFinish(lv)
|
|
|
+ ELSE MGen.Drop
|
|
|
+ END;
|
|
|
MGen.DefLabel(lChk);
|
|
|
- MGen.LoadVar(lv);
|
|
|
+ MGen.PushVar(lv);
|
|
|
MGen.LoadTemp(ht);
|
|
|
IF neg THEN MGen.IGe
|
|
|
ELSE MGen.ILe END;
|
|
|
@@ -546,18 +716,54 @@ PRODUCTIONS
|
|
|
SymTab.PopScope;
|
|
|
MGen.NoSupExit
|
|
|
END; .) .
|
|
|
+ ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ lx: MGen.LitStr;
|
|
|
+ v: BOOLEAN;
|
|
|
+ vn: SymTab.Name;
|
|
|
+ hasE, doRet, conv: BOOLEAN; .)
|
|
|
+ = "RETURN" (. hasE := FALSE; .)
|
|
|
+ [ Expr<t, lx, v, vn> (. hasE := TRUE;
|
|
|
+ doRet := FALSE;
|
|
|
+ IF ~SymTab.InProc() THEN
|
|
|
+ SemError(232)
|
|
|
+ ELSIF ~SymTab.InFunction() THEN
|
|
|
+ SemError(232)
|
|
|
+ ELSIF ~SymTab.Assignable(
|
|
|
+ t, SymTab.CurRet()) THEN
|
|
|
+ SemError(232)
|
|
|
+ ELSE doRet := TRUE
|
|
|
+ END;
|
|
|
+ conv := doRet
|
|
|
+ & SymTab.IsIntFamily(t)
|
|
|
+ & (SymTab.ClassOf(
|
|
|
+ SymTab.CurRet())
|
|
|
+ = SymTab.ClReal);
|
|
|
+ IF doRet THEN
|
|
|
+ IF conv THEN
|
|
|
+ MGen.IntToReal
|
|
|
+ END;
|
|
|
+ MGen.Leave(
|
|
|
+ SymTab.CurNPar(), TRUE)
|
|
|
+ ELSE MGen.Drop
|
|
|
+ END; .) ]
|
|
|
+ (. IF ~hasE THEN
|
|
|
+ IF ~SymTab.InProc() THEN
|
|
|
+ SemError(232)
|
|
|
+ ELSIF SymTab.InFunction() THEN
|
|
|
+ SemError(232)
|
|
|
+ ELSE MGen.Leave(
|
|
|
+ SymTab.CurNPar(), FALSE)
|
|
|
+ END
|
|
|
+ END; .) .
|
|
|
|
|
|
- (* Expressions: Designator without ActualParameters.
|
|
|
- Only record fields resolve qualified access; WITH pushes an
|
|
|
- inner scope so field names also work unqualified in its body.
|
|
|
- Each expression synthesizes its SymTab type in t and, for
|
|
|
- single literals, the source text in lx ("" otherwise, used for
|
|
|
- CONST validation). Values travel on the MC64 stack. *)
|
|
|
- Design <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr>
|
|
|
- (. VAR n, m: SymTab.Name;
|
|
|
- it: SymTab.TypeIndex;
|
|
|
- lxI: MGen.LitStr;
|
|
|
+ (* Expressions: Designator without ActualParameters (calls use
|
|
|
+ CallTail). Each expression synthesizes its SymTab type in t,
|
|
|
+ the source text in lx for single literals ("" otherwise), and
|
|
|
+ whether it is a plain variable (v/vn) for VAR actuals.
|
|
|
+ Values travel on the MC64 stack. *)
|
|
|
+ DesignHead <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr>
|
|
|
+ (. VAR n: SymTab.Name;
|
|
|
cls: INTEGER; .)
|
|
|
= GetIdent<n> (. MGen.CopyName(n, bn);
|
|
|
lx[0] := 0C;
|
|
|
@@ -603,7 +809,10 @@ PRODUCTIONS
|
|
|
MGen.PushInt(0)
|
|
|
END
|
|
|
END
|
|
|
- ELSIF k = SymTab.KindVar THEN
|
|
|
+ ELSIF (k = SymTab.KindVar)
|
|
|
+ OR (k = SymTab.KindParam)
|
|
|
+ OR (k
|
|
|
+ = SymTab.KindVarPar) THEN
|
|
|
cls := SymTab.ClassOf(t);
|
|
|
IF (cls = SymTab.ClInt)
|
|
|
OR (cls = SymTab.ClReal)
|
|
|
@@ -614,7 +823,7 @@ PRODUCTIONS
|
|
|
OR (cls
|
|
|
= SymTab.ClSet) THEN
|
|
|
IF doLoad THEN
|
|
|
- MGen.LoadVar(n)
|
|
|
+ MGen.PushVar(n)
|
|
|
END
|
|
|
ELSE SemError(230);
|
|
|
IF doLoad THEN
|
|
|
@@ -634,8 +843,17 @@ PRODUCTIONS
|
|
|
SemError(230)
|
|
|
END
|
|
|
END
|
|
|
- END; .)
|
|
|
- { "." (. lx[0] := 0C; .)
|
|
|
+ END; .) .
|
|
|
+ DesignTail <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr;
|
|
|
+ VAR sfx: BOOLEAN>
|
|
|
+ (. VAR m: SymTab.Name;
|
|
|
+ it: SymTab.TypeIndex;
|
|
|
+ lxI: MGen.LitStr;
|
|
|
+ vI: BOOLEAN;
|
|
|
+ vnI: SymTab.Name; .)
|
|
|
+ = (. sfx := FALSE; .)
|
|
|
+ { "." (. sfx := TRUE; lx[0] := 0C; .)
|
|
|
GetIdent<m> (. IF t = SymTab.InvalidType THEN
|
|
|
ELSIF SymTab.ClassOf(t) #
|
|
|
SymTab.ClRecord THEN
|
|
|
@@ -650,8 +868,8 @@ PRODUCTIONS
|
|
|
IF doLoad THEN
|
|
|
MGen.Drop; MGen.PushInt(0)
|
|
|
END; .)
|
|
|
- | "["
|
|
|
- Expr<it, lxI> (. MGen.Drop;
|
|
|
+ | "[" (. sfx := TRUE; lx[0] := 0C; .)
|
|
|
+ Expr<it, lxI, vI, vnI> (. MGen.Drop;
|
|
|
IF t = SymTab.InvalidType THEN
|
|
|
ELSIF SymTab.ClassOf(t) #
|
|
|
SymTab.ClArray THEN
|
|
|
@@ -670,13 +888,13 @@ PRODUCTIONS
|
|
|
MGen.Drop; MGen.PushInt(0)
|
|
|
END; .)
|
|
|
{ ","
|
|
|
- Expr<it, lxI> (. MGen.Drop;
|
|
|
+ Expr<it, lxI, vI, vnI> (. MGen.Drop;
|
|
|
IF (it # SymTab.InvalidType)
|
|
|
& ~SymTab.IsIntFamily(it) THEN
|
|
|
SemError(218) END; .) }
|
|
|
"]"
|
|
|
- | "^" (. lx[0] := 0C;
|
|
|
- IF t = SymTab.InvalidType THEN
|
|
|
+ | "^" (. sfx := TRUE; lx[0] := 0C; .)
|
|
|
+ (. IF t = SymTab.InvalidType THEN
|
|
|
ELSIF SymTab.ClassOf(t) #
|
|
|
SymTab.ClPtr THEN
|
|
|
SemError(219);
|
|
|
@@ -687,13 +905,21 @@ PRODUCTIONS
|
|
|
IF doLoad THEN
|
|
|
MGen.Drop; MGen.PushInt(0)
|
|
|
END; .) } .
|
|
|
- Expr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
|
|
|
+ Design <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr>
|
|
|
+ (. VAR sfxD: BOOLEAN; .)
|
|
|
+ = DesignHead<t, k, bn, doLoad, lx>
|
|
|
+ DesignTail<t, k, bn, doLoad, lx, sfxD> .
|
|
|
+ Expr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
|
|
|
+ VAR v: BOOLEAN; VAR vn: SymTab.Name>
|
|
|
(. VAR t2: SymTab.TypeIndex;
|
|
|
tc, op: INTEGER;
|
|
|
lx2: MGen.LitStr;
|
|
|
+ v2: BOOLEAN;
|
|
|
+ vn2: SymTab.Name;
|
|
|
r: BOOLEAN; .)
|
|
|
- = SimExpr<t, lx> [ Rel<op> SimExpr<t2, lx2>
|
|
|
- (. lx[0] := 0C;
|
|
|
+ = SimExpr<t, lx, v, vn> [ Rel<op> SimExpr<t2, lx2, v2, vn2>
|
|
|
+ (. lx[0] := 0C; v := FALSE;
|
|
|
IF op = SymTab.OpIn THEN
|
|
|
IF SymTab.InCheck(t, t2) THEN
|
|
|
t := SymTab.BoolType();
|
|
|
@@ -738,14 +964,18 @@ PRODUCTIONS
|
|
|
| ">" (. op := SymTab.OpGt; .)
|
|
|
| ">=" (. op := SymTab.OpGe; .)
|
|
|
| "IN" (. op := SymTab.OpIn; .) .
|
|
|
- SimExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
|
|
|
+ SimExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
|
|
|
+ VAR v: BOOLEAN; VAR vn: SymTab.Name>
|
|
|
(. VAR t2, res2: SymTab.TypeIndex;
|
|
|
op: INTEGER;
|
|
|
lx2: MGen.LitStr;
|
|
|
+ v2: BOOLEAN;
|
|
|
+ vn2: SymTab.Name;
|
|
|
neg, isR: BOOLEAN; .)
|
|
|
= (. neg := FALSE; .)
|
|
|
[ "+" | "-" (. neg := TRUE; .) ]
|
|
|
- Term<t, lx> (. IF neg THEN
|
|
|
+ Term<t, lx, v, vn> (. IF neg THEN
|
|
|
+ v := FALSE;
|
|
|
IF MGen.IsLit(lx) THEN
|
|
|
MGen.NegFold(lx, lx)
|
|
|
ELSE lx[0] := 0C
|
|
|
@@ -756,8 +986,8 @@ PRODUCTIONS
|
|
|
ELSE MGen.NegInt
|
|
|
END
|
|
|
END; .)
|
|
|
- { AddOp<op> Term<t2, lx2>
|
|
|
- (. lx[0] := 0C;
|
|
|
+ { AddOp<op> Term<t2, lx2, v2, vn2>
|
|
|
+ (. lx[0] := 0C; v := FALSE;
|
|
|
IF op = SymTab.OpOr THEN
|
|
|
IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
t := SymTab.BoolType()
|
|
|
@@ -778,14 +1008,17 @@ PRODUCTIONS
|
|
|
= "+" (. op := SymTab.OpAdd; .)
|
|
|
| "-" (. op := SymTab.OpSub; .)
|
|
|
| "OR" (. op := SymTab.OpOr; .) .
|
|
|
- Term <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
|
|
|
+ Term <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
|
|
|
+ VAR v: BOOLEAN; VAR vn: SymTab.Name>
|
|
|
(. VAR t2, res2: SymTab.TypeIndex;
|
|
|
op: INTEGER;
|
|
|
lx2: MGen.LitStr;
|
|
|
+ v2: BOOLEAN;
|
|
|
+ vn2: SymTab.Name;
|
|
|
isR: BOOLEAN;
|
|
|
mt: INTEGER; .)
|
|
|
- = Fact<t, lx> { MulOp<op> Fact<t2, lx2>
|
|
|
- (. lx[0] := 0C;
|
|
|
+ = Fact<t, lx, v, vn> { MulOp<op> Fact<t2, lx2, v2, vn2>
|
|
|
+ (. lx[0] := 0C; v := FALSE;
|
|
|
IF op = SymTab.OpAnd THEN
|
|
|
IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
|
|
|
t := SymTab.BoolType()
|
|
|
@@ -816,19 +1049,25 @@ PRODUCTIONS
|
|
|
| "MOD" (. op := SymTab.OpMod; .)
|
|
|
| "AND" (. op := SymTab.OpAnd; .)
|
|
|
| "&" (. op := SymTab.OpAnd; .) .
|
|
|
- Fact <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
|
|
|
+ Fact <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
|
|
|
+ VAR v: BOOLEAN; VAR vn: SymTab.Name>
|
|
|
(. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
t2, et, dt, st: SymTab.TypeIndex;
|
|
|
dk: INTEGER;
|
|
|
bnF: SymTab.Name;
|
|
|
lxD, lx2: MGen.LitStr;
|
|
|
- v: INTEGER;
|
|
|
+ v2: BOOLEAN;
|
|
|
+ vn2: SymTab.Name;
|
|
|
+ vi: INTEGER;
|
|
|
c: CARDINAL;
|
|
|
- b: LONGCARD; .)
|
|
|
+ b: LONGCARD;
|
|
|
+ sfxF: BOOLEAN;
|
|
|
+ okF: BOOLEAN; .)
|
|
|
= integer (. LexString(s);
|
|
|
MGen.CopyName(s, lx);
|
|
|
- IF MGen.ParseInt(s, v) THEN
|
|
|
- MGen.PushInt(v)
|
|
|
+ v := FALSE;
|
|
|
+ IF MGen.ParseInt(s, vi) THEN
|
|
|
+ MGen.PushInt(vi)
|
|
|
ELSIF MGen.ParseCard(s, c) THEN
|
|
|
MGen.PushBits(
|
|
|
VAL(LONGCARD, c))
|
|
|
@@ -837,12 +1076,14 @@ PRODUCTIONS
|
|
|
t := SymTab.IntType(); .)
|
|
|
| real (. LexString(s);
|
|
|
MGen.CopyName(s, lx);
|
|
|
+ v := FALSE;
|
|
|
IF MGen.ParseReal(s, b) THEN
|
|
|
MGen.PushBits(b)
|
|
|
ELSE MGen.PushBits(0H)
|
|
|
END;
|
|
|
t := SymTab.RealType(); .)
|
|
|
| string (. LexString(s);
|
|
|
+ v := FALSE;
|
|
|
IF SymTab.StrLen(s) <= 3 THEN
|
|
|
t := SymTab.CharType();
|
|
|
MGen.CopyName(s, lx);
|
|
|
@@ -853,22 +1094,43 @@ PRODUCTIONS
|
|
|
lx[0] := 0C;
|
|
|
MGen.PushInt(0)
|
|
|
END; .)
|
|
|
- | Design<dt, dk, bnF, TRUE, lxD> (. t := dt;
|
|
|
- MGen.CopyName(lxD, lx); .)
|
|
|
+ | DesignHead<dt, dk, bnF, TRUE, lxD>
|
|
|
+ DesignTail<dt, dk, bnF, TRUE, lxD, sfxF>
|
|
|
+ (. t := dt;
|
|
|
+ MGen.CopyName(lxD, lx);
|
|
|
+ v := ~sfxF
|
|
|
+ & ((dk = SymTab.KindVar)
|
|
|
+ OR (dk = SymTab.KindParam)
|
|
|
+ OR (dk
|
|
|
+ = SymTab.KindVarPar));
|
|
|
+ MGen.CopyName(bnF, vn); .)
|
|
|
+ [ CallTail<bnF, sfxF, TRUE, okF, TRUE>
|
|
|
+ (. IF okF THEN
|
|
|
+ IF SymTab.SymKind(bnF)
|
|
|
+ = SymTab.KindProc THEN
|
|
|
+ t := SymTab.ProcRet(bnF)
|
|
|
+ ELSE
|
|
|
+ t := SymTab.InvalidType
|
|
|
+ END
|
|
|
+ ELSE t := SymTab.InvalidType
|
|
|
+ END;
|
|
|
+ lx[0] := 0C; v := FALSE; .) ]
|
|
|
| "("
|
|
|
- Expr<et, lx> ")" (. t := et; .)
|
|
|
+ Expr<et, lx, v, vn> ")" (. t := et; .)
|
|
|
| ( "NOT" | "~" )
|
|
|
- Fact<t2, lx2> (. lx[0] := 0C;
|
|
|
+ Fact<t2, lx2, v2, vn2> (. lx[0] := 0C; v := FALSE;
|
|
|
IF SymTab.BoolCheck(t2) THEN
|
|
|
t := SymTab.BoolType()
|
|
|
ELSE SemError(212);
|
|
|
t := SymTab.InvalidType END;
|
|
|
MGen.Not; .)
|
|
|
- | SetLit<st> (. lx[0] := 0C;
|
|
|
+ | SetLit<st> (. lx[0] := 0C; v := FALSE;
|
|
|
t := st; .) .
|
|
|
SetLit <VAR t: SymTab.TypeIndex>
|
|
|
(. VAR first, et: SymTab.TypeIndex;
|
|
|
lxE, lxE2: MGen.LitStr;
|
|
|
+ vE, vE2: BOOLEAN;
|
|
|
+ vnE, vnE2: SymTab.Name;
|
|
|
hasR: BOOLEAN; .)
|
|
|
= "{"
|
|
|
(. MGen.PushInt(0);
|
|
|
@@ -887,11 +1149,13 @@ PRODUCTIONS
|
|
|
"}" .
|
|
|
Elem <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
|
|
|
VAR lx2: MGen.LitStr; VAR hasR: BOOLEAN>
|
|
|
- (. VAR t2: SymTab.TypeIndex; .)
|
|
|
- = Expr<t, lx> (. hasR := FALSE;
|
|
|
+ (. VAR t2: SymTab.TypeIndex;
|
|
|
+ vD, vD2: BOOLEAN;
|
|
|
+ vnD, vnD2: SymTab.Name; .)
|
|
|
+ = Expr<t, lx, vD, vnD> (. hasR := FALSE;
|
|
|
lx2[0] := 0C; .)
|
|
|
[ ".."
|
|
|
- Expr<t2, lx2> (. IF ~SymTab.SetElemCheck(t, t2) THEN
|
|
|
+ Expr<t2, lx2, vD2, vnD2> (. IF ~SymTab.SetElemCheck(t, t2) THEN
|
|
|
SemError(222) END;
|
|
|
hasR := TRUE; .) ] .
|
|
|
|