{ > PasExpr2 } { Created by Tutu 21-Feb-86 from overflow of code out of PasExpr } PROCEDURE FACTOR; { This procedure parses a factor. Declared FORWARD at the start of this file. } VAR NEGATE : BOOLEAN; STKP : UW; PROCEDURE SETSTUFF; { This procedure parses a set constant. Set members which are constants are stored in a set and code generated to push the constant set onto TOS. } LABEL 13; VAR SETONSTK : BOOLEAN; SETSZ : SI; IBYTE : UB; SETCONSTS : RECORD CASE BOOLEAN OF TRUE : (A : PACKED ARRAY[0..31] OF UB); FALSE: (S : SET OF UB) END; SETDESC, HIGHLIMIT : SYMREC; PROCEDURE GETMEM; { This procedure parses a set member. } BEGIN RETKONST := TRUE; EXPRESS (SETDESC); X.STKINC := X.STKINC - reasize { Tutu - was 5 } END; { getmem } PROCEDURE ADDSET; { This procedure generates code to do set union on the 2 sets on top of stack. } BEGIN IF SETONSTK THEN BEGIN FLUSHNGEN (126{Op_add_set}); STKUP (64); X.STKINC := X.STKINC - 64 END; SETONSTK := TRUE END; { addset } BEGIN { setstuff } NXTSYMOK; { Initialise set constant array to empty set ie all zeros } SETCONSTS.S := []; IBYTE := MAXSET; SETSZ := PRED (0); SETONSTK := FALSE; IF SYM = RBRAK THEN BEGIN {Set is an empty set and therefore does not have a base type} CODEINFO.REF := NIL; FLUSHNGEN (4{PushK_set}); GENUB (0) END ELSE BEGIN GETMEM; CODEINFO := SETDESC; 13: IF SETDESC.IDTYP <> SUBR THEN ERROR (122); IF NOT EQTYPS (CODEINFO,SETDESC,FALSE) THEN ERROR (147); IF SYM = DDOT THEN BEGIN NXTSYMOK; EXPRESS (HIGHLIMIT); X.STKINC := X.STKINC - reasize; { Tutu - was 5 } IF NOT EQTYPS (SETDESC,HIGHLIMIT,FALSE) THEN ERROR (118); IF ISINT (HIGHLIMIT) THEN FLUSHNGEN (45{Set_sbr_int}) ELSE FLUSHNGEN (43{Set_sbr_bce}); ADDSET END ELSE IF (SETDESC.OBJ = KONST) AND (RETKONST) THEN BEGIN { Add constant to set constant } IBYTE := SETDESC.VAL DIV 8; IF (IBYTE >= MAXSET) OR (SETDESC.VAL < 0) THEN ERROR (124) ELSE BEGIN SETCONSTS.S := SETCONSTS.S + [SETDESC.VAL]; IF IBYTE > SETSZ THEN SETSZ := IBYTE END END ELSE BEGIN IF ISINT (SETDESC) THEN FLUSHNGEN (44{Set_elt_int}) ELSE FLUSHNGEN (42{Set_elt_bce}); ADDSET END; IF ISCOMA THEN BEGIN NXTSYMOK; GETMEM; GOTO 13 { Bad programming practice but Ben made me do it } END; IF IBYTE < MAXSET THEN BEGIN { set included constants so output set constant } FLUSHNGEN (4{PushK_set}); GENUB (SUCC (SETSZ)); FOR IBYTE := 0 TO SETSZ DO GENUB (SETCONSTS.A[IBYTE]); ADDSET END END; CODEINFO.IDTYP := SETT; CODEINFO.OBJ := KONST; RETKONST := FALSE; CHKNEXT (RBRAK) END; { setstuff } PROCEDURE FUNCS (VAR CODEINFO : SYMREC); { This procedure parses and generates code for standard and extension functions } VAR RNGCHKONSUCCANDPRED, INTP : BOOLEAN; { True if integer parameter } PARAMS, FUNKNO : UB; PARAMDESC : SYMREC; BEGIN FUNKNO := CODEINFO.FUNCNO; NXTSYMOK; RNGCHKONSUCCANDPRED := FALSE; IF CODEINFO.OBJ = EFUNC THEN BEGIN ISOERR; IF ABS (241-FUNKNO) <> 8 { (FUNKNO <> 233) AND (FUNKNO <> 249)} THEN BEGIN { Time and Base have no args } PARAMS := PRED (0); CHK (LPAREN); REPEAT NXTSYMOK; PARAMS := SUCC (PARAMS); IF (FUNKNO = 237) AND (PARAMS = 2) THEN VARACCESS (PARAMDESC) { Tutu - I've taken over code1 -> fcall (addr, regs^). Above code still ok ! } ELSE BEGIN EXPRESS (PARAMDESC); IF FUNKNO <= 212 {rval} THEN BEGIN IF PARAMDESC.IDTYP <> STRNG THEN ERROR (61) END ELSE IF NOT ISINT (PARAMDESC) THEN ERROR (81) END UNTIL NOT ISCOMA; IF PARAMS > CODEINFO.NPARAMS THEN ERROR (60) ELSE IF PARAMS < CODEINFO.NPARAMS THEN ERROR (17); CHKNEXT (RPAREN) END END ELSE IF FUNKNO <= EOFFN THEN IF SYM = LPAREN THEN BEGIN NXTSYMOK; VARACCESS (PARAMDESC); IF (FUNKNO <> EOFFN) AND (PARAMDESC.REF <> CHARDESC) THEN ERROR (70); IF PARAMDESC.IDTYP < FYLE THEN ERROR (69); CHKNEXT (RPAREN) END ELSE GENMOV (LOCATE,INPTSYMP^) ELSE BEGIN CHKNEXT (LPAREN); EXPRESS (PARAMDESC); { INTP is used to hold boolean (is func param a integer)} INTP := ISINT (PARAMDESC); { Convert case of integer to char to save on code, case selector is scaled down by 142 therefore 192 = '0' } CASE CHR (FUNKNO-142) OF '0'{190odd}, '1'{191chr} : IF NOT INTP THEN ERROR (81); '2'{192ord} : BEGIN IF PARAMDESC.IDTYP <> SUBR THEN ERROR (68); IF INTP THEN FUNKNO := 0 END; '3'{193succ}, '4'{194pred} : BEGIN IF PARAMDESC.IDTYP <> SUBR THEN ERROR (68); CODEINFO.REF := PARAMDESC.REF; FUNKNO := FUNKNO + ORD (INTP) * 2; RNGCHKONSUCCANDPRED := TRUE; END; '8'{198abs}, '9'{199sqr} : BEGIN IF (PARAMDESC.IDTYP <> REEL) AND (NOT INTP) THEN ERROR (80); CODEINFO.IDTYP := PARAMDESC.IDTYP; CODEINFO.REF := PARAMDESC.REF; FUNKNO := FUNKNO + ORD (NOT INTP) * 3 END END {CASE} OTHERWISE BEGIN IF (FUNKNO < 209{sin,cos,exp,ln,sqrt,arctan}) AND INTP THEN BEGIN FLUSHNGEN (FLTROP); PARAMDESC.IDTYP := REEL END; IF PARAMDESC.IDTYP <> REEL THEN ERROR (79) END; CHKNEXT (RPAREN); END; IF FUNKNO <> 0 THEN FLUSHNGEN (FUNKNO); IF (FUNKNO = 212 {rval}) OR (FUNKNO = 211 {ival}) THEN GENUB (LIMITS (PARAMDESC)); IF RNGCHKONSUCCANDPRED THEN {Do range checking on succ + pred } RNGCHKONSUCCANDPRED := EQTYPS (PARAMDESC,PARAMDESC,TRUE) END; BEGIN { factor } NEGATE := (SYM = NOTSY); IF NEGATE THEN NXTSYMOK; CODEINFO := THISSYMP^; STKP := X.STKINC; CASE SYM OF KONST, NILSY : BEGIN UC; CODEINFO := THISSYMP^; IF CODEINFO.IDTYP = STRNG THEN BEGIN GENLORS (LOCILD,CODEINFO.STRLEN); GENSTR (SUCC (CODEINFO.STRPTR),CODEINFO.STRLEN); RETKONST := FALSE; NEXTSYM END ELSE BEGIN NEXTSYM; IF NOT RETKONST THEN GENMOV (PUSH,CODEINFO); END END; BOUNDID : BEGIN IF X.ACTIVLEV <> CODEINFO.LEV THEN SETLEV (CODEINFO.LEV); GENLORS (10{Push_ptr},CODEINFO.ADESC); GENLORS (41{Use_offset},CODEINFO.OFSET); GENMOV (IPUSH,CODEINFO); NXTSYMOK END; LPAREN : BEGIN NXTSYMOK; EXPRESS (CODEINFO); CHKNEXT (RPAREN) END; FUNC : BEGIN SETFUN (CODEINFO,THISSYMP^); PFCALL (THISSYMP); DEBLINE END; LBRAK : SETSTUFF; SFUNC, EFUNC : FUNCS (CODEINFO) END OTHERWISE BEGIN VARACCESS (CODEINFO); IF (CODEINFO.IDTYP < STRNG) AND (NOT NOCODE) THEN GENMOV (IPUSH,CODEINFO) END; IF NEGATE THEN BEGIN IF CODEINFO.REF <> BOOLDESC THEN ERROR (161); FLUSHNGEN (NOTOP) END; X.STKINC := STKP; STKEL := 0; IF CODEINFO.IDTYP < SETT THEN STKEL := reasize { Tutu - was 5 } ELSE IF CODEINFO.IDTYP = SETT THEN STKEL := 32; STKUP (STKEL) END; PROCEDURE BOOLEXP (VAR CODEINFO : SYMREC); { This procedure } VAR STKP : UW; BEGIN STKP := X.STKINC; EXPRESS (CODEINFO); X.STKINC := STKP; IF BOOLDESC <> CODEINFO.REF THEN ERROR (161) END; { boolexp } PROCEDURE APARAMLIST; { This procedure } VAR ARGDESC, PARCOPY : SYMREC; ITP : TYPES; LASTP : SYMP; LASTCA, LASTAP : STP; PROCEDURE GETARG (PARAM : SYMP; SYMAFTERARG : SYMBOLS); { This procedure } VAR CLAIM_PATCH : UW; PROCEDURE CHKPROCPARAM (FPARAM, APARAM : SYMP); { This procedure } VAR PROCDESC : SYMP; ARGDESC, PARCOPY : SYMREC; FPLIST, APLIST : PARAMP; BEGIN IF (APARAM^.OBJ <> PROC) AND (APARAM^.OBJ <> FUNC) THEN ERROR (53) ELSE BEGIN IF FPARAM^.OBJ = APARAM^.OBJ THEN BEGIN WITH APARAM^.REF^ DO BEGIN APLIST := PLIST; FPLIST := FPARAM^.REF^.PLIST; WHILE FPLIST <> NIL DO BEGIN IF (APLIST = NIL) OR (FPLIST^.No <> APLIST^.No) THEN ERROR (95); FPLIST := FPLIST^.NEXTNo; APLIST := APLIST^.NEXTNo END; IF APLIST <> NIL THEN ERROR (95); IF FPARAM^.REF^.FUNCREF <> FUNCREF THEN ERROR (49); PROCDESC := LASTPARAM END; FPARAM := FPARAM^.REF^.LASTPARAM; WHILE FPARAM <> NIL DO BEGIN PARCOPY := FPARAM^; ARGDESC := PROCDESC^; { If fparam = procedural param } IF PARCOPY.OBJ >= PROC THEN CHKPROCPARAM (FPARAM,PROCDESC) ELSE IF (PARCOPY.IDTYP = CARAY) THEN BEGIN { Check that conformant array specs are the same } REPEAT { Check that index types match and both are VARS or not } IF (PARCOPY.REF^.IREF <> ARGDESC.REF^.IREF) OR ((PARCOPY.REF^.ALEV>127) <> (ARGDESC.REF^.ALEV>127)) OR (ARGDESC.IDTYP <> CARAY) THEN ERROR (90); PARCOPY.IDTYP := PARCOPY.REF^.TYP; PARCOPY.REF := PARCOPY.REF^.ELREF; ARGDESC.IDTYP := ARGDESC.REF^.TYP; ARGDESC.REF := ARGDESC.REF^.ELREF UNTIL PARCOPY.IDTYP <> CARAY; IF ARGDESC.REF <> PARCOPY.REF THEN ERROR (90) END ELSE IF (PARCOPY.REF <> ARGDESC.REF) OR (PARCOPY.NRM <> ARGDESC.NRM) THEN ERROR (90); FPARAM := FPARAM^.LINK; PROCDESC := PROCDESC^.LINK; IF (FPARAM <> NIL) AND (PROCDESC = NIL) THEN ERROR (90) END; { while } IF FPARAM <> PROCDESC THEN ERROR (90) END ELSE ERROR (50) END END; { chkprocparam } BEGIN { getarg } IF PARAM^.LINK <> NIL THEN GETARG (PARAM^.LINK,COMMA); PARCOPY := PARAM^; IF PARCOPY.OBJ <> BOUNDID THEN BEGIN IF PARCOPY.OBJ >= PROC THEN BEGIN { Procedural / functional parameter } CHKPROCPARAM (PARAM,THISSYMP); IF THISSYMP^.NRM THEN BEGIN { Tutu - was GENOPWTB (1,THISSYMP^.ADR); { Push_k_ptr } flushngen (2); gensi (thissymp^.adr); { Tutu - pshK_int proc.no } GENUB (67) { Push Display } END ELSE BEGIN IF X.ACTIVLEV <> THISSYMP^.LEV THEN SETLEV (THISSYMP^.LEV); GENLORS (16, THISSYMP^.ADR); { Locate proc adr and display } GENUB (31); { Push I blk Short } GENUB (dspNprocsize) { Tutu - was block size = 18 } END; STKUP (dspNprocsize); { Tutu - was 18 } NEXTSYM END ELSE BEGIN IF PARCOPY.IDTYP = CARAY THEN BEGIN IF PARCOPY.NRM THEN BEGIN { Value param conformant array } { Make a copy of the array on the heap } writeln ('Value parm conformant array used !'); { Tutu } GENOPWTB (1,stracc); {Push pointer stracc onto stack} GENOPWTB (&DC,0); {Claim block from heap using long form of NEW address of block claimed goes into stracc} CLAIM_PATCH := X.LASTADR; { Get address of block claimed onto TOS } GENOPWTB (1,stracc); {Push pointer stracc onto stack} GENUB (&19); { PshI_ptr } { Get address of block claimed onto TOS } GENOPWTB (1,stracc); {Push pointer stracc onto stack} GENUB (&19); { PshI_ptr } EXPRESS (ARGDESC); IF ARGDESC.OBJ = KONST THEN BEGIN STORPATCH (CLAIM_PATCH,ARGDESC.STRLEN); GENLORS (40{PshI_blk_s},ARGDESC.STRLEN); GENSI (&10B07{Locate_ild,0B,01,00}); GENUB (4); GENSI (1); GENSI (ARGDESC.STRLEN); GENOPWTB (1,ARGDESC.STRLEN) {Push size of array onto stack} END ELSE BEGIN STORPATCH (CLAIM_PATCH,ARGDESC.REF^.VARSIZ); GENLORS (40{PshI_blk_s},ARGDESC.REF^.VARSIZ); IF X.ACTIVLEV <> (ADESCREF^.ALEV MOD 128) THEN SETLEV (ADESCREF^.ALEV MOD 128); GENLORS (16{Locate_var},ADESCREF^.ADESCOFF+ADESC); GENOPWTB (1,ARGDESC.REF^.VARSIZ) {Push array size onto stack} END; IF ARGDESC.IDTYP = CARAY THEN ERROR (46); STKUP (ptrsize) { Tutu - was 2 } END ELSE { Var param conformant array } BEGIN VARACCESS (ARGDESC); if (not (simple or ext)) and argdesc.funcass then error (170); { Tutu - Filthy fudge for 6.6.3.7.3 - can't pass a component of a packed structure to a var conformant array - apart from if you set $X+ !!! } FLUSH; IF X.ACTIVLEV <> (ADESCREF^.ALEV MOD 128) THEN SETLEV (ADESCREF^.ALEV MOD 128); IF ARGDESC.IDTYP = CARAY THEN BEGIN GENLORS (10{Push_ptr},ADESCREF^.ADESCOFF{OPTYPVAL}); GENLORS (41{Use_offset},ADESC) END ELSE GENLORS (16{Locate_var},ADESCREF^.ADESCOFF+ADESC); END; STKUP (twiceptrsize); { Tutu - was 4 } { Type check the conformant array } IF (PARCOPY.REF = LASTCA) AND ((ARGDESC.REF <> LASTAP) OR (ARGDESC.OBJ = KONST)) THEN ERROR (76); { Variable type is not the same as the last param } LASTCA := PARCOPY.REF; LASTAP := ARGDESC.REF; REPEAT IF (ARGDESC.IDTYP < STRNG) OR (ARGDESC.IDTYP > ARAY) THEN ERROR (151); { Check that indicies match } IF ARGDESC.OBJ = KONST THEN ITP := INT ELSE ITP := ARGDESC.REF^.IREF^.TYP; WITH PARCOPY.REF^.IREF^ DO BEGIN IF ((HIGH < LIMITS (ARGDESC)) OR (LOW > LLIM)) AND (ARGDESC.IDTYP <> CARAY) THEN ERROR (108); IF TYP <> ITP THEN ERROR (160) END; IF ARGDESC.PAK <> PARCOPY.PAK THEN ERROR (23); IF ARGDESC.OBJ = KONST THEN BEGIN ARGDESC.IDTYP := SUBR; ARGDESC.OBJ := VARID END ELSE BEGIN ARGDESC.IDTYP := ARGDESC.REF^.TYP; ARGDESC.PAK := ARGDESC.REF^.ALEV > 127; ARGDESC.REF := ARGDESC.REF^.ELREF END; PARCOPY.IDTYP := PARCOPY.REF^.TYP; PARCOPY.PAK := PARCOPY.REF^.ALEV > 127; PARCOPY.REF := PARCOPY.REF^.ELREF UNTIL PARCOPY.IDTYP <> CARAY; IF PARCOPY.REF <> ARGDESC.REF THEN ERROR (90) END ELSE BEGIN IF PARCOPY.NRM THEN BEGIN { Value parameter } EXPRESS (ARGDESC); IF ARGDESC.IDTYP >= STRNG THEN BEGIN IF ARGDESC.IDTYP <> REKORD THEN STKUP (LIMITS (ARGDESC)) ELSE STKUP (ARGDESC.REF^.VARSIZ); IF ARGDESC.OBJ = KONST THEN GENLORS (31{I_PUSH_BLK},ARGDESC.STRLEN) ELSE GENMOV (IPUSH,ARGDESC) END; IF NOT EQTYPS (PARCOPY,ARGDESC,TRUE) THEN ERROR (90) END ELSE BEGIN { Var parameter } VARP := TRUE; VARACCESS (ARGDESC); STKUP (ptrsize); { Tutu - was 2 } VARP := FALSE; IF (ARGDESC.PERM) AND (ARGDESC.IDTYP = SUBR) THEN ERROR (55); IF ARGDESC.OBJ = BOUNDID THEN ERROR (48); IF (ARGDESC.PAK) AND (NOT PARCOPY.PAK) AND (ARGDESC.IDTYP < STRNG) THEN IF EXT THEN BEGIN IF ISINT (ARGDESC) THEN ERROR (18) END ELSE ERROR (18); IF ARGDESC.REF <> PARCOPY.REF THEN ERROR (90); IF ARGDESC.OBJ = TAG THEN ERROR (101); IF NOT EQTYPS (PARCOPY,ARGDESC,FALSE) THEN ERROR (90) END END END; CHKNEXT (SYMAFTERARG) END END; { getarg } BEGIN { aparamlist } NXTSYMOK; IF SYM = LPAREN THEN BEGIN NXTSYMOK; IF LASTPARAM = NIL THEN ERROR (91) {Should have no args} ELSE BEGIN LASTP := LASTPARAM; WHILE LASTP^.OBJ = BOUNDID DO LASTP := LASTP^.LINK; LASTCA := NIL; LASTAP := NIL; GETARG (LASTP,RPAREN) END END ELSE BEGIN IF LASTPARAM <> NIL THEN ERROR (17) { Missing args } END END; { aparamlist } {$S'PasStmt'}