home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #6
/
amigamamagazinepolishissue1998.iso
/
coders
/
jËzyki_programowania
/
oberon
/
nonfpu
/
opb.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1977-12-31
|
56KB
|
1,517 lines
Syntax24b.Scn.Fnt
ParcElems
Alloc
Syntax10.Scn.Fnt
(* Amiga NonFPU *)
MODULE OPB; (* RC 6.3.89 / 5.1.93 *)
(* build parse tree *)
IMPORT OPT, OPS, OPM, AmigaMathL;
CONST
(* symbol values or ops *)
times = 1; slash = 2; div = 3; mod = 4;
and = 5; plus = 6; minus = 7; or = 8; eql = 9;
neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
in = 15; is = 16; ash = 17; msk = 18; len = 19;
conv = 20; abs = 21; cap = 22; odd = 23; not = 33;
(*SYSTEM*)
adr = 24; cc = 25; bit = 26; lsh = 27; rot = 28; val = 29;
(* object modes *)
Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7;
SProc = 8; CProc = 9; IProc = 10; Mod = 11; Head = 12; TProc = 13;
(* Structure forms *)
Undef = 0; Byte = 1; Bool = 2; Char = 3; SInt = 4; Int = 5; LInt = 6;
Real = 7; LReal = 8; Set = 9; String = 10; NilTyp = 11; NoTyp = 12;
Pointer = 13; ProcTyp = 14; Comp = 15;
intSet = {SInt..LInt}; realSet = {Real, LReal};
(* composite structure forms *)
Basic = 1; Array = 2; DynArr = 3; Record = 4;
(* nodes classes *)
Nvar = 0; Nvarpar = 1; Nfield = 2; Nderef = 3; Nindex = 4; Nguard = 5; Neguard = 6;
Nconst = 7; Ntype = 8; Nproc = 9; Nupto = 10; Nmop = 11; Ndop = 12; Ncall = 13;
Ninittd = 14; Nif = 15; Ncaselse = 16; Ncasedo = 17; Nenter = 18; Nassign = 19;
Nifelse = 20; Ncase = 21; Nwhile = 22; Nrepeat = 23; Nloop = 24; Nexit = 25;
Nreturn = 26; Nwith = 27; Ntrap = 28;
(*function number*)
assign = 0;
haltfn = 0; newfn = 1; absfn = 2; capfn = 3; ordfn = 4;
entierfn = 5; oddfn = 6; minfn = 7; maxfn = 8; chrfn = 9;
shortfn = 10; longfn = 11; sizefn = 12; incfn = 13; decfn = 14;
inclfn = 15; exclfn = 16; lenfn = 17; copyfn = 18; ashfn = 19; assertfn = 32;
(*SYSTEM function number*)
adrfn = 20; ccfn = 21; lshfn = 22; rotfn = 23;
getfn = 24; putfn = 25; getrfn = 26; putrfn = 27;
bitfn = 28; valfn = 29; sysnewfn = 30; movefn = 31;
(* module visibility of objects *)
internal = 0; external = 1; externalR = 2;
(* procedure flags (conval^.setval) *)
hasBody = 1; isRedef = 2; slNeeded = 3;
AssertTrap = 0; (* default trap number *)
typSize*: PROCEDURE(typ: OPT.Struct; allocDesc: BOOLEAN);
exp: INTEGER; (*side effect of log*)
maxExp: LONGINT; (* max n in ASH(1, n) on this machine *)
PROCEDURE err(n: INTEGER);
BEGIN OPM.err(n)
END err;
PROCEDURE NewLeaf*(obj: OPT.Object): OPT.Node;
VAR node: OPT.Node;
BEGIN
CASE obj^.mode OF
Var:
node := OPT.NewNode(Nvar); node^.readonly := (obj^.vis = externalR) & (obj^.mnolev < 0)
| VarPar:
node := OPT.NewNode(Nvarpar)
| Con:
node := OPT.NewNode(Nconst); node^.conval := OPT.NewConst();
node^.conval^ := obj^.conval^ (* string is not copied, only its ref *)
| Typ:
node := OPT.NewNode(Ntype)
| LProc..IProc:
node := OPT.NewNode(Nproc)
ELSE err(127); node := OPT.NewNode(Nvar)
END ;
node^.obj := obj; node^.typ := obj^.typ;
RETURN node
END NewLeaf;
PROCEDURE Construct*(class: SHORTINT; VAR x: OPT.Node; y: OPT.Node);
VAR node: OPT.Node;
BEGIN
node := OPT.NewNode(class); node^.typ := OPT.notyp;
node^.left := x; node^.right := y; x := node
END Construct;
PROCEDURE Link*(VAR x, last: OPT.Node; y: OPT.Node);
BEGIN
IF x = NIL THEN x := y ELSE last^.link := y END ;
WHILE y^.link # NIL DO y := y^.link END ;
last := y
END Link;
PROCEDURE BoolToInt(b: BOOLEAN): LONGINT;
BEGIN
IF b THEN RETURN 1 ELSE RETURN 0 END
END BoolToInt;
PROCEDURE IntToBool(i: LONGINT): BOOLEAN;
BEGIN
IF i = 0 THEN RETURN FALSE ELSE RETURN TRUE END
END IntToBool;
PROCEDURE NewBoolConst*(boolval: BOOLEAN): OPT.Node;
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nconst); x^.typ := OPT.booltyp;
x^.conval := OPT.NewConst(); x^.conval^.intval := BoolToInt(boolval); RETURN x
END NewBoolConst;
PROCEDURE OptIf*(VAR x: OPT.Node); (* x^.link = NIL *)
VAR if, pred: OPT.Node;
BEGIN
if := x^.left;
WHILE if^.left^.class = Nconst DO
IF IntToBool(if^.left^.conval^.intval) THEN x := if^.right; RETURN
ELSIF if^.link = NIL THEN x := x^.right; RETURN
ELSE if := if^.link; x^.left := if
END
END ;
pred := if; if := if^.link;
WHILE if # NIL DO
IF if^.left^.class = Nconst THEN
IF IntToBool(if^.left^.conval^.intval) THEN
pred^.link := NIL; x^.right := if^.right; RETURN
ELSE if := if^.link; pred^.link := if
END
ELSE pred := if; if := if^.link
END
END
END OptIf;
PROCEDURE Nil*(): OPT.Node;
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nconst); x^.typ := OPT.niltyp;
x^.conval := OPT.NewConst(); x^.conval^.intval := OPM.nilval; RETURN x
END Nil;
PROCEDURE EmptySet*(): OPT.Node;
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nconst); x^.typ := OPT.settyp;
x^.conval := OPT.NewConst(); x^.conval^.setval := {}; RETURN x
END EmptySet;
PROCEDURE SetIntType(node: OPT.Node);
VAR v: LONGINT;
BEGIN v := node^.conval^.intval;
IF (OPM.MinSInt <= v) & (v <= OPM.MaxSInt) THEN node^.typ := OPT.sinttyp
ELSIF (OPM.MinInt <= v) & (v <= OPM.MaxInt) THEN node^.typ := OPT.inttyp
ELSIF (OPM.MinLInt <= v) & (v <= OPM.MaxLInt) (*bootstrap or cross*) THEN
node^.typ := OPT.linttyp
ELSE err(203); node^.typ := OPT.sinttyp; node^.conval^.intval := 1
END
END SetIntType;
PROCEDURE NewIntConst*(intval: LONGINT): OPT.Node;
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nconst); x^.conval := OPT.NewConst();
x^.conval^.intval := intval; SetIntType(x); RETURN x
END NewIntConst;
PROCEDURE NewRealConst*(realval: LONGREAL; typ: OPT.Struct): OPT.Node;
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nconst); x^.conval := OPT.NewConst();
x^.conval^.realval := realval; x^.typ := typ; x^.conval^.intval := OPM.ConstNotAlloc;
RETURN x
END NewRealConst;
PROCEDURE NewString*(VAR str: OPS.String; len: LONGINT): OPT.Node;
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nconst); x^.conval := OPT.NewConst(); x^.typ := OPT.stringtyp;
x^.conval^.intval := OPM.ConstNotAlloc; x^.conval^.intval2 := len;
x^.conval^.ext := OPT.NewExt(); x^.conval^.ext^ := str;
RETURN x
END NewString;
PROCEDURE CharToString(n: OPT.Node);
VAR ch: CHAR;
BEGIN
n^.typ := OPT.stringtyp; ch := CHR(n^.conval^.intval); n^.conval^.ext := OPT.NewExt();
IF ch = 0X THEN n^.conval^.intval2 := 1 ELSE n^.conval^.intval2 := 2; n^.conval^.ext[1] := 0X END ;
n^.conval^.ext[0] := ch; n^.conval^.intval := OPM.ConstNotAlloc; n^.obj := NIL
END CharToString;
PROCEDURE BindNodes(class: SHORTINT; typ: OPT.Struct; VAR x: OPT.Node; y: OPT.Node);
VAR node: OPT.Node;
BEGIN
node := OPT.NewNode(class); node^.typ := typ;
node^.left := x; node^.right := y; x := node
END BindNodes;
PROCEDURE NotVar(x: OPT.Node): BOOLEAN;
BEGIN RETURN (x^.class >= Nconst) & ((x^.class # Nmop) OR (x^.subcl # val) OR (x^.left^.class >= Nconst))
END NotVar;
PROCEDURE DeRef*(VAR x: OPT.Node);
BEGIN
IF x^.class >= Nconst THEN err(78)
ELSIF x^.typ^.form = Pointer THEN BindNodes(Nderef, x^.typ^.BaseTyp, x, NIL)
ELSE err(84)
END
END DeRef;
PROCEDURE Index*(VAR x: OPT.Node; y: OPT.Node);
VAR f: INTEGER; typ: OPT.Struct;
BEGIN
f := y^.typ^.form;
IF x^.class >= Nconst THEN err(79)
ELSIF ~(f IN intSet) THEN err(80); y^.typ := OPT.inttyp END ;
IF x^.typ^.comp = Array THEN typ := x^.typ^.BaseTyp;
IF (y^.class = Nconst) & ((y^.conval^.intval < 0) OR (y^.conval^.intval >= x^.typ^.n)) THEN err(81) END
ELSIF x^.typ^.comp = DynArr THEN typ := x^.typ^.BaseTyp;
IF (y^.class = Nconst) & (y^.conval^.intval < 0) THEN err(81) END
ELSE err(82); typ := OPT.undftyp
END ;
BindNodes(Nindex, typ, x, y); x^.readonly := x^.left^.readonly
END Index;
PROCEDURE Field*(VAR x: OPT.Node; y: OPT.Object);
BEGIN (*x^.typ^.comp = Record*)
IF x^.class >= Nconst THEN err(77)
ELSIF (y # NIL) & (y^.mode IN {Fld, TProc}) THEN
BindNodes(Nfield, y^.typ, x, NIL); x^.obj := y;
x^.readonly := x^.left^.readonly OR ((y^.vis = externalR) & (y^.mnolev < 0))
ELSE err(83); x^.typ := OPT.undftyp
END
END Field;
PROCEDURE TypTest*(VAR x: OPT.Node; obj: OPT.Object; guard: BOOLEAN);
PROCEDURE GTT(t0, t1: OPT.Struct);
VAR node: OPT.Node; t: OPT.Struct;
BEGIN t := t0;
WHILE (t # NIL) & (t # t1) & (t # OPT.undftyp) DO t := t^.BaseTyp END ;
IF t # t1 THEN
WHILE (t1 # NIL) & (t1 # t0) & (t1 # OPT.undftyp) DO t1 :=
t1^.BaseTyp END ;
IF t1 = t0 THEN
IF guard THEN BindNodes(Nguard, NIL, x, NIL); x^.readonly :=
x^.left^.readonly
ELSE node := OPT.NewNode(Nmop); node^.subcl := is; node^.left := x;
node^.obj := obj; x := node
END
ELSE err(85)
END
ELSIF t0 # t1 THEN err(85) (* prevent down guard *)
ELSIF ~guard THEN
IF x^.class = Nguard THEN (* cannot skip guard *)
node := OPT.NewNode(Nmop); node^.subcl := is; node^.left := x;
node^.obj := obj; x := node
ELSE x := NewBoolConst(TRUE)
END
END
END GTT;
BEGIN
IF NotVar(x) THEN err(112)
ELSIF x^.typ^.form = Pointer THEN
IF x^.typ^.BaseTyp^.comp # Record THEN err(85)
ELSIF obj^.typ^.form = Pointer THEN GTT(x^.typ^.BaseTyp,
obj^.typ^.BaseTyp)
ELSE err(86)
END
ELSIF (x^.typ^.comp = Record) & (x^.class = Nvarpar) & (obj^.typ^.comp =
Record) THEN
GTT(x^.typ, obj^.typ)
ELSE err(87)
END ;
IF guard THEN x^.typ := obj^.typ ELSE x^.typ := OPT.booltyp END
END TypTest;
PROCEDURE In*(VAR x: OPT.Node; y: OPT.Node);
VAR f: INTEGER; k: LONGINT;
BEGIN f := x^.typ^.form;
IF (x^.class = Ntype) OR (x^.class = Nproc) OR (y^.class = Ntype) OR (y^.class = Nproc) THEN err(126)
ELSIF (f IN intSet) & (y^.typ^.form = Set) THEN
IF x^.class = Nconst THEN
k := x^.conval^.intval;
IF (k < 0) OR (k > OPM.MaxSet) THEN err(202)
ELSIF y^.class = Nconst THEN x^.conval^.intval := BoolToInt(k IN y^.conval^.setval); x^.obj := NIL
ELSE BindNodes(Ndop, OPT.booltyp, x, y); x^.subcl := in
END
ELSE BindNodes(Ndop, OPT.booltyp, x, y); x^.subcl := in
END
ELSE err(92)
END ;
x^.typ := OPT.booltyp
END In;
PROCEDURE log(x: LONGINT): LONGINT;
BEGIN exp := 0;
IF x > 0 THEN
WHILE ~ODD(x) DO x := x DIV 2; INC(exp) END
END ;
RETURN x
END log;
PROCEDURE CheckRealType(f, nr: INTEGER; x: OPT.Const);
VAR min, max, r: LONGREAL;Dummy: REAL;
BEGIN
IF f = Real THEN
AmigaMathL.Long(OPM.MinReal,min);(* min := OPM.MinReal; *)
AmigaMathL.Long(OPM.MaxReal,max);(* max := OPM.MaxReal; *)
ELSE min := OPM.MinLReal; max := OPM.MaxLReal
END ;
AmigaMathL.Abs(x^.realval,r);
(* r := ABS(x^.realval);*)
IF (AmigaMathL.Cmp(r,max)>0) OR (AmigaMathL.Cmp(r,min)<0) THEN
(* IF (r > max) OR (r < min) THEN*)
err(nr); x^.realval := 1(*.0*)
ELSIF f = Real THEN
AmigaMathL.Short(x^.realval, Dummy);
AmigaMathL.Long(Dummy, x^.realval);
(* x^.realval := SHORT(x^.realval) (* single precision only *)*)
END ;
x^.intval := OPM.ConstNotAlloc
END CheckRealType;
PROCEDURE MOp*(op: SHORTINT; VAR x: OPT.Node);
VAR f: INTEGER; typ: OPT.Struct;
PROCEDURE NewOp;
VAR node: OPT.Node;
BEGIN
node := OPT.NewNode(Nmop); node^.subcl := op; node^.typ := typ;
node^.left := x; x := node
END NewOp;
BEGIN
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSE typ := x^.typ; f := typ^.form;
CASE op OF
not:
IF f = Bool THEN
IF x^.class = Nconst THEN
x^.conval^.intval := BoolToInt(~IntToBool(x^.conval^.intval)); x^.obj := NIL
ELSE NewOp
END
ELSE err(98)
END
| plus:
IF ~(f IN intSet + realSet) THEN err(96) END
| minus:
IF f IN intSet + realSet +{Set}THEN
IF x^.class = Nconst THEN
IF f IN intSet THEN
IF x^.conval^.intval = MIN(LONGINT) THEN err(203)
ELSE x^.conval^.intval := -x^.conval^.intval; SetIntType(x)
END
ELSIF f IN realSet THEN
AmigaMathL.Neg(x^.conval^.realval, x^.conval^.realval);
(* x^.conval^.realval := -x^.conval^.realval *)
ELSE x^.conval^.setval := -x^.conval^.setval
END ;
x^.obj := NIL
ELSE NewOp
END
ELSE err(97)
END
| abs:
IF f IN intSet + realSet THEN
IF x^.class = Nconst THEN
IF f IN intSet THEN
IF x^.conval^.intval = MIN(LONGINT) THEN err(203)
ELSE x^.conval^.intval := ABS(x^.conval^.intval); SetIntType(x)
END
ELSE
AmigaMathL.Abs(x^.conval^.realval, x^.conval^.realval);
(* x^.conval^.realval := ABS(x^.conval^.realval) *)
END ;
x^.obj := NIL
ELSE NewOp
END
ELSE err(111)
END
| cap:
IF f = Char THEN
IF x^.class = Nconst THEN
x^.conval^.intval := ORD(CAP(CHR(x^.conval^.intval))); x^.obj := NIL
ELSE NewOp
END
ELSE err(111); x^.typ := OPT.chartyp
END
| odd:
IF f IN intSet THEN
IF x^.class = Nconst THEN
x^.conval^.intval := BoolToInt(ODD(x^.conval^.intval)); x^.obj := NIL
ELSE NewOp
END
ELSE err(111)
END ;
x^.typ := OPT.booltyp
| adr: (*SYSTEM.ADR*)
IF (x^.class < Nconst) OR (f = String) THEN NewOp
ELSE err(127)
END ;
x^.typ := OPT.linttyp
| cc: (*SYSTEM.CC*)
IF (f IN intSet) & (x^.class = Nconst) THEN
IF (0 <= x^.conval^.intval) & (x^.conval^.intval <= OPM.MaxCC) THEN NewOp ELSE err(219) END
ELSE err(69)
END ;
x^.typ := OPT.booltyp
END
END
END MOp;
PROCEDURE CheckPtr(x, y: OPT.Node);
VAR g: INTEGER; p, q, t: OPT.Struct;
BEGIN g := y^.typ^.form;
IF g = Pointer THEN
p := x^.typ^.BaseTyp; q := y^.typ^.BaseTyp;
IF (p^.comp = Record) & (q^.comp = Record) THEN
IF p^.extlev < q^.extlev THEN t := p; p := q; q := t END ;
WHILE (p # q) & (p # NIL) & (p # OPT.undftyp) DO p := p^.BaseTyp END ;
IF p = NIL THEN err(100) END
ELSE err(100)
END
ELSIF g # NilTyp THEN err(100)
END
END CheckPtr;
PROCEDURE CheckParameters*(fp, ap: OPT.Object; checkNames: BOOLEAN);
VAR ft, at: OPT.Struct;
BEGIN
WHILE fp # NIL DO
IF ap # NIL THEN
ft := fp^.typ; at := ap^.typ;
WHILE (ft^.comp = DynArr) & (at^.comp = DynArr) DO
ft := ft^.BaseTyp; at := at^.BaseTyp
END ;
IF ft # at THEN
IF (ft^.form = ProcTyp) & (at^.form = ProcTyp) THEN
IF ft^.BaseTyp = at^.BaseTyp THEN CheckParameters(ft^.BaseTyp^.link, at^.BaseTyp^.link, FALSE)
ELSE err(117)
END
ELSE err(115)
END
END ;
IF (fp^.mode # ap^.mode) OR checkNames & (fp^.name # ap^.name) THEN err(115) END ;
ap := ap^.link
ELSE err(116)
END ;
fp := fp^.link
END ;
IF ap # NIL THEN err(116) END
END CheckParameters;
PROCEDURE CheckProc(x: OPT.Struct; y: OPT.Object); (* proc var x := proc y, check compatibility *)
BEGIN
IF y^.mode IN {XProc, IProc, LProc} THEN
IF y^.mode = LProc THEN
IF y^.mnolev = 0 THEN y^.mode := XProc
ELSE err(73)
END
END ;
IF x^.BaseTyp = y^.typ THEN CheckParameters(x^.link, y^.link, FALSE)
ELSE err(117)
END
ELSE err(113)
END
END CheckProc;
PROCEDURE ConstOp(op: INTEGER; x, y: OPT.Node);
VAR f, g: INTEGER; xval, yval: OPT.Const; xv, yv: LONGINT;
temp: BOOLEAN; (* temp avoids err 215 *)
LDummy, xAbs, yAbs: LONGREAL;
PROCEDURE ConstCmp(): INTEGER;
VAR res: INTEGER;
BEGIN
CASE f OF
Undef:
res := eql
| Byte, Char..LInt:
IF xval^.intval < yval^.intval THEN res := lss
ELSIF xval^.intval > yval^.intval THEN res := gtr
ELSE res := eql
END
| Real, LReal:
IF AmigaMathL.Cmp(xval^.realval, yval^.realval)<0 THEN res := lss
ELSIF AmigaMathL.Cmp(xval^.realval, yval^.realval)>0 THEN res := gtr
ELSE res := eql
END
(* IF xval^.realval < yval^.realval THEN res := lss
ELSIF xval^.realval > yval^.realval THEN res := gtr
ELSE res := eql
END *)
| Bool:
IF xval^.intval # yval^.intval THEN res := neq
ELSE res := eql
END
| Set:
IF xval^.setval # yval^.setval THEN res := neq
ELSE res := eql
END
| String:
IF xval^.ext^ < yval^.ext^ THEN res := lss
ELSIF xval^.ext^ > yval^.ext^ THEN res := gtr
ELSE res := eql
END
| NilTyp, Pointer, ProcTyp:
IF xval^.intval # yval^.intval THEN res := neq
ELSE res := eql
END
END ;
x^.typ := OPT.booltyp; RETURN res
END ConstCmp;
BEGIN
f := x^.typ^.form; g := y^.typ^.form; xval := x^.conval; yval := y^.conval;
IF f # g THEN
CASE f OF
Char:
IF g = String THEN CharToString(x)
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END ;
| SInt:
IF g IN intSet THEN x^.typ := y^.typ
ELSIF g = Real THEN
x^.typ := OPT.realtyp;
AmigaMathL.IntToReal(xval^.intval, xval^.realval); (*xval^.realval := xval^.intval*)
ELSIF g = LReal THEN
x^.typ := OPT.lrltyp;
AmigaMathL.IntToReal(xval^.intval, xval^.realval); (*xval^.realval := xval^.intval*)
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END
| Int:
IF g = SInt THEN y^.typ := OPT.inttyp
ELSIF g IN intSet THEN x^.typ := y^.typ
ELSIF g = Real THEN x^.typ := OPT.realtyp;
AmigaMathL.IntToReal(xval^.intval, xval^.realval); (*xval^.realval := xval^.intval*)
ELSIF g = LReal THEN x^.typ := OPT.lrltyp;
AmigaMathL.IntToReal(xval^.intval, xval^.realval); (*xval^.realval := xval^.intval*)
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END
| LInt:
IF g IN intSet THEN y^.typ := OPT.linttyp
ELSIF g = Real THEN x^.typ := OPT.realtyp;
AmigaMathL.IntToReal(xval^.intval, xval^.realval); (*xval^.realval := xval^.intval*)
ELSIF g = LReal THEN x^.typ := OPT.lrltyp;
AmigaMathL.IntToReal(xval^.intval, xval^.realval); (*xval^.realval := xval^.intval*)
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END
| Real:
IF g IN intSet THEN y^.typ := x^.typ;
AmigaMathL.IntToReal(yval^.intval, yval^.realval); (*yval^.realval := yval^.intval*)
ELSIF g = LReal THEN x^.typ := OPT.lrltyp
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END
| LReal:
IF g IN intSet THEN y^.typ := x^.typ;
AmigaMathL.IntToReal(yval^.intval, yval^.realval); (*yval^.realval := yval^.intval*)
ELSIF g = Real THEN y^.typ := OPT.lrltyp
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END
| String:
IF g = Char THEN CharToString(y); g := String
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END ;
| NilTyp:
IF ~(g IN {Pointer, ProcTyp}) THEN err(100) END
| Pointer:
CheckPtr(x, y)
| ProcTyp:
IF g # NilTyp THEN err(100) END
ELSE err(100); y^.typ := x^.typ; yval^ := xval^
END ;
f := x^.typ^.form
END ; (* {x^.typ = y^.typ} *)
CASE op OF
times:
IF f IN intSet THEN xv := xval^.intval; yv := yval^.intval;
IF (xv = 0) OR (yv = 0) OR (* division with negative numbers is not defined *)
(xv > 0) & (yv > 0) & (yv <= MAX(LONGINT) DIV xv) OR
(xv > 0) & (yv < 0) & (yv >= MIN(LONGINT) DIV xv) OR
(xv < 0) & (yv > 0) & (xv >= MIN(LONGINT) DIV yv) OR
(xv < 0) & (yv < 0) & (xv # MIN(LONGINT)) & (yv # MIN(LONGINT)) & (-xv <= MAX(LONGINT) DIV (-yv)) THEN
xval^.intval := xv * yv; SetIntType(x)
ELSE err(204)
END
ELSIF f IN realSet THEN
AmigaMathL.Abs(yval^.realval, yAbs);AmigaMathL.Abs(xval^.realval, xAbs);
temp:=AmigaMathL.Cmp(yAbs, 1) <= 0;
AmigaMathL.Div(MAX(LONGREAL), yAbs, LDummy);
IF temp OR (AmigaMathL.Cmp(xAbs, LDummy) <= 0) THEN
(* temp := ABS(yval^.realval) <= 1(*.0*);
IF temp OR (ABS(xval^.realval) <= MAX(LONGREAL) / ABS(yval^.realval)) THEN*)
AmigaMathL.Mul(xval^.realval, yval^.realval, xval^.realval);
(* xval^.realval := xval^.realval * yval^.realval; *)
CheckRealType(f, 204, xval)
ELSE err(204)
END
ELSIF f = Set THEN
xval^.setval := xval^.setval * yval^.setval
ELSIF f # Undef THEN err(101)
END
| slash:
IF f IN intSet THEN
IF yval^.intval # 0 THEN
AmigaMathL.IntToReal(xval^.intval, xAbs);
AmigaMathL.IntToReal(yval^.intval, yAbs);
AmigaMathL.Div(xAbs, yAbs, xval^.realval);
(* xval^.realval := xval^.intval / yval^.intval; *)
CheckRealType(Real, 205, xval)
ELSE err(205); AmigaMathL.IntToReal(1, xval^.realval); (*xval^.realval := 1(*.0*)*)
END ;
x^.typ := OPT.realtyp
ELSIF f IN realSet THEN
AmigaMathL.Abs(yval^.realval, yAbs);AmigaMathL.Abs(xval^.realval, xAbs);
temp:=AmigaMathL.Cmp(yAbs, 1) >= 0; (* !?!?! *)
AmigaMathL.Mul(MAX(LONGREAL), yAbs, LDummy);
IF temp OR (AmigaMathL.Cmp(xAbs, LDummy) <= 0) THEN
(* temp := ABS(yval^.realval) >= 1(*.0*);
IF temp OR (ABS(xval^.realval) <= MAX(LONGREAL) * ABS(yval^.realval)) THEN*)
AmigaMathL.Div(xval^.realval, yval^.realval, xval^.realval);
(* xval^.realval := xval^.realval / yval^.realval; *)
CheckRealType(f, 205, xval)
ELSE err(205)
END
ELSIF f = Set THEN
xval^.setval := xval^.setval / yval^.setval
ELSIF f # Undef THEN err(102)
END
| div:
IF f IN intSet THEN
IF yval^.intval # 0 THEN
xval^.intval := xval^.intval DIV yval^.intval; SetIntType(x)
ELSE err(205)
END
ELSIF f # Undef THEN err(103)
END
| mod:
IF f IN intSet THEN
IF yval^.intval # 0 THEN
xval^.intval := xval^.intval MOD yval^.intval; SetIntType(x)
ELSE err(205)
END
ELSIF f # Undef THEN err(104)
END
| and:
IF f = Bool THEN
xval^.intval := BoolToInt(IntToBool(xval^.intval) & IntToBool(yval^.intval))
ELSE err(94)
END
| plus:
IF f IN intSet THEN
temp := (yval^.intval >= 0) & (xval^.intval <= MAX(LONGINT) - yval^.intval);
IF temp OR (yval^.intval < 0) & (xval^.intval >= MIN(LONGINT) - yval^.intval) THEN
INC(xval^.intval, yval^.intval); SetIntType(x)
ELSE err(206)
END
ELSIF f IN realSet THEN
AmigaMathL.Sub(MAX(LONGREAL), yval^.realval, LDummy);
temp := (AmigaMathL.Tst(yval^.realval) >= 0) & (AmigaMathL.Cmp(xval^.realval, LDummy) <= 0);
AmigaMathL.Sub(-MAX(LONGREAL), yval^.realval, LDummy);
IF temp OR (AmigaMathL.Tst(yval^.realval) < 0 ) & (AmigaMathL.Cmp(xval^.realval, LDummy) >= 0) THEN
(* temp := (yval^.realval >= 0(*.0*)) & (xval^.realval <= MAX(LONGREAL) - yval^.realval);
IF temp OR (yval^.realval < 0(*.0*)) & (xval^.realval >= -MAX(LONGREAL) - yval^.realval) THEN*)
AmigaMathL.Add(xval^.realval, yval^.realval, xval^.realval); CheckRealType(f, 206, xval)
(* xval^.realval := xval^.realval + yval^.realval; CheckRealType(f, 206, xval) *)
ELSE err(206)
END
ELSIF f = Set THEN
xval^.setval := xval^.setval + yval^.setval
ELSIF f # Undef THEN err(105)
END
| minus:
IF f IN intSet THEN
IF (yval^.intval >= 0) & (xval^.intval >= MIN(LONGINT) + yval^.intval) OR
(yval^.intval < 0) & (xval^.intval <= MAX(LONGINT) + yval^.intval) THEN
DEC(xval^.intval, yval^.intval); SetIntType(x)
ELSE err(207)
END
ELSIF f IN realSet THEN
AmigaMathL.Add(-MAX(LONGREAL), yval^.realval, LDummy);
temp := (AmigaMathL.Tst(yval^.realval) >= 0) & (AmigaMathL.Cmp(xval^.realval, LDummy) >= 0);
AmigaMathL.Add(MAX(LONGREAL), yval^.realval, LDummy);
IF temp OR (AmigaMathL.Tst(yval^.realval) < 0) & (AmigaMathL.Cmp(xval^.realval, LDummy) <= 0) THEN
(* temp := (yval^.realval >= 0(*.0*)) & (xval^.realval >= -MAX(LONGREAL) + yval^.realval);
IF temp OR (yval^.realval < 0(*.0*)) & (xval^.realval <= MAX(LONGREAL) + yval^.realval) THEN *)
AmigaMathL.Sub(xval^.realval, yval^.realval, xval^.realval); CheckRealType(f, 207, xval)
(* xval^.realval := xval^.realval - yval^.realval; CheckRealType(f, 207, xval) *)
ELSE err(207)
END
ELSIF f = Set THEN
xval^.setval := xval^.setval - yval^.setval
ELSIF f # Undef THEN err(106)
END
| or:
IF f = Bool THEN
xval^.intval := BoolToInt(IntToBool(xval^.intval) OR IntToBool(yval^.intval))
ELSE err(95)
END
| eql:
xval^.intval := BoolToInt(ConstCmp() = eql)
| neq:
xval^.intval := BoolToInt(ConstCmp() # eql)
| lss:
IF f IN {Bool, Set, NilTyp, Pointer} THEN err(108)
ELSE xval^.intval := BoolToInt(ConstCmp() = lss)
END
| leq:
IF f IN {Bool, Set, NilTyp, Pointer} THEN err(108)
ELSE xval^.intval := BoolToInt(ConstCmp() # gtr)
END
| gtr:
IF f IN {Bool, Set, NilTyp, Pointer} THEN err(108)
ELSE xval^.intval := BoolToInt(ConstCmp() = gtr)
END
| geq:
IF f IN {Bool, Set, NilTyp, Pointer} THEN err(108)
ELSE xval^.intval := BoolToInt(ConstCmp() # lss)
END
END
END ConstOp;
PROCEDURE Convert(VAR x: OPT.Node; typ: OPT.Struct);
VAR node: OPT.Node; f, g: INTEGER; k: LONGINT; r: LONGREAL; Max, Min: LONGREAL;
BEGIN f := x^.typ^.form; g := typ^.form;
IF x^.class = Nconst THEN
IF f IN intSet THEN
IF g IN intSet THEN
IF f > g THEN SetIntType(x);
IF x^.typ^.form > g THEN err(203); x^.conval^.intval := 1 END
END
ELSIF g IN realSet THEN
AmigaMathL.IntToReal(x^.conval^.intval, x^.conval^.realval);
(* x^.conval^.realval := x^.conval^.intval; *)
x^.conval^.intval := OPM.ConstNotAlloc
ELSE (*g = Char*) k := x^.conval^.intval;
IF (0 > k) OR (k > 0FFH) THEN err(220) END
END
ELSIF f IN realSet THEN
IF g IN realSet THEN CheckRealType(g, 203, x^.conval)
ELSE (*g = LInt*)
r := x^.conval^.realval;
AmigaMathL.IntToReal(MIN(LONGINT), Min);
AmigaMathL.IntToReal(MAX(LONGINT), Max);
IF (AmigaMathL.Cmp(r, Min) < 0) OR (AmigaMathL.Cmp(r, Max) > 0) THEN err(203); r := 1 END ;
(* IF (r < MIN(LONGINT)) OR (r > MAX(LONGINT)) THEN err(203); r := 1 END ;*)
x^.conval^.intval := AmigaMathL.Entier(r); SetIntType(x)
(* x^.conval^.intval := ENTIER(r); SetIntType(x) *)
END
ELSE (* (f IN {Char, Byte}) & (g IN {Byte} + intSet) OR (f = Undef) *)
END ;
x^.obj := NIL
ELSIF (x^.class = Nmop) & (x^.subcl = conv) & ((x^.left^.typ^.form < f) OR (f > g)) THEN
(* don't create new node *)
IF x^.left^.typ = typ THEN (* and suppress existing node *) x := x^.left END
ELSE node := OPT.NewNode(Nmop); node^.subcl := conv; node^.left := x; x := node
END ;
x^.typ := typ
END Convert;
PROCEDURE Op*(op: SHORTINT; VAR x: OPT.Node; y: OPT.Node);
VAR f, g: INTEGER; t: OPT.Node; typ: OPT.Struct; do: BOOLEAN; val: LONGINT;
PROCEDURE NewOp;
VAR node: OPT.Node;
BEGIN
node := OPT.NewNode(Ndop); node^.subcl := op; node^.typ := typ;
node^.left := x; node^.right := y; x := node
END NewOp;
PROCEDURE strings(): BOOLEAN;
VAR ok, xCharArr, yCharArr: BOOLEAN;
BEGIN
xCharArr := ((x^.typ^.comp IN {Array, DynArr}) & (x^.typ^.BaseTyp^.form=Char)) OR (f=String);
yCharArr := (((y^.typ^.comp IN {Array, DynArr}) & (y^.typ^.BaseTyp^.form=Char)) OR (g=String));
IF xCharArr & (g = Char) & (y^.class = Nconst) THEN CharToString(y); g := String; yCharArr := TRUE END ;
IF yCharArr & (f = Char) & (x^.class = Nconst) THEN CharToString(x); f := String; xCharArr := TRUE END ;
ok := xCharArr & yCharArr;
IF ok THEN (* replace ""-string compare with 0X-char compare, if possible *)
IF (f=String) & (x^.conval^.intval2 = 1) THEN (* y is array of char *)
x^.typ := OPT.chartyp; x^.conval^.intval := 0;
Index(y, NewIntConst(0))
ELSIF (g=String) & (y^.conval^.intval2 = 1) THEN (* x is array of char *)
y^.typ := OPT.chartyp; y^.conval^.intval := 0;
Index(x, NewIntConst(0))
END
END ;
RETURN ok
END strings;
BEGIN
IF (x^.class = Ntype) OR (x^.class = Nproc) OR (y^.class = Ntype) OR (y^.class = Nproc) THEN err(126)
ELSIF (x^.class = Nconst) & (y^.class = Nconst) THEN ConstOp(op, x, y); x^.obj := NIL
ELSE
IF x^.typ # y^.typ THEN
g := y^.typ^.form;
CASE x^.typ^.form OF
SInt:
IF g IN intSet + realSet THEN Convert(x, y^.typ)
ELSE err(100)
END
| Int:
IF g = SInt THEN Convert(y, x^.typ)
ELSIF g IN intSet + realSet THEN Convert(x, y^.typ)
ELSE err(100)
END
| LInt:
IF g IN intSet THEN Convert(y, x^.typ)
ELSIF g IN realSet THEN Convert(x, y^.typ)
ELSE err(100)
END
| Real:
IF g IN intSet THEN Convert(y, x^.typ)
ELSIF g IN realSet THEN Convert(x, y^.typ)
ELSE err(100)
END
| LReal:
IF g IN intSet + realSet THEN Convert(y, x^.typ)
ELSIF g IN realSet THEN Convert(y, x^.typ)
ELSE err(100)
END
| NilTyp:
IF ~(g IN {Pointer, ProcTyp}) THEN err(100) END
| Pointer:
CheckPtr(x, y)
| ProcTyp:
IF g # NilTyp THEN err(100) END
| String:
| Comp:
IF x^.typ^.comp = Record THEN err(100) END
ELSE err(100)
END
END ; (* {x^.typ = y^.typ} *)
typ := x^.typ; f := typ^.form; g := y^.typ^.form;
CASE op OF
times:
do := TRUE;
IF f IN intSet THEN
IF x^.class = Nconst THEN val := x^.conval^.intval;
IF val = 1 THEN do := FALSE; x := y
ELSIF val = 0 THEN do := FALSE
ELSIF log(val) = 1 THEN
t := y; y := x; x := t;
op := ash; y^.typ := OPT.sinttyp; y^.conval^.intval := exp; y^.obj := NIL
END
ELSIF y^.class = Nconst THEN val := y^.conval^.intval;
IF val = 1 THEN do := FALSE
ELSIF val = 0 THEN do := FALSE; x := y
ELSIF log(val) = 1 THEN
op := ash; y^.typ := OPT.sinttyp; y^.conval^.intval := exp; y^.obj := NIL
END
END
ELSIF ~(f IN {Undef, Real..Set}) THEN err(105); typ := OPT.undftyp
END ;
IF do THEN NewOp END
| slash:
IF f IN intSet THEN
IF (y^.class = Nconst) & (y^.conval^.intval = 0) THEN err(205) END ;
Convert(x, OPT.realtyp); Convert(y, OPT.realtyp);
typ := OPT.realtyp
ELSIF f IN realSet THEN
IF (y^.class = Nconst) & (AmigaMathL.Tst(y^.conval^.realval) = 0) THEN err(205) END
(* IF (y^.class = Nconst) & (y^.conval^.realval = 0(*.0*)) THEN err(205) END*)
ELSIF (f # Set) & (f # Undef) THEN err(102); typ := OPT.undftyp
END ;
NewOp
| div:
do := TRUE;
IF f IN intSet THEN
IF y^.class = Nconst THEN val := y^.conval^.intval;
IF val = 0 THEN err(205)
ELSIF val = 1 THEN do := FALSE
ELSIF log(val) = 1 THEN
op := ash; y^.typ := OPT.sinttyp; y^.conval^.intval := -exp; y^.obj := NIL
END
END
ELSIF f # Undef THEN err(103); typ := OPT.undftyp
END ;
IF do THEN NewOp END
| mod:
IF f IN intSet THEN
IF y^.class = Nconst THEN
IF y^.conval^.intval = 0 THEN err(205)
ELSIF log(y^.conval^.intval) = 1 THEN
op := msk; y^.conval^.intval := ASH(-1, exp); y^.obj := NIL
END
END
ELSIF f # Undef THEN err(104); typ := OPT.undftyp
END ;
NewOp
| and:
IF f = Bool THEN
IF x^.class = Nconst THEN
IF IntToBool(x^.conval^.intval) THEN x := y END
ELSIF (y^.class = Nconst) & IntToBool(y^.conval^.intval) THEN (* optimize x & TRUE -> x *)
(* ELSIF (y^.class = Nconst) & ~IntToBool(y^.conval^.intval) THEN
don't optimize x & FALSE -> FALSE: side effects possible *)
ELSE NewOp
END
ELSIF f # Undef THEN err(94); x^.typ := OPT.undftyp
END
| plus:
IF ~(f IN {Undef, SInt..Set}) THEN err(105); typ := OPT.undftyp END ;
do := TRUE;
IF f IN intSet THEN
IF (x^.class = Nconst) & (x^.conval^.intval = 0) THEN do := FALSE; x := y END ;
IF (y^.class = Nconst) & (y^.conval^.intval = 0) THEN do := FALSE END
END ;
IF do THEN NewOp END
| minus:
IF ~(f IN {Undef, SInt..Set}) THEN err(106); typ := OPT.undftyp END ;
IF ~(f IN intSet) OR (y^.class # Nconst) OR (y^.conval^.intval # 0) THEN NewOp END
| or:
IF f = Bool THEN
IF x^.class = Nconst THEN
IF ~IntToBool(x^.conval^.intval) THEN x := y END
ELSIF (y^.class = Nconst) & ~IntToBool(y^.conval^.intval) THEN (* optimize x OR FALSE -> x *)
(* ELSIF (y^.class = Nconst) & IntToBool(y^.conval^.intval) THEN
don't optimize x OR TRUE -> TRUE: side effects possible *)
ELSE NewOp
END
ELSIF f # Undef THEN err(95); x^.typ := OPT.undftyp
END
| eql, neq:
IF (f IN {Undef..Set, NilTyp, Pointer, ProcTyp}) OR strings() THEN typ := OPT.booltyp
ELSE err(107); typ := OPT.undftyp
END ;
NewOp
| lss, leq, gtr, geq:
IF (f IN {Undef, Char..LReal}) OR strings() THEN typ := OPT.booltyp
ELSE err(108); typ := OPT.undftyp
END ;
NewOp
END
END
END Op;
PROCEDURE SetRange*(VAR x: OPT.Node; y: OPT.Node);
VAR k, l: LONGINT;
BEGIN
IF (x^.class = Ntype) OR (x^.class = Nproc) OR (y^.class = Ntype) OR (y^.class = Nproc) THEN err(126)
ELSIF (x^.typ^.form IN intSet) & (y^.typ^.form IN intSet) THEN
IF x^.class = Nconst THEN
k := x^.conval^.intval;
IF (0 > k) OR (k > OPM.MaxSet) THEN err(202) END
END ;
IF y^.class = Nconst THEN
l := y^.conval^.intval;
IF (0 > l) OR (l > OPM.MaxSet) THEN err(202) END
END ;
IF (x^.class = Nconst) & (y^.class = Nconst) THEN
IF k <= l THEN
x^.conval^.setval := {k..l}
ELSE err(201); x^.conval^.setval := {l..k}
END ;
x^.obj := NIL
ELSE BindNodes(Nupto, OPT.settyp, x, y)
END
ELSE err(93)
END ;
x^.typ := OPT.settyp
END SetRange;
PROCEDURE SetElem*(VAR x: OPT.Node);
VAR k: LONGINT;
BEGIN
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF ~(x^.typ^.form IN intSet) THEN err(93)
ELSIF x^.class = Nconst THEN
k := x^.conval^.intval;
IF (0 <= k) & (k <= OPM.MaxSet) THEN x^.conval^.setval := {k}
ELSE err(202)
END ;
x^.obj := NIL
ELSE Convert(x, OPT.settyp)
END ;
x^.typ := OPT.settyp
END SetElem;
PROCEDURE CheckAssign(x: OPT.Struct; ynode: OPT.Node); (* x := y *)
VAR f, g: INTEGER; y, p, q: OPT.Struct;
BEGIN
y := ynode^.typ; f := x^.form; g := y^.form;
IF (ynode^.class = Ntype) OR (ynode^.class = Nproc) & (f # ProcTyp) THEN err(126) END ;
CASE f OF
Undef:
| Byte:
IF ~(g IN {Byte, Char, SInt}) THEN err(113) END
| Bool, Char, SInt, Set:
IF g # f THEN err(113) END
| Int:
IF ~(g IN {SInt, Int}) THEN err(113) END
| LInt:
IF ~(g IN intSet) THEN err(113) END
| Real:
IF ~(g IN {SInt..Real}) THEN err(113) END
| LReal:
IF ~(g IN {SInt..LReal}) THEN err(113) END
| Pointer:
IF (x = y) OR (g = NilTyp) OR (x = OPT.sysptrtyp) & (g = Pointer) THEN (* ok *)
ELSIF g = Pointer THEN
p := x^.BaseTyp; q := y^.BaseTyp;
IF (p^.comp = Record) & (q^.comp = Record) THEN
WHILE (q # p) & (q # NIL) & (q # OPT.undftyp) DO q := q^.BaseTyp END ;
IF q = NIL THEN err(113) END
ELSE err(113)
END
ELSE err(113)
END
| ProcTyp:
IF ynode^.class = Nproc THEN CheckProc(x, ynode^.obj)
ELSIF (x = y) OR (g = NilTyp) THEN (* ok *)
ELSE err(113)
END
| NoTyp, NilTyp:
err(113)
| Comp:
IF x^.comp = Array THEN
IF (ynode^.class = Nconst) & (g = Char) THEN CharToString(ynode); y := ynode^.typ; g := String END ;
IF x = y THEN (* ok *)
ELSIF (g = String) & (x^.BaseTyp = OPT.chartyp) THEN (*check length of string*)
IF ynode^.conval^.intval2 > x^.n THEN err(114) END ;
ELSE err(113)
END
ELSIF x^.comp = Record THEN
IF x = y THEN (* ok *)
ELSIF y^.comp = Record THEN
q := y^.BaseTyp;
WHILE (q # NIL) & (q # x) & (q # OPT.undftyp) DO q := q^.BaseTyp END ;
IF q = NIL THEN err(113) END
ELSE err(113)
END
ELSE (*DynArr*) err(113)
END
END ;
IF (ynode^.class = Nconst) & (g < f) & (g IN {SInt..Real}) & (f IN {Int..LReal}) THEN
Convert(ynode, x)
END
END CheckAssign;
PROCEDURE CheckLeaf(x: OPT.Node; dynArrToo: BOOLEAN);
BEGIN
IF (x^.class = Nmop) & (x^.subcl = val) THEN x := x^.left END ;
IF x^.class = Nguard THEN x := x^.left END ; (* skip last (and unique) guard *)
IF (x^.class = Nvar) & (dynArrToo OR (x^.typ^.comp # DynArr)) THEN x^.obj^.leaf := FALSE END
END CheckLeaf;
PROCEDURE StPar0*(VAR par0: OPT.Node; fctno: INTEGER); (* par0: first param of standard proc *)
VAR f: INTEGER; typ: OPT.Struct; x: OPT.Node; Dummy:LONGREAL;
BEGIN x := par0; f := x^.typ^.form;
CASE fctno OF
haltfn: (*HALT*)
IF (f IN intSet) & (x^.class = Nconst) THEN
IF (OPM.MinHaltNr <= x^.conval^.intval) & (x^.conval^.intval <= OPM.MaxHaltNr) THEN
BindNodes(Ntrap, OPT.notyp, x, x)
ELSE err(218)
END
ELSE err(69)
END ;
x^.typ := OPT.notyp
| newfn: (*NEW*)
typ := OPT.notyp;
IF NotVar(x) THEN err(112)
ELSIF f = Pointer THEN
IF OPM.NEWusingAdr THEN CheckLeaf(x, TRUE) END ;
IF x^.readonly THEN err(76) END ;
f := x^.typ^.BaseTyp^.comp;
IF f IN {Record, DynArr, Array} THEN
IF f = DynArr THEN typ := x^.typ^.BaseTyp END ;
BindNodes(Nassign, OPT.notyp, x, NIL); x^.subcl := newfn
ELSE err(111)
END
ELSE err(111)
END ;
x^.typ := typ
| absfn: (*ABS*)
MOp(abs, x)
| capfn: (*CAP*)
MOp(cap, x)
| ordfn: (*ORD*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f = Char THEN Convert(x, OPT.inttyp)
ELSE err(111)
END ;
x^.typ := OPT.inttyp
| entierfn: (*ENTIER*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN realSet THEN Convert(x, OPT.linttyp)
ELSE err(111)
END ;
x^.typ := OPT.linttyp
| oddfn: (*ODD*)
MOp(odd, x)
| minfn: (*MIN*)
IF x^.class = Ntype THEN
CASE f OF
Bool: x := NewBoolConst(FALSE)
| Char: x := NewIntConst(0); x^.typ := OPT.chartyp
| SInt: x := NewIntConst(OPM.MinSInt)
| Int: x := NewIntConst(OPM.MinInt)
| LInt: x := NewIntConst(OPM.MinLInt)
| Set: x := NewIntConst(0); x^.typ := OPT.inttyp
| Real:
AmigaMathL.Long(OPM.MinReal, Dummy);
x := NewRealConst(Dummy, OPT.realtyp)
(* x := NewRealConst(OPM.MinReal, OPT.realtyp) *)
| LReal: x := NewRealConst(OPM.MinLReal, OPT.lrltyp)
ELSE err(111)
END
ELSE err(110)
END
| maxfn: (*MAX*)
IF x^.class = Ntype THEN
CASE f OF
Bool: x := NewBoolConst(TRUE)
| Char: x := NewIntConst(0FFH); x^.typ := OPT.chartyp
| SInt: x := NewIntConst(OPM.MaxSInt)
| Int: x := NewIntConst(OPM.MaxInt)
| LInt: x := NewIntConst(OPM.MaxLInt)
| Set: x := NewIntConst(OPM.MaxSet); x^.typ := OPT.inttyp
| Real:
AmigaMathL.Long(OPM.MaxReal, Dummy);
x := NewRealConst(Dummy, OPT.realtyp)
(* x := NewRealConst(OPM.MaxReal, OPT.realtyp) *)
| LReal: x := NewRealConst(OPM.MaxLReal, OPT.lrltyp)
ELSE err(111)
END
ELSE err(110)
END
| chrfn: (*CHR*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN {Undef, SInt..LInt} THEN Convert(x, OPT.chartyp)
ELSE err(111); x^.typ := OPT.chartyp
END
| shortfn: (*SHORT*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f = Int THEN Convert(x, OPT.sinttyp)
ELSIF f = LInt THEN Convert(x, OPT.inttyp)
ELSIF f = LReal THEN Convert(x, OPT.realtyp)
ELSE err(111)
END
| longfn: (*LONG*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f = SInt THEN Convert(x, OPT.inttyp)
ELSIF f = Int THEN Convert(x, OPT.linttyp)
ELSIF f = Real THEN Convert(x, OPT.lrltyp)
ELSIF f = Char THEN Convert(x, OPT.linttyp)
ELSE err(111)
END
| incfn, decfn: (*INC, DEC*)
IF NotVar(x) THEN err(112)
ELSIF ~(f IN intSet) THEN err(111)
ELSIF x^.readonly THEN err(76)
END
| inclfn, exclfn: (*INCL, EXCL*)
IF NotVar(x) THEN err(112)
ELSIF x^.typ # OPT.settyp THEN err(111); x^.typ := OPT.settyp
ELSIF x^.readonly THEN err(76)
END
| lenfn: (*LEN*)
IF ~(x^.typ^.comp IN {DynArr, Array}) THEN err(131) END
| copyfn: (*COPY*)
IF (x^.class = Nconst) & (f = Char) THEN CharToString(x); f := String END ;
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF (~(x^.typ^.comp IN {DynArr, Array}) OR (x^.typ^.BaseTyp^.form # Char))
& (f # String) THEN err(111)
END
| ashfn: (*ASH*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN intSet THEN
IF f # LInt THEN Convert(x, OPT.linttyp) END
ELSE err(111); x^.typ := OPT.linttyp
END
| adrfn: (*SYSTEM.ADR*)
CheckLeaf(x, FALSE); MOp(adr, x)
| sizefn: (*SIZE*)
IF x^.class # Ntype THEN err(110); x := NewIntConst(1)
ELSIF (f IN {Byte..Set, Pointer, ProcTyp}) OR (x^.typ^.comp IN {Array, Record}) THEN
typSize(x^.typ, FALSE); x := NewIntConst(x^.typ^.size)
ELSE err(111); x := NewIntConst(1)
END
| ccfn: (*SYSTEM.CC*)
MOp(cc, x)
| lshfn, rotfn: (*SYSTEM.LSH, SYSTEM.ROT*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF ~(f IN intSet + {Byte, Char, Set}) THEN err(111)
END
| getfn, putfn, bitfn, movefn: (*SYSTEM.GET, SYSTEM.PUT, SYSTEM.BIT, SYSTEM.MOVE*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF (x^.class = Nconst) & (f IN {SInt, Int}) THEN Convert(x, OPT.linttyp)
ELSIF ~(f IN {LInt, Pointer}) THEN err(111); x^.typ := OPT.linttyp
END
| getrfn, putrfn: (*SYSTEM.GETREG, SYSTEM.PUTREG*)
IF (f IN intSet) & (x^.class = Nconst) THEN
IF (x^.conval^.intval < OPM.MinRegNr) OR (x^.conval^.intval > OPM.MaxRegNr) THEN err(220) END
ELSE err(69)
END
| valfn: (*SYSTEM.VAL*)
IF x^.class # Ntype THEN err(110)
ELSIF (f IN {Undef, String, NoTyp}) OR (x^.typ^.comp = DynArr) THEN err(111)
END
| sysnewfn: (*SYSTEM.NEW*)
IF NotVar(x) THEN err(112)
ELSIF f = Pointer THEN
IF OPM.NEWusingAdr THEN CheckLeaf(x, TRUE) END
ELSE err(111)
END
| assertfn: (*ASSERT*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126); x := NewBoolConst(FALSE)
ELSIF f # Bool THEN err(120); x := NewBoolConst(FALSE)
ELSE MOp(not, x)
END
END ;
par0 := x
END StPar0;
PROCEDURE StPar1*(VAR par0: OPT.Node; x: OPT.Node; fctno: SHORTINT); (* x: second parameter of standard proc *)
VAR f, L: INTEGER; typ: OPT.Struct; p, t: OPT.Node;
PROCEDURE NewOp(class: SHORTINT);
VAR node: OPT.Node;
BEGIN
node := OPT.NewNode(class);
node^.left := p; node^.right := x; p := node
END NewOp;
BEGIN p := par0; f := x^.typ^.form;
CASE fctno OF
incfn, decfn: (*INC DEC*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126); p^.typ := OPT.notyp
ELSE
IF x^.typ # p^.typ THEN
IF (x^.class = Nconst) & (f IN intSet) THEN Convert(x, p^.typ)
ELSE err(111)
END
END ;
NewOp(Nassign); p^.subcl := fctno;
p^.typ := OPT.notyp
END
| inclfn, exclfn: (*INCL, EXCL*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN intSet THEN
IF (x^.class = Nconst) & ((0 > x^.conval^.intval) OR (x^.conval^.intval > OPM.MaxSet)) THEN err(202)
END ;
NewOp(Nassign); p^.subcl := fctno
ELSE err(111)
END ;
p^.typ := OPT.notyp
| lenfn: (*LEN*)
IF ~(f IN intSet) OR (x^.class # Nconst) THEN err(69)
ELSIF f = SInt THEN
L := SHORT(x^.conval^.intval); typ := p^.typ;
WHILE (L > 0) & (typ^.comp IN {DynArr, Array}) DO typ := typ^.BaseTyp; DEC(L) END ;
IF (L # 0) OR ~(typ^.comp IN {DynArr, Array}) THEN err(132)
ELSE x^.obj := NIL;
IF typ^.comp = DynArr THEN
WHILE p^.class = Nindex DO p := p^.left; INC(x^.conval^.intval) END ; (* possible side effect ignored *)
NewOp(Ndop); p^.subcl := len; p^.typ := OPT.linttyp
ELSE p := x; p^.conval^.intval := typ^.n; SetIntType(p)
END
END
ELSE err(132)
END
| copyfn: (*COPY*)
IF NotVar(x) THEN err(112)
ELSIF (x^.typ^.comp IN {Array, DynArr}) & (x^.typ^.BaseTyp^.form = Char) THEN
IF x^.readonly THEN err(76) END ;
t := x; x := p; p := t; NewOp(Nassign); p^.subcl := copyfn
ELSE err(111)
END ;
p^.typ := OPT.notyp
| ashfn: (*ASH*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN intSet THEN
IF (p^.class = Nconst) & (x^.class = Nconst) THEN
IF (-maxExp > x^.conval^.intval) OR (x^.conval^.intval > maxExp) THEN err(208); p^.conval^.intval := 1
ELSIF x^.conval^.intval >= 0 THEN
IF ABS(p^.conval^.intval) <= MAX(LONGINT) DIV ASH(1, x^.conval^.intval) THEN
p^.conval^.intval := p^.conval^.intval * ASH(1, x^.conval^.intval)
ELSE err(208); p^.conval^.intval := 1
END
ELSE p^.conval^.intval := ASH(p^.conval^.intval, x^.conval^.intval)
END ;
p^.obj := NIL
ELSE NewOp(Ndop); p^.subcl := ash; p^.typ := OPT.linttyp
END
ELSE err(111)
END
| newfn: (*NEW(p, x...)*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF p^.typ^.comp = DynArr THEN
IF f IN intSet THEN
IF (x^.class = Nconst) & ((x^.conval^.intval <= 0) OR (x^.conval^.intval > OPM.MaxIndex)) THEN err(63) END
ELSE err(111)
END ;
p^.right := x; p^.typ := p^.typ^.BaseTyp
ELSE err(64)
END
| lshfn, rotfn: (*SYSTEM.LSH, SYSTEM.ROT*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF ~(f IN intSet) THEN err(111)
ELSE NewOp(Ndop); p^.typ := p^.left^.typ;
IF fctno = lshfn THEN p^.subcl := lsh ELSE p^.subcl := rot END
END
| getfn, putfn, getrfn, putrfn: (*SYSTEM.GET, SYSTEM.PUT, SYSTEM.GETREG, SYSTEM.PUTREG*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN {Undef..Set, Pointer, ProcTyp} THEN
IF (fctno = getfn) OR (fctno = getrfn) THEN
IF NotVar(x) THEN err(112) END ;
t := x; x := p; p := t
END ;
NewOp(Nassign); p^.subcl := fctno
ELSE err(111)
END ;
p^.typ := OPT.notyp
| bitfn: (*SYSTEM.BIT*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN intSet THEN
NewOp(Ndop); p^.subcl := bit
ELSE err(111)
END ;
p^.typ := OPT.booltyp
| valfn: (*SYSTEM.VAL*) (* type is changed without considering the byte ordering on the target machine *)
IF (x^.class = Ntype) OR (x^.class = Nproc) OR
(f IN {Undef, String, NoTyp}) OR (x^.typ^.comp = DynArr) THEN err(126)
END ;
IF (x^.class >= Nconst) OR ((f IN realSet) # (p^.typ^.form IN realSet)) THEN
t := OPT.NewNode(Nmop); t^.subcl := val; t^.left := x; x := t
ELSE x^.readonly := FALSE
END ;
x^.typ := p^.typ; p := x
| sysnewfn: (*SYSTEM.NEW*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN intSet THEN
NewOp(Nassign); p^.subcl := sysnewfn
ELSE err(111)
END ;
p^.typ := OPT.notyp
| movefn: (*SYSTEM.MOVE*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF (x^.class = Nconst) & (f IN {SInt, Int}) THEN Convert(x, OPT.linttyp)
ELSIF ~(f IN {LInt, Pointer}) THEN err(111); x^.typ := OPT.linttyp
END ;
p^.link := x
| assertfn: (*ASSERT*)
IF (f IN intSet) & (x^.class = Nconst) THEN
IF (OPM.MinHaltNr <= x^.conval^.intval) & (x^.conval^.intval <= OPM.MaxHaltNr) THEN
BindNodes(Ntrap, OPT.notyp, x, x);
x^.conval := OPT.NewConst(); x^.conval^.intval := OPM.errpos;
Construct(Nif, p, x); p^.conval := OPT.NewConst(); p^.conval^.intval := OPM.errpos;
Construct(Nifelse, p, NIL); OptIf(p);
IF p = NIL THEN (* ASSERT(TRUE) *)
ELSIF p^.class = Ntrap THEN err(99)
ELSE p^.subcl := assertfn
END
ELSE err(218)
END
ELSE err(69)
END
ELSE err(64)
END ;
par0 := p
END StPar1;
PROCEDURE StParN*(VAR par0: OPT.Node; x: OPT.Node; fctno, n: INTEGER); (* x: n+1-th param of standard proc *)
VAR node: OPT.Node; f: INTEGER; p: OPT.Node;
BEGIN p := par0; f := x^.typ^.form;
IF fctno = newfn THEN (*NEW(p, ..., x...*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF p^.typ^.comp # DynArr THEN err(64)
ELSIF f IN intSet THEN
IF (x^.class = Nconst) & ((x^.conval^.intval <= 0) OR (x^.conval^.intval > OPM.MaxIndex)) THEN err(63) END ;
node := p^.right; WHILE node^.link # NIL DO node := node^.link END;
node^.link := x; p^.typ := p^.typ^.BaseTyp
ELSE err(111)
END
ELSIF (fctno = movefn) & (n = 2) THEN (*SYSTEM.MOVE*)
IF (x^.class = Ntype) OR (x^.class = Nproc) THEN err(126)
ELSIF f IN intSet THEN
node := OPT.NewNode(Nassign); node^.subcl := movefn; node^.right := p;
node^.left := p^.link; p^.link := x; p := node
ELSE err(111)
END ;
p^.typ := OPT.notyp
ELSE err(64)
END ;
par0 := p
END StParN;
PROCEDURE StFct*(VAR par0: OPT.Node; fctno: SHORTINT; parno: INTEGER);
VAR dim: INTEGER; x, p: OPT.Node;
BEGIN p := par0;
IF fctno <= ashfn THEN
IF (fctno = newfn) & (p^.typ # OPT.notyp) THEN
IF p^.typ^.comp = DynArr THEN err(65) END ;
p^.typ := OPT.notyp
ELSIF fctno <= sizefn THEN (* 1 param *)
IF parno < 1 THEN err(65) END
ELSE (* more than 1 param *)
IF ((fctno = incfn) OR (fctno = decfn)) & (parno = 1) THEN (*INC, DEC*)
BindNodes(Nassign, OPT.notyp, p, NewIntConst(1)); p^.subcl := fctno
ELSIF (fctno = lenfn) & (parno = 1) THEN (*LEN*)
IF p^.typ^.comp = DynArr THEN dim := 0;
WHILE p^.class = Nindex DO p := p^.left; INC(dim) END ; (* possible side effect ignored *)
BindNodes(Ndop, OPT.linttyp, p, NewIntConst(dim)); p^.subcl := len
ELSE
p := NewIntConst(p^.typ^.n)
END
ELSIF parno < 2 THEN err(65)
END
END
ELSIF fctno = assertfn THEN
IF parno = 1 THEN x := NIL;
BindNodes(Ntrap, OPT.notyp, x, NewIntConst(AssertTrap));
x^.conval := OPT.NewConst(); x^.conval^.intval := OPM.errpos;
Construct(Nif, p, x); p^.conval := OPT.NewConst(); p^.conval^.intval := OPM.errpos;
Construct(Nifelse, p, NIL); OptIf(p);
IF p = NIL THEN (* ASSERT(TRUE) *)
ELSIF p^.class = Ntrap THEN err(99)
ELSE p^.subcl := assertfn
END
ELSIF parno < 1 THEN err(65)
END
ELSE (*SYSTEM*)
IF (parno < 1) OR
(fctno > ccfn) & (parno < 2) OR
(fctno = movefn) & (parno < 3) THEN err(65)
END
END ;
par0 := p
END StFct;
PROCEDURE DynArrParCheck(ftyp, atyp: OPT.Struct; fvarpar: BOOLEAN);
VAR f: INTEGER;
BEGIN (* ftyp^.comp = DynArr *)
f := atyp^.comp; ftyp := ftyp^.BaseTyp; atyp := atyp^.BaseTyp;
IF fvarpar & (ftyp = OPT.bytetyp) THEN (* ok, but ... *)
IF ~(f IN {Array, DynArr}) OR ~(atyp^.form IN {Byte..SInt}) THEN err(-301) END (* ... warning 301 *)
ELSIF f IN {Array, DynArr} THEN
IF ftyp^.comp = DynArr THEN DynArrParCheck(ftyp, atyp, fvarpar)
ELSIF ftyp # atyp THEN
IF ~fvarpar & (ftyp.form = Pointer) & (atyp.form = Pointer) THEN
ftyp := ftyp^.BaseTyp; atyp := atyp^.BaseTyp;
IF (ftyp^.comp = Record) & (atyp^.comp = Record) THEN
WHILE (ftyp # atyp) & (atyp # NIL) & (atyp # OPT.undftyp) DO atyp := atyp^.BaseTyp END ;
IF atyp = NIL THEN err(113) END
ELSE err(66)
END
ELSE err(66)
END
END ;
ELSE err(67)
END
END DynArrParCheck;
PROCEDURE CheckReceiver(VAR x: OPT.Node; fp: OPT.Object);
BEGIN
IF fp^.typ^.form = Pointer THEN
IF x^.class = Nderef THEN x := x^.left (*undo DeRef*) ELSE (*x^.typ^.comp = Record*) err(71) END
END
END CheckReceiver;
PROCEDURE PrepCall*(VAR x: OPT.Node; VAR fpar: OPT.Object);
BEGIN
IF (x^.obj # NIL) & (x^.obj^.mode IN {LProc, XProc, TProc, CProc}) THEN
fpar := x^.obj^.link;
IF x^.obj^.mode = TProc THEN CheckReceiver(x^.left, fpar); fpar := fpar^.link END
ELSIF (x^.class # Ntype) & (x^.typ # NIL) & (x^.typ^.form = ProcTyp) THEN
fpar := x^.typ^.link
ELSE err(121); fpar := NIL; x^.typ := OPT.undftyp
END
END PrepCall;
PROCEDURE Param*(ap: OPT.Node; fp: OPT.Object);
VAR q: OPT.Struct;
BEGIN
IF fp.typ.form # Undef THEN
IF fp^.mode = VarPar THEN
IF NotVar(ap) THEN err(122)
ELSE CheckLeaf(ap, FALSE)
END ;
IF ap^.readonly THEN err(76) END ;
IF fp^.typ^.comp = DynArr THEN DynArrParCheck(fp^.typ, ap^.typ, TRUE)
ELSIF (fp^.typ^.comp = Record) & (ap^.typ^.comp = Record) THEN
q := ap^.typ;
WHILE (q # fp^.typ) & (q # NIL) & (q # OPT.undftyp) DO q := q^.BaseTyp END ;
IF q = NIL THEN err(111) END
ELSIF (fp^.typ = OPT.sysptrtyp) & (ap^.typ^.form = Pointer) THEN (* ok *)
ELSIF (ap^.typ # fp^.typ) & ~((fp^.typ^.form = Byte) & (ap^.typ^.form IN {Char, SInt})) THEN err(123)
END
ELSIF fp^.typ^.comp = DynArr THEN
IF (ap^.class = Nconst) & (ap^.typ^.form = Char) THEN CharToString(ap) END ;
IF (ap^.typ^.form = String) & (fp^.typ^.BaseTyp^.form = Char) THEN (* ok *)
ELSIF ap^.class >= Nconst THEN err(59)
ELSE DynArrParCheck(fp^.typ, ap^.typ, FALSE)
END
ELSE CheckAssign(fp^.typ, ap)
END
END
END Param;
PROCEDURE StaticLink*(dlev: SHORTINT);
VAR scope: OPT.Object;
BEGIN
scope := OPT.topScope;
WHILE dlev > 0 DO DEC(dlev);
INCL(scope^.link^.conval^.setval, slNeeded);
scope := scope^.left
END
END StaticLink;
PROCEDURE Call*(VAR x: OPT.Node; apar: OPT.Node; fp: OPT.Object);
VAR typ: OPT.Struct; p: OPT.Node; lev: SHORTINT;
BEGIN
IF x^.class = Nproc THEN typ := x^.typ;
lev := x^.obj^.mnolev;
IF lev > 0 THEN StaticLink(OPT.topScope^.mnolev-lev) END ;
IF x^.obj^.mode = IProc THEN err(121) END
ELSIF (x^.class = Nfield) & (x^.obj^.mode = TProc) THEN typ := x^.typ;
x^.class := Nproc; p := x^.left; x^.left := NIL; p^.link := apar; apar := p; fp := x^.obj^.link
ELSE typ := x^.typ^.BaseTyp
END ;
BindNodes(Ncall, typ, x, apar); x^.obj := fp
END Call;
PROCEDURE Enter*(VAR procdec: OPT.Node; stat: OPT.Node; proc: OPT.Object);
VAR x: OPT.Node;
BEGIN
x := OPT.NewNode(Nenter); x^.typ := OPT.notyp; x^.obj := proc;
x^.left := procdec; x^.right := stat; procdec := x
END Enter;
PROCEDURE Return*(VAR x: OPT.Node; proc: OPT.Object);
VAR node: OPT.Node;
BEGIN
IF proc = NIL THEN (* return from module *)
IF x # NIL THEN err(124) END
ELSE
IF x # NIL THEN CheckAssign(proc^.typ, x)
ELSIF proc^.typ # OPT.notyp THEN err(124)
END
END ;
node := OPT.NewNode(Nreturn); node^.typ := OPT.notyp; node^.obj := proc; node^.left := x; x := node
END Return;
PROCEDURE Assign*(VAR x: OPT.Node; y: OPT.Node);
VAR z: OPT.Node;
BEGIN
IF x^.class >= Nconst THEN err(56) END ;
CheckAssign(x^.typ, y);
IF x^.readonly THEN err(76) END ;
IF x^.typ^.comp = Record THEN
IF x^.class = Nguard THEN z := x^.left ELSE z := x END ;
IF (z^.class = Nderef) & (z^.left^.class = Nguard) THEN
z^.left := z^.left^.left (* skip guard before dereferencing *)
END ;
IF (x^.typ^.strobj # NIL) & ((z^.class = Nderef) OR (z^.class = Nvarpar)) THEN
BindNodes(Neguard, x^.typ, z, NIL); x := z
END
ELSIF (x^.typ^.comp = Array) & (x^.typ^.BaseTyp = OPT.chartyp) &
(y^.typ^.form = String) & (y^.conval^.intval2 = 1) THEN (* replace array := "" with array[0] := 0X *)
y^.typ := OPT.chartyp; y^.conval^.intval := 0;
Index(x, NewIntConst(0))
END ;
BindNodes(Nassign, OPT.notyp, x, y); x^.subcl := assign
END Assign;
PROCEDURE Inittd*(VAR inittd, last: OPT.Node; typ: OPT.Struct);
VAR node: OPT.Node;
BEGIN
node := OPT.NewNode(Ninittd); node^.typ := typ;
node^.conval := OPT.NewConst(); node^.conval^.intval := typ^.txtpos;
IF inittd = NIL THEN inittd := node ELSE last^.link := node END ;
last := node
END Inittd;
BEGIN
maxExp := log(MAX(LONGINT) DIV 2 + 1); maxExp := exp
END OPB.