.TITLE CC103 .IDENT /X01/ .NLIST BEX .ENABL LC ; ; C COMPILER ; EXPRESSION TO TREE ; ; VERSION X01 ; ; DAVID G. CONROY 14-NOV-77 ; .GLOBL EXPR .GLOBL BUILD .GLOBL RCVN .GLOBL GTYPE .GLOBL CLRTRE .GLOBL TREESP .GLOBL OUTREE .GLOBL INITFG .MCALL CALL .MCALL CALLR .MCALL RETURN ; ; EQUIVALENCES ; PRIO = 000077 ;BITS IN THE OPDOPE VECTOR BINOP = 000100 ;BINARY OP RASSOC = 000200 ;RIGHT ASSOCIATIVE OP HLV = 000400 ;RESULT HAS LVALUE NLV = 001000 ;LVALUE REQUIRED ON LEFT LW = 002000 ;WORD REQUIRED ON LEFT RW = 004000 ;WORD REQUIRED ON RIGHT NF = 010000 ;NO FLOATS NP = 020000 ;NO POINTERS SSIZE = 20. ;SIZE OF THE EXPRESSION STACKS TSIZE = 500. ;SIZE OF THE TREE SPACE ; ; LOCAL DATA ; ONE: .WORD OP.CON ;A CONSTANT 1 TREE .BYTE 0,TY.INT ;CLASS AND TYPE .WORD 0 ;DIMP .WORD 0 ;STRUCTURE SIZE .WORD 1 ;CONSTANT VALUE FV: .WORD OP.REG ;STUFFED FOR RCVN CONVERSION .BYTE CL.REG ;CLASS FV1: .BLKB 1 ;STUFFED BY TYPE FV2: .BLKW 1 ;STUFFED BY DIMP FV3: .BLKW 1 ;STUFFED BY SIZE .WORD 0 ;OFFSET .WORD 0 ;REGISTER R0 INITFG: .WORD 0 ;INIT FLAG, ALWAYS FALSE TPTR: .WORD TREE ;POINTER TO NEXT FREE TREE BYTE OPXPCT: .BLKW 1 ;OPERATOR EXPECTED FLAG NPTR: .BLKW 1 ;OPERAND STACK POINTER OPTR: .BLKW 1 ;OPERATOR STACK POINTER PPTR: .BLKW 1 ;PRIORITY STACK POINTER NSTACK: .BLKW SSIZE ;THE EXPRESSION STACKS OSTACK: .BLKW SSIZE ; PSTACK: .BLKW SSIZE ; TREE: .BLKW TSIZE ;TREE SPACE ; ; ERRORS ; ERR01: .ASCIZ "Expression too complex" ERR02: .ASCIZ "Out of tree space" ERR03: .ASCIZ "Expression syntax" ERR04: .ASCIZ "Illegal structure/union operation" ERR05: .ASCIZ "Lvalue required" ERR06: .ASCIZ "Mismatched '?' and ':'" ERR07: .ASCIZ "Call of non function" ERR08: .ASCIZ "Illegal indirection" ERR09: .ASCIZ "Structure/union member required" ERR10: .ASCIZ "Type clash" .EVEN .PAGE ;+ ; ** EXPR - EXPRESSION TO TREE ; ; READ IN AN EXPRESSION AND BUILD A TREE IN THE TREE SPACE. IT'S THE ; CLASSICAL PRIORITY DRIVEN, BOTTOM UP APPROACH. MOST OF THE CODE WAS ; STOLEN FROM DMR. ; ; INPUTS: ; LEX0=THE FIRST TOKEN OF THE EXPRESSION ; ; OUTPUTS: ; R5=POINTER TO TREE ; LEX0=TOKEN THAT STOPPED THE SCAN ;- EXPR: MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) ; MOV R2,-(SP) ; MOV R3,-(SP) ; MOV R4,-(SP) ; MOV #NSTACK-2,NPTR ;INITIALIZE STACKS MOV #OSTACK,OPTR ; MOV #PSTACK,PPTR ; MOV #OP.EOF,@OPTR ; MOV #6,@PPTR ; CLR OPXPCT ;NOT EXPECTING OPERATOR MOV LEX0,R0 ;PICK UP TOKEN AND ... BR 20$ ; ... GO 10$: CALL SCAN ;RE ENTER TO GET NEXT TOKEN ; ; OPERANDS ; IDENTIFIERS ; CONSTANTS ; STRINGS ; 20$: CMP R0,#OP.ID ;IDENTIFIER BNE 25$ ;NO MOV VAL0,R5 ;PTR TO SYMBOL NODE TSTB S.CLAS(R5) ;UNDEFINED BNE 40$ ;NO CMP LEX1,#OP.LPA ;IS THE NEXT TOKEN A '(' BNE 30$ ;NO MOV #D.LENG,R0 ;YES, MAKE FUNCTION RETURNING INT CALL $ALLOC ; CLR D.LINK(R0) ; CLR D.BOUN(R0) ; MOV #DT.FUN,D.TYPE(R0) MOV R0,S.DIMP(R5) ;SET INTO DIM LIST OF THE SYMBOL BR 32$ ;FINISH IN COMMON CODE 25$: BR 50$ ;MAKE BRANCH REACH 30$: TST INITFG ;NOT FUNCTION, ARE WE DOING INITIALISERS BEQ 35$ ;NO 32$: MOVB #CL.GBR,S.CLAS(R5) ;DEFAULT TO GLOBAL REFERENCE MOVB #TY.INT,S.TYPE(R5) ;INT BIS #SF.PRM,S.FLAG(R5) ;AND NON DELETEBLE BR 40$ 35$: CALL UNDEF ;IT UNDEFINED, COMPLAIN MOVB #CL.AUT,S.CLAS(R5) MOVB #TY.INT,S.TYPE(R5) 40$: MOVB S.CLAS(R5),R0 ;GET THE CLASS OF THE NAME MOV S.ADDR(R5),R1 ;AND THE ADDRESS FROM THE NODE CMP R0,#CL.AUT ;AUTO BNE 42$ ;NO MOV #ES.REG,R2 ;BUILD CALL TREESP ;INDEX MOV #OP.INX,(R2) ;NODE MOV #5,E.REG(R2) ;OFF MOV R1,E.OFFS(R2) ;REGISTER R5 BR 47$ 42$: CMP R0,#CL.REG ;REGISTER BNE 43$ ;NO MOV #ES.REG,R2 ;BUILD REGISTER NODE CALL TREESP MOV #OP.REG,(R2) MOV R1,E.REG(R2) BR 47$ 43$: CMP R0,#CL.MOS ;MEMBER OF STRUCTURE BNE 45$ ;NO MOV R1,R0 ;YES, BUILD CONSTANT CALL BCONST BR 47$ 45$: CMP R0,#CL.SIN ;STATIC BNE 46$ ;NO MOV #ES.LID,R2 ;BUILD LOCAL ID NODE CALL TREESP MOV #OP.LID,(R2) MOV R1,E.LAB(R2) BR 47$ 46$: MOV #ES.ID,R2 ;BUILD ID NODE CALL TREESP MOV #OP.ID,(R2) MOV R5,R3 ADD #S.NAME,R3 MOV R2,R4 ADD #E.NAME,R4 460$: MOVB (R3)+,(R4)+ BNE 460$ 47$: MOVB S.CLAS(R5),E.CLAS(R2) ;COPY SYMBOL CLASS MOV S.DIMP(R5),E.DIMP(R2) ;AND DIMENSIONS MOVB S.TYPE(R5),R0 ;COPY THE TYPE INTO THE MOVB R0,E.TYPE(R2) ;TREE NODE CMP R0,#TY.STR ;AND IF THE TYPE IS STRUCT (OR UNION) BLO 70$ ;THEN MOV S.DOPE(R5),R0 ;SET THE STRUCTURE SIZE MOV S.SSIZ(R0),E.SSIZ(R2) ;FROM THE SYMBOL DOPE BR 70$ ;AND GO TO COMMON CODE 50$: CMP R0,#OP.CON ;CONSTANT BNE 52$ ;NO MOV #TY.INT,R0 ;SET TYPE BR 58$ ; 52$: CMP R0,#OP.LCN ;LONG CONSTANT BNE 54$ ;NO MOV #TY.LNG,R0 ;SET TYPE BR 58$ ; 54$: CMP R0,#OP.DCN ;DOUBLE CONSTANT BNE 60$ ;NO MOV #TY.DBL,R0 ;SET TYPE 58$: MOV #ES.CON,R2 ;GET A CONSTANT NODE CALL TREESP ; MOV #OP.CON,(R2) ;SET OPERATOR MOVB R0,E.TYPE(R2) ;SET TYPE MOV VAL0,E.VAL(R2) ;SET VALUE MOV VAL0+2,E.VAL+2(R2) MOV VAL0+4,E.VAL+4(R2) MOV VAL0+6,E.VAL+6(R2) BR 70$ ;GO PUSH IT 60$: CMP R0,#OP.CST ;C STRING? BNE 80$ ;NO CALL GETSTR ;GOBBLE UP THE STRING MOV #D.LENG,R2 ;MAKE A LOCAL ID, ARRAY+CHAR CALL TREESP ;MAKE DIM NODE IN THE TREE SPACE MOV #DT.ARY,D.TYPE(R2) ;TYPE IS ARRAY MOV R2,R5 ;THEN MOV #ES.LID,R2 ;GET THE LOCAL CALL TREESP ;ID NODE MOV #OP.LID,(R2) ;OP MOVB #TY.CHR,E.TYPE(R2) ;TYPE MOV R5,E.DIMP(R2) ;DIMP MOV R0,E.LAB(R2) ;LABEL OF THE STRING 70$: TST OPXPCT ;WAS AN OPERATOR EXPECTED? BNE 94$ ;YES, ERROR CALL BUMPN ;PUSH ONTO OPERAND STACK MOV R2,@NPTR INC OPXPCT ;SET OPERATOR EXPECTED JMP 10$ ; ; OPERATORS ; MODIFY CERTAIN OPERATORS TO THEIR UNARY MEANINGS ; SET '++' AND '--' TO PREFIX OR POSTFIX FORM, AS REQUIRED. ; 80$: CMP R0,#OP.INB ;PREFIX '++' OR '--' BEQ 82$ CMP R0,#OP.DEB BNE 90$ 82$: TST OPXPCT ;IF EXPECTING OPERATOR BEQ 150$ INC R0 ;CHANGE TO 'AFTER' FORM. BR 150$ 90$: CMP R0,#OP.NOT ;MAKE SURE '!' BEQ 92$ CMP R0,#OP.SIZ ;AND SIZEOF BEQ 92$ CMP R0,#OP.COM ;AND TILDE BNE 100$ 92$: TST OPXPCT ;ARE BEING USED IN UNARY SENSE BEQ 150$ 94$: JMP 270$ 100$: CMP R0,#OP.SUB ;'-', MAY BE NEGATION BNE 110$ TST OPXPCT BNE 102$ MOV #OP.NEG,R0 ;CHANGE TO UNARY FORM 102$: CLR OPXPCT ;IN ANY CASE, NEED OPERAND NOW BR 150$ 110$: CMP R0,#OP.AND ;CHANGE AND AND MUL TO ADR AND IND BEQ 112$ CMP R0,#OP.MUL BNE 120$ 112$: TST OPXPCT ;IF EXPECTING OPERAND BEQ 114$ CLR OPXPCT ;IF BINARY, NEED OPERAND NOW BR 150$ 114$: CMP R0,#OP.AND ;MAKE THE CHANGE BNE 116$ MOV #OP.ADR,R0 BR 150$ 116$: MOV #OP.IND,R0 BR 150$ 120$: CMP R0,#OP.LPA ;'(', MAKE BE FUNCTION CALL BNE 130$ TST OPXPCT BEQ 150$ CMP LEX1,#OP.RPA ;IS IT THE '()' OF A NO ARGS CALL? BNE 122$ ;NO CALL SCAN ;YES, SKIP OVER THE ')' MOV #OP.NAC,R0 ;MAKE OPERATOR A NO ARGS CALL BR 150$ 122$: MOV #OP.JSR,R0 ;MAKE OPERATOR NORMAL CALL CLR OPXPCT BR 150$ 130$: CMP R0,#OP.RSQ ;']' MUST BE AT CORRECT TIME BEQ 132$ CMP R0,#OP.RPA ;')' DITTO BNE 140$ 132$: TST OPXPCT BNE 150$ 134$: JMP 270$ 140$: TST OPXPCT ;ALL BINARIES BEQ 134$ ;ERROR IF NOT EXPECTING OPERATOR CLR OPXPCT ;NEED OPERAND NOW ; ; PUSH OPERATOR ONTO STACK ; POP LOWER PRIORITY OPERATORS INTO THE TREE ; 150$: MOV R0,R1 ;GET DOPE ASL R1 MOV OPDOPE(R1),R1 MOV R1,R2 ;AND PRIORITY BIC #^C,R2 CMP R0,#OP.CMA ;LOWER STRENGTH OF ',' IN BNE 160$ ;INITIALIZERS TST INITFG BEQ 160$ MOV #5,R2 160$: CMP R2,@PPTR ;COMPARE THIS OP TO STACK OP BHI 170$ ;HIGHER, PUSH BLO 200$ ;LOWER, POP STACK INTO TREE BIT #RASSOC,R1 ;EQUAL, POP IF LEFT ASSOCIATIVE BEQ 200$ 170$: CMP R0,#OP.INA ;ADJUST STRENGTHS BEFORE THE PUSH BEQ 172$ CMP R0,#OP.DEA BNE 174$ 172$: MOV #37,R2 BR 180$ 174$: CMP R0,#OP.LPA BEQ 176$ CMP R0,#OP.LSQ BEQ 176$ CMP R0,#OP.JSR BNE 180$ 176$: MOV #4,R2 180$: ADD #2,OPTR CMP OPTR,#OSTACK+<2*SSIZE> BHIS 185$ MOV R0,@OPTR ADD #2,PPTR MOV R2,@PPTR JMP 10$ 185$: MOV #ERR01,R0 ;EXPRESSION TOO COMPLEX CALL ERROR IOT ; ; POP OPERATOR OFF THE STACK AND INTO THE TREE. ; R0=INPUT OP ; R1=DOPE OF INPUT OP ; R2=PRIORITY OF INPUT OP ; MUST NOT ALTER ANY OF THESE ; 200$: SUB #2,PPTR ;SLUFF MOV @OPTR,R3 ;OP FROM TOP OF STACK SUB #2,OPTR CMP R3,#OP.EOF ;IF EOF BEQ 300$ ;YES, DONE CMP R3,#OP.CMA ;',' NOT IN AN ARGLIST IS SEQ. BNE 210$ CMP @OPTR,#OP.JSR BEQ 260$ MOV #OP.SEQ,R3 BR 260$ 210$: CMP R3,#OP.JSR ;CALL MUST BE POPPED BY ')' BNE 220$ CMP R0,#OP.RPA BNE 270$ CALL BUILD ;MAKE TREE NODE JMP 10$ 220$: CMP R3,#OP.NAC ;FAKE ARGLIST FOR NAC BNE 230$ CALL BUMPN CLR @NPTR MOV #OP.JSR,R3 BR 260$ 230$: CMP R3,#OP.INA ;CONSTANT 1 ROP FOR '++', '--' BEQ 232$ CMP R3,#OP.INB BEQ 232$ CMP R3,#OP.DEA BEQ 232$ CMP R3,#OP.DEB BNE 240$ 232$: CALL BUMPN MOV #ONE,@NPTR BR 260$ 240$: CMP R3,#OP.LPA ;CHECK FOR BALANCED PARENS. BNE 250$ ;AND DELETE BOTH CMP R0,#OP.RPA BNE 270$ JMP 10$ 250$: CMP R3,#OP.LSQ ;CHECK FOR BALANCED BRACKETS. BNE 260$ ;AND DELETE BOTH CMP R0,#OP.RSQ BNE 270$ CALL BUILD ;AFTER BUILDING THE TREE NODE JMP 10$ 260$: CALL BUILD ;MAKE THE NODE, AND JMP 160$ ;TRY TO POP AGAIN ; ; SYNTAX ERROR ; PRINT THE DIAGNOSTIC, THEN SKIP TO A DELIMITER. ; 270$: MOV #ERR03,R0 ;EXPRESSION SYNTAX CALL ERROR CLR R5 ;RETURN VALUE IS A NULL POINTER MOV LEX0,R0 280$: CMP R0,#OP.EOF ;STOP ON EOF BEQ 310$ CMP R0,#OP.SEM ;SEMICOLON BEQ 310$ CMP R0,#OP.LBR ;OPEN BRACE BEQ 310$ CMP R0,#OP.RBR ;CLOSE BRACE BEQ 310$ CALL ESCAN BR 280$ ; ; END OF EXPRESSION ; THE TREE IS ON THE TOP OF THE OPERAND STACK ; 300$: CALL BUILD ;FLUSH OUT CONVERSIONS MOV @NPTR,R5 ;GET TREE 310$: MOV (SP)+,R4 ;RETURN MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ;+ ; ** BUMPN - BUMP NSTACK POINTER (NPTR) ; ; THIS ROUTINE IS CALLED FROM ALL OVER BUILD AND EXPR TO SEE ; IF THERE IS ROOM ON THE OPERAND STACK, AND TO ADVANCE THE ; POINTER. IF THERE IS NO ROOM WE BLOW UP. ;- BUMPN: ADD #2,NPTR CMP NPTR,#NSTACK+<2*SSIZE> BLO 10$ MOV #ERR01,R0 CALL ERROR IOT 10$: RETURN .PAGE ;+ ; ** BUILD - BUILD TREE NODE ; ; THIS ROUTINE TAKES OPERANDS OFF THE TOP OF THE OPERAND STACK ; AND BUILD A TREE NODE. THE POINTER TO THE TREE NODE IS THEN ; RETURNED ON THE TOP OF THE OPERAND STACK. ; ; MOST OF THE WORK IS THE INSERTION OF THE NECESSARY CONVERSION ; OPERATORS AND MAKING SURE THE DIMS ARE SET UP PROPERLY. ; ; INPUTS: ; R3=OPERATOR ;- ROP = 6 ;RIGHT OPERAND RT = 4 ;RIGHT OPERAND TYPE LOP = 2 ;LEFT OPERAND LT = 0 ;LEFT OPERAND TYPE BUILD: MOV R5,-(SP) ;SAVE THE REGISTERS MOV R4,-(SP) MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) SUB #10,SP ;AND GET 4 WORDS OF LOCALS ; ; A[B] IS CONVERTED TO *(A+B) ; CMP R3,#OP.LSQ ;IS IT A SUBSCRIPTING OP BNE 10$ ;NO MOV #OP.ADD,R3 ;BUILD UP CALL BUILD ;A+B MOV #OP.IND,R3 ;THEN '*' THROUGH THE RESULT ; ; PERFORM THE REQUIRED TRANSFORMATIONS ON NAMES OF ARRAYS AND ; OF FUNCTIONS. ; 10$: MOV R3,R4 ;GET ASL R4 ;OFFSET AND MOV OPDOPE(R4),R4 ;GET THE DOPE CLR ROP(SP) ;SET DEFAULTS FOR THE CLR RT(SP) ;RIGHT SIDE BIT #BINOP,R4 ;BINARY OP BEQ 20$ ;NO MOV @NPTR,R2 ;YES, GET THE SUB #2,NPTR ;OPERAND TST R2 ;MAY BE NULL IN BEQ 20$ ;FUNCTION CALL CALL CHARY ;CHECK FOR ARRAYS CALL CHFUN ;AND FUNCTIONS MOV R2,ROP(SP) ;SAVE POINTER TO THE RIGHT SIDE CALL GTYPE ;AND MOV R0,RT(SP) ;THE TYPE OF THE RIGHT SIDE 20$: MOV @NPTR,R2 ;GET LEFT (OR ONLY) OPERAND SUB #2,NPTR ;BACK UP OPERAND STACK POINTER CMP R3,#OP.SIZ ;SIZEOF BNE 30$ ;NO CALL ELENG ;GET SIZE (TREE IN R2) CALL BCONST ;MAKE UP THE INTEGER CONSTANT 25$: JMP 400$ ;AND RETURN IT 30$: CMP R3,#OP.ADR ;IS THE OPERATOR '&' BEQ 40$ ;YES CALL CHARY ;NO, DO THE ARRAY GAME CMP R3,#OP.JSR ;AND IF THE OPERATOR IS NOT A CALL BEQ 40$ ;THEN CALL CHFUN ;PLAY THE FUNCTION GAME 40$: CMP R3,#OP.EOF ;ARE WE FLUSHING CONVERSIONS BEQ 25$ ;YES, FINISHED (YES, ITS BACKWARD) MOV R2,LOP(SP) ;SAVE LEFT OPERAND CALL GTYPE ;AND MOV R0,LT(SP) ;THE LEFT TYPE ; ; CHECK FOR OPERANDS INCOMPATABLE WITH OPERATORS. ; IF ANY FUNNYNESSES ARE FOUND, THE TYPES ARE CHANGED INTO ; HARMLESS INTEGERS. THIS PREVENTS MORE TYPE CLASH ERRORS ; FROM BEING GENERATED LATER ON (WHEN THE NODE IS BUILT). ; CMP R3,#OP.ADR ;'&' BEQ 60$ CMP R3,#OP.DOT ;'.' BEQ 60$ CMP R3,#OP.ARO ;'->' BEQ 60$ CMP LT(SP),#TY.STR ;CHECK IF LOP A STRUCTURE BEQ 50$ ;ERROR IF YES CMP RT(SP),#TY.STR ;CHECK IF ROP A STRUCTURE BNE 60$ ;BR IF NOT 50$: MOV #ERR04,R0 ;ILLEGAL STRUCTURE OP CALL ERROR 60$: BIT #NLV,R4 ;LVALUE REQUIRED ON LEFT BEQ 80$ ;NO MOV @LOP(SP),R0 ;GET LEFT SUBTREE OPERATOR CMP R3,#OP.ADR ;CANNOT BNE 65$ ;TAKE CMP R0,#OP.REG ;ADDRESS OF BEQ 70$ ;REGISTER 65$: ASL R0 ;OTHERWISE CHECK BIT #HLV,OPDOPE(R0) ;IF THE OPERATOR BNE 80$ ;HAS AN LVALUE RESULT 70$: MOV #ERR05,R0 ;LVALUE REQUIRED CALL ERROR 80$: MOV LT(SP),R0 ;GET THE TYPES MOV RT(SP),R1 ;OF THE OPERANDS BIT #LW,R4 ;WORD OPERAND REQUIRED ON LEFT BEQ 90$ ;NO CMP R0,#TY.LNG ;ERROR IF LONG, FLOAT, DOUBLE BHIS 120$ 90$: BIT #RW,R4 ;WORD OPERAND REQUIRED ON RIGHT BEQ 100$ ;NO CMP R1,#TY.LNG ;ERROR IF LONG, FLOAT, DOUBLE BHIS 120$ 100$: BIT #NF,R4 ;NON FLOAT REQUIRED ON BOTH BEQ 110$ ;NO CMP R0,#TY.FLT ;ERROR IF LEFT BHIS 120$ ;IS FLOAT OR DOUBLE CMP R1,#TY.FLT ;ERROR IF RIGHT BHIS 120$ ;IS FLOAT OR DOUBLE 110$: BIT #NP,R4 ;NON POINTER REQUIRED ON BOTH BEQ 130$ ;NO CMP R0,#TY.PTR ;ERROR IF LEFT BEQ 120$ ;IS POINTER CMP R1,#TY.PTR ;ERROR IF RIGHT BNE 130$ ;IS POINTER 120$: CALL CLASH ;TYPE CLASH MOV #TY.INT,LT(SP) ;CHANGE BOTH TYPES TO MOV #TY.INT,RT(SP) ;HARMLESS INTEGERS ; ; BEGIN CONSTRUCTION OF THE TREE NODE ; R3=OP R4=LEFT R5=RIGHT ; 130$: MOV LOP(SP),R4 ;SET UP REGISTERS MOV ROP(SP),R5 ;IN STANDARD WAY CMP R3,#OP.QRY ;QUESTION BNE 140$ ;NO CMP (R5),#OP.CLN ;THE QUESTION MUST MATCH WITH A COLON BEQ 142$ ;OR MOV #ERR06,R0 ;ILLEGAL CONDITIONAL CALL ERROR BR 142$ 140$: CMP R3,#OP.SEQ ;SEQUENTIAL EXECUTION BNE 150$ ;NO 142$: MOV RT(SP),R0 ;GETS TYPE AND DIMS MOV E.DIMP(R5),R1 ;FROM ROP BR 178$ ;AND GO BUILD NODE 150$: CMP R3,#OP.CMA ;COMMA IN ARGLIST BNE 160$ ;NO CLR R0 ;IS UNDEFINED CLR R1 ;IN BOTH TYPE AND DIMS BR 178$ ;GO BUILD NODE 160$: CMP R3,#OP.AA ;LOGICAL AND BEQ 162$ CMP R3,#OP.OO ;LOGICAL OR BEQ 162$ CMP R3,#OP.NOT ;LOGICAL NOT BNE 170$ 162$: MOV #TY.INT,R0 ;RETURN SCALAR INT CLR R1 ;FOR ALL OPERANDS BR 178$ ;GO BUILD NODE ; ; CALL ; FIDDLE THE DIMS TO REMOVE THE FUNCTION NODE. ; CHECK TYPE FOR CHARS AND FLOATS AND ADJUST TO CORRESPOND ; WITH REALITY. ; 170$: CMP R3,#OP.JSR ;CALL BNE 180$ ;NO MOV E.DIMP(R4),R1 ;TEST FOR CALL OF NON FUNCTION BEQ 172$ ;CANNOT CALL A SCALAR CMP D.TYPE(R1),#DT.FUN ;OR BNE 172$ ;A POINTER OR ARRAY MOV (R1),R1 ;RESULT DIMS IS DECREF(DIMS) BR 174$ 172$: MOV #ERR07,R0 ;CALL OF NON FUNCTION CALL ERROR 174$: MOVB E.TYPE(R4),R0 ;GET RESULT TYPE TST R1 ;IS THE RESULT A SCALAR BNE 178$ ;NO CMP R0,#TY.CHR ;FUNCTIONS NEVER RETURN CHAR BNE 176$ MOV #TY.INT,R0 BR 178$ 176$: CMP R0,#TY.FLT ;OR FLOAT BNE 178$ MOV #TY.DBL,R0 178$: JMP 300$ ; ; INDIRECTION ; CHANGE 'POINTER TO X' TO PLAIN 'X' IN THE DIM ; 180$: CMP R3,#OP.IND ;INDIRECTION BNE 190$ ;NO ; CMP (R4),#OP.ADR ;DELETE ; BNE 182$ ;'*' ; MOV E.LOP(R4),R2 ;OF ; JMP 400$ ;'&' 182$: MOV E.DIMP(R4),R1 ;CHECK FOR ILLEGAL INDIRECTION BEQ 184$ ;CANNOT INDIRECT THROUGH A SCALAR CMP D.TYPE(R1),#DT.FUN ;OR BEQ 184$ ;A FUNCTION MOV (R1),R1 ;DECREF BR 194$ ;DIMENSIONS 184$: MOV #ERR08,R0 ;ILLEGAL INDIRECTION CALL ERROR BR 194$ ; ; ADDRESS ; CHANGE PLAIN 'X' TO 'POINTER TO X' ; 190$: CMP R3,#OP.ADR ;ADDRESS BNE 200$ ;NO ; CMP (R4),#OP.IND ;DELETE ; BNE 192$ ;'&' ; MOV E.LOP(R4),R2 ;OF ; JMP 400$ ;'*' 192$: CALL MPTR ;MAKE A POINTER NODE MOV E.DIMP(R4),(R2) ;MAKE X INTO POINTER TO X MOV R2,R1 ;THIS IS THE NEW DIMP 194$: JMP 290$ ;GO PICK UP TYPE AND BUILD NODE ; ; STRUCTURE OPS ; A.B GETS TRANSFORMED INTO &A->B ; A->B IS DONE AS *(A+CONST OFFSET OF B), WHERE THE ADDITION IS ; DONE WITHOUT CONVERSIONS ; SETYPE IS USED TO FIDDLE ALL OF THE TYPES DOWN THE LEFT ; SUBTREE. ; THE TYPE OF THE RIGHT SUBTREE (THE CONSTANT) IS FORCED ; TO INT. ; 200$: CMP R3,#OP.DOT ;STRUCTURE DOT BNE 210$ ;NO CALL BUMPN ;GET THE ADDRESS OF THE LOP MOV R4,@NPTR ;BY USING BUILD MOV #OP.ADR,R3 ;THEN CALL BUILD ;PRETEND ITS AN MOV @NPTR,R4 ;'->' SUB #2,NPTR ;OPERATOR BR 211$ 210$: CMP R3,#OP.ARO ;STRUCTURE POINTER ARROW BNE 220$ ;NO 211$: CMPB E.CLAS(R5),#CL.MOS ;THE BEQ 213$ ;CLASS MOV #ERR09,R0 ;MUST BE CALL ERROR ;MEMBER OF STRUCTURE 213$: CALL MPTR ;MAKE A POINTER DIM ENTRY MOV E.DIMP(R5),(R2) ;ADD TO FRONT OF THE DIMS MOV R2,-(SP) ;SAVE IT AWHILE MOV #ES.OP,R2 ;BUILD A '+' NODE CALL TREESP MOV #OP.ADD,(R2) ;ADDING IN THE OFFSET MOVB E.TYPE(R5),E.TYPE(R2) ;THE RESULT IS POINTER TO ROP MOV E.SSIZ(R5),E.SSIZ(R2) ;WITH THE SAME STRUCTURE ATTRIBUTES MOV (SP)+,E.DIMP(R2) ;AS MOV R4,E.LOP(R2) ;THE ROP MOV R5,E.ROP(R2) ;THIS IS THE CONSTANT NODE MOVB #TY.INT,E.TYPE(R5) ;FORCE THE CONSTANT TO CLR E.DIMP(R5) ;SCALAR INT CLR E.SSIZ(R5) ;(SSIZ COULD PROBABLY BE LEFT) CALL BUMPN ;THEN '*' THROUGH IT MOV R2,@NPTR ;THIS LEAVES THE RESULT ON THE TOP MOV #OP.IND,R3 ;OF THE CALL BUILD ;OPERAND STACK CALL SETYPE ;FORCE THE TYPE AND DIMP JMP 410$ ;TO AGREE ; ; COMMON PROCESSING FOR OTHER OPS ; TYPE CONVERSIONS ARE REQUIRED ; 220$: CMP R3,#OP.LT ;USE UNSIGNED RELATIONS BLO 224$ ;IF CMP R3,#OP.GT ;NECESSARY BHI 224$ MOV LT(SP),R0 ;REQUIRED FOR POINTERS AND UNSIGNEDS CMP R0,#TY.PTR BEQ 222$ CMP R0,#TY.UNS BEQ 222$ MOV RT(SP),R0 CMP R0,#TY.PTR BEQ 222$ CMP R0,#TY.UNS BNE 224$ 222$: ADD #OP.LTU-OP.LT,R3 224$: TST RT(SP) ;IF THE RIGHT TYPE IS UNDEFINED BNE 225$ ;AS IT IS FOR UNARY OPS MOV LT(SP),RT(SP) ;MAKE SURE CONVERSIONS WORK 225$: MOV LT(SP),R1 ;GET ENTRY FROM CONVERSION TABLE SUB #TY.CHR,R1 MOV #7,-(SP) ;7 WORDS PER ROW CALL $MULR1 ; TST (SP)+ ; ADD RT(SP),R1 SUB #TY.CHR,R1 MOV CVTAB(R1),R1 ;GET ENTRY FROM CONVERSION TABLE BNE 226$ ;LEGAL COMBINATION CALL CLASH ;IF 0, ITS A TYPE CLASH MOV #TY.INT,R1 ;FORCE TO INTEGER RESULT 226$: CMP R3,#OP.ASG ;NO CONVERSIONS APPLY TO BEQ 227$ ;WORD ASSIGNMENTS CMP R3,#OP.EQ ;OR BLO 228$ ;WORD CMP R3,#OP.GTU ;RELATIONAL BHI 228$ ;OPS 227$: MOV LT(SP),R0 SUB #TY.INT,R0 CMP R0,#TY.LNG-TY.INT BHIS 228$ MOV RT(SP),R0 SUB #TY.INT,R0 CMP R0,#TY.LNG-TY.INT BLO 240$ 228$: BIT #R,R1 ;APPLY CONVERSIONS TO RIGHT BEQ 230$ ;BR IF N/A MOV ROP(SP),R4 ;TREE BEQ 230$ ;NO TREE, MUST BE UNARY MOV LOP(SP),R5 ;OTHER TREE CALL CVR ;PERFORM CONVERSION TO REGISTER MOV R2,ROP(SP) ;REPLACE TREE 230$: MOV LOP(SP),R4 ;SET UP TO CONVERT LEFT MOV ROP(SP),R5 ;OTHER TREE CMP R3,#OP.ASG ;IS THIS AN ASSIGNMENT OP BEQ 232$ ;YES CMP R3,#OP.ADA ;MAYBE BLO 234$ ;NO CMP R3,#OP.XRA ;MAYBE BHI 234$ ;NO 232$: BIT #LA,R1 ;CONVERT LEFT/ASSIGNMENT BEQ 240$ ;NO CALL CVM ;YES, ADD OP.CVM BR 236$ 234$: BIT #L,R1 ;NOT ASSIGNMENT, DO WE CONVERT BEQ 240$ ;NO CALL CVR ;ADD OP.CVR 236$: MOV R2,LOP(SP) ;SAVE NEW LEFT TREE 240$: BIC #^C,R1 ;GET THE GOAL TYPE CMP R3,#OP.EQ ;IF THE OPERATOR IS A RELATIONAL BLO 241$ ;THEN CMP R3,#OP.GTU ;THE GOAL IS BHI 241$ ;ALWAYS MOV #TY.INT,R1 ;INTEGER 241$: MOV #ES.OP,R2 ;ALLOCATE A CALL TREESP ;TREE NODE MOV LOP(SP),R4 ;GET LEFT AND MOV ROP(SP),R5 ;RIGHT SUBTREES CMP R1,#TY.PTR ;IS THE RESULT A POINTER BNE 243$ ;NO MOV R4,R0 ;ASSUME THE LEFT IS THE POINTER CMP LT(SP),#TY.PTR ;CORRECT ASSUMPTION BEQ 242$ ;YES MOV R5,R0 ;NO, GET RIGHT TREE 242$: MOVB E.TYPE(R0),R1 ;GET TYPE INTO R1 MOV E.DIMP(R0),E.DIMP(R2) ;SETUP THE DIMS AND MOV E.SSIZ(R0),E.SSIZ(R2) ;THE SSTRUCTURE SIZE 243$: MOV R3,(R2) ;SET OP MOVB R1,E.TYPE(R2) ;SET RESULT TYPE MOV R4,E.LOP(R2) ;LEFT SUBTREE MOV R5,E.ROP(R2) ;RIGHT SUBTREE ; ; SOME FINAL CHECKS ; PTR+PTR IS ILLEGAL ; THE ROP OF AN '=-' OR '=+' CANNOT BE PTR ; ADD OP.CVR/PTR TO INTEGER FOR PTR-PTR ; CMP LT(SP),#TY.PTR ;TEST IF BOTH BNE 244$ CMP RT(SP),#TY.PTR ;ARE POINTERS BNE 244$ CMP R3,#OP.ADD ;CANNOT ADD TWO POINTERS BEQ 250$ CMP R3,#OP.SUB ;IS THIS PTR-PTR BNE 244$ ;NO MOV R2,R4 ;SAVE TREE MOV LOP(SP),R2 ;SEE IF THE POINTERS CALL PLENG MOV ROP(SP),R2 ;HAVE THE SAME LENGTH MOV R0,-(SP) ;SAVE LENGTH OF LOP CALL PLENG MOV R4,R2 ;THIS GETS THE TREE BACK CMP R0,(SP)+ BNE 250$ ;ERROR OF NOT MOV LOP(SP),R5 ;OTHER TREE MOV #TY.INT,R1 ;GOAL TYPE CALL CVR ;PERFORM PTOI CONVERSION BR 400$ 244$: CMP R1,#TY.PTR ;IS THE RESULT OF THE NODE POINTER BNE 400$ ;NO CMP R3,#OP.ADA ;'=+' BEQ 246$ CMP R3,#OP.SBA ;'=-' BNE 400$ 246$: CMP RT(SP),#TY.PTR ;CANNOT HAVE POINTER ON RIGHT BNE 400$ 250$: CALL CLASH ;TYPE CLASH BR 400$ ; ; COMMON RETURNS ; 290$: MOVB E.TYPE(R4),R0 ;GET TYPE OF LEFT BEFORE CALLING THE 300$: MOV #ES.OP,R2 ;GENERAL NODE BUILDER CALL TREESP MOVB R0,E.TYPE(R2) ;TYPE IN R0 MOV R1,E.DIMP(R2) ;DIMP IN R1 MOV R3,(R2) ;OP IN R3 MOV R4,E.LOP(R2) ;LEFT OP IN R4 MOV R5,E.ROP(R2) ;RIGHT OP IN R5 MOV E.SSIZ(R4),E.SSIZ(R2) ;COPY STRUCTURE SIZE FOR '&' 400$: CALL BUMPN ;PUSH R2 ONTO THE OPERAND STACK MOV R2,@NPTR 410$: ADD #10,SP ;RETURN MOV (SP)+,R0 MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 MOV (SP)+,R5 RETURN ;+ ; ** CVR - INSERT AN OP.CVR NODE ; ** CVM - INSERT AN OP.CVM NODE ; ; INPUTS: ; R1=GOAL TYPE (MASKED BY GOAL) ; R4=TREE ; R5=THE OTHER TREE ; ; OUTPUTS: ; R2=CONVERTED TREE ; ; USES: ; R0 ;- .ENABL LSB CVR: MOV #OP.CVR,-(SP) ;SAVE OP BR 10$ CVM: MOV #OP.CVM,-(SP) ;SAVE OP 10$: CLR R0 ;DEFAULT TO NULL POINTER MOV R5,R2 ;PICK UP OTHER TREE BEQ 20$ ;NULL, CONVERTING UNARY OP CALL PLENG ;THE LENGTH OF THE POINTER CALL BCONST MOV R2,R0 20$: MOV #ES.OP,R2 ;ALLOCATE A CALL TREESP ;TREE NODE MOV (SP)+,(R2) ;OP MOV R4,E.LOP(R2) ;TREE WE ARE CONVERTING MOV R0,E.ROP(R2) ;OTHER SIZE MOV E.SSIZ(R5),E.SSIZ(R2) ;STRUCTURE SIZE MOV R1,R0 ;MASK OFF THE BIC #^C,R0 ;GOAL TYPE AND MOVB R0,E.TYPE(R2) ;SAVE IT IN THE NODE RETURN ;RETURN .DSABL LSB ;+ ; ** CLASH - REPORT TYPE CLASH ; ; USES: ; R0 ;- CLASH: MOV #ERR10,R0 ;TYPE CLASH CALLR ERROR ;+ ; ** MPTR - MAKE A POINTER DIM ENTRY IN TREE SPACE ; ; OUTPUTS: ; R2=POINTER TO DIM ENTRY ;- MPTR: MOV #D.LENG,R2 ;ALLOCATE CALL TREESP ;DIM NODE MOV #DT.PTR,D.TYPE(R2) ;SET TYPE TO POINTER AND RETURN ;RETURN ;+ ; ** GTYPE - GET THE TYPE OF A TREE ; ; GIVEN A TREE, RETURN A TYPE THAT CAN BE USED TO INDEX INTO THE ; CONVERSION TABLES. ALL POINTERS RETURN A COMMON TYPE OF TY.PTR ; ALL STRUCTURES AND UNIONS LOOK LIKE STRUCTURES. ; ; INPUTS: ; R2=TREE ; ; OUTPUTS: ; R0=TYPE ;- GTYPE: MOV #TY.PTR,R0 ;IF THERE ARE ANY DIMS CALL TST E.DIMP(R2) ;IT POINTER BNE 10$ MOVB E.TYPE(R2),R0 ;OTHERWISE GET THE TYPE FROM THE CMP R0,#TY.UST ;NODE BLO 10$ MOV #TY.STR,R0 ;ALL STRUCTS 10$: RETURN ;+ ; ** CHFUN - CHECK FOR FUNCTIONS (AND ADD AN AMPERSAND) ; ** CHARY - CHECK FOR ARRAYS (AND ADD AN AMPERSAND) ; ; INPUTS: ; R2=TREE ; ; OUTPUTS: ; R2=TREE ; ; USES: ; R0 ;- .ENABL LSB CHFUN: MOV E.DIMP(R2),R0 ;GET DIMS OF THE TREE BEQ 20$ ;SCALAR CMP D.TYPE(R0),#DT.FUN ;IS IT A FUNCTION BNE 20$ ;BR IF NOT BR 10$ ;GO ADD AMPERSAND IF YES CHARY: CMPB E.CLAS(R2),#CL.MOS ;DON'T DO THIS IF THE BEQ 20$ ;CLASS IS MOS (P->ARRAY) MOV E.DIMP(R2),R0 ;GET DIMS OF THE TREE BEQ 20$ ;SCALAR CMP D.TYPE(R0),#DT.ARY ;IS IT AN ARRAY BNE 20$ ;NO MOV (R0),E.DIMP(R2) ;YES, REMOVE THE ARRAY DIM 10$: MOV R3,-(SP) ;SAVE R3 CALL BUMPN ;PUSH THE TREE ONTO MOV R2,@NPTR ;THE OPERAND STACK MOV #OP.ADR,R3 ;ADD CALL BUILD ;AMPERSAND CALL SETYPE ;MAKE TYPE AND DIMP RIGHT MOV @NPTR,R2 ;GET THE SUB #2,NPTR ;TREE BACK MOV (SP)+,R3 ;RESTORE R3 20$: RETURN .DSABL LSB ;+ ; ** SETYPE - SET TYPE AND DIMP ; ; THIS ROUTINE ADJUSTS THE TYPE AND DIMP OF A TREE TO AGGREE WITH ; THE VIEWPOINT OF THE TOP OF THE TREE. ; ; INPUTS: ; THE TREE IS ON THE TOP OF THE OPERAND STACK ; ; USES: ; NONE ;- SETYPE: MOV R5,-(SP) ;SAVE MOV R4,-(SP) ;REGISTERS MOV R3,-(SP) ; MOV R2,-(SP) ; MOV @NPTR,R5 ;GET THE TREE MOVB E.TYPE(R5),R4 ;ITS TYPE MOV E.SSIZ(R5),R3 ;ITS STRUCTURE SIZE MOV E.DIMP(R5),R2 ;ITS DIMS 10$: CMP (R5),#OP.IND ;IS THE TOP OF THE TREE A '*' BNE 20$ ;NO MOV R2,-(SP) ;THE DIMS BELOW IT CALL MPTR ;MUST HAVE BEEN MOV (SP)+,(R2) ;POINTER TO BR 40$ ; 20$: CMP (R5),#OP.ADR ;IS THE TOP OF THE TREE A '&' BNE 30$ ;NO MOV (R2),R2 ;REMOVE THE PTR DIM BR 40$ ; 30$: CMP (R5),#OP.ADD ;IS THE TOP OF THE TREE A '+' BNE 50$ ;NO, RETURN 40$: MOV E.LOP(R5),R5 ;FOLLOW DOWN THE LEFT TREE MOV R2,E.DIMP(R5) ;RESET DIMS MOV R3,E.SSIZ(R5) ;STRUCTURE SIZE MOVB R4,E.TYPE(R5) ;AND TYPE BR 10$ ;CONTINUE 50$: MOV (SP)+,R2 ;RETURN MOV (SP)+,R3 ; MOV (SP)+,R4 ; MOV (SP)+,R5 ; RETURN ;FINIS ;+ ; ** ELENG - GET SIZE OF AN EXPRESSION TREE ; ; INPUTS: ; R2=TREE ; ; OUTPUTS: ; R0=SIZE ;- ELENG: MOV R2,-(SP) ;SAVE REGISTERS MOV R1,-(SP) MOV #1,R1 ;START OFF AS A SCALAR MOV E.DIMP(R2),R0 ;GET POINTER TO DIMS BEQ 30$ ;IT IS A SCALAR 10$: CMP D.TYPE(R0),#DT.ARY ;AS LONG AS WE FIND ARRAYS BNE 20$ ;JUST MOV D.BOUN(R0),-(SP);MULTIPLY THE BOUNDS CALL $MULR1 ; TST (SP)+ ; MOV (R0),R0 ;TOGETHER BNE 10$ BR 30$ 20$: CLR R0 ;FUNCTIONS HAVE CMP D.TYPE(R0),#DT.FUN ;ZERO LENGTH BEQ 40$ ;BR IF FUNCTION MOV #2,R0 ;MUST BE A POINTER BR 40$ ;WHICH IS 2 BYTES LONG 30$: TST R1 ;IF 0 LENGTH ARRAY ([]) BEQ 45$ ;YOU KNOW THE SIZE MOVB E.TYPE(R2),R0 ;GET THE BASIC TYPE CMP R0,#TY.STR ;IF STRUCT (OR UNION) BLO 35$ ; MOV E.SSIZ(R2),R2 ;GET STRUCTURE SIZE 35$: CALL BASIZE ;GET BASIC SIZE OF THE ITEM 40$: MOV R0,-(SP) ;COMPUTE SIZE IN BYTES CALL $MULR1 ; TST (SP)+ ; 45$: MOV R1,R0 ;RETURN SIZE IN R0 MOV (SP)+,R1 ;RETURN MOV (SP)+,R2 ; RETURN ; ;+ ; ** PLENG - POINTER SIZE ; ; IF THE TREE IS A POINTER RETURN THE SIZE OF THE ITEM TO WHICH ; THE POINTER POINTS. IF IT IS NOT A POINTER RETURN 1. ; ; INPUTS: ; R2=TREE ; ; OUTPUTS: ; R0=SIZE ;- PLENG: MOV E.DIMP(R2),R0 ;CHECK FOR POINTERS BEQ 10$ CMP D.TYPE(R0),#DT.PTR BNE 10$ MOV R0,-(SP) ;SAVE OLD DIM MOV (R0),E.DIMP(R2) ;REMOVE 1 LEVEL OF POINTERS CALL ELENG ;COMPUTE THE SIZE AND MOV (SP)+,E.DIMP(R2);PUT THE DIMS BACK BR 20$ 10$: MOV #1,R0 ;NOT A REFERENCE 20$: RETURN ;+ ; ** BCONST - BUILD CONSTANT NODE ; ; INPUTS: ; R0=VALUE OF THE CONSTANT ; ; OUTPUTS: ; R2=NODE POINTER ;- BCONST: MOV #ES.CON,R2 ;GET TREE SPACE CALL TREESP MOV #OP.CON,(R2) ;SET OP MOVB #TY.INT,E.TYPE(R2) ;SET THE TYPE MOV R0,E.VAL(R2) ;SET THE CONSTANT VALUE RETURN ;+ ; ** RCVN - RETURN STATEMENT TYPE CONVERSIONS ; ; THIS ROUTINE CONVERTS THE RESULT OF A TREE SO THAT IT MATCHES ; THE TYPE OF THE FUNCTION WE ARE RETURNING FROM. IT DOES THIS ; BY FAKING AN ASSIGNMENT TO A BUILT ON THE FLY REGISTER, AND ; THROWING THE ASSIGNMENT AWAY. ; ; INPUTS: ; R5=TREE ; ; OUTPUTS: ; R5=TREE ; ; USES: ; R0, R1, R3 ;- RCVN: MOV FSYMBL,R0 ;GET POINTER TO FUNCTION NAME CLR FV3 ;E.SSIZ = 0 MOV S.DIMP(R0),R1 ;SET DIMS FROM THE SYMBOL MOV (R1),FV2 ;THE FIRST WILL BE 'FUNCTION' MOVB S.TYPE(R0),R1 ;SET TYPE FROM MOVB R1,FV1 ;THE SYMBOL CMP R1,#TY.STR ;IF THE SYMBOL IS A STRUCTURE (OR UNION) BLO 10$ ;THEN MOV S.DOPE(R0),R1 ;SET THE MOV S.SSIZ(R1),FV3 ;STRUCTURE SIZE 10$: CALL BUMPN ;PUSH THE LEFT OP MOV #FV,@NPTR ;OF THE FAKE ASSIGNMENT CALL BUMPN ;PUSH THE RIGHT OP MOV R5,@NPTR ;OF THE FAKE ASSIGNMENT MOV #OP.ASG,R3 ;BUILD THE CALL BUILD ;ASSIGNMENT THEN MOV @NPTR,R5 ;RECOVER THE SUB #2,NPTR ;RESULT AND MOV E.ROP(R5),R5 ;DISCARD THE ASSIGNMENT OP RETURN ;DONE ;+ ; ** CLRTRE - CLEAR TREE SPACE ; ** TREESP - ALLOCATE TREE SPACE ; ; INPUTS: ; R2=SIZE REQUIRED (BYTES; TREESP) ; ; OUTPUTS: ; R2=POINTER TO THE SPACE (TREESP) ; TREE SPACE ALLOCATED IS ZEROED ;- CLRTRE: MOV #TREE,TPTR ;WIND BACK POINTER RETURN TREESP: MOV R5,-(SP) ;SAVE REGISTERS MOV R2,R5 ;GET WORKING SIZE INC R5 BIC #1,R5 MOV TPTR,R2 ;DOES IT FIT? ADD R5,R2 CMP R2,#TREE+<2*TSIZE> BHI 30$ ;NO MOV TPTR,R2 ;GET POINTER TO THE SPACE ADD TPTR,R5 ;GET NEW END OF TREE SPACE MOV R5,TPTR ;UPDATE TREE SPACE POINTERS 10$: CMP R5,R2 ;CLEAR NEW SPACE BLOS 20$ CLR -(R5) BR 10$ 20$: MOV (SP)+,R5 RETURN 30$: MOV #ERR02,R0 ;OUT OF TREE SPACE CALL ERROR IOT ;+ ; ** OUTREE - PUT OUT TREE ; ; CAVEAT: OUTREE IGNORES THE E.OFFS FIELD OF OP.LID AND OP.ID NODES ; THIS FIELD IS ALWAYS 0 NOW; IF THIS EVER CHANGES REMEMBER TO FIX ; THIS ROUTINE. ; ; INPUTS: ; R5=TREE POINTER ;- OUTREE: MOV R2,-(SP) ;SAVE R2 MOV R5,-(SP) ;SAVE TREE POINTER MOVB #'Z,R0 ;PUT OUT THE RECORD HEADER CALL CODC CALL 70$ TST R5 ;IF THE TREE IS NULL PUT OUT EOF BNE 5$ MOV #OP.EOF,R0 BR 40$ 5$: MOV (R5),R0 ;PUT OUT THE OPERATOR CALL CODNUM CALL 70$ MOV R5,R2 ;TYPE CALL GTYPE CALL CODNUM CALL 70$ MOV (R5),R0 ;OPCODE CMP R0,#OP.CON ;CONSTANT BNE 10$ ;NO MOV E.VAL(R5),R0 ;PUT OUT ALL 4 WORDS CALL CODNUM ; CALL 70$ ; MOV E.VAL+2(R5),R0 ; CALL CODNUM ; CALL 70$ ; MOV E.VAL+4(R5),R0 ; CALL CODNUM ; CALL 70$ ; MOV E.VAL+6(R5),R0 ; BR 40$ ; 10$: CMP R0,#OP.REG ;REGISTER BNE 15$ MOV E.REG(R5),R0 BR 40$ 15$: CMP R0,#OP.INX ;INDEX (FOR AUTOS) BNE 20$ MOV E.REG(R5),R0 CALL CODNUM CALL 70$ MOV E.OFFS(R5),R0 BR 40$ 20$: CMP R0,#OP.ID ;IDENTIFIER BNE 25$ MOV R5,R0 ADD #E.NAME,R0 CALL CODSTR BR 50$ 25$: CMP R0,#OP.LID ;LOCAL IDENTIFIER BNE 30$ MOV E.LAB(R5),R0 BR 40$ 30$: CALL CODNL ;OPERATOR MOV E.LOP(R5),R5 ;LEFT SUBTREE CALL OUTREE MOV (SP),R5 ;RIGHT SUBTREE MOV E.ROP(R5),R5 CALL OUTREE BR 60$ 40$: CALL CODNUM 50$: CALL CODNL 60$: MOV (SP)+,R5 MOV (SP)+,R2 RETURN 70$: MOVB #' ,R0 CALLR CODC .PAGE ;+ ; OPERATOR DOPE TABLE ; INDEXED BY OPERATOR NUMBER (*2) ; ; 000077 PRIORITY OF THE OPERATOR ; 000100 BINARY ; 000200 RIGHT ASSOCIATIVE ; 000400 HAS LVALUE ; 001000 NEEDS LVALUE ON LEFT ; 002000 NEEDS WORD OPERAND ON LEFT ; 004000 NEEDS WORD OPERAND ON RIGHT ; 010000 NEEDS NON FLOATING OPERAND ON BOTH SIDES ; 020000 NEEDS NON POINTER OPERAND ON BOTH SIDES ;- OPDOPE: .WORD 000000 ;OP.EOF .WORD 000000 ;OP.CON .WORD 000400 ;OP.ID .WORD 000400 ;OP.LID .WORD 000000 ;OP.LCN .WORD 000000 ;OP.DCN .WORD 000400 ;OP.REG .WORD 000400 ;OP.INX .WORD 000400 ;OP.AUI .WORD 000400 ;OP.AUD .WORD 000130 ;OP.ADD .WORD 000130 ;OP.SUB .WORD 020132 ;OP.MUL .WORD 020132 ;OP.DIV .WORD 030132 ;OP.MOD .WORD 030126 ;OP.ASL .WORD 030126 ;OP.ASR .WORD 030120 ;OP.AND .WORD 030117 ;OP.OR .WORD 030117 ;OP.XOR .WORD 001312 ;OP.ADA .WORD 001312 ;OP.SBA .WORD 021312 ;OP.MUA .WORD 021312 ;OP.DVA .WORD 031312 ;OP.MOA .WORD 031312 ;OP.ALA .WORD 031312 ;OP.ARA .WORD 031312 ;OP.ANA .WORD 031312 ;OP.ORA .WORD 031312 ;OP.XRA .WORD 000122 ;OP.EQ .WORD 000122 ;OP.NE .WORD 000124 ;OP.LT .WORD 000124 ;OP.LE .WORD 000124 ;OP.GE .WORD 000124 ;OP.GT .WORD 000124 ;OP.LT UNSIGNED .WORD 000124 ;OP.LE UNSIGNED .WORD 000124 ;OP.GE UNSIGNED .WORD 000124 ;OP.GT UNSIGNED .WORD 006116 ;OP.ANDAND .WORD 006115 ;OP.OROR .WORD 011334 ;OP.INB .WORD 011334 ;OP.INA .WORD 011334 ;OP.DEB .WORD 011334 ;OP.DEA .WORD 001312 ;OP.ASG .WORD 001234 ;OP.ADR .WORD 000634 ;OP.IND .WORD 020234 ;OP.NEG .WORD 030234 ;OP.COM .WORD 002234 ;OP.NOT .WORD 002314 ;OP.QRY .WORD 000314 ;OP.CLN .WORD 000307 ;OP.CMA .WORD 000107 ;OP.SEQ .WORD 000000 ;OP.BIC .WORD 000000 ;OP.BCA .WORD 000000 ;OP.BIT .WORD 000136 ;OP.JSR .WORD 000000 ;OP.CVR .WORD 000000 ;OP.CVM .WORD 000000 ;OP.FSR .WORD 000000 ;OP.FSM .WORD 000000 ;OP.LOD .WORD 000000 ;OP.CST .WORD 000136 ;OP.NAC .WORD 000000 ;OP.SEM .WORD 001136 ;OP.DOT .WORD 002136 ;OP.ARO .WORD 000036 ;OP.LPA .WORD 000002 ;OP.RPA .WORD 000036 ;OP.LSQ .WORD 000002 ;OP.RSQ .WORD 000000 ;OP.LBR .WORD 000000 ;OP.RBR .WORD 000000 ;OP.114 .WORD 000000 ;OP.115 .WORD 000000 ;OP.INT .WORD 000000 ;OP.CHR .WORD 000000 ;OP.FLT .WORD 000000 ;OP.DBL .WORD 000000 ;OP.UNS .WORD 000000 ;OP.LNG .WORD 000000 ;OP.STR .WORD 000000 ;OP.AUT .WORD 000000 ;OP.STA .WORD 000000 ;OP.EXT .WORD 000000 ;OP.GOT .WORD 000000 ;OP.RET .WORD 000000 ;OP.IF .WORD 000000 ;OP.WHI .WORD 000000 ;OP.ELS .WORD 000000 ;OP.SWI .WORD 000000 ;OP.CAS .WORD 000000 ;OP.BRK .WORD 000000 ;OP.CON .WORD 000000 ;OP.DO .WORD 000000 ;OP.DEF .WORD 000000 ;OP.FOR .WORD 000000 ;OP.TYP .WORD 000234 ;OP.SIZ (SIZEOF) .WORD 000000 ;OP.SHO .WORD 000000 ;OP.UNI .PAGE ;+ ; ** CONVERSION TABLE ; ; INDEXED BY 7*(LT-TY.CHR) + (RT-TY.CHR) ;- NASTY = 0 ;ILLEGAL CONVERSION GOAL = 000377 ;GOAL TYPE R = 000400 ;CONVERT RIGHT L = 001000 ;CONVERT LEFT LA = 002000 ;CONVERT LEFT FOR ASSIGNMENT CVTAB: .WORD TY.INT+R+L+LA ;C :: C .WORD TY.INT+L+LA ;C :: I .WORD TY.UNS+L+LA ;C :: U .WORD TY.PTR+L+LA ;C :: P .WORD TY.LNG+L+LA ;C :: L .WORD TY.DBL+R+L+LA ;C :: F .WORD TY.DBL+L+LA ;C :: D .WORD TY.INT+R ;I :: C .WORD TY.INT ;I :: I .WORD TY.UNS ;I :: U .WORD TY.PTR+L+LA ;I :: P .WORD TY.LNG+L+LA ;I :: L .WORD TY.DBL+R+L+LA ;I :: F .WORD TY.DBL+L+LA ;I :: D .WORD TY.UNS+R ;U :: C .WORD TY.UNS ;U :: I .WORD TY.UNS ;U :: U .WORD TY.PTR+L+LA ;U :: P .WORD TY.LNG+L+LA ;U :: L .WORD TY.DBL+R+L+LA ;U :: F .WORD TY.DBL+L+LA ;U :: D .WORD TY.PTR+R ;P :: C .WORD TY.PTR+R ;P :: I .WORD TY.PTR+R ;P :: U .WORD TY.PTR ;P :: P .WORD TY.PTR+R ;P :: L .WORD NASTY ;P :: F .WORD NASTY ;P :: D .WORD TY.LNG+R ;L :: C .WORD TY.LNG+R ;L :: I .WORD TY.LNG+R ;L :: U .WORD TY.PTR+L+LA ;L :: P .WORD TY.LNG ;L :: L .WORD TY.DBL+R+L+LA ;L :: F .WORD TY.DBL+L+LA ;L :: D .WORD TY.DBL+R+L+LA ;F :: C .WORD TY.DBL+R+L+LA ;F :: I .WORD TY.DBL+R+L+LA ;F :: U .WORD NASTY ;F :: P .WORD TY.DBL+R+L+LA ;F :: L .WORD TY.DBL+R+L+LA ;F :: F .WORD TY.DBL+L+LA ;F :: D .WORD TY.DBL+R ;D :: C .WORD TY.DBL+R ;D :: I .WORD TY.DBL+R ;D :: U .WORD NASTY ;D :: P .WORD TY.DBL+R ;D :: L .WORD TY.DBL+R ;D :: F .WORD TY.DBL ;D :: D .END