| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301 |
- MODULE M3PL; (*NW 6.3.83 / 20.5.85 / 2.8.86*)
- (*One-pass Modula-2 Compiler for Lilith. Copyright N.Wirth*)
- FROM Terminal IMPORT Read, Write, WriteString, WriteLn;
- FROM FileSystem IMPORT Lookup, Response, GetPos, Close, Delete;
- FROM Clock IMPORT Time, GetTime;
- FROM M3DL IMPORT
- WordSize, MaxCodeLength,
- cardtyp, inttyp, realtyp, chartyp, bitstyp, dbltyp, notyp, stringtyp,
- addrtyp, undftyp, mainmod, sysmod,
- ObjPtr, StrPtr, ParPtr, ConstValue, StrForm, ObjClass;
- FROM M2S IMPORT
- Symbol, sym, id, numtyp, intval, dblval, realval, source, IdBuf, scanerr,
- InitScanner, GetSym, Diff, KeepId, Mark, CloseScanner;
- FROM M3TL IMPORT
- topScope, Scope, NewObj, NewStr, NewPar, NewImp,
- NewScope, CloseScope, Find, FindImport, FindInScope, CheckUDP,
- MarkHeap, ReleaseHeap, InitTableHandler;
- FROM M3RL IMPORT
- ModNo, ModList, RefFile,
- InitRef, InRef, OpenRef, OutPos, OutUnit, CloseRef;
- FROM M3GL IMPORT
- LabelRange, ItemMode, Item, curLev, curPrio, pc, rngchk,
- load, loadAdr, fixup, fixupC, FixupEnter, CheckStack, AllocString,
- GenNeg, GenNot, GenAnd, GenOr, GenOp, GenIn, GenSet, GenSingSet,
- GenItem, GenIndex, GenField, GenWith, GenDeRef,
- PrepAss, GenAssign, GenFJ, GenCFJ, GenBJ, GenCBJ,
- PrepCall, GenParam, GenCall, GenEnter, GenEnterMod, GenResult, GenReturn,
- GenCase1, GenCase2, GenCase3, GenTrap, GenFor1, GenFor2, GenFor3, GenFor4,
- GenStParam, GenStFct, GenEndDecl, InitGenerator, OutCodeFile;
- CONST NL = 27; (*max name length*)
- NofCases = 128;
- NofExits = 16;
- LoopLevels = 4;
- MaxInt = 32767;
- EnumTypSize = 1;
- SetTypSize = 1;
- PointerTypSize = 1;
- ProcTypSize = 1;
- DynArrDesSize = 2;
- StartAddress = 4;
- VAR ch: CHAR;
- pno, pnoI: CARDINAL;
- isdef, isimp, constFlag: BOOLEAN;
- FileName: ARRAY [0..NL] OF CHAR;
- TM: Time;
- PROCEDURE Type(VAR typ: StrPtr); FORWARD;
- PROCEDURE Expression(VAR x: Item); FORWARD;
- PROCEDURE Block(ancestor: ObjPtr; qual: BOOLEAN;
- VAR adr: INTEGER; VAR L0: CARDINAL); FORWARD;
- PROCEDURE err(n: CARDINAL);
- BEGIN Mark(n)
- END err;
- PROCEDURE CheckSym(s: Symbol; n: CARDINAL);
- BEGIN
- IF sym = s THEN GetSym ELSE Mark(n) END
- END CheckSym;
- PROCEDURE RefPoint;
- VAR p0, p1: CARDINAL;
- BEGIN GetPos(source, p0, p1); OutPos(p1, pc)
- END RefPoint;
- PROCEDURE qualident(VAR obj: ObjPtr);
- BEGIN (*sym = ident*)
- obj := Find(id); GetSym;
- WHILE (sym = period) & (obj # NIL) & (obj^.class = Module) DO
- GetSym;
- IF sym = ident THEN
- obj := FindInScope(id, obj^.root); GetSym;
- IF (obj # NIL) & NOT obj^.exported THEN obj := NIL END
- ELSE err(10)
- END
- END
- END qualident;
- PROCEDURE ConstExpression(VAR x: Item);
- BEGIN constFlag := TRUE; Expression(x);
- IF x.mode # conMd THEN
- err(44); x.mode := conMd; x.val.C := 1
- END ;
- constFlag := FALSE
- END ConstExpression;
- PROCEDURE CheckComp(t0, t1: StrPtr);
- BEGIN
- IF (t0 # t1) & ((t0 # inttyp) OR (t1 # cardtyp)) THEN err(61) END
- END CheckComp;
- PROCEDURE CaseLabelList(Ltyp: StrPtr;
- VAR n: CARDINAL; VAR tab: ARRAY OF LabelRange);
- VAR x,y: Item; i,j: CARDINAL; f: StrForm;
- BEGIN f := Ltyp^.form;
- IF f = Range THEN Ltyp := Ltyp^.RBaseTyp
- ELSIF (f > Int) & (f # Enum) THEN err(83)
- END ;
- LOOP ConstExpression(x); CheckComp(Ltyp, x.typ);
- IF sym = ellipsis THEN
- GetSym; ConstExpression(y); CheckComp(Ltyp, y.typ);
- IF y.val.I < x.val.I THEN err(63); y := x 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.val.I THEN
- IF tab[i-1].high >= x.val.I THEN err(62) END ;
- EXIT
- END ;
- tab[i] := tab[i-1]; i := i-1
- END ;
- WITH tab[i] DO
- low := x.val.I; high := y.val.I; label := pc
- END ;
- n := n+1
- ELSE err(92)
- END ;
- IF sym = comma THEN GetSym
- ELSIF (sym = number) OR (sym = ident) THEN err(11)
- ELSE EXIT
- END
- END
- END CaseLabelList;
- PROCEDURE Subrange(VAR typ: StrPtr);
- VAR x, y: Item; f: StrForm;
- BEGIN typ := NewStr(Range); ConstExpression(x); f := x.typ^.form;
- IF (f <= Int) OR (f = Enum) THEN typ^.min := x.val.I ELSE err(82) END ;
- CheckSym(ellipsis, 21); ConstExpression(y); CheckComp(x.typ, y.typ);
- IF (y.typ = cardtyp) & (y.val.C > MaxInt) THEN err(95) END ;
- WITH typ^ DO max := y.val.I;
- IF min > max THEN err(63); min := max END ;
- RBaseTyp := x.typ; size := x.typ^.size
- END
- END Subrange;
- PROCEDURE SimpleType(VAR typ: StrPtr);
- VAR obj, last: ObjPtr; typ0: StrPtr; n: CARDINAL;
- BEGIN typ := undftyp;
- IF sym = ident THEN
- qualident(obj);
- IF (obj # NIL) & (obj^.class = Typ) THEN typ := obj^.typ
- ELSE err(52)
- END ;
- IF sym = lbrak THEN
- GetSym; typ0 := typ; Subrange(typ);
- IF typ^.RBaseTyp # typ0 THEN
- IF (typ0 = inttyp) & (typ^.RBaseTyp = cardtyp) THEN
- typ^.RBaseTyp := inttyp
- ELSE err(61)
- END
- END ;
- IF sym = rbrak THEN GetSym ELSE err(16);
- IF sym = rparen THEN GetSym END
- END
- END
- ELSIF sym = lparen THEN
- GetSym; typ := NewStr(Enum); last := NIL; n := 0;
- LOOP
- IF sym = ident THEN
- obj := NewObj(id, Const); KeepId;
- obj^.conval.C := n; obj^.conval.prev := last;
- obj^.typ := typ; last := obj; n := n+1; GetSym
- ELSE err(10)
- END ;
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSE EXIT
- END
- END ;
- WITH typ^ DO
- ConstLink := last; NofConst := n; size := EnumTypSize
- END ;
- CheckSym(rparen, 15)
- ELSIF sym = lbrak THEN
- GetSym; Subrange(typ);
- IF sym = rbrak THEN GetSym ELSE err(16);
- IF sym = rparen THEN GetSym END
- END
- ELSE err(32)
- END
- END SimpleType;
- PROCEDURE FieldListSequence(VAR maxadr: INTEGER; adr: INTEGER);
- VAR fld1, last, tagfldtyp: ObjPtr; typ: StrPtr; size: INTEGER;
- PROCEDURE VariantPart;
- (*variables of Fieldlist used: maxadr, adr*)
- VAR lastadr: INTEGER; N: CARDINAL;
- tab: ARRAY [0..NofCases-1] OF LabelRange;
- BEGIN maxadr := adr; N := 0;
- LOOP
- IF sym < bar THEN CaseLabelList(typ, N, tab);
- CheckSym(colon, 13); FieldListSequence(lastadr, adr);
- IF lastadr > maxadr THEN maxadr := lastadr END
- END ;
- IF sym = bar THEN GetSym ELSE EXIT END
- END ;
- IF sym = else THEN
- GetSym; FieldListSequence(lastadr, adr);
- IF lastadr > maxadr THEN maxadr := lastadr END
- END
- END VariantPart;
- BEGIN typ := undftyp;
- IF (sym = ident) OR (sym = case) THEN
- LOOP
- IF sym = ident THEN last := topScope^.last;
- LOOP
- IF sym = ident THEN
- fld1 := NewObj(id, Field); KeepId; GetSym
- ELSE err(10)
- END ;
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSE EXIT
- END
- END ;
- CheckSym(colon, 13); Type(typ); size := typ^.size;
- fld1 := last^.next;
- WHILE fld1 # NIL DO
- fld1^.typ := typ; fld1^.offset := adr;
- adr := adr + size; fld1 := fld1^.next
- END
- ELSIF sym = case THEN
- GetSym; fld1 := NIL; tagfldtyp := NIL;
- IF sym = ident THEN
- fld1 := NewObj(id, Field); KeepId; GetSym
- END ;
- CheckSym(colon, 13);
- IF sym = ident THEN qualident(tagfldtyp) ELSE err(10) END ;
- IF (tagfldtyp # NIL) & (tagfldtyp^.class = Typ) THEN
- typ := tagfldtyp^.typ
- ELSE err(52)
- END ;
- IF fld1 # NIL THEN
- fld1^.offset := adr; fld1^.typ := typ;
- adr := adr + typ^.size
- END ;
- CheckSym(of, 23); VariantPart; adr := maxadr;
- CheckSym(end, 20)
- END ;
- IF sym = semicolon THEN GetSym
- ELSIF sym = ident THEN err(12)
- ELSE EXIT
- END
- END
- END ;
- maxadr := adr
- END FieldListSequence;
- PROCEDURE FormalType(VAR typ: StrPtr);
- VAR objtyp: ObjPtr;
- BEGIN typ := undftyp;
- IF sym = array THEN
- GetSym; typ := NewStr(Array);
- WITH typ^ DO
- strobj := NIL; size := DynArrDesSize; dyn := TRUE
- END ;
- CheckSym(of, 23);
- IF sym = ident THEN
- qualident(objtyp);
- IF (objtyp # NIL) & (objtyp^.class = Typ) THEN
- typ^.ElemTyp := objtyp^.typ
- ELSE err(52)
- END
- ELSE err(10)
- END
- ELSIF sym = ident THEN
- qualident(objtyp);
- IF (objtyp # NIL) & (objtyp^.class = Typ) THEN
- typ := objtyp^.typ
- ELSE err(52)
- END
- ELSE err(10)
- END
- END FormalType;
- PROCEDURE FormalTypeList(proctyp: StrPtr);
- VAR obj: ObjPtr; par, par0, par1: ParPtr; isvar: BOOLEAN;
- BEGIN par := NIL;
- IF (sym = ident) OR (sym = var) OR (sym = array) THEN
- LOOP
- IF sym = var THEN GetSym; isvar := TRUE ELSE isvar := FALSE END ;
- par := NewPar(0, isvar, par); FormalType(par^.typ);
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSE EXIT
- END
- END
- END ;
- CheckSym(rparen, 15);
- par1 := NIL; (*reverse list*)
- WHILE par # NIL DO
- par0 := par; par := par0^.next; par0^.next := par1; par1 := par0
- END ;
- proctyp^.firstPar := par1;
- IF sym = colon THEN
- GetSym; proctyp^.resTyp := undftyp;
- IF sym = ident THEN qualident(obj);
- IF (obj # NIL) & (obj^.class = Typ) THEN proctyp^.resTyp := obj^.typ
- ELSE err(52)
- END
- ELSE err(10)
- END
- ELSE proctyp^.resTyp := notyp
- END
- END FormalTypeList;
- PROCEDURE ArrayType(VAR typ: StrPtr);
- VAR a,b: INTEGER;
- BEGIN typ := NewStr(Array); typ^.dyn := FALSE; a := 0;
- SimpleType(typ^.IndexTyp);
- WITH typ^.IndexTyp^ DO
- IF form # Range THEN
- err(94); form := Range; RBaseTyp := cardtyp; min := 0; max := 0
- END ;
- a := min; b := max
- END ;
- IF sym = of THEN
- GetSym; Type(typ^.ElemTyp)
- ELSIF sym = comma THEN
- GetSym; ArrayType(typ^.ElemTyp)
- ELSE err(23)
- END ;
- IF b >= 0 THEN
- IF b - MaxInt >= a THEN err(210); a := b END
- ELSIF a < 0 THEN
- IF b >= a + MaxInt THEN err(210); a := b END
- END ;
- a := b-a+1; b := typ^.ElemTyp^.size;
- IF typ^.ElemTyp^.form = Char THEN a := (a+1) DIV 2
- ELSIF MaxInt DIV b >= a THEN a := a*b
- ELSE err(210); a := 1
- END ;
- typ^.size := a
- END ArrayType;
- PROCEDURE Type(VAR typ: StrPtr);
- VAR obj: ObjPtr; btyp: StrPtr;
- BEGIN
- IF sym < lparen THEN err(33);
- REPEAT GetSym UNTIL sym >= lparen
- END ;
- IF sym = array THEN
- GetSym; ArrayType(typ)
- ELSIF sym = record THEN
- GetSym; typ := NewStr(Record); NewScope(Typ);
- FieldListSequence(typ^.size, 0); typ^.firstFld := topScope^.next;
- CheckSym(end, 20); CloseScope
- ELSIF sym = set THEN
- GetSym; CheckSym(of, 23);
- typ := NewStr(Set); SimpleType(typ^.SBaseTyp);
- btyp := typ^.SBaseTyp;
- IF btyp^.form = Enum THEN
- IF btyp^.NofConst > WordSize THEN err(209) END
- ELSIF btyp^.form = Range THEN
- IF (btyp^.min < 0) OR (btyp^.max >= WordSize) THEN err(209) END
- ELSE err(60)
- END ;
- typ^.size := SetTypSize
- ELSIF sym = pointer THEN
- GetSym; typ := NewStr(Pointer);
- typ^.BaseId := 0; typ^.size := PointerTypSize; CheckSym(to, 24);
- IF sym = ident THEN qualident(obj);
- IF obj = NIL THEN typ^.BaseId := id; KeepId (*forward ref*)
- ELSIF obj^.class = Typ THEN typ^.PBaseTyp := obj^.typ
- ELSE err(52)
- END
- ELSE Type(typ^.PBaseTyp)
- END
- ELSIF sym = procedure THEN
- GetSym; typ := NewStr(ProcTyp); typ^.size := ProcTypSize;
- IF sym = lparen THEN
- GetSym; FormalTypeList(typ)
- ELSE typ^.resTyp := notyp
- END
- ELSE
- SimpleType(typ)
- END ;
- IF (sym < semicolon) OR (else < sym) THEN err(34);
- WHILE (sym < ident) OR (else < sym) & (sym < begin) DO
- GetSym
- END
- END
- END Type;
- PROCEDURE selector(VAR x: Item; obj: ObjPtr);
- VAR y: Item;
- BEGIN GenItem(x, obj, Scope);
- LOOP
- IF sym = lbrak THEN GetSym;
- LOOP loadAdr(x); Expression(y); GenIndex(x, y);
- IF sym = comma THEN GetSym ELSE EXIT END
- END ;
- CheckSym(rbrak, 16)
- ELSIF sym = period THEN
- GetSym;
- IF sym = ident THEN
- IF (x.typ # NIL) & (x.typ^.form = Record) THEN
- obj := FindInScope(id, x.typ^.firstFld); GenField(x, obj)
- ELSE err(57)
- END ;
- GetSym
- ELSE err(10)
- END
- ELSIF sym = arrow THEN
- GetSym; GenDeRef(x)
- ELSE EXIT
- END
- END
- END selector;
- PROCEDURE ActualParameters(VAR x: Item; fpar: ParPtr);
- VAR apar: Item;
- BEGIN
- IF sym # rparen THEN
- LOOP Expression(apar);
- IF fpar # NIL THEN
- GenParam(apar, fpar); fpar := fpar^.next
- ELSE err(64)
- END ;
- IF sym = comma THEN GetSym
- ELSIF (lparen <= sym) & (sym <= ident) THEN GetSym; err(11)
- ELSE EXIT
- END
- END
- END ;
- IF fpar # NIL THEN err(65) END
- END ActualParameters;
- PROCEDURE StandProcCall(VAR p: Item);
- VAR x: Item; m, n: CARDINAL;
- BEGIN m := p.cod^.cnum; n := 0;
- IF m = 1 THEN GenTrap(10); p.typ := notyp ELSE
- CheckSym(lparen, 22);
- LOOP Expression(x); GenStParam(p, x, m, n); n := n+1;
- IF sym = comma THEN GetSym ELSIF sym # ident THEN EXIT END
- END ;
- CheckSym(rparen, 15); GenStFct(p, m, n)
- END
- END StandProcCall;
- PROCEDURE Element(VAR x: Item);
- VAR e1, e2: Item;
- BEGIN Expression(e1);
- IF sym = ellipsis THEN GetSym;
- IF e1.mode = conMd THEN Expression(e2);
- IF e2.mode # conMd THEN err(90) END
- ELSE load(e1); Expression(e2)
- END ;
- GenSet(x, e1, e2)
- ELSE GenSingSet(x, e1)
- END ;
- END Element;
- PROCEDURE Sets(VAR x: Item; styp: StrPtr);
- VAR y: Item;
- BEGIN x.typ := styp; y.typ := styp;
- IF sym # rbrace THEN
- Element(x);
- LOOP
- IF sym = comma THEN GetSym
- ELSIF (lparen <= sym) & (sym <= ident) THEN err(11)
- ELSE EXIT
- END ;
- Element(y); GenOp(ORD(plus), x, y)
- END
- ELSE x.mode := conMd; x.val.S := {}
- END ;
- CheckSym(rbrace, 17)
- END Sets;
- PROCEDURE Factor(VAR x: Item);
- VAR obj: ObjPtr; xt: StrPtr; fpar: ParPtr;
- BEGIN
- IF sym < lparen THEN err(31);
- REPEAT GetSym UNTIL sym >= lparen
- END ;
- IF sym = ident THEN
- qualident(obj);
- IF sym = lbrace THEN
- GetSym;
- IF (obj # NIL) & (obj^.class = Typ) &
- (obj^.typ^.form = Set) THEN Sets(x, obj^.typ)
- ELSE err(52); Sets(x, bitstyp)
- END
- ELSE
- selector(x, obj);
- IF (x.mode = codMd) & (x.cod^.cnum > 0) THEN StandProcCall(x)
- ELSIF sym = lparen THEN GetSym;
- IF x.mode = typMd THEN (*type transfer function*)
- xt := x.typ; Expression(x); load(x); (*may be chartyp!*)
- IF xt^.size # x.typ^.size THEN err(81) END ;
- x.typ := xt
- ELSE PrepCall(x, fpar); ActualParameters(x, fpar); GenCall(x)
- END ;
- CheckSym(rparen, 15)
- END
- END
- ELSIF sym = number THEN
- GetSym; x.mode := conMd;
- CASE numtyp OF
- 1: x.typ := cardtyp; x.val.C := intval |
- 2: x.typ := dbltyp; x.val.D := dblval |
- 3: x.typ := chartyp; x.val.C := intval |
- 4: x.typ := realtyp; x.val.R := realval
- END
- ELSIF sym = string THEN
- x.typ := stringtyp; x.mode := conMd;
- AllocString(id, x.val.D0, x.val.D1); GetSym
- ELSIF sym = lparen THEN
- GetSym; Expression(x); CheckSym(rparen, 15)
- ELSIF sym = lbrace THEN GetSym; Sets(x, bitstyp)
- ELSIF sym = not THEN
- GetSym; Factor(x); GenNot(x)
- ELSE err(31); x.typ := undftyp; x.mode := expMd
- END
- END Factor;
- PROCEDURE Term(VAR x: Item);
- VAR y: Item; mulop: Symbol;
- BEGIN Factor(x);
- IF sym = and THEN
- GetSym; GenAnd(x); Term(y); GenOp(ORD(and), x, y)
- ELSE
- WHILE (times <= sym) & (sym < and) DO
- mulop := sym; GetSym;
- IF ~constFlag & ((x.mode # conMd) OR (mulop # times)) THEN load(x) END ;
- Factor(y); GenOp(ORD(mulop), x, y)
- END
- END
- END Term;
- PROCEDURE SimpleExpression(VAR x: Item);
- VAR y: Item; addop: Symbol;
- BEGIN
- IF sym = minus THEN
- GetSym; Term(x); GenNeg(x)
- ELSE
- IF sym = plus THEN GetSym END ;
- Term(x)
- END ;
- IF sym = or THEN
- GetSym; GenOr(x); SimpleExpression(y); GenOp(ORD(or), x, y)
- ELSE
- WHILE (plus <= sym) & (sym < or) DO
- addop := sym; GetSym;
- IF ~constFlag & ((x.mode # conMd) OR (addop = minus)) THEN load(x) END ;
- Term(y); GenOp(ORD(addop), x, y)
- END
- END
- END SimpleExpression;
- PROCEDURE Expression(VAR x: Item);
- VAR y: Item; relation: Symbol;
- BEGIN SimpleExpression(x);
- IF (eql <= sym) & (sym <= geq) THEN
- relation := sym; GetSym;
- IF ~constFlag THEN load(x) END ;
- SimpleExpression(y); GenOp(ORD(relation), x, y)
- ELSIF sym = in THEN GetSym;
- IF ~constFlag THEN load(x) END ;
- SimpleExpression(y); GenIn(x, y)
- END
- END Expression;
- PROCEDURE Priority;
- VAR x: Item;
- BEGIN
- IF sym = lbrak THEN
- GetSym; ConstExpression(x);
- IF (x.typ = cardtyp) & (x.val.C < 16) THEN curPrio := x.val.C + 1
- ELSE err(147)
- END ;
- CheckSym(rbrak, 16)
- END
- END Priority;
- PROCEDURE ImportList(impmod: ObjPtr);
- VAR obj: ObjPtr;
- BEGIN
- IF (impmod # NIL) & (impmod^.class # Module) THEN
- impmod := NIL; err(55)
- END ;
- LOOP
- IF sym = ident THEN
- IF impmod = NIL THEN obj := FindImport(id)
- ELSE obj := FindInScope(id, impmod^.root);
- IF (obj # NIL) & NOT obj^.exported THEN obj := NIL END
- END ;
- IF obj # NIL THEN NewImp(topScope, obj) ELSE err(50) END ;
- GetSym
- ELSE err(10)
- END ;
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSE EXIT
- END
- END ;
- CheckSym(semicolon, 12)
- END ImportList;
- PROCEDURE ExportList;
- VAR obj: ObjPtr;
- BEGIN
- LOOP
- IF sym = ident THEN
- obj := NewObj(id, Temp); KeepId; GetSym
- ELSE err(10)
- END ;
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSE EXIT
- END
- END ;
- CheckSym(semicolon, 12)
- END ExportList;
- PROCEDURE FormalParameters(proc: ObjPtr);
- VAR isvar: BOOLEAN;
- par, par0, par1: ParPtr; typ0: StrPtr;
- BEGIN par := NIL;
- IF (sym = ident) OR (sym = var) THEN
- LOOP par1 := par; isvar := FALSE;
- IF sym = var THEN GetSym; isvar := TRUE END ;
- LOOP
- IF sym = ident THEN
- par := NewPar(id, isvar, par); KeepId; GetSym
- ELSE err(10)
- END ;
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSIF sym = var THEN err(11); GetSym
- ELSE EXIT
- END
- END ;
- CheckSym(colon, 13); FormalType(typ0); par0 := par;
- WHILE par0 # par1 DO
- par0^.typ := typ0; par0 := par0^.next
- END ;
- IF sym = semicolon THEN GetSym
- ELSIF sym = ident THEN err(12)
- ELSE EXIT
- END
- END
- END ;
- par1 := NIL; (*reverse list*)
- WHILE par # NIL DO
- par0 := par; par := par0^.next; par0^.next := par1; par1 := par0
- END ;
- proc^.firstParam := par1;
- CheckSym(rparen, 15)
- END FormalParameters;
- PROCEDURE CheckParameters(proc: ObjPtr);
- VAR isvar: BOOLEAN;
- par, par0, par1: ParPtr; typ0: StrPtr;
- BEGIN par0 := proc^.firstParam;
- IF (sym = ident) OR (sym = var) THEN
- LOOP par1 := par0; isvar := FALSE;
- IF sym = var THEN GetSym; isvar := TRUE END ;
- LOOP
- IF sym = ident THEN
- IF par0 # NIL THEN par0^.name := id; par0 := par0^.next
- ELSE err(66)
- END ;
- KeepId; GetSym
- ELSE err(10)
- END ;
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSIF sym = var THEN err(11); GetSym
- ELSE EXIT
- END
- END ;
- CheckSym(colon, 13); FormalType(typ0); par := par1;
- WHILE par # par0 DO
- IF (par^.typ # typ0) &
- ((par^.typ^.form # Array) OR (typ0^.form # Array) OR
- (par^.typ^.ElemTyp # typ0^.ElemTyp)) THEN err(69)
- END ;
- IF par^.varpar # isvar THEN err(68) END ;
- par := par^.next
- END ;
- IF sym = semicolon THEN GetSym
- ELSIF sym = ident THEN err(12)
- ELSE EXIT
- END
- END
- END ;
- IF par0 # NIL THEN err(70) END ;
- CheckSym(rparen, 15)
- END CheckParameters;
- PROCEDURE MakeParameterObjects(proc: ObjPtr; VAR adr: INTEGER);
- VAR par: ParPtr; obj: ObjPtr; typ0: StrPtr; addr: INTEGER;
- BEGIN par := proc^.firstParam; addr := StartAddress;
- WHILE par # NIL DO
- obj := NewObj(par^.name, Var); par^.name := addr;
- (*address used when unstacking parameters*)
- WITH obj^ DO
- typ := par^.typ; vmod := 0; vlev := curLev; vadr := addr;
- IF par^.varpar THEN param := {1} ELSE param := {0} END
- END ;
- IF addr > 255 THEN err(99); addr := 0 END ;
- typ0 := par^.typ;
- IF (typ0^.form = Array) & typ0^.dyn THEN
- addr := addr + DynArrDesSize
- ELSIF par^.varpar THEN addr := addr + PointerTypSize
- ELSIF typ0^.size <= 2 THEN addr := addr + typ0^.size
- ELSE addr := addr+1
- END ;
- par := par^.next
- END ;
- adr := addr
- END MakeParameterObjects;
- PROCEDURE ProcedureDeclaration(VAR proc: ObjPtr);
- VAR i, L0: CARDINAL; adr: INTEGER; res: ObjPtr;
- BEGIN
- IF curLev = 0 THEN proc := Find(id) ELSE proc := NIL END ;
- IF (proc # NIL) & (proc^.class = Proc) &
- (proc^.pmod = 0) & (proc^.pd^.adr = 0) THEN
- (*procedure heading in definition module or forward declaration*)
- CheckSym(ident, 10);
- IF sym = lparen THEN
- GetSym; CheckParameters(proc);
- IF sym = colon THEN GetSym;
- IF sym = ident THEN qualident(res);
- IF (res = NIL) OR (res^.class # Typ) OR (res^.typ # proc^.typ) THEN
- err(71)
- END
- ELSE err(10)
- END
- ELSIF proc^.typ # notyp THEN err(72)
- END
- ELSIF proc^.firstParam # NIL THEN err(73)
- END
- ELSE
- proc := NewObj(id, Proc); KeepId; pno := pno + 1;
- WITH proc^ DO
- pmod := 0; typ := notyp; firstParam := NIL;
- pd^.num := pno; pd^.lev := curLev; pd^.adr := 0
- END ;
- CheckSym(ident, 10);
- IF sym = lparen THEN
- GetSym; FormalParameters(proc);
- IF sym = colon THEN
- GetSym; proc^.typ := undftyp;
- IF sym = ident THEN qualident(res);
- IF (res # NIL) & (res^.class = Typ) THEN proc^.typ := res^.typ
- ELSE err(52)
- END
- ELSE err(10)
- END
- END
- END
- END ;
- IF NOT isdef THEN
- CheckSym(semicolon, 12); MarkHeap;
- NewScope(Proc); curLev := curLev + 1;
- MakeParameterObjects(proc, adr);
- IF sym = code THEN GetSym;
- IF proc^.pd^.num > pnoI THEN pno := pno - 1;
- ELSE (*this procedure declared in definition module*) err(74)
- END ;
- i := 0;
- LOOP
- IF sym = number THEN GetSym;
- IF (i < MaxCodeLength) & (numtyp = 1) & (intval < 400B) THEN
- proc^.cd^.cod[i] := CHAR(intval); i := i+1
- ELSE err(91)
- END
- END ;
- IF sym = semicolon THEN GetSym
- ELSIF sym = number THEN err(12)
- ELSE EXIT
- END
- END ;
- WITH proc^ DO
- class := Code; (*!!!*) cnum := 0; length := i
- END ;
- CheckSym(end, 20);
- IF sym = ident THEN
- IF Diff(id, proc^.name) # 0 THEN err(77) END ;
- GetSym
- ELSE err(10)
- END
- ELSIF sym = forward THEN GetSym
- ELSE proc^.pd^.adr := pc;
- Block(proc, FALSE, adr, L0);
- IF proc^.typ = notyp THEN GenReturn ELSE GenTrap(9) END ;
- FixupEnter(L0, adr)
- END ;
- CloseScope; curLev := curLev - 1; ReleaseHeap
- ELSE proc^.pd^.size := adr; proc^.pd^.adr := 0
- END
- END ProcedureDeclaration;
- PROCEDURE ModuleDeclaration(VAR mod: ObjPtr; VAR adr: INTEGER);
- VAR L0, prio: CARDINAL; qual: BOOLEAN; impmod: ObjPtr;
- BEGIN qual := FALSE; CheckSym(ident, 10);
- mod := NewObj(id, Module); KeepId;
- pno := pno + 1; mod^.modno := pno; prio := curPrio; Priority;
- CheckSym(semicolon, 12); NewScope(Module);
- WHILE (sym = from) OR (sym = import) DO impmod := NIL;
- IF sym = from THEN GetSym;
- IF sym = ident THEN
- impmod := FindImport(id); GetSym
- ELSE err(10)
- END ;
- CheckSym(import, 30)
- ELSE GetSym
- END ;
- ImportList(impmod)
- END ;
- IF sym = export THEN GetSym;
- IF sym = qualified THEN GetSym; qual := TRUE END ;
- ExportList
- END ;
- Block(mod, qual, adr, L0); GenReturn;
- CloseScope; curPrio := prio; curLev := curLev - 1
- END ModuleDeclaration;
- MODULE Loops;
- IMPORT fixup, err, LoopLevels, NofExits;
- EXPORT EnterLoop, RecordExit, ExitLoop;
- VAR h,k: CARDINAL;
- index: ARRAY [0..LoopLevels-1] OF CARDINAL;
- label: ARRAY [0..NofExits-1] OF CARDINAL;
- PROCEDURE EnterLoop;
- BEGIN index[h] := k; h := h+1
- END EnterLoop;
- PROCEDURE RecordExit(L: CARDINAL);
- BEGIN
- IF h = 0 THEN err(39)
- ELSIF k < NofExits THEN label[k] := L; k := k+1
- ELSE err(93)
- END
- END RecordExit;
- PROCEDURE ExitLoop;
- BEGIN h := h-1;
- WHILE k > index[h] DO k := k-1; fixup(label[k]) END
- END ExitLoop;
- BEGIN h := 0; k := 0
- END Loops;
- PROCEDURE Block(ancestor: ObjPtr; qual: BOOLEAN;
- VAR adr: INTEGER; VAR L0: CARDINAL);
- VAR obj, last: ObjPtr; newtypdef: BOOLEAN;
- id0: CARDINAL; x: Item; typ: StrPtr;
- PROCEDURE StatSeq;
- VAR obj: ObjPtr; fpar: ParPtr; x, y: Item; L0, L1: CARDINAL;
- PROCEDURE ElsePart;
- VAR L0, L1: CARDINAL;
- BEGIN
- IF (sym = elsif) OR (sym = bar) THEN
- GetSym; Expression(x); GenCFJ(x, L0);
- CheckSym(then, 27); StatSeq;
- IF sym = end THEN fixup(L0)
- ELSE GenFJ(L1); fixup(L0); ElsePart; fixup(L1)
- END
- ELSIF sym = else THEN
- GetSym; StatSeq
- END
- END ElsePart;
- PROCEDURE CasePart;
- VAR x: Item; n, L0, L1: CARDINAL;
- tab: ARRAY [0..NofCases-1] OF LabelRange;
- BEGIN n := 0;
- Expression(x); GenCase1(x, L0); CheckSym(of, 23);
- LOOP
- IF sym < bar THEN
- CaseLabelList(x.typ, n, tab);
- CheckSym(colon, 13); StatSeq; GenCase2
- END ;
- IF sym = bar THEN GetSym ELSE EXIT END
- END ;
- L1 := pc;
- IF sym = else THEN
- GetSym; StatSeq; GenCase2
- ELSE GenTrap(4)
- END ;
- RefPoint; GenCase3(L0, L1, n, tab)
- END CasePart;
- PROCEDURE ForPart;
- VAR obj: ObjPtr;
- v, e1, e2, e3: Item;
- L0, L1: CARDINAL;
- BEGIN obj := NIL;
- IF sym = ident THEN
- obj := Find(id);
- IF obj # NIL THEN
- IF (obj^.class # Var) OR (obj^.param # {}) OR
- (obj^.vmod > 0) THEN err(75) END
- ELSE err(50)
- END ;
- GetSym
- ELSE err(10)
- END ;
- GenItem(v, obj, Scope); loadAdr(v);
- IF sym = becomes THEN GetSym ELSE err(19);
- IF sym = eql THEN GetSym END
- END ;
- Expression(e1); GenFor1(v,e1);
- CheckSym(to, 24); Expression(e2); GenFor2(v,e2);
- IF sym = by THEN
- GetSym; ConstExpression(e3)
- ELSE e3.typ := inttyp; e3.mode := conMd; e3.val.I := 1
- END ;
- GenFor3(e3, L0, L1);
- CheckSym(do, 25); StatSeq; GenFor4(e3, L0, L1)
- END ForPart;
- BEGIN
- LOOP
- IF sym < ident THEN err(35);
- REPEAT GetSym UNTIL sym >= ident
- END ;
- IF sym = ident THEN
- RefPoint; qualident(obj); selector(x, obj);
- IF sym = becomes THEN
- GetSym; PrepAss(x); Expression(y); GenAssign(x, y)
- ELSIF sym = eql THEN
- err(19); GetSym; PrepAss(x); Expression(y); GenAssign(x, y)
- ELSIF (x.mode = codMd) & (x.cod^.cnum > 0) THEN
- StandProcCall(x);
- IF x.typ # notyp THEN err(76) END
- ELSE PrepCall(x, fpar);
- IF sym = lparen THEN
- GetSym; ActualParameters(x, fpar); CheckSym(rparen, 15)
- ELSIF fpar # NIL THEN err(65)
- END ;
- GenCall(x);
- IF x.typ # notyp THEN err(76) END
- END
- ELSIF sym = if THEN
- GetSym; RefPoint; Expression(x); GenCFJ(x, L0);
- CheckSym(then, 27); StatSeq;
- IF sym = end THEN fixup(L0)
- ELSE GenFJ(L1); fixup(L0); ElsePart; fixup(L1)
- END ;
- CheckSym(end, 20)
- ELSIF sym = case THEN
- GetSym; RefPoint; CasePart; CheckSym(end, 20)
- ELSIF sym = while THEN
- GetSym; L1 := pc; RefPoint; Expression(x); GenCFJ(x, L0);
- CheckSym(do, 25); StatSeq; GenBJ(L1); fixup(L0);
- WHILE sym = bar DO
- GetSym; RefPoint; Expression(x); GenCFJ(x, L0);
- CheckSym(do, 25); StatSeq; GenBJ(L1); fixup(L0)
- END ;
- CheckSym(end, 20)
- ELSIF sym = repeat THEN
- GetSym; L0 := pc; StatSeq;
- IF sym = until THEN
- GetSym; RefPoint; Expression(x); GenCBJ(x, L0)
- ELSE err(26)
- END
- ELSIF sym = loop THEN
- GetSym; EnterLoop; L0 := pc; StatSeq; GenBJ(L0); ExitLoop;
- CheckSym(end, 20)
- ELSIF sym = for THEN
- GetSym; RefPoint; ForPart; CheckSym(end, 20)
- ELSIF sym = with THEN
- GetSym; x.typ := NIL;
- IF sym = ident THEN
- qualident(obj); selector(x, obj);
- IF (x.typ # NIL) & (x.typ^.form = Record) THEN
- NewScope(Typ); GenWith(x, adr);
- topScope^.withadr := adr; topScope^.right := x.typ^.firstFld;
- IF adr > 255 THEN err(99); adr := 0 END ;
- adr := adr + 1 (*allocate anonymous variable for address*)
- ELSE err(57); x.typ := NIL
- END
- ELSE err(10)
- END ;
- CheckSym(do, 25); StatSeq; CheckSym(end, 20);
- IF x.typ # NIL THEN CloseScope END
- ELSIF sym = exit THEN
- GetSym; GenFJ(L0); RecordExit(L0)
- ELSIF sym = return THEN GetSym;
- IF sym < semicolon THEN
- Expression(x); GenResult(x, ancestor)
- ELSIF ancestor^.typ # notyp THEN err(139)
- END ;
- GenReturn
- END ;
- CheckStack;
- IF sym = semicolon THEN GetSym
- ELSIF (sym <= ident) OR (if <= sym) & (sym <= for) THEN err(12)
- ELSE EXIT
- END
- END
- END StatSeq;
- PROCEDURE CheckExports(obj: ObjPtr);
- BEGIN
- IF obj # NIL THEN
- IF obj^.class = Temp THEN err(80)
- ELSIF ~qual & obj^.exported THEN (*import in outer scope*)
- NewImp(topScope^.left, obj)
- END ;
- CheckExports(obj^.left); CheckExports(obj^.right)
- END
- END CheckExports;
- BEGIN (*Block*)
- LOOP
- IF sym = const THEN
- GetSym;
- WHILE sym = ident DO
- id0 := id; KeepId; GetSym;
- IF sym = eql THEN
- GetSym; ConstExpression(x)
- ELSIF sym = becomes THEN
- err(18); GetSym; ConstExpression(x)
- ELSE err(18)
- END ;
- obj := NewObj(id0, Const); obj^.typ := x.typ; obj^.conval := x.val;
- IF x.typ = stringtyp THEN obj^.conval.D2 := id; KeepId END ;
- CheckSym(semicolon, 12)
- END
- ELSIF sym = type THEN
- GetSym;
- WHILE sym = ident DO
- typ := undftyp; obj := NIL; newtypdef := TRUE;
- IF isimp & (curLev = 0) THEN
- obj := Find(id);
- IF (obj # NIL) & (obj^.class = Typ) & (obj^.typ^.form = Opaque) THEN
- newtypdef := FALSE
- END
- END ;
- IF newtypdef THEN id0 := id; KeepId END ;
- GetSym;
- IF sym = eql THEN
- GetSym; Type(typ)
- ELSIF (sym = becomes) OR (sym = colon) THEN
- err(18); GetSym; Type(typ)
- ELSIF NOT isdef THEN err(18)
- ELSE typ := NewStr(Opaque); typ^.size := PointerTypSize
- END ;
- IF newtypdef THEN
- obj := NewObj(id0, Typ); obj^.typ := typ; obj^.mod := mainmod;
- IF typ^.strobj = NIL THEN typ^.strobj := obj END ;
- ELSIF typ^.size = PointerTypSize THEN obj^.typ^ := typ^
- ELSE err(87)
- END ;
- CheckUDP(obj, topScope^.right); (*check for undefined pointer types*)
- CheckSym(semicolon, 12)
- END
- ELSIF sym = var THEN
- GetSym;
- WHILE sym = ident DO last := topScope^.last; obj := last;
- LOOP
- IF sym = ident THEN
- obj := NewObj(id, Var); KeepId; GetSym
- ELSE err(10)
- END ;
- IF sym = comma THEN GetSym
- ELSIF sym = ident THEN err(11)
- ELSE EXIT
- END
- END ;
- CheckSym(colon, 13); Type(typ);
- WHILE last # obj DO
- last := last^.next; last^.typ := typ;
- WITH last^ DO
- param := {}; vmod := 0; vlev := curLev; vadr := adr
- END ;
- IF typ^.size <= 2 THEN adr := adr + typ^.size
- ELSE adr := adr + 1
- END ;
- IF adr > 255 THEN err(99); adr := 0 END
- END ;
- CheckSym(semicolon, 12)
- END
- ELSIF sym = procedure THEN
- GetSym; ProcedureDeclaration(obj); CheckSym(semicolon, 12)
- ELSIF sym = module THEN
- GetSym; ModuleDeclaration(obj, adr); CheckSym(semicolon, 12)
- ELSE
- IF (sym # begin) & (sym # end) THEN err(36);
- REPEAT GetSym UNTIL (sym >= begin) OR (sym = end)
- END ;
- IF (sym <= begin) OR (sym = eof) THEN EXIT END
- END
- END ;
- IF ancestor^.class = Module THEN
- ancestor^.firstObj := topScope^.next; ancestor^.root := topScope^.right;
- IF ancestor = mainmod THEN
- fixupC(L0); GenEndDecl(ancestor, ModNo)
- ELSE CheckExports(topScope^.right);
- curLev := curLev + 1; GenEnterMod(ancestor)
- END
- ELSE (*procedure*) ancestor^.firstLocal := topScope^.next;
- GenEnter(L0, ancestor); GenEndDecl(ancestor, 0)
- END ;
- IF sym = begin THEN
- IF isdef THEN err(37) END ;
- GetSym; StatSeq; RefPoint
- END ;
- CheckSym(end, 20); OutUnit(ancestor);
- IF sym = ident THEN
- IF Diff(id, ancestor^.name) # 0 THEN err(77) END ;
- GetSym
- ELSE err(10)
- END
- END Block;
- PROCEDURE CompilationUnit;
- VAR id0, L0: CARDINAL; adr: INTEGER;
- hdr, importMod: ObjPtr; impok: BOOLEAN;
- FName: ARRAY [0..NL] OF CHAR;
- PROCEDURE GetFileName(j: CARDINAL;
- VAR FName: ARRAY OF CHAR; ext: ARRAY OF CHAR);
- VAR i,L: CARDINAL;
- BEGIN i := 3; L := CARDINAL(IdBuf[j]) + j-1;
- WHILE j < L DO
- j := j+1; FName[i] := IdBuf[j]; i := i+1
- END ;
- j := 0; L := HIGH(ext);
- WHILE j <= L DO
- FName[i] := ext[j]; i := i+1; j := j+1
- END ;
- FName[i] := 0C
- END GetFileName;
- PROCEDURE ImportModule;
- VAR adr: INTEGER; pno: CARDINAL;
- BEGIN
- IF sym = ident THEN
- IF Diff(id, sysmod^.name) = 0 THEN importMod := sysmod
- ELSE GetFileName(id, FileName, ".SBL"); WriteLn;
- WriteString(" - "); WriteString(FileName);
- InRef(FileName, hdr, adr, pno);
- IF hdr # NIL THEN importMod := hdr^.right
- ELSE impok := FALSE;
- importMod := NIL; WriteString(" not found (or bad)")
- END
- END ;
- GetSym
- ELSE err(10)
- END ;
- END ImportModule;
- PROCEDURE Out(n: CARDINAL);
- VAR k: CARDINAL; d: ARRAY [0..5] OF CARDINAL;
- BEGIN k := 0; Write(" ");
- REPEAT d[k] := n MOD 10; n := n DIV 10; k := k+1 UNTIL n = 0;
- REPEAT k := k-1; Write(CHAR(d[k]+60B)) UNTIL k = 0
- END Out;
- PROCEDURE CheckUDProc(obj: ObjPtr);
- BEGIN (*check for undefined procedure bodies*)
- WHILE obj # NIL DO
- IF (obj^.class = Proc) & (obj^.pmod = 0) &
- (obj^.pd^.adr = 0) THEN err(89)
- END ;
- obj := obj^.next
- END
- END CheckUDProc;
- BEGIN isdef := FALSE; isimp := FALSE; impok := TRUE;
- curLev := 0; curPrio := 0; constFlag := FALSE;
- FName := "DK."; GetSym;
- IF sym = definition THEN GetSym; isdef := TRUE
- ELSIF sym = implementation THEN GetSym; isimp := TRUE
- END ;
- IF sym = module THEN
- GetSym;
- IF sym = ident THEN
- id0 := id; mainmod^.name := id0; KeepId; GetSym;
- IF NOT isdef THEN Priority END ;
- CheckSym(semicolon, 12); MarkHeap; NewScope(Module);
- IF isimp THEN
- GetFileName(id0, FName, ".SBL"); WriteLn;
- WriteString(" - "); WriteString(FName);
- InRef(FName, hdr, adr, pno);
- IF hdr # NIL THEN importMod := hdr^.right;
- topScope^.right := importMod^.root; (*mainmod*)
- topScope^.next := hdr^.next; topScope^.last := hdr^.last
- ELSE importMod := NIL;
- WriteString(" not found (or bad)"); impok := FALSE
- END
- ELSE adr := 3; pno := 0; mainmod^.key := sysmod^.key
- END ;
- WHILE (sym = from) OR (sym = import) DO
- IF sym = from THEN
- GetSym; ImportModule; CheckSym(import, 30);
- ImportList(importMod)
- ELSE (*sym = import*) GetSym;
- LOOP ImportModule;
- IF importMod # NIL THEN NewImp(topScope, importMod) END ;
- IF sym = comma THEN GetSym
- ELSIF sym # ident THEN EXIT
- END
- END ;
- CheckSym(semicolon, 12)
- END
- END ;
- IF sym = export THEN
- GetSym; err(38);
- WHILE sym # semicolon DO GetSym END ;
- GetSym
- END ;
- IF impok THEN
- pnoI := pno;
- IF isdef THEN GetFileName(id0, FName, ".SBL")
- ELSE GetFileName(id0, FName, ".RFC")
- END ;
- WriteLn; WriteString(" + "); WriteString(FName);
- Lookup(RefFile, FName, TRUE);
- IF RefFile.res # done THEN err(222) END ;
- OpenRef; GenFJ(L0); Block(mainmod, TRUE, adr, L0);
- IF sym # period THEN err(14) END ;
- IF NOT isdef THEN CheckUDProc(mainmod^.firstObj) END ;
- IF NOT scanerr THEN
- IF NOT isdef THEN
- GetFileName(id0, FName, ".OBJ"); WriteLn;
- WriteString(" + "); WriteString(FName); Out(pc);
- OutCodeFile(FName, mainmod^.key, adr, pno+1, id0, ModNo, ModList)
- END ;
- CloseRef(adr, pno); Close(RefFile)
- ELSE Delete(RefFile)
- END
- END ;
- CloseScope; ReleaseHeap
- ELSE err(10)
- END ;
- ELSE err(28)
- END ;
- IF scanerr THEN WriteString(" errors detected") END
- END CompilationUnit;
- PROCEDURE ReadName;
- CONST DEL = 177C;
- VAR i: CARDINAL;
- BEGIN
- REPEAT Read(ch) UNTIL (ch >= "A") OR (ch = 33C);
- FileName := "DK."; i := 3;
- WHILE (CAP(ch) >= "A") & (CAP(ch) <= "Z")
- OR (ch >= "0") & (ch <= "9")
- OR (ch = ".") OR (ch = DEL) DO
- IF ch = DEL THEN
- IF i > 3 THEN Write(DEL); i := i-1 END
- ELSIF i < NL THEN
- Write(ch); FileName[i] := ch; i := i+1
- END ;
- Read(ch)
- END ;
- IF (3 < i) & (i < NL) & (FileName[i-1] = ".") THEN
- FileName[i] := "M"; i := i+1;
- FileName[i] := "O"; i := i+1;
- FileName[i] := "D"; i := i+1; WriteString("MOD");
- END ;
- FileName[i] := 0C
- END ReadName;
- BEGIN WriteString("ETHZ M3L NW 2.8.86"); WriteLn;
- LOOP WriteString("in> "); rngchk := TRUE; ReadName;
- IF (ch = 33C) OR (FileName[3] < "A") THEN EXIT END ;
- IF ch = "/" THEN
- Write("/"); Read(ch);
- IF ch = "r" THEN Write("r"); rngchk := FALSE END
- END ;
- Lookup(source, FileName, FALSE);
- IF source.res = done THEN GetTime(TM);
- WITH sysmod^.key^ DO
- k0 := TM.day; k1 := TM.minute; k2 := TM.millisecond
- END ;
- InitScanner(FileName); InitTableHandler; InitRef; InitGenerator;
- CompilationUnit; Close(source);
- ELSE WriteString(" not found")
- END ;
- WriteLn
- END ;
- CloseScanner; WriteLn
- END M3PL.
|