home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-08-19 | 60.9 KB | 2,046 lines |
- (***************************************************************************
-
- $RCSfile: Compiler.mod $
- Description: Recursive-descent parser
-
- Created by: fjc (Frank Copeland)
- $Revision: 4.12 $
- $Author: fjc $
- $Date: 1994/08/19 20:02:03 $
-
- Copyright © 1990-1993, ETH Zuerich
- Copyright © 1993-1994, Frank Copeland
- This module forms part of the OC program
- See OC.doc for conditions of use and distribution
-
- Log entries are at the end of the file.
-
- ***************************************************************************)
-
- MODULE Compiler;
-
- (*
- ** $C= CaseChk $I= IndexChk $L= LongAdr $N= NilChk
- ** $P- PortableCode $R= RangeChk $S= StackChk $T= TypeChk
- ** $V= OvflChk $Z= ZeroVars
- *)
-
- IMPORT
- Str := Strings, IO := StdIO, Oberon, Files, OCG, OCS, OCT, OCC, OCI,
- OCE, OCP, OCH, SYS := SYSTEM;
-
-
- (* --- Exported declarations -------------------------------------------- *)
-
-
- VAR
- newSF * : BOOLEAN;
- forceCode * : BOOLEAN;
-
-
- (* --- Local declarations ----------------------------------------------- *)
-
-
- CONST
-
- NofCases = 128; RecDescSize = 8; AdrSize = OCG.PtrSize;
- ProcSize = OCG.ProcSize; PtrSize = OCG.PtrSize; ParOrg = 2 * AdrSize;
- LParOrg = 3 * AdrSize; XParOrg = 3 * AdrSize; ProcVarSize = 32768;
-
- ModNameLen = 26; (* Max. module name length, imposed by AmigaDOS *)
-
- (* Symbols *)
-
- null = OCS.null; times = OCS.times; slash = OCS.slash;
- div = OCS.div; mod = OCS.mod; and = OCS.and;
- plus = OCS.plus; minus = OCS.minus; or = OCS.or;
- eql = OCS.eql; neq = OCS.neq; lss = OCS.lss;
- leq = OCS.leq; gtr = OCS.gtr; geq = OCS.geq;
- in = OCS.in; is = OCS.is; arrow = OCS.arrow;
- period = OCS.period; comma = OCS.comma; colon = OCS.colon;
- upto = OCS.upto; rparen = OCS.rparen; rbrak = OCS.rbrak;
- rbrace = OCS.rbrace; of = OCS.of; then = OCS.then;
- do = OCS.do; to = OCS.to; lparen = OCS.lparen;
- lbrak = OCS.lbrak; lbrace = OCS.lbrace; not = OCS.not;
- becomes = OCS.becomes; number = OCS.number; nil = OCS.nil;
- string = OCS.string; ident = OCS.ident; semicolon = OCS.semicolon;
- bar = OCS.bar; end = OCS.end; else = OCS.else;
- elsif = OCS.elsif; until = OCS.until; if = OCS.if;
- case = OCS.case; while = OCS.while; repeat = OCS.repeat;
- loop = OCS.loop; with = OCS.with; exit = OCS.exit;
- return = OCS.return; array = OCS.array; record = OCS.record;
- pointer = OCS.pointer; begin = OCS.begin; const = OCS.const;
- type = OCS.type; var = OCS.var; procedure = OCS.procedure;
- import = OCS.import; module = OCS.module; eof = OCS.eof;
- cpointer = OCS.cpointer; bpointer = OCS.bpointer; libcall = OCS.libcall;
- for = OCS.for; by = OCS.by;
-
- (* object modes *)
- Var = OCG.Var; VarR = OCG.VarR; Ind = OCG.Ind; IndR = OCG.IndR;
- Con = OCG.Con; Reg = OCG.Reg; Fld = OCG.Fld; Typ = OCG.Typ;
- LProc = OCG.LProc; XProc = OCG.XProc; SProc = OCG.SProc;
- TProc = OCG.TProc; FProc = OCG.FProc; Mod = OCG.Mod; Abs = OCG.Abs;
- VarArg = OCG.VarArg;
-
- (* object modes for language extensions *)
- LibCall = OCG.LibCall;
-
- (* structure forms *)
- Undef = OCT.Undef; Byte = OCT.Byte; Bool = OCT.Bool; Char = OCT.Char;
- SInt = OCT.SInt; Int = OCT.Int; LInt = OCT.LInt; Real = OCT.Real;
- LReal = OCT.LReal; BSet = OCT.BSet; WSet = OCT.WSet; Set = OCT.Set;
- String = OCT.String; NilTyp = OCT.NilTyp; NoTyp = OCT.NoTyp;
- PtrTyp = OCT.PtrTyp; CPtrTyp = OCT.CPtrTyp; BPtrTyp = OCT.BPtrTyp;
- Pointer = OCT.Pointer; CPointer = OCT.CPointer; BPointer = OCT.BPointer;
- ProcTyp = OCT.ProcTyp; Array = OCT.Array; DynArr = OCT.DynArr;
- Record = OCT.Record;
-
- intSet = {SInt, Int, LInt};
- ptrSet = {Pointer, CPointer, BPointer};
- uptrSet = {CPointer, BPointer};
- labeltyps = {Char, SInt, Int, LInt};
-
- NumLoopLevels = 16; MaxLoopLevel = NumLoopLevels - 1;
-
- VAR
-
- sym, procNo : INTEGER;
- LoopLevel, ExitNo : INTEGER;
- LoopExit : ARRAY NumLoopLevels OF INTEGER;
-
- (* CONST mname = "Compiler"; *)
-
- (* --- Procedure declarations ------------------------------------------- *)
-
-
- (*----------------------------------)-*)
- PROCEDURE^ Type (VAR typ : OCT.Struct);
- PROCEDURE^ Expression (VAR x : OCT.Item);
- PROCEDURE^ Block
- (proc : OCT.Object; VAR dsize : LONGINT; VAR retList : INTEGER);
-
- (*------------------------------------*)
- PROCEDURE CheckSym (s : INTEGER);
-
- BEGIN (* CheckSym *)
- IF sym = s THEN OCS.Get (sym) ELSE OCS.Mark (s) END
- END CheckSym;
-
- (*------------------------------------*)
- PROCEDURE qualident (VAR x : OCT.Item; allocDesc : BOOLEAN);
-
- (* CONST pname = "qualident"; *)
-
- VAR mnolev : INTEGER; obj : OCT.Object; desc : OCT.Desc; b : BOOLEAN;
-
- BEGIN (* qualident *)
- (* OCG.TraceIn (mname, pname); *)
- (* sym = ident *)
- OCT.Find (obj, mnolev); IF obj = NIL THEN OCS.Mark (0) END; OCS.Get (sym);
- IF (sym = period) & (obj # NIL) & (obj.mode = Mod) THEN
- OCS.Get (sym); mnolev := SHORT (-obj.a0);
- IF sym = ident THEN
- OCT.FindImport (obj, obj); IF obj = NIL THEN OCS.Mark (0) END;
- OCS.Get (sym)
- ELSE
- OCS.Mark (10); obj := NIL
- END;
- END;
- x.lev := mnolev; x.obj := obj;
- IF obj # NIL THEN
- x.mode := obj.mode; x.typ := obj.typ; x.a0 := obj.a0;
- x.a1 := obj.a1; x.a2 := obj.a2; x.symbol := obj.symbol;
- x.rdOnly := (mnolev < 0) & (obj.visible = OCT.RdOnly);
- (*
- IF mnolev < 0 THEN
- b := (obj.visible = OCT.RdOnly); x.rdOnly := b
- ELSE x.rdOnly := FALSE
- END;
- *)
- IF
- allocDesc & (x.mode IN {Var, Ind}) & (x.typ # NIL)
- & (x.typ.form = DynArr)
- THEN
- desc := OCT.AllocDesc (); desc.mode := Var; desc.lev := x.lev;
- desc.a0 := x.a0; desc.a1 := 0; desc.a2 := 0; x.desc := desc
- ELSE
- x.desc := NIL
- END
- ELSE
- x.mode := Var; x.typ := OCT.undftyp; x.a0 := 0; x.obj := NIL;
- x.rdOnly := FALSE; x.desc := NIL
- END
- (* ;OCG.TraceOut (mname, pname); *)
- END qualident;
-
- (*------------------------------------*)
- PROCEDURE ConstExpression (VAR x : OCT.Item);
-
- (* CONST pname = "ConstExpression"; *)
-
- CONST
- ConstTypes = {Undef .. NilTyp, CPtrTyp, BPtrTyp, CPointer, BPointer};
-
- BEGIN (* ConstExpression *)
- (* OCG.TraceIn (mname, pname); *)
- Expression (x);
- IF (x.mode # Con) OR ~(x.typ.form IN ConstTypes) THEN
- OCS.Mark (50); x.mode := Con; x.typ := OCT.inttyp; x.a0 := 1;
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END ConstExpression;
-
- (*------------------------------------*)
- PROCEDURE NewStr (form : INTEGER) : OCT.Struct;
-
- (* CONST pname = "NewStr"; *)
-
- VAR typ : OCT.Struct;
-
- BEGIN (* NewStr *)
- (* OCG.TraceIn (mname, pname); *)
- typ := OCT.AllocStruct ();
- typ.form := form; typ.mno := 0; typ.size := 4; typ.ref := 0;
- typ.BaseTyp := OCT.undftyp; typ.strobj := NIL; typ.link := NIL;
- (* ;OCG.TraceOut (mname, pname); *)
- RETURN typ
- END NewStr;
-
- (*------------------------------------*)
- PROCEDURE CheckMark (VAR mk : SHORTINT; readOnly : BOOLEAN);
-
- (* CONST pname = "CheckMark"; *)
-
- BEGIN (* CheckMark *)
- (* OCG.TraceIn (mname, pname); *)
- OCS.Get (sym);
- IF sym = times THEN
- IF OCC.level = 0 THEN mk := OCT.Exp
- ELSE mk := OCT.NotExp; OCS.Mark (46)
- END;
- OCS.Get (sym)
- ELSIF sym = minus THEN
- IF (OCC.level = 0) & readOnly THEN mk := OCT.RdOnly
- ELSE mk := OCT.NotExp; OCS.Mark (47)
- END;
- OCS.Get (sym)
- ELSE
- mk := OCT.NotExp
- END
- (* ;OCG.TraceOut (mname, pname); *)
- END CheckMark;
-
- (*------------------------------------*)
- PROCEDURE CheckUndefPointerTypes ();
-
- (* CONST pname = "CheckUndefPointerTypes"; *)
-
- (*------------------------------------*)
- PROCEDURE CheckObj (obj : OCT.Object);
-
- BEGIN (* CheckObj *)
- IF obj # NIL THEN
- IF obj.mode = Undef THEN OCS.Mark (48) END;
- CheckObj (obj.left); CheckObj (obj.right)
- END
- END CheckObj;
-
- BEGIN (* CheckUndefPointerTypes *)
- (* OCG.TraceIn (mname, pname); *)
- CheckObj (OCT.topScope.link)
- (* ;OCG.TraceOut (mname, pname); *)
- END CheckUndefPointerTypes;
-
- (*------------------------------------*)
- PROCEDURE CheckForwardProcs ();
-
- (* CONST pname = "CheckForwardProcs"; *)
-
- (*------------------------------------*)
- PROCEDURE CheckObj ( obj : OCT.Object );
-
- (*------------------------------------*)
- PROCEDURE CheckTyp ( typ : OCT.Struct );
- VAR fld : OCT.Object;
- BEGIN (* CheckTyp *)
- IF (typ # NIL) & (typ.form = Record) THEN
- fld := typ.link;
- WHILE fld # NIL DO
- IF (fld.mode = TProc) & (fld.a2 < 0) THEN OCS.Mark (129) END;
- fld := fld.left
- END
- END
- END CheckTyp;
-
- BEGIN (* CheckObj *)
- IF obj # NIL THEN
- IF obj.mode IN {XProc, LProc} THEN
- IF obj.a2 < 0 THEN OCS.Mark (129) END
- ELSIF obj.mode = Typ THEN
- CheckTyp (obj.typ)
- END;
- CheckObj (obj.left); CheckObj (obj.right)
- END
- END CheckObj;
-
- BEGIN (* CheckForwardProcs *)
- (* OCG.TraceIn (mname, pname); *)
- CheckObj (OCT.topScope.link)
- (* ;OCG.TraceOut (mname, pname); *)
- END CheckForwardProcs;
-
- (*------------------------------------*)
- PROCEDURE RecordType (VAR typ : OCT.Struct);
-
- (* CONST pname = "RecordType"; *)
-
- VAR
- adr, size : LONGINT;
- fld, fld0, fld1, fld2 : OCT.Object;
- ftyp : OCT.Struct;
- base : OCT.Item;
-
- BEGIN (* RecordType *)
- (* OCG.TraceIn (mname, pname); *)
- typ := NewStr (Record); typ.BaseTyp := NIL; typ.n := 0; adr := 0;
- IF sym = lparen THEN
- OCS.Get (sym); (* record extension *)
- IF sym = ident THEN
- qualident (base, FALSE);
- IF (base.mode = Typ) & (base.typ.form = Record) THEN
- typ.BaseTyp := base.typ; typ.n := base.typ.n + 1;
- adr := base.typ.size
- ELSE
- OCS.Mark (52)
- END;
- ELSE
- OCS.Mark (10)
- END;
- CheckSym (rparen)
- END;
- OCT.OpenScope (0); fld := NIL; fld1 := OCT.AllocObj(); fld2 := NIL;
- LOOP
- (* OCG.TraceIn (mname, "LOOP1"); *)
- IF sym = ident THEN
- LOOP
- (* OCG.TraceIn (mname, "LOOP2"); *)
- IF sym = ident THEN
- IF typ.BaseTyp # NIL THEN
- OCT.FindField (typ.BaseTyp, fld0);
- IF fld0 # NIL THEN OCS.Mark (1) END
- END;
- OCT.Insert (OCS.name, fld, Fld); CheckMark (fld.visible, TRUE);
- IF (fld # fld2) & (fld.link = NIL) THEN
- IF fld2 = NIL THEN fld1.link := fld; OCT.topScope.right := fld
- ELSE fld2.link := fld
- END;
- fld2 := fld
- END;
- ELSE
- OCS.Mark (10)
- END;
- IF sym = comma THEN
- OCS.Get (sym)
- ELSIF sym = ident THEN
- OCS.Mark (19)
- ELSE
- (* ;OCG.TraceOut (mname, "LOOP2"); *)
- EXIT
- END;
- (* ;OCG.TraceOut (mname, "LOOP2"); *)
- END; (* LOOP *)
- CheckSym (colon); Type (ftyp);
- IF ftyp.form = DynArr THEN ftyp := OCT.undftyp; OCS.Mark (325) END;
- size := ftyp.size;
- IF size > 1 THEN
- INC (adr, adr MOD 2); INC (size, size MOD 2) (* word align *)
- END;
- WHILE fld1.link # NIL DO
- (* OCG.TraceIn (mname, "WHILE1"); *)
- fld1 := fld1.link; fld1.typ := ftyp;
- fld1.a0 := adr; INC (adr, size)
- (* ;OCG.TraceOut (mname, "WHILE1"); *)
- END;
- END; (* IF *)
- IF sym = semicolon THEN
- OCS.Get (sym)
- ELSIF sym = ident THEN
- OCS.Mark (38)
- ELSE
- (* ;OCG.TraceOut (mname, "LOOP1"); *)
- EXIT
- END;
- (* ;OCG.TraceOut (mname, "LOOP1"); *)
- END; (* LOOP *)
- typ.size := adr + (adr MOD 2); typ.link := OCT.topScope.right;
- CheckUndefPointerTypes ();
- fld0 := OCT.topScope.right;
- WHILE fld0 # NIL DO
- (* OCG.TraceIn (mname, "WHILE2"); *)
- fld1 := fld0.link; fld0.link := NIL;
- fld0.left := fld1; fld0.right := NIL;
- fld0 := fld1
- (* ;OCG.TraceOut (mname, "WHILE2"); *)
- END;
- OCT.CloseScope ();
- (* ;OCG.TraceOut (mname, pname); *)
- END RecordType;
-
- (*------------------------------------*)
- PROCEDURE ArrayType (VAR typ : OCT.Struct);
-
- (* CONST pname = "ArrayType"; *)
-
- VAR x : OCT.Item; f, n : INTEGER;
-
- BEGIN (* ArrayType *)
- (* OCG.TraceIn (mname, pname); *)
- IF sym # of THEN
- typ := NewStr (Array); ConstExpression (x); f := x.typ.form;
- IF f IN intSet THEN
- IF (x.a0 > 0) & (x.a0 <= MAX (INTEGER)) THEN n := SHORT (x.a0)
- ELSE n := 1; OCS.Mark (68)
- END
- ELSE
- OCS.Mark (51); n := 1
- END;
- typ.n := n;
- IF sym = of THEN OCS.Get (sym); Type (typ.BaseTyp)
- ELSIF sym = comma THEN OCS.Get (sym); ArrayType (typ.BaseTyp)
- ELSE OCS.Mark (34)
- END;
- IF typ.BaseTyp.form = DynArr THEN
- typ.BaseTyp := OCT.undftyp; OCS.Mark (325)
- END;
- typ.size := n * typ.BaseTyp.size;
- INC (typ.size, typ.size MOD 2); (* keep word alignment *)
- ELSE
- typ := NewStr (DynArr); OCS.Get (sym); Type (typ.BaseTyp);
- IF typ.BaseTyp.form = DynArr THEN
- typ.size := typ.BaseTyp.size + 4; typ.adr := typ.BaseTyp.adr + 4
- ELSE
- typ.size := 8; typ.adr := 4
- END
- END
- (* ;OCG.TraceOut (mname, pname); *)
- END ArrayType;
-
- (*------------------------------------*)
- (*
- $ FormalParameters = "(" [FPSection {";" FPSection}] ")"
- $ [":" qualident].
- $ FPSection = [VAR] ident [RegSpec] {"," ident [RegSpec]}
- $ ":" Type.
- $ RegSpec = "{" ConstExpression "}" [".."].
- *)
- PROCEDURE FormalParameters (
- VAR resTyp : OCT.Struct; VAR psize : LONGINT; regPars : BOOLEAN);
-
- (* CONST pname = "FormalParameters"; *)
- CONST
- D0 = 0; A5 = 13;
-
- VAR
- mode : SHORTINT; gotUpto : BOOLEAN;
- adr, size : LONGINT; res, reg : OCT.Item;
- par, par1, par2: OCT.Object; typ : OCT.Struct;
-
- BEGIN (* FormalParameters *)
- (* OCG.TraceIn (mname, pname); *)
- adr := 0; gotUpto := FALSE;
- (* Make allowance for the receiver of type-bound and libcall procedures *)
- IF OCT.topScope.right # NIL THEN
- par1 := OCT.topScope.right; adr := par1.a0
- ELSE
- par1 := OCT.AllocObj()
- END;
- par2 := par1;
- IF (sym = ident) OR (sym = var) THEN
- LOOP
- IF sym = var THEN
- OCS.Get (sym); IF regPars THEN mode := IndR ELSE mode := Ind END
- ELSIF regPars THEN mode := VarR
- ELSE mode := Var
- END;
- LOOP
- IF sym = ident THEN
- OCT.Insert (OCS.name, par, mode); OCS.Get (sym);
- IF OCT.topScope.right = NIL THEN OCT.topScope.right := par END;
- IF (par # par2) & (par.link = NIL) THEN
- par2.link := par;
- IF par1.link = NIL THEN par1.link := par END;
- END;
- par2 := par
- ELSE OCS.Mark (10)
- END;
-
- IF sym = lbrak THEN (* Register specification *)
- OCS.Get (sym); ConstExpression (reg);
- IF reg.typ.form IN intSet THEN
- IF (reg.a0 >= D0) & (reg.a0 <= A5) THEN par.a0 := reg.a0;
- ELSE OCS.Mark (903)
- END
- ELSE OCS.Mark (902)
- END;
- CheckSym (rbrak);
- IF ~regPars THEN OCS.Mark (901); par.mode := Var; par.a0 := 0 END
- ELSIF regPars THEN OCS.Mark (340)
- END;
-
- IF sym = upto THEN
- IF mode = VarR THEN par.mode := VarArg ELSE OCS.Mark (336) END;
- gotUpto := TRUE; OCS.Get (sym)
- END;
-
- IF sym = comma THEN OCS.Get (sym)
- ELSIF sym = ident THEN OCS.Mark (19)
- ELSIF sym = var THEN OCS.Mark (19); OCS.Get (sym)
- ELSE EXIT
- END;
- END; (* LOOP *)
- CheckSym (colon); Type (typ);
- (*IF (mode = VarArg) & (typ.size > PtrSize) THEN OCS.Mark (338) END;*)
-
- IF ~regPars THEN
- IF mode = Ind THEN (* VAR param *)
- IF typ.form = Record THEN size := RecDescSize
- ELSIF typ.form = DynArr THEN size := typ.size
- ELSE size := AdrSize
- END
- ELSE
- size := typ.size; IF ODD (size) THEN INC (size) END;
- END;
- WHILE par1.link # NIL DO
- par1 := par1.link; par1.typ := typ;
- DEC (adr, size); par1.a0 := adr
- END;
- ELSE
- WHILE par1.link # NIL DO par1 := par1.link; par1.typ := typ END
- END;
- IF sym = semicolon THEN OCS.Get (sym)
- ELSIF sym = ident THEN OCS.Mark (38)
- ELSE EXIT
- END;
- IF gotUpto THEN OCS.Mark (337) END
- END; (* LOOP *)
- END; (* IF *)
-
- IF ~regPars THEN
- psize := psize - adr;
- IF psize > OCG.ParLimit THEN OCS.Mark (209); psize := 0 END;
- par := OCT.topScope.right;
- WHILE par # NIL DO INC (par.a0, psize); par := par.link END;
- END;
-
- CheckSym (rparen);
- IF sym = colon THEN
- OCS.Get (sym); resTyp := OCT.undftyp;
- IF sym = ident THEN
- qualident (res, FALSE);
- IF res.mode = Typ THEN
- IF res.typ.form <= ProcTyp THEN
- resTyp := res.typ
- ELSE
- OCS.Mark (54)
- END
- ELSE
- OCS.Mark (52)
- END
- ELSE
- OCS.Mark (10)
- END;
- ELSE
- resTyp := OCT.notyp
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END FormalParameters;
-
- (*------------------------------------*)
- PROCEDURE ProcType (VAR typ : OCT.Struct);
-
- (* CONST pname = "ProcType"; *)
-
- VAR psize : LONGINT;
-
- BEGIN (* ProcType *)
- (* OCG.TraceIn (mname, pname); *)
- typ := NewStr (ProcTyp); typ.size := ProcSize;
- IF sym = lparen THEN
- OCS.Get (sym); OCT.OpenScope (OCC.level); psize := ParOrg;
- FormalParameters (typ.BaseTyp, psize, FALSE);
- typ.link := OCT.topScope.right; OCT.CloseScope ();
- ELSE
- typ.BaseTyp := OCT.notyp; typ.link := NIL
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END ProcType;
-
- (*------------------------------------*)
- PROCEDURE SetPtrBase (ptyp, btyp : OCT.Struct);
-
- (* CONST pname = "SetPtrBase"; *)
-
- BEGIN (* SetPtrBase *)
- (* OCG.TraceIn (mname, pname); *)
- ptyp.symbol := OCT.OberonSysPtr;
- IF (ptyp.form IN {CPointer, BPointer}) THEN
- IF btyp.form = DynArr THEN
- ptyp.BaseTyp := OCT.undftyp; OCS.Mark (326)
- ELSE
- ptyp.BaseTyp := btyp
- END
- ELSIF btyp.form IN {Record, Array, DynArr} THEN
- ptyp.BaseTyp := btyp;
- IF btyp.form = DynArr THEN
- ptyp.size := btyp.size; OCC.AllocTypDesc (ptyp)
- END
- ELSE
- ptyp.BaseTyp := OCT.undftyp; OCS.Mark (57)
- END
- (* ;OCG.TraceOut (mname, pname); *)
- END SetPtrBase;
-
- (*------------------------------------*)
- (*
- $ type = qualident | ArrayType | RecordType | StructType| PointerType |
- $ ProcedureType.
- *)
- PROCEDURE Type (VAR typ : OCT.Struct);
-
- (* CONST pname = "Type"; *)
-
- VAR lev : INTEGER; obj : OCT.Object; x : OCT.Item;
-
- BEGIN (* Type *)
- (* OCG.TraceIn (mname, pname); *)
- typ := OCT.undftyp;
- IF sym < lparen THEN
- OCS.Mark (12); REPEAT OCS.Get (sym) UNTIL sym >= lparen
- END;
- IF sym = ident THEN
- qualident (x, FALSE);
- IF x.mode = Typ THEN
- typ := x.typ; IF typ = OCT.notyp THEN OCS.Mark (58) END
- ELSE
- OCS.Mark (52)
- END
- ELSIF sym = array THEN
- OCS.Get (sym); ArrayType (typ)
- ELSIF sym = record THEN
- OCS.Get (sym); (*IF ~OCS.createObj THEN OCS.Mark (917) END;*)
- RecordType (typ); OCC.AllocTypDesc (typ); CheckSym (end)
- ELSIF (sym = pointer) OR (sym = cpointer) OR (sym = bpointer) THEN
- typ := NewStr (Pointer);
- IF sym = cpointer THEN
- IF OCS.portableCode THEN OCS.Mark (915) END;
- typ.form := CPointer
- ELSIF sym = bpointer THEN
- IF OCS.portableCode THEN OCS.Mark (915) END;
- typ.form := BPointer
- END;
- OCS.Get (sym); typ.link := NIL; typ.size := PtrSize; CheckSym (to);
- IF sym = ident THEN
- OCT.Find (obj, lev);
- IF obj = NIL THEN (* forward reference *)
- OCT.Insert (OCS.name, obj, Undef); typ.BaseTyp := OCT.undftyp;
- obj.typ := typ; OCS.Get (sym)
- ELSE
- qualident (x, FALSE);
- IF x.mode = Typ THEN SetPtrBase (typ, x.typ)
- ELSE typ.BaseTyp := OCT.undftyp; OCS.Mark (52)
- END
- END
- ELSE Type (x.typ); SetPtrBase (typ, x.typ)
- END
- ELSIF sym = procedure THEN
- OCS.Get (sym); ProcType (typ)
- ELSE
- OCS.Mark (12)
- END;
- IF (sym # semicolon) & (sym # rparen) & (sym # end) THEN
- OCS.Mark (15);
- WHILE (sym < ident) OR (else < sym) & (sym < begin) DO
- OCS.Get (sym)
- END
- END
- (* ;OCG.TraceOut (mname, pname); *)
- END Type;
-
- (*------------------------------------*)
- (*
- $ designator = qualident
- $ {"." ident | "[" ExpList "]" | "(" qualident ")" | "^" }.
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- $ ExpList = expression {"," expression}.
- *)
- PROCEDURE selector (VAR x, rcvr : OCT.Item);
-
- (* CONST pname = "selector"; *)
-
- VAR fld : OCT.Object; y : OCT.Item; t : OCT.Struct; f : INTEGER;
-
- BEGIN (* selector *)
- (* OCG.TraceIn (mname, pname); *)
- rcvr.mode := Undef;
- LOOP
- IF sym = lbrak THEN
- OCS.Get (sym);
- LOOP
- IF (x.typ # NIL) & (x.typ.form IN ptrSet) THEN OCE.DeRef (x) END;
- Expression (y); OCE.Index (x, y);
- IF sym = comma THEN OCS.Get (sym) ELSE EXIT END
- END;
- CheckSym (rbrak)
- ELSIF sym = period THEN
- OCS.Get (sym);
- IF sym = ident THEN
- IF x.typ # NIL THEN
- t := x.typ; f := t.form; IF f IN ptrSet THEN t := t.BaseTyp END;
- IF (t.form = Record) THEN
- OCT.FindField (t, fld);
- IF fld # NIL THEN
- IF fld.mode = Fld THEN
- IF f IN ptrSet THEN OCE.DeRef (x) END; OCE.Field (x, fld)
- ELSIF fld.mode = TProc THEN
- rcvr := x; x.mode := TProc; x.a0 := fld.a0; x.a2 := 0;
- x.obj := fld; x.typ := fld.typ; x.symbol := fld.symbol
- ELSIF fld.mode = LibCall THEN
- rcvr := x; x.mode := LibCall; x.a0 := fld.a0;
- x.obj := fld; x.typ := fld.typ
- END
- ELSE
- OCS.Mark (83); x.typ := OCT.undftyp; x.mode := Var;
- x.rdOnly := FALSE
- END
- ELSE
- OCS.Mark (53)
- END;
- ELSE
- OCS.Mark (52) (* ? *)
- END;
- OCS.Get (sym)
- ELSE
- OCS.Mark (10)
- END;
- ELSIF sym = arrow THEN
- IF x.mode = TProc THEN
- IF (rcvr.mode IN {Var,Ind}) & (rcvr.a2 < 0) THEN
- OCT.SuperCall (x.a0, rcvr.typ, fld);
- IF fld # NIL THEN
- x.a2 := -1; x.obj := fld; x.symbol := fld.symbol
- ELSE OCS.Mark (333)
- END
- ELSE OCS.Mark (332)
- END;
- OCS.Get (sym)
- ELSE
- OCS.Get (sym); OCE.DeRef (x)
- END
- ELSIF (sym = lparen) & (x.mode < Typ) & (x.typ.form # ProcTyp) THEN
- OCS.Get (sym);
- IF sym = ident THEN
- qualident (y, FALSE);
- IF y.mode = Typ THEN OCE.TypTest (x, y, FALSE)
- ELSE OCS.Mark (52)
- END
- ELSE
- OCS.Mark (10)
- END;
- CheckSym (rparen)
- ELSE
- EXIT
- END;
- END; (* LOOP *)
- (* ;OCG.TraceOut (mname, pname); *)
- END selector;
-
- (*------------------------------------*)
- PROCEDURE IsParam (obj : OCT.Object) : BOOLEAN;
-
- BEGIN (* IsParam *)
- RETURN (obj # NIL) & (obj.mode <= IndR) & (obj.a0 >= 0)
- END IsParam;
-
- (*------------------------------------*)
- PROCEDURE VarArgs
- ( VAR apar : OCT.Item; fpar : OCT.Object;
- VAR stackload : LONGINT; load : BOOLEAN );
-
- VAR x : OCT.Item;
-
- BEGIN (* VarArgs *)
- IF sym = comma THEN
- OCS.Get (sym); Expression (x); VarArgs (x, fpar, stackload, FALSE)
- END;
- OCH.VarArg (apar, fpar, stackload, load)
- END VarArgs;
-
- (*------------------------------------*)
- (*
- $ ActualParameters = "(" [ExpList] ")" .
- $ ExpList = expression {"," expression}.
- *)
- PROCEDURE ActualParameters (fpar: OCT.Object; VAR stackload : LONGINT);
-
- (* CONST pname = "ActualParameters"; *)
-
- VAR apar : OCT.Item; R : SET;
-
- BEGIN (* ActualParameters *)
- (* OCG.TraceIn (mname, pname); *)
- IF sym # rparen THEN
- R := OCC.RegSet;
- LOOP
- Expression (apar);
- IF IsParam (fpar) THEN
- IF fpar.mode = VarArg THEN VarArgs (apar, fpar, stackload, TRUE)
- ELSE OCH.Param (apar, fpar)
- END;
- fpar := fpar.link
- ELSE
- OCS.Mark (64)
- END;
- IF sym = comma THEN OCS.Get (sym)
- ELSIF (lparen <= sym) & (sym <= ident) THEN OCS.Mark (19)
- ELSE EXIT
- END
- END;
- OCC.FreeRegs (R);
- END;
- IF IsParam (fpar) THEN OCS.Mark (65) END
- (* ;OCG.TraceOut (mname, pname); *)
- END ActualParameters;
-
- (*------------------------------------*)
- PROCEDURE StandProcCall (VAR x : OCT.Item);
-
- (* CONST pname = "StandProcCall"; *)
-
- VAR y : OCT.Item; m, n : INTEGER; R : SET;
-
- BEGIN (* StandProcCall *)
- (* OCG.TraceIn (mname, pname); *)
- m := SHORT (x.a0); n := 0; R := {};
- IF (sym = lparen) THEN
- OCS.Get (sym);
- IF sym # rparen THEN
- LOOP
- IF m = OCT.pINLINE THEN
- Expression (x); OCP.Inline (x);
- ELSIF n = 0 THEN
- Expression (x); OCP.StPar1 (x, m, R); n := 1
- ELSIF m = OCT.pNEW THEN
- Expression (y); OCP.NewPar (x, y, n); INC (n)
- ELSIF n = 1 THEN
- Expression (y); OCP.StPar2 (x, y, m, R); n := 2;
- ELSIF n = 2 THEN
- Expression (y); OCP.StPar3 (x, y, m, R); n := 3;
- ELSE
- OCS.Mark (64); Expression (y);
- END;
- IF sym = comma THEN
- OCS.Get (sym)
- ELSIF (lparen <= sym) & (sym <= ident) THEN
- OCS.Mark (19)
- ELSE
- EXIT
- END;
- END; (* LOOP *)
- CheckSym (rparen)
- ELSE
- OCS.Get (sym)
- END;
- OCP.StFct (x, m, n, R)
- ELSIF m = OCT.pGC THEN
- OCP.StFct (x, m, n, R)
- ELSE
- OCS.Mark (29)
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END StandProcCall;
-
- (*------------------------------------*)
- (*
- $ element = expression [".." expression].
- *)
- PROCEDURE Element (VAR x : OCT.Item);
-
- (* CONST pname = "Element"; *)
-
- VAR e1, e2 : OCT.Item;
-
- BEGIN (* Element *)
- (* OCG.TraceIn (mname, pname); *)
- Expression (e1);
- IF sym = upto THEN
- OCS.Get (sym); Expression (e2); OCE.Set1 (x, e1, e2)
- ELSE
- OCE.Set0 (x, e1)
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END Element;
-
- (*------------------------------------*)
- (*
- $ set = "{" [element {"," element}] "}".
- *)
- PROCEDURE Sets (VAR x : OCT.Item);
-
- (* CONST pname = "Sets"; *)
-
- VAR y : OCT.Item;
-
- BEGIN (* Sets *)
- (* OCG.TraceIn (mname, pname); *)
- x.typ := OCT.settyp; y.typ := OCT.settyp;
- IF sym # rbrace THEN
- Element (x);
- LOOP
- IF sym = comma THEN
- OCS.Get (sym)
- ELSIF (lparen <= sym) & (sym <= ident) THEN
- OCS.Mark (19)
- ELSE
- EXIT
- END;
- Element (y); OCE.Op (plus, x, y, TRUE) (* x := x + y *)
- END; (* LOOP *)
- ELSE
- x.mode := Con; x.a0 := 0
- END;
- CheckSym (rbrace);
- (* ;OCG.TraceOut (mname, pname); *)
- END Sets;
-
- (*------------------------------------*)
- (*
- $ factor = number | CharConstant | string | NIL | set |
- $ designator [ActualParameters] | "(" expression ")" | "~" factor.
- *)
- PROCEDURE Factor (VAR x : OCT.Item);
-
- (* CONST pname = "Factor"; *)
-
- VAR
- fpar : OCT.Object; rcvr : OCT.Item; R, mask : SET;
- stackload : LONGINT;
-
- BEGIN (* Factor *)
- (* OCG.TraceIn (mname, pname); *)
- IF sym < lparen THEN
- OCS.Mark (13);
- REPEAT OCS.Get (sym) UNTIL sym >= lparen
- END;
- x.desc := NIL;
- IF sym = ident THEN
- qualident (x, TRUE); selector (x, rcvr);
- IF x.mode = SProc THEN
- StandProcCall (x)
- ELSIF sym = lparen THEN
- OCH.PrepCall (x, fpar, mask); OCC.SaveRegisters (R, x, mask);
- IF x.mode = TProc THEN OCH.Receiver (rcvr, x.obj.link) END;
- OCS.Get (sym); stackload := 0; ActualParameters (fpar, stackload);
- IF x.mode = LibCall THEN OCH.CallLibCall (x, rcvr, stackload)
- ELSIF x.mode = TProc THEN OCH.CallTypeBound (x, rcvr)
- ELSE OCH.Call (x)
- END;
- OCC.RestoreRegisters (R, x);
- CheckSym (rparen)
- END;
- ELSIF sym = number THEN
- OCS.Get (sym); x.mode := Con;
- CASE OCS.numtyp OF
- 1 : x.typ := OCT.chartyp; x.a0 := OCS.intval
- |
- 2 : x.a0 := OCS.intval; OCE.SetIntType (x)
- |
- 3 : x.typ := OCT.realtyp; OCE.AssReal (x, OCS.realval)
- |
- 4 : x.typ := OCT.lrltyp; OCE.AssLReal (x, OCS.lrlval)
- |
- END; (* CASE OCS.numtyp *)
- ELSIF sym = string THEN
- x.typ := OCT.stringtyp; x.mode := Con;
- OCC.AllocString (OCS.name, OCS.intval, x); OCS.Get (sym);
- IF ~OCS.portableCode THEN
- WHILE sym = string DO
- OCC.ConcatString (OCS.name, OCS.intval, x); OCS.Get (sym)
- END
- END
- ELSIF sym = nil THEN
- OCS.Get (sym); x.typ := OCT.niltyp; x.mode := Con; x.a0 := 0
- ELSIF sym = lparen THEN
- OCS.Get (sym); Expression (x); CheckSym (rparen)
- ELSIF sym = lbrak THEN
- OCS.Get (sym); OCS.Mark (29); Expression (x); CheckSym (rparen)
- ELSIF sym = lbrace THEN
- OCS.Get (sym); Sets (x)
- ELSIF sym = not THEN
- OCS.Get (sym); Factor (x); OCE.MOp (not, x)
- ELSE
- OCS.Mark (13); OCS.Get (sym); x.typ := OCT.undftyp; x.mode := Var;
- x.a0 := 0
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END Factor;
-
- (*------------------------------------*)
- (*
- $ term = factor {MulOperator factor}.
- $ MulOperator = "*" | "/" | DIV | MOD | "&" .
- *)
- PROCEDURE Term (VAR x : OCT.Item);
-
- (* CONST pname = "Term"; *)
-
- VAR
- y : OCT.Item; mulop : INTEGER;
-
- BEGIN (* Term *)
- (* OCG.TraceIn (mname, pname); *)
- Factor (x);
- WHILE (times <= sym) & (sym <= and) DO
- mulop := sym; OCS.Get (sym);
- IF mulop = and THEN OCE.MOp (and, x) END;
- Factor (y); OCE.Op (mulop, x, y, TRUE);
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END Term;
-
- (*------------------------------------*)
- (*
- $ SimpleExpression = ["+"|"-"] term {AddOperator term}.
- $ AddOperator = "+" | "-" | OR .
- *)
- PROCEDURE SimpleExpression (VAR x : OCT.Item);
-
- (* CONST pname = "SimpleExpression"; *)
-
- VAR y : OCT.Item; addop : INTEGER;
-
- BEGIN (* SimpleExpression *)
- (* OCG.TraceIn (mname, pname); *)
- IF sym = minus THEN OCS.Get (sym); Term (x); OCE.MOp (minus, x)
- ELSIF sym = plus THEN OCS.Get (sym); Term (x); OCE.MOp (plus, x)
- ELSE Term (x)
- END;
- WHILE (plus <= sym) & (sym <= or) DO
- addop := sym; OCS.Get (sym); IF addop = or THEN OCE.MOp (or, x) END;
- Term (y); OCE.Op (addop, x, y, TRUE);
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END SimpleExpression;
-
- (*------------------------------------*)
- (*
- $ expression = SimpleExpression [relation SimpleExpression].
- $ relation = "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.
- *)
- PROCEDURE Expression (VAR x : OCT.Item);
-
- (* CONST pname = "Expression"; *)
-
- VAR
- y : OCT.Item; relation : INTEGER;
-
- BEGIN (* Expression *)
- (* OCG.TraceIn (mname, pname); *)
- SimpleExpression (x);
- IF (eql <= sym) & (sym <= geq) THEN
- relation := sym; OCS.Get (sym);
- IF x.typ = OCT.booltyp THEN OCE.MOp (relation, x) END;
- SimpleExpression (y); OCE.Op (relation, x, y, TRUE)
- ELSIF sym = in THEN
- OCS.Get (sym); SimpleExpression (y); OCE.In (x, y)
- ELSIF sym = is THEN
- IF x.mode >= Typ THEN OCS.Mark (112) END;
- OCS.Get (sym);
- IF sym = ident THEN
- qualident (y, FALSE);
- IF y.mode = Typ THEN OCE.TypTest (x, y, TRUE) ELSE OCS.Mark (52) END
- ELSE
- OCS.Mark (10)
- END;
- END;
- (* ;OCG.TraceOut (mname, pname); *)
- END Expression;
-
- (*------------------------------------*)
- PROCEDURE Receiver (VAR rtyp : OCT.Struct; libCall : BOOLEAN);
-
- (* CONST pname = "Receiver"; *)
-
- VAR
- mode : SHORTINT; mnolev : INTEGER; recvr, obj : OCT.Object;
- typ : OCT.Struct;
-
- BEGIN (* Receiver *)
- (* OCG.TraceIn (mname, pname); *)
- recvr := NIL; rtyp := OCT.undftyp;
- IF sym = var THEN mode := Ind; OCS.Get (sym)
- ELSE mode := Var
- END;
- IF sym = ident THEN
- OCT.Insert (OCS.name, recvr, mode); OCS.Get (sym);
- OCT.topScope.right := recvr
- ELSE
- recvr := OCT.AllocObj (); OCS.Mark (10)
- END;
- recvr.typ := OCT.undftyp; recvr.a2 := -1; CheckSym (colon);
- IF sym = ident THEN
- OCT.Find (obj, mnolev); IF obj = NIL THEN OCS.Mark (0) END;
- OCS.Get (sym);
- IF (sym = period) & (obj # NIL) & (obj.mode = Mod) THEN
- OCS.Get (sym);
- IF sym = ident THEN
- OCT.FindImport (obj, obj); IF obj = NIL THEN OCS.Mark (0) END;
- OCS.Get (sym)
- ELSE
- OCS.Mark (10); obj := NIL
- END;
- OCS.Mark (305)
- END;
- IF (obj # NIL) & (obj.mode = Typ) THEN
- typ := obj.typ; IF typ = NIL THEN typ := OCT.undftyp END;
- IF typ = OCT.undftyp THEN OCS.Mark (58)
- ELSIF (mode = Ind) & (typ.form # Record) THEN
- OCS.Mark (307); typ := OCT.undftyp
- ELSIF (mode = Var) THEN
- IF libCall THEN
- IF typ.form # CPointer THEN OCS.Mark (308); typ := OCT.undftyp END
- ELSE
- IF typ.form # Pointer THEN OCS.Mark (306); typ := OCT.undftyp END
- END;
- END;
- IF typ.form IN ptrSet THEN rtyp := typ.BaseTyp ELSE rtyp := typ END;
- recvr.typ := typ;
- IF libCall THEN recvr.a0 := 0
- ELSIF mode = Var THEN recvr.a0 := -AdrSize
- ELSE recvr.a0 := -RecDescSize
- END
- ELSE
- OCS.Mark (52)
- END;
- ELSE
- OCS.Mark (10)
- END;
- CheckSym (rparen);
- (* ;OCG.TraceOut (mname, pname); *)
- END Receiver;
-
- (*------------------------------------*)
- (*
- $ LibCallDeclaration = LIBCALL identdef ["*"] LibCallSpec
- $ [FormalParameters]
- $ LibCallSpec = "{" identdef "," ConstExpression "}"
- *)
- PROCEDURE LibCallDeclaration ();
-
- (* CONST pname = "LibCallDeclaration"; *)
-
- VAR
- proc, par : OCT.Object;
- psize, dsize : LONGINT;
- rtyp : OCT.Struct;
-
- BEGIN (* LibCallDeclaration *)
- (* OCG.TraceIn (mname, pname); *)
- IF OCS.portableCode THEN OCS.Mark (915) END;
- rtyp := OCT.undftyp;
- IF sym = lparen THEN
- OCT.OpenScope (OCC.level + 1); OCS.Get (sym); Receiver (rtyp, TRUE)
- ELSE OCS.Mark (303)
- END;
- IF sym = ident THEN
- (* See if there is a forward declaration already *)
- OCT.FindField (rtyp, proc);
- IF proc # NIL THEN (* multiple definition *) OCS.Mark (1) END;
- proc := OCT.AllocObj(); proc.name := OCT.InsertName (OCS.name);
- IF rtyp # OCT.undftyp THEN
- proc.left := rtyp.link; rtyp.link := proc
- END;
- CheckMark (proc.visible, FALSE);
- proc.mode := LibCall; proc.typ := OCT.notyp; proc.link := NIL;
- proc.a0 := 0; proc.a1 := 0;
- INC (OCC.level);
- IF sym = lparen THEN (* Get formal parameters *)
- psize := 0; OCS.Get (sym); FormalParameters (proc.typ, psize, TRUE);
- proc.link := OCT.topScope.right
- END;
- CheckSym (semicolon);
- IF sym = minus THEN OCS.Get (sym) END;
- IF sym = number THEN proc.a0 := -OCS.intval; OCS.Get (sym)
- ELSE OCS.Mark (17)
- END;
- DEC (OCC.level); OCT.CloseScope ()
- END; (* IF *)
- (* ;OCG.TraceOut (mname, pname); *)
- END LibCallDeclaration;
-
- (*------------------------------------*)
- (*
- $ ProcedureDeclaration = ProcedureHeading ";" ProcedureBody ident.
- $ ProcedureHeading = PROCEDURE ["*"] identdef [FormalParameters].
- $ ForwardDeclaration = PROCEDURE "^" identdef [FormalParameters].
- *)
- PROCEDURE ProcedureDeclaration ();
-
- (* CONST pname = "ProcedureDeclaration"; *)
-
- VAR
- proc, proc1, par : OCT.Object;
- rtyp : OCT.Struct;
- retList, L1 : INTEGER; mode : SHORTINT;
- body, forward : BOOLEAN;
- psize, dsize : LONGINT;
- x : OCT.Item;
- symbol : OCT.Symbol;
-
- BEGIN (* ProcedureDeclaration *)
- (* OCG.TraceIn (mname, pname); *)
- dsize := 0; proc := NIL; body := TRUE; forward := FALSE; mode := LProc;
- IF (sym # ident) & (OCC.level = 0) THEN
- (* Process specifier after procedure symbol *)
- IF sym = times THEN mode := XProc; OCS.Get (sym)
- ELSIF sym = arrow THEN forward := TRUE; body := FALSE; OCS.Get (sym)
- END;
- IF sym = lparen THEN (* Type-bound procedure *)
- mode := TProc; OCS.Get (sym); OCT.OpenScope (OCC.level + 1);
- Receiver (rtyp, FALSE)
- ELSIF sym # ident THEN OCS.Mark (10)
- END;
- END;
-
- IF sym = ident THEN
- IF mode = TProc THEN
- (*
- We must be aware of two possibilities for type-bound procedures:
- - There is a forward declaration for the *same* type
- (proc1.a1 = rtyp.n) & (proc1.a2 = -1);
- - It is a redefinition of a procedure from a base type
- (proc1.a1 # rtyp.n) & (proc1.a2 = 0).
- *)
- OCT.FindField (rtyp, proc1);
- IF proc1 # NIL THEN
- IF proc1.mode # TProc THEN (* Name used for a record field *)
- OCS.Mark (329); proc1 := NIL
- ELSIF (proc1.a1 = rtyp.n) & (proc1.a2 = 0) THEN
- (* Procedure already declared *)
- OCS.Mark (1); proc1 := NIL
- END
- END;
- proc := OCT.AllocObj (); proc.name := OCT.InsertName (OCS.name);
- CheckMark (proc.visible, FALSE);
- (* Assign a procedure number *)
- IF proc1 # NIL THEN proc.a0 := proc1.a0
- ELSE proc.a0 := OCT.NextProc (rtyp)
- END;
- (* Note the type level *)
- proc.a1 := rtyp.n;
- (* Prepare to parse the parameters *)
- INC (OCC.level);
- IF (proc.visible = OCT.Exp) & ~OCS.longVars THEN
- (* return address + frame ptr + global var base *)
- psize := XParOrg
- ELSE
- (* return address + frame ptr *)
- psize := ParOrg
- END
- ELSE
- (* See if there is a forward declaration already *)
- IF OCC.level = 0 THEN OCT.Find (proc1, L1) ELSE proc1 := NIL END;
- IF (proc1 # NIL) & (proc1.a2 < 0) THEN
- (* there exists a corresponding forward declaration *)
- proc := OCT.AllocObj (); CheckMark (proc.visible, FALSE);
- IF proc.visible = OCT.Exp THEN mode := XProc END;
- ELSE
- IF proc1 # NIL THEN OCS.Mark (1); proc1 := NIL END;
- OCT.Insert (OCS.name, proc, mode); CheckMark (proc.visible, FALSE);
- IF (proc.visible = OCT.Exp) & (mode = LProc) THEN mode := XProc END;
- IF (proc.visible # OCT.Exp) & (OCC.level > 0) THEN
- proc.a0 := procNo; INC (procNo)
- ELSE
- proc.a0 := 0
- END
- END;
-
- INC (OCC.level); OCT.OpenScope (OCC.level);
- (* work out offset of procedure parameters *)
- IF (mode = LProc) & (OCC.level > 1) THEN
- psize := LParOrg (* return address + frame ptr + static link *)
- ELSIF (mode = XProc) & ~OCS.longVars THEN
- psize := XParOrg (* return address + frame ptr + global var base *)
- ELSE
- psize := ParOrg (* return address + frame ptr *)
- END;
- END;
-
- IF sym = lbrak THEN (* Foreign procedure *)
- IF mode = TProc THEN OCS.Mark (344)
- ELSIF forward THEN OCS.Mark (343); forward := FALSE
- END;
- mode := FProc; body := FALSE; OCS.Get (sym);
- IF sym = string THEN
- NEW (symbol, Str.Length (OCS.name) + 1); COPY (OCS.name, symbol^);
- OCS.Get (sym)
- ELSE OCS.Mark (342); symbol := NIL
- END;
- CheckSym (rbrak);
- END;
-
- proc.mode := mode; proc.typ := OCT.notyp;
- IF forward THEN proc.a2 := -1 ELSE proc.a2 := 0 END;
-
- IF sym = lparen THEN (* Get formal parameters *)
- OCS.Get (sym); FormalParameters (proc.typ, psize, (mode = FProc));
- ELSIF mode = TProc THEN (* fixup receiver parameter *)
- par := OCT.topScope.right;
- IF par # NIL THEN
- par.a0 := psize;
- IF par.mode = Ind THEN INC (psize, RecDescSize)
- ELSE INC (psize, AdrSize)
- END
- END
- END;
- proc.link := OCT.topScope.right;
-
- IF proc1 # NIL THEN
- IF mode = TProc THEN (* forward declaration or redefinition *)
- IF
- (proc1.a2 = 0) & (rtyp.strobj.visible = OCT.Exp)
- & (proc1.visible = OCT.Exp) & (proc.visible # OCT.Exp)
- THEN (* Redefined procedure must be exported *)
- OCS.Mark (330)
- END;
- OCH.CompareParLists (proc.link.link, proc1.link.link);
- ELSE (* forward declaration *)
- OCH.CompareParLists (proc.link, proc1.link);
- END;
- IF proc.typ # proc1.typ THEN OCS.Mark (118) END;
- IF proc1.a2 < 0 THEN (* forward declaration *)
- proc.link := NIL; OCT.FreeObj (proc);
- proc := proc1; OCT.FreeObj (proc.link);
- proc.link := OCT.topScope.right
- END
- END;
- IF forward OR (proc.a2 = 0) THEN
- IF mode = TProc THEN
- IF rtyp # OCT.undftyp THEN
- proc.left := rtyp.link; rtyp.link := proc;
- OCT.MakeTProcSymbol (rtyp.symbol, proc)
- END
- ELSIF mode = FProc THEN
- proc.symbol := symbol
- ELSE
- OCT.MakeProcSymbol (proc)
- END
- END;
- IF ~forward THEN proc.a2 := 0 END;
-
- IF body THEN
- CheckSym (semicolon); OCT.topScope.typ := proc.typ;
-
- OCH.StartProcedure (proc);
- Block (proc, dsize, retList);
- proc.link := OCT.topScope.right; (* update *)
- OCH.EndProcBody (proc, SHORT (psize), retList, dsize # 0);
- OCS.ResetProcSwitches ();
-
- (* Check size of local variables *)
- IF dsize > ProcVarSize THEN OCS.Mark (209); dsize := 0 END;
-
- (* Check name at end of procedure *)
- IF sym = ident THEN
- IF OCT.InsertName (OCS.name) # proc.name THEN OCS.Mark (4) END;
- OCS.Get (sym)
- ELSE
- OCS.Mark (10)
- END;
- END; (* IF *)
-
- IF proc.link # NIL THEN
- par := proc.link; WHILE IsParam (par.link) DO par := par.link END;
- (*OCT.FreeObj (par.link);*) par.link := NIL
- END;
- DEC (OCC.level); OCT.CloseScope ()
- END; (* IF *)
- (* ;OCG.TraceOut (mname, pname); *)
- END ProcedureDeclaration;
-
- (*------------------------------------*)
- (*
- $ CaseLabelList = CaseLabels {"," CaseLabels}.
- $ CaseLabels = ConstExpression [".." ConstExpression].
- *)
- PROCEDURE CaseLabelList (
- LabelForm : INTEGER; VAR n : INTEGER; VAR tab : ARRAY OF OCH.LabelRange);
-
- (* CONST pname = "CaseLabelList"; *)
-
- VAR
- x, y : OCT.Item; i, f, g : INTEGER;
-
- BEGIN (* CaseLabelList *)
- (* OCG.TraceIn (mname, pname); *)
- IF ~(LabelForm IN labeltyps) THEN OCS.Mark (61) END;
- LOOP
- ConstExpression (x); f := x.typ.form;
- IF (f = String) & (x.a1 <= 2) THEN
- x.a0 := x.a2; x.typ := OCT.chartyp; f := Char
- END;
- IF f IN intSet THEN
- IF LabelForm < f THEN OCS.Mark (60) END
- ELSIF f # LabelForm THEN
- OCS.Mark (60)
- END;
- IF sym = upto THEN
- OCS.Get (sym); ConstExpression (y); g := y.typ.form;
- IF (g = String) & (y.a1 <= 2) THEN
- y.a0 := y.a2; y.typ := OCT.chartyp; g := Char
- END;
- IF (g # f) & ~((f IN intSet) & (g IN intSet)) THEN
- OCS.Mark (60)
- END;
- IF y.a0 < x.a0 THEN OCS.Mark (63); y.a0 := x.a0 END
- ELSE
- y := x
- END;
- (* enter label range into ordered table *)
- i := n;
- IF i < NofCases THEN
- LOOP
- IF i = 0 THEN EXIT END;
- IF tab [i-1].low <= y.a0 THEN
- IF tab[i-1].high >= x.a0 THEN OCS.Mark (62) END;
- EXIT
- END;
- tab [i] := tab[i-1]; DEC (i)
- END; (* LOOP *)
- tab [i].low := SHORT (x.a0); tab[i].high := SHORT (y.a0);
- tab[i].label := OCC.pc; INC (n)
- ELSE
- OCS.Mark (213)
- END;
- IF sym = comma THEN
- OCS.Get (sym)
- ELSIF (sym = number) OR (sym = ident) THEN
- OCS.Mark (19)
- ELSE
- EXIT
- END;
- END; (* LOOP *)
- (* ;OCG.TraceOut (mname, pname); *)
- END CaseLabelList;
-
- (*------------------------------------*)
- (*
- $ StatementSequence = statement {";" statement}.
-
- $ statement = [assignment | ProcedureCall |
- $ IfStatement | CaseStatement | WhileStatement | RepeatStatement |
- $ LoopStatement | WithStatement | EXIT | RETURN [expression] ].
-
- $ assignment = designator ":=" expression.
-
- $ ProcedureCall = designator [ActualParameters].
-
- $ IfStatement = IF expression THEN StatementSequence
- $ {ELSIF expression THEN StatementSequence}
- $ [ELSE StatementSequence]
- $ END.
-
- $ CaseStatement = CASE expression OF case {"|" case}
- $ [ELSE StatementSequence] END.
- $ case = [CaseLabelList ":" StatementSequence].
-
- $ WhileStatement = WHILE expression DO StatementSequence END.
-
- $ RepeatStatement = REPEAT StatementSequence UNTIL expression.
-
- $ LoopStatement = LOOP StatementSequence END.
-
- $ WithStatement = WITH qualident ":" qualident DO
- $ StatementSequence END.
- *)
- PROCEDURE StatSeq (VAR retList : INTEGER);
-
- (* CONST pname = "StatSeq"; *)
-
- VAR
- fpar : OCT.Object; xtyp : OCT.Struct; stackload : LONGINT;
- x, rcvr, y, z, step : OCT.Item; L0, L1, ExitIndex : INTEGER;
- R, R1, mask : SET;
-
- (*------------------------------------*)
- PROCEDURE CasePart ();
-
- (* CONST pname = "CasePart"; *)
-
- VAR
- x : OCT.Item; n, L0, L1, L2 : INTEGER;
- tab : ARRAY NofCases OF OCH.LabelRange;
-
- BEGIN (* CasePart *)
- (* OCG.TraceIn (mname, pname); *)
- n := 0; L1 := 0;
- Expression (x); OCH.CaseIn (x, L0); CheckSym (of);
- LOOP
- IF sym < bar THEN
- CaseLabelList (x.typ.form, n, tab);
- CheckSym (colon); StatSeq (retList); OCH.FJ (L1)
- END;
- IF sym = bar THEN OCS.Get (sym) ELSE EXIT END
- END; (* LOOP *)
- L2 := OCC.pc;
- IF sym = else THEN
- OCS.Get (sym); StatSeq (retList); OCH.FJ (L1)
- ELSE
- IF OCS.caseCheck THEN OCC.Trap (OCC.CaseCheck)
- ELSE OCH.FJ (L1)
- END
- END;
- OCH.CaseOut (x, L0, L1, L2, n, tab)
- (* ;OCG.TraceOut (mname, pname); *)
- END CasePart;
-
- BEGIN (* StatSeq *)
- (* OCG.TraceIn (mname, pname); *)
- R := OCC.RegSet;
- LOOP
- IF sym < ident THEN (* illegal symbol *)
- OCS.Mark (14);
- REPEAT OCS.Get (sym) UNTIL sym >= ident;
- END;
-
- IF sym = ident THEN (* assignment or procedure call *)
- qualident (x, TRUE); selector (x, rcvr);
- IF sym = becomes THEN (* assignment *)
- OCS.Get (sym); Expression (y); OCH.Assign (x, y, FALSE)
- ELSIF sym = eql THEN (* typo ? *)
- OCS.Mark (33); OCS.Get (sym); Expression (y);
- OCH.Assign (x, y, FALSE)
- ELSIF x.mode = SProc THEN (* standard procedure call *)
- StandProcCall (x); IF x.typ # OCT.notyp THEN OCS.Mark (55) END
- ELSE (* procedure call *)
- OCH.PrepCall (x, fpar, mask); OCC.SaveRegisters (R1, x, mask);
- IF x.mode = TProc THEN OCH.Receiver (rcvr, x.obj.link) END;
- stackload := 0;
- IF sym = lparen THEN
- OCS.Get (sym); ActualParameters (fpar, stackload);
- CheckSym (rparen);
- ELSIF IsParam (fpar) THEN (* parameters missing *)
- OCS.Mark (65)
- END;
- IF x.mode = LibCall THEN OCH.CallLibCall (x, rcvr, stackload)
- ELSIF x.mode = TProc THEN OCH.CallTypeBound (x, rcvr)
- ELSE OCH.Call (x)
- END;
- OCC.RestoreRegisters (R1, x);
- IF x.typ # OCT.notyp THEN OCS.Mark (55) END;
- END;
- (*OCT.FreeDesc (x.desc);*)
-
- ELSIF sym = if THEN (* if statement *)
- OCS.Get (sym); Expression (x); OCH.CFJ (x, L0); OCC.FreeRegs (R);
- CheckSym (then); StatSeq (retList); L1 := 0;
- WHILE sym = elsif DO
- OCS.Get (sym); OCH.FJ (L1); OCC.FixLink (L0);
- Expression (x); OCH.CFJ (x, L0); OCC.FreeRegs (R);
- CheckSym (then); StatSeq (retList)
- END;
- IF sym = else THEN
- OCS.Get (sym); OCH.FJ (L1); OCC.FixLink (L0);
- StatSeq (retList)
- ELSE
- OCC.FixLink (L0)
- END;
- OCC.FixLink (L1); CheckSym (end)
-
- ELSIF sym = case THEN (* case statement *)
- OCS.Get (sym); CasePart (); CheckSym (end)
-
- ELSIF sym = while THEN (* while statement *)
- OCS.Get (sym); L1 := OCC.pc;
- Expression (x); OCH.CFJ (x, L0); OCC.FreeRegs (R);
- CheckSym (do); StatSeq (retList); OCH.BJ (L1); OCC.FixLink (L0);
- CheckSym (end)
-
- ELSIF sym = repeat THEN (* repeat statement *)
- OCS.Get (sym); L0 := OCC.pc; StatSeq (retList);
- IF sym = until THEN
- OCS.Get (sym); Expression (x); OCH.CBJ (x, L0)
- ELSE
- OCS.Mark (43)
- END;
-
- ELSIF sym = for THEN
- OCS.Get (sym);
- IF sym = ident THEN
- qualident (x, FALSE);
- IF x.lev < 0 THEN OCS.Mark (327)
- ELSIF ~(x.typ.form IN intSet) THEN OCS.Mark (314)
- END;
- CheckSym (becomes); Expression (y);
- IF ~(y.typ.form IN intSet) THEN OCS.Mark (315) END;
- CheckSym (to); Expression (z);
- IF ~(z.typ.form IN intSet) THEN OCS.Mark (315) END;
- IF sym = by THEN OCS.Get (sym); ConstExpression (step);
- IF ~(step.typ.form IN intSet) THEN OCS.Mark (17)
- ELSIF step.a0 = 0 THEN OCS.Mark (316); step.a0 := 1
- END;
- ELSE step.mode := Con; step.a0 := 1; step.typ := OCT.sinttyp
- END;
- OCH.BeginFor (x, y, z, step, L0, L1); OCC.FreeRegs (R);
- IF z.mode = Reg THEN OCC.ReserveReg (SHORT (z.a0)) END;
- CheckSym (do); StatSeq (retList); OCH.EndFor (x, step, L0, L1);
- IF z.mode = Reg THEN OCC.UnReserveReg (SHORT (z.a0)) END;
- CheckSym (end)
- ELSE OCS.Mark (10)
- END;
-
- ELSIF sym = loop THEN (* loop statement *)
- OCS.Get (sym); ExitIndex := ExitNo; INC (LoopLevel);
- L0 := OCC.pc; StatSeq (retList); OCH.BJ (L0); DEC (LoopLevel);
- WHILE ExitNo > ExitIndex DO
- DEC (ExitNo); OCC.fixup (LoopExit [ExitNo])
- END;
- CheckSym (end)
-
- ELSIF sym = with THEN (* regional type guard *)
- L1 := 0;
- REPEAT
- OCS.Get (sym); x.obj := NIL; xtyp := NIL;
- IF sym = ident THEN (* got variable OK *)
- qualident (x, FALSE); CheckSym (colon);
- IF sym = ident THEN
- qualident (y, FALSE);
- IF y.mode = Typ THEN (* got type OK *)
- IF x.obj # NIL THEN
- xtyp := x.typ; x.obj.typ := y.typ; OCE.TypTest (x, y, TRUE)
- ELSE OCS.Mark (130) (* variable has anonymous type *)
- END
- ELSE OCS.Mark (52) (* not a type *)
- END
- ELSE OCS.Mark (10)
- END
- ELSE OCS.Mark (10)
- END;
- CheckSym (do); OCC.FreeRegs (R); OCH.CFJ (x, L0); StatSeq (retList);
- IF (sym = bar) OR (sym = else) THEN
- OCH.FJ (L1); OCC.FixLink (L0)
- END;
- IF xtyp # NIL THEN x.obj.typ := xtyp END;
- UNTIL sym # bar;
- IF sym = else THEN OCS.Get (sym); StatSeq (retList)
- ELSIF OCS.typeCheck THEN OCC.TypeTrap (L0)
- ELSE OCC.FixLink (L0)
- END;
- OCC.FixLink (L1);
- CheckSym (end);
-
- ELSIF sym = exit THEN (* Loop exit statement *)
- OCS.Get (sym); L0 := 0; OCH.FJ (L0);
- IF LoopLevel = 0 THEN OCS.Mark (45)
- ELSIF ExitNo < NumLoopLevels THEN
- LoopExit [ExitNo] := L0; INC (ExitNo)
- ELSE OCS.Mark (214)
- END;
-
- ELSIF sym = return THEN (* Procedure return statement *)
- OCS.Get (sym);
- IF OCC.level > 0 THEN (* Return from procedure *)
- IF sym < semicolon THEN
- Expression (x); OCH.Result (x, OCT.topScope.typ)
- ELSIF OCT.topScope.typ # OCT.notyp THEN (* expression missing *)
- OCS.Mark (124)
- END;
- OCH.FJ (retList)
- ELSE (* return from module body *)
- IF sym < semicolon THEN Expression (x); OCS.Mark (124) END;
- OCH.FJ (retList)
- END;
- END;
-
- OCC.FreeRegs (R);
-
- IF sym = semicolon THEN
- OCS.Get (sym)
- ELSIF (sym <= ident) OR (if <= sym) & (sym <= return) THEN
- OCS.Mark (38)
- ELSE
- EXIT
- END;
- END; (* LOOP *)
- (* ;OCG.TraceOut (mname, pname); *)
- END StatSeq;
-
- (*------------------------------------*)
- (*
- $ module = MODULE ident ";" [ImportList]
- $ DeclarationSequence [BEGIN StatementSequence] END ident "." .
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- $ ProcedureBody = DeclarationSequence [BEGIN StatementSequence] END.
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- $ DeclarationSequence = {CONST {ConstantDeclaration ";"} |
- $ TYPE {TypeDeclaration ";"} | VAR {VariableDeclaration ";"}}
- $ {ProcedureDeclaration ";" | ForwardDeclaration ";"}.
- *)
- PROCEDURE Block (
- proc : OCT.Object; VAR dsize : LONGINT; VAR retList : INTEGER);
-
- (* CONST pname = "Block"; *)
-
- VAR
- typ, forward : OCT.Struct;
- obj, first, last : OCT.Object;
- x : OCT.Item;
- L0 : INTEGER;
- adr, size : LONGINT;
- mk : SHORTINT;
- id0 : ARRAY 32 OF CHAR;
-
- BEGIN (* Block *)
- (* OCG.TraceIn (mname, pname); *)
- (* Calculate base address of variables *)
- IF OCC.level = 0 THEN
- (* +ve offsets from module variable base *)
- adr := dsize;
- ELSE
- (* -ve offsets from frame pointer *)
- adr := -dsize;
- END;
-
- last := OCT.topScope.right;
- IF last # NIL THEN
- WHILE last.link # NIL DO last := last.link END;
- END;
-
- LOOP
- IF sym = const THEN (* Constant declaration(s) *)
- OCS.Get (sym);
- WHILE sym = ident DO
- COPY (OCS.name, id0); CheckMark (mk, FALSE);
- IF sym = eql THEN
- OCS.Get (sym); ConstExpression (x)
- ELSIF sym = becomes THEN
- OCS.Mark (9); OCS.Get (sym); ConstExpression (x)
- ELSE
- OCS.Mark (9)
- END;
-
- (* Enforce limitation on aliasing imported string constants *)
- IF (x.lev < 0) & (x.typ = OCT.stringtyp) & (x.a1 > 2) THEN
- OCS.Mark (323)
- END;
-
- (* Insert in symbol table *)
- OCT.Insert (id0, obj, SHORT (x.mode));
- obj.typ := x.typ; obj.a0 := x.a0; obj.a1 := x.a1; obj.a2 := x.a2;
- obj.visible := mk; obj.symbol := x.symbol;
-
- CheckSym (semicolon)
- END; (* WHILE *)
- END; (* IF *)
-
- IF sym = type THEN (* Type declaration(s) *)
- OCS.Get (sym);
- WHILE sym = ident DO
- (* Insert in symbol table *)
- typ := OCT.undftyp; OCT.Insert (OCS.name, obj, Typ);
- forward := obj.typ; obj.typ := OCT.notyp;
- CheckMark (obj.visible, FALSE);
-
- IF sym = eql THEN
- OCS.Get (sym); Type (typ);
- ELSIF (sym = becomes) OR (sym = colon) THEN
- OCS.Mark (9);
- OCS.Get (sym); Type (typ);
- ELSE
- OCS.Mark (9); typ := OCT.undftyp
- END;
- IF typ.form = DynArr THEN typ := OCT.undftyp; OCS.Mark (325) END;
-
- obj.typ := typ;
- IF typ.strobj = NIL THEN typ.strobj := obj END;
- IF forward # NIL THEN (* fixup *) SetPtrBase (forward, typ) END;
-
- CheckSym (semicolon);
- END; (* WHILE *)
- END; (* IF *)
-
- IF sym = var THEN (* Variable declarations *)
- (*IF (OCC.level = 0) & ~OCS.createObj THEN OCS.Mark (918) END;*)
- OCS.Get (sym);
- WHILE sym = ident DO
- (* Insert in symbol table *)
- OCT.Insert (OCS.name, obj, Var); CheckMark (obj.visible, TRUE);
- IF (obj # last) & (obj.link = NIL) THEN
- IF last = NIL THEN OCT.topScope.right := obj
- ELSE last.link := obj
- END;
- first := obj; last := obj
- END;
-
- LOOP (* Get identifier list *)
- IF sym = comma THEN OCS.Get (sym)
- ELSIF sym = ident THEN OCS.Mark (19)
- ELSE EXIT
- END;
- IF sym = ident THEN
- OCT.Insert (OCS.name, obj, Var); CheckMark (obj.visible, TRUE);
- IF (obj # last) & (obj.link = NIL) THEN
- last.link := obj; last := obj
- END
- ELSE
- OCS.Mark (10)
- END;
- END; (* LOOP *)
-
- (* Get type *)
- CheckSym (colon); Type (typ);
- IF typ.form = DynArr THEN typ := OCT.undftyp; OCS.Mark (325) END;
- size := typ.size;
- IF (size > 1) & ODD (size) THEN INC (size) END;
-
- (* Calculate variable addresses *)
- IF OCC.level = 0 THEN (* Global variable *)
- IF (size > 1) & ODD (adr) THEN INC (adr) END; (* Word align *)
- WHILE first # NIL DO
- first.typ := typ; first.a0 := adr; INC (adr, size);
- first := first.link
- END;
- ELSE (* Local procedure variable *)
- IF (size > 1) & ODD (adr) THEN DEC (adr) END; (* Word align *)
- WHILE first # NIL DO
- first.typ := typ; DEC (adr, size); first.a0 := adr;
- first := first.link
- END;
- END;
-
- CheckSym (semicolon);
- END; (* WHILE *)
- END; (* IF *)
- IF (sym < const) OR (sym > var) THEN EXIT END;
- END; (* LOOP *)
-
- CheckUndefPointerTypes ();
-
- WHILE sym = libcall DO (* Library call declarations *)
- OCS.Get (sym); LibCallDeclaration (); CheckSym (semicolon)
- END;
-
- WHILE sym = procedure DO (* Procedure declarations *)
- OCS.Get (sym); ProcedureDeclaration (); CheckSym (semicolon)
- END;
-
- CheckForwardProcs ();
-
- (* Calculate data size (rounded up to even value) *)
- IF OCC.level = 0 THEN dsize := adr
- ELSE dsize := -adr
- END;
- IF ODD (dsize) THEN INC (dsize) END;
-
- retList := 0; (* set up list of return branches *)
- IF OCC.level = 0 THEN OCH.StartModuleBody (dsize, retList) END;
- IF sym = begin THEN (* Main body of block *)
- (*IF (OCC.level <= 1) & ~OCS.createObj THEN OCS.Mark (919) END;*)
- IF OCC.level > 0 THEN OCH.StartProcBody (proc, dsize) END;
- OCS.Get (sym); StatSeq (retList);
- END;
-
- CheckSym (end);
- (* ;OCG.TraceOut (mname, pname); *)
- END Block;
-
- (*------------------------------------*)
- (*
- $ module = MODULE ident ";" [ImportList] DeclarationSequence
- $ [BEGIN StatementSequence] END ident "." .
- $ ImportList = IMPORT import {"," import} ";" .
- $ import = identdef [":" ident].
- *)
- PROCEDURE CompilationUnit * ( source : Files.File);
-
- (* CONST pname = "CompilationUnit"; *)
-
- VAR
- L0, retList : INTEGER; ch : CHAR;
- time, date, key, dsize : LONGINT;
- impid : ARRAY 32 OF CHAR;
- FName : ARRAY 256 OF CHAR;
-
- (*------------------------------------*)
- (* $D- disable copying of open arrays *)
- PROCEDURE MakeFileName (
- path, module, ext : ARRAY OF CHAR;
- VAR FName : ARRAY OF CHAR);
-
- BEGIN (* MakeFileName *)
- COPY (path, FName); Str.Append (FName, module); Str.Append (FName, ext)
- END MakeFileName;
-
- BEGIN (* CompilationUnit *)
- (* OCG.TraceIn (mname, pname); *)
- procNo := 1; dsize := 0; LoopLevel := 0; ExitNo := 0;
- OCC.Init (); OCT.Init (); OCS.Init (source);
-
- REPEAT OCS.Get (sym) UNTIL (sym = eof) OR (sym = module);
- IF sym # module THEN
- IO.WriteStr (" !! Err #16: MODULE keyword not found\n");
- RETURN
- END;
-
- OCS.Get (sym);
- IF sym = ident THEN
- L0 := 0; ch := OCS.name [0];
- WHILE (ch # 0X) & (L0 < ModNameLen) DO
- OCT.ModuleName [L0] := ch; INC (L0); ch := OCS.name [L0];
- END;
- OCT.ModuleName [L0] := 0X;
- IF ch # 0X THEN OCS.Mark (334) END;
-
- OCS.StartModule (OCT.ModuleName); OCT.StartModule ();
- OCT.OpenScope (0);
-
- OCS.Get (sym); CheckSym (semicolon);
-
- OCS.allowGlobalSwitches := FALSE;
- OCH.ModulePrologue ();
-
- IF sym = import THEN
- OCS.Get (sym);
-
- LOOP
- IF sym = ident THEN
- COPY (OCS.name, impid);
- OCS.Get (sym);
- MakeFileName ("", impid, ".Sym", FName);
-
- IF sym = becomes THEN
- OCS.Get (sym);
- IF sym = ident THEN
- MakeFileName ("", OCS.name, ".Sym", FName);
- OCS.Get (sym);
- ELSE
- OCS.Mark (10);
- END;
- END;
-
- OCT.Import (impid, FName);
- ELSE
- OCS.Mark (10);
- END;
-
- IF sym = comma THEN OCS.Get (sym);
- ELSIF sym = ident THEN OCS.Mark (19);
- ELSE EXIT;
- END;
- END; (* LOOP *)
-
- CheckSym (semicolon);
- END; (* IF *)
-
- IF ~OCS.scanerr THEN
- Block (NIL, dsize, retList);
- OCH.EndModuleBody (retList);
-
- IF sym = ident THEN
- IF OCS.name # OCT.ModuleName THEN OCS.Mark (4) END;
- OCS.Get (sym);
- ELSE
- OCS.Mark (10);
- END;
-
- IF sym # period THEN OCS.Mark (18) END;
-
- IF ~OCS.scanerr OR forceCode THEN
- IF ~OCS.scanerr THEN
- Oberon.GetClock (time, date);
- key := (date MOD 4000H) * 20000H + time;
- MakeFileName ("", OCT.ModuleName, ".Sym", FName);
- OCT.Export (FName, newSF, key);
- IF newSF THEN
- MakeFileName (OCT.DestPath, OCT.ModuleName, ".Sym", FName);
- IO.WriteF1 (" >> New symbol file : %s\n", SYS.ADR (FName))
- END
- END;
- IF ~OCS.scanerr OR forceCode THEN
- MakeFileName (OCT.DestPath, OCT.ModuleName, ".Obj", FName);
- IO.WriteF1 (" >> Object file : %s\n", SYS.ADR (FName));
- OCC.OutCode (FName, key, dsize);
- IO.WriteF3
- ( " CODE: %ld, DATA: %ld, VARS: %ld",
- LONG (OCC.pc), OCC.DataSize (), dsize);
- IO.WriteF1 (", TOTAL: %ld\n", OCC.pc + dsize + OCC.DataSize ())
- END;
- END; (* IF *)
- END; (* IF *)
- OCT.CloseScope ();
- OCT.EndModule (); OCS.EndModule ();
- ELSE
- IO.WriteStr (" !! Err #10: identifier expected after MODULE\n")
- END;
-
- IF OCS.scanerr THEN IO.WriteStr (" !! Errors detected\n") END;
- (* ;OCG.TraceOut (mname, pname); *)
- END CompilationUnit;
-
-
- BEGIN (* Compiler *)
- newSF := FALSE; forceCode := FALSE
- END Compiler.
-
- (***************************************************************************
-
- $Log: Compiler.mod $
- Revision 4.12 1994/08/19 20:02:03 fjc
- - Fixed bug in FormalParameters() which caused an infinite
- loop if a parameter name was declared twice.
-
- Revision 4.10 1994/07/25 00:54:09 fjc
- - Implemented check for parameter list limit.
-
- Revision 4.9 1994/07/24 00:31:02 fjc
- - Changed to using square brackets in register parameter
- declarations, in line with Oakwood guidelines.
-
- Revision 4.8 1994/07/23 16:07:02 fjc
- - Changed to allow A5 as a legal register parameter.
- - Changed to use new formats for OCC.SaveRegisters() and
- OCH.PrepCall().
-
- Revision 4.7 1994/07/22 14:23:06 fjc
- - Added code to parse foreign procedure declarations.
- - Changed to use new procedure names in OCH.
- - Fixed bug in register parameter declarations.
-
- Revision 4.6 1994/07/10 13:33:04 fjc
- - Commented out trace code.
- - Added check for unimplemented forward declared procedures.
-
- Revision 4.5 1994/06/17 17:39:00 fjc
- - Fixed stackload bug
-
- Revision 4.4 1994/06/10 12:50:39 fjc
- - Changed Factor() to concatenate string literals.
-
- Revision 4.3 1994/06/06 18:28:42 fjc
- - Implemented varargs for LibCall procedures:
- - Created VarArgs() to push the parameters in reverse order;
- - Modified ActualParameters() to call VarArgs();
- - Modified Factor() and StatSeq() to fix up stack afterwards;
- - Modified FormalParameters() to parse the new syntax.
-
- Revision 4.2 1994/06/05 22:31:46 fjc
- - Changed to conform to new symbol table format.
- - Added forceCode option.
-
- Revision 4.1 1994/06/01 09:33:44 fjc
- - Bumped version number
-
- ***************************************************************************)
-
-