ROUTINESPEC READ SYMBOL(INTEGERNAME I) INTEGERFNSPEC NEXT SYMBOL ROUTINESPEC SKIP SYMBOL ROUTINESPEC PRINT SYMBOL(INTEGER I) ROUTINESPEC READ(INTEGERNAME I) ROUTINESPEC WRITE(INTEGER I,J) ROUTINESPEC SPACE ROUTINESPEC SPACES(INTEGER I) ROUTINESPEC NEWLINE ROUTINESPEC NEWLINES(INTEGER I) ROUTINESPEC NEWPAGE BEGIN ROUTINESPEC READ PS ROUTINESPEC READ LINE INTEGERFNSPEC COMPARE ROUTINESPEC SS ROUTINESPEC FAULT(INTEGER A,B,C,D) INTEGERFNSPEC CHNEXT INTEGERFNSPEC NEWCELL INTEGERFNSPEC RETURN CELL(INTEGER I) ROUTINESPEC PRINT NAME(INTEGER I) INTEGER AP,APP,TP,PSP,ASL,BTN,CTN,CHP,FAULTS,LEVEL,CA,COMP,SCF INTEGERARRAY PS(-1000:-600) ; ! REDUCED PHRASE STRUCTURE INTEGERARRAY TAG,LINK(0:1023) ; ! TAGS LISTS INTEGERARRAY A(1:200) ; ! ANALYSIS RECORD INTEGERARRAY T(1:300) ; ! SOURCE TEXT INTEGERARRAY BAT,COT(0:1023) ; ! BRANCH, CONST TABLES INTEGERARRAY CH(1:512) ; ! NAME CHAR TABLE INTEGERARRAY JUMP,STAR,BRT,NAME,RTP,BR,CHPP,START,RAD(0:15) ; ! LEVEL INFORMATION INTEGERARRAY TRUE,FALSE(1:6) ; ! CONDITIONAL BRANCH INSTRUCTIONS INTEGERARRAY PREC,UCN(1:12) ; ! OPERATOR PRECEDENCES, TYPES INTEGERARRAY OPR(0:12) ; ! MACHINE OPERATIONS INTEGERARRAY PT,PN,PTC(1:15) ; ! FOR RT SPECS, HEADINGS READ PS ;! READ IN AND REDUCE PHRASE STRUCTURE ASL=0 ;! CLEAR HASHING AREA & 10: TAG(ASL)=0 ;! CREATE AVAILABLE SPACE LIST LINK(ASL)=0 ;! IN REMAINDER IF ASL>=256 AND ASL<1023 THEN LINK(ASL)=ASL+1 ASL=ASL+1 IF ASL<=1023 THEN ->10 ASL=256 ;! AVAILABLE SPACE LIST POINTER BR(0)=M'BR0' ;! BASE REGISTER MNEMONICS BR(1)=M'BR1' BR(2)=M'BR2' BR(3)=M'BR3' BR(4)=M'BR4' BR(5)=M'BR5' BR(6)=M'BR6' BR(7)=M'BR7' BR(8)=M'BR8' BR(9)=M'BR9' BR(10)=M'BR10' BR(11)=M'BR11' BR(12)=M'BR12' BR(13)=M'BR13' BR(14)=M'BR14' BR(15)=M'BR15' TRUE(1)=M'BZ' ;! CONDITIONAL BRANCH MNEMONICS FALSE(1)=M'BNZ' TRUE(2)=M'BNZ' FALSE(2)=M'BZ' TRUE(3)=M'BNG' FALSE(3)=M'BG' TRUE(4)=M'BL' FALSE(4)=M'BNL' TRUE(5)=M'BNL' FALSE(5)=M'BL' TRUE(6)=M'BG' FALSE(6)=M'BNG' PREC(1)=3 ;! OPERATOR PRECEDENCES PREC(2)=3 ;! 4 : HIGHEST PREC(3)=2 ;! 1 : LOWEST PREC(4)=1 PREC(5)=1 PREC(6)=3 PREC(7)=2 PREC(8)=2 PREC(9)=1 PREC(10)=1 PREC(11)=1 PREC(12)=4 OPR(0)=M'LOAD' ;! MACHINE INSTRUCTION MNEMONICS OPR(1)=M'SHL' OPR(2)=M'SHR' OPR(3)=M'AND' OPR(4)=M'XOR' OPR(5)=M'OR' OPR(6)=M'EXP' OPR(7)=M'DIV' OPR(8)=M'MLT' OPR(9)=M'ADD' OPR(10)=M'SUB' OPR(11)=M'NEG' OPR(12)=M'NOT' UCN(1)=3 ;! OPERATOR TYPES UCN(2)=3 ;! 1 : UNARY UCN(3)=2 ;! 2 : BINARY COMMUTATIVE UCN(3)=2 ;! 3 : BINARY NON-COMMUTATIVE UCN(4)=2 UCN(5)=2 UCN(6)=3 UCN(7)=3 UCN(8)=2 UCN(9)=2 UCN(10)=3 UCN(11)=1 UCN(12)=1 BTN=0 ;! BRANCH TABLE POINTER CTN=0 ;! CONSTANT TABLE POINTER CHP=1 ;! NAME CHARACTER TABLE POINTER FAULTS=0 ;! FAULT COUNT LEVEL=0 ;! TEXTUAL LEVEL SCF=0 ;! CONDITION FLAG JUMP(0)=0 ;! JUMP LIST POINTER STAR(0)=0 ;! STORAGE ALLOCATION POSITION IN COT NAME(0)=0 ;! NAME LIST POINTER RTP(0)=-1 ;! ROUTINE TYPE CHPP(0)=0 ;! NAME CHARACTER TABLE POSITION START(0)=0 ;! START/FINISH LIST RAD(0)=10 ;! NEXT RELATIVE ADDRESS TO BE ALLOCATED CA=0 ;! CURRENT CODE DUMPING ADDRESS PRINT SYMBOL('P') PRINT SYMBOL('R') PRINT SYMBOL('G') PRINT SYMBOL(':') ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! 1: READ LINE TP=1 ;! TEXT POINTER 2: IF T(TP)='!' THEN ->3 ; ! COMMENT - SKIP TO END PSP=-1000 ;! START OF <SS> IN PHRASE STRUCTURE TABLES AP=1 IF COMPARE=1 THEN START ; ! SUCCESSFUL ANALYSIS AP=1 ;! ANALYSIS RECORD POINTER SS ;! PROCESS SOURCE STATEMENT IF T(TP-1)=';' THEN ->2 ; ! FURTHER STATEMENT ON THIS LINE ->1 ; FINISH ; ! GO TO READ NEXT LINE FAULT(M'SYNT',M'AX ?',M' ',M' ') ;! UNSUCCESSFUL ANALYSIS 5: IF T(TP)=10 THEN ->1 ; ! NEWLINE - READ NEXT LINE IF T(TP)=';' THEN START ; ! END OF STATEMENT TP=TP+1 ;! TP TO START OF NEXT STATEMENT ->2 ; FINISH ; ! GO TO EXAMINE NEXT STATEMENT 3: TP=TP+1 ;! SKIP TO NEXT CHARACTER OF STATEMENT ->5 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE READ PS ! READ IN AND REDUCE PHRASE STRUCTURE INTEGER PNP,ALT,P,I,J,K INTEGERARRAY PN,PSP(256:300) ; ! PHRASE NAME CHARS & POINTERS TO START OF PHRASES IN PS ROUTINESPEC INSERT LIT INTEGERFNSPEC GET PN PNP=256 ;! PN POINTER P=-1000 ;! PS POINTER 1: READ SYMBOL(I) IF I='B' THEN START ; ! BUILT-IN PHRASE 2: READ SYMBOL(I) ;! SKIP TO < IF I¬='<' THEN ->2 J=GET PN ;! READ PHRASE NAME & GET POSITION IN PSP 3: READ SYMBOL(I) ;! SKIP TO = IF I¬='=' THEN ->3 READ(K) ;! READ PHRASE NUMBER PSP(J)=K ;! FILL IN PHRASE NUMBER ->1 ; FINISH ; ! GO TO DEAL WITH NEXT PHRASE IF I='P' THEN START ; ! PHRASE 4: READ SYMBOL(I) ;! SKIP TO < IF I¬='<' THEN ->4 PSP(GET PN)=P ;! READ PHRASE NAME & FILL IN PS POSITION 7: ALT=P ;! REMEMBER START POSITION IN PS OF THIS ALTERNATIVE 6: P=P+1 ;! NEXT PS POSITION 5: READ SYMBOL(I) ;! START OF NEXT ITEM IN THIS ALTERNATIVE IF I='''' THEN START ; ! LITERAL TEXT INSERT LIT ;! READ LITERAL & INSERT IN PS ->5 ; FINISH ; ! GO FOR NEXT ITEM IF I='<' THEN START ; ! ITEM IS A PHRASE NAME PS(P)=GET PN ;! READ PHRASE NAME & FILL IN PS WITH PSP POSITION ->6 ; FINISH ; ! GO FOR NEXT ITEM IF I=',' THEN START ; ! END OF THIS ALTERNATIVE PS(ALT)=P ;! FILL IN POINTER TO END OF ALTERNATIVE ->7 ; FINISH ; ! GO FOR START OF NEXT ALTERNATIVE IF I=';' THEN START ; ! END OF PHRASE DEFINITION PS(ALT)=P ;! FILL IN POINTER TO END OF ALTERNATIVE PS(P)=0 ;! FILL IN END OF PHRASE MARKER P=P+1 ;! NEXT PS POSITION FOR START OF NEXT PHRASE DEFINITION ->1 ; FINISH ; ! GO FOR NEXT PHRASE ->5 ; FINISH ; ! SKIP TO SOMETHING SIGNIFICANT IF I='E' THEN START ; ! END OF PHRASE STRUCTURE DEFINITIONS I=-1000 ;! REPLACE ALL POINTERS TO PSP WITH CORRECT PS POINTERS 8: IF PS(I)>=256 THEN PS(I)=PSP(PS(I)) I=I+1 IF I¬=P THEN ->8 RETURN ; FINISH ->1 ;! SKIP TO SOMETHING SIGNIFICANT ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE INSERT LIT ! INSERT LITERAL TEXT INTO 'PS' INTEGER SH,I SH=0 ;! % SHIFT VALUE TO 0 1: READ SYMBOL(I) IF I='''' THEN START IF NEXT SYMBOL¬='''' THEN RETURN ; ! END OF LITERAL READ SYMBOL(I) ;! QUOTE INSIDE LITERAL - IGNORE ONE FINISH IF I='%' THEN SH=128 ELSE START ; ! SHIFT VALUE TO 128 FOR % IF I<'A' OR I>'Z' THEN SH=0 ; ! END OF KEYWORD - SHIFT VALUE TO 0 PS(P)=I+SH ;! STORE SHIFTED (POSSIBLY) CHAR IN PS P=P+1 ;! MOVE TO NEXT POSITION IN PS FINISH ->1 END ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! INTEGERFN GET PN ! READ IN PHRASE NAME AND GET INDEX IN 'PSP' INTEGER NP,S,I NP=0 ;! TO ACCUMULATE PHRASE NAME CHARS S=24 ;! INITIAL SHIFT VALUE TO PACK CHARS 1: READ SYMBOL(I) IF I¬='>' THEN START ; ! NOT END OF NAME YET NP=NP!I<<S ;! PACK NEXT CHAR OF PHRASE NAME S=S-8 ;! REDUCE SHIFT VALUE FOR NEXT CHAR ->1 ; FINISH IF PNP¬=256 THEN START ; ! NOT FIRST PHRASE NAME I=256 ;! SCAN NAMES TO FIND IF ALREADY IN 2: IF NP=PN(I) THEN RESULT=I I=I+1 IF I¬=PNP THEN ->2 FINISH PN(PNP)=NP ;! INSERT NEW NAME IN DICTIONARY PSP(PNP)=99999 ;! UNDEFINED PHRASE MARKER PNP=PNP+1 ;! MOVE TO NEXT DICTIONARY POSITION RESULT=PNP-1 END END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE READ LINE ! LEXICAL PHASE - READ & CLEAN UP NEXT LINE OF TEXT ROUTINESPEC STORE(INTEGER I) INTEGER SH,I NEWLINES(2) PRINT SYMBOL(';') SH=0 ;! % & LITERAL SHIFT VALUE TO 0 TP=1 ;! POINTER TO TEXT ARRAY T 1: READ SYMBOL(I) IF I=10 AND TP=1 THEN ->1 PRINT SYMBOL(I) IF I='''' THEN START SH=128 ;! SHIFT VALUE FOR LITERAL 2: STORE(I) ;! STORE SHIFTED CHAR IN TEXT ARRAY READ SYMBOL(I) PRINT SYMBOL(I) IF I=10 THEN PRINT SYMBOL(';') IF I¬='''' THEN ->2 ; ! NOT END OF LITERAL YET READ SYMBOL(I) PRINT SYMBOL(I) IF I='''' THEN ->2 ; ! QUOTE IN LITERAL - IGNORE ONE SH=0 ;! SHIFT VALUE TO 0 FOR END OF LITERAL STORE('''') ;! STORE UNSHIFTED VALUE TO MARK END FINISH IF I='%' THEN SH=128 ELSE START ; ! SHIFT VALUE TO 128 FOR KEYWORD IF I<'A' OR I>'Z' THEN SH=0 ; ! SHIFT VALUE TO 0 FOR END OF KEYWORD IF I¬=' ' THEN START ; ! IGNORE SPACES STORE(I) IF I=10 THEN START ; ! NEWLINE CHAR IF T(TP-2)='C'+128 THEN START TP=TP-2 PRINT SYMBOL(';') FINISH ELSE RETURN FINISH FINISH FINISH ->1 ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE STORE(INTEGER I) ! STORE (POSSIBLY) SHIFTED CHARACTER IN TEXT ARRAY & CHECK LINE NOT TOO LONG IF TP>300 THEN START FAULT(M'STAT',M'MNT ',M'TOO ',M'LONG') TP=1 FINISH T(TP)=I+SH ;! STORE CHAR IN TEXT ARRAY TP=TP+1 ;! MOVE TO NEXT POSITION END END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN COMPARE ! ANALYSE PHRASE INTEGERFNSPEC NAME ; ! BUILT-IN PHRASE NAME INTEGERFNSPEC CNST ; ! BUILT-IN PHRASE <CNST> INTEGER APP,TPP,PSPP,AE,N TPP=TP ;! PRESERVE INITIAL TEXT POINTER APP=AP ;! PRESERVE INITIAL ANALYSIS RECORD A(AP)=1 ;! ALTERNATIVE 1 FIRST 11: AE=PS(PSP) ;! POINTER TO END OF ALTERNATIVE PSP=PSP+1 ;! FIRST ITEM OF ALTERNATIVE DEFN 12: IF PSP=AE THEN RESULT=1 ; ! END OF ALT REACHED - SUCCESS N=PS(PSP) ;! NEXT ITEM OF ALT DEFN PSP=PSP+1 ;! FOR FOLLOWING ITEM IF N<0 THEN START ; ! SUB-PHRASE PSPP=PSP ;! PRESERVE PS POINTER PSP=N ;! POINTER TO DEFN OF SUB-PHRASE AP=AP+1 ;! NEXT ANALYSIS RECORD POSITION N=COMPARE ;! RECURSIVE COMPARISON FOR SUB-PHRASE PSP=PSPP ;! RESTORE PS POINTER IF N=1 THEN ->12 ; ! SUCCESSFUL COMPARISON - GO FOR NEXT ITEM ->13 ; FINISH ; ! UNSUCCESSFUL - GO FOR NEXT ALTERNATIVE IF N=1 THEN START ; ! BUILT-IN PHRASE <NAME> IF NAME=1 THEN ->12 ; ! SUCCESS ->13 ; FINISH ; ! FAILURE IF N=2 THEN START ; ! BUILT-IN PHRASE CNST IF CNST=1 THEN ->12 ; ! SUCCESS ->13 ; FINISH ; ! FAILURE IF N=T(TP) THEN START ; ! LITERAL - MATCHES SOURCE CHAR TP=TP+1 ;! MOVE TO NEXT SOURCE CHAR ->12 ; FINISH ; ! GO FOR NEXT ITEM 13: IF PS(AE)=0 THEN RESULT=0 ; ! END OF PHRASE PSP=AE ;! START OF DEFN OF NEXT ALTERNATIVE TP=TPP ;! BACKTRACK SOURCE TEXT AP=APP ;! AND ANALYSIS RECORD POINTERS A(AP)=A(AP)+1 ;! COUNT ALTERNATIVE NUMBER ON ONE ->11 ;! GO TO ANALYSE NEW ALTERNATIVE ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! INTEGERFN NAME ! RECOGNISE AND INSERT NAME IN HASHING AREA OF TAG/LINK ARRAYS INTEGER I,J,K,L,M,N I=T(TP) ;! FIRST SOURCE CHAR IF I<'A' OR I>'Z' OR (I='M' AND T(TP+1)=''''+128) THENRESULT=0 ;! FAILURE - NOT A LETTER OR AN M-TYPE CONSTANT J=CHP ;! NEXT POSITION IN CHARACTER ARRAY K=I<<16 ;! LEAVE HOLE FOR LENGTH & PACK FIRST CHAR L=1 ;! NO OF CHARS M=8 ;! NEXT SHIFT VALUE FOR PACKING N=I ;! SUM VALUE OF CHARS FOR HASHING 1: TP=TP+1 I=T(TP) ;! NEXT CHAR FROM TEXT ARRAY IF ('0'<=I AND I<='9') OR ('A'<=I AND I<='Z') THEN START ;! A DIGIT OR A LETTER K=K!I<<M ;! PACK NEXT LETTER L=L+1 ;! CHARACTER COUNT M=M-8 ;! NEXT SHIFT N=N+I ;! SUM OF LETTERS IF M<0 THEN START ; ! PACKED WORD OF CHARS FULL CH(CH NEXT)=K ;! STORE WORD IN CHAR ARRAY K=0 ;! PACKING WORD TO ZERO M=24 ;! NEW SHIFT VALUE FINISH ->1 ; FINISH ; ! GO FOR NEXT CHAR IF K¬=0 THEN CH(CH NEXT)=K ; ! STORE ANY REMAINING CHARS IN CHAR ARRAY CH(J)=CH(J)!L<<24 ;! FILL IN LENGTH IN HOLE LEFT IN FIRST WORD I=(N&15)<<4!N>>4&15 ;! HASH VALUE K=I ;! SCAN DICTIONARY FOR NAME 2: IF TAG(K)¬=0 THEN START ; ! A NAME IN THIS POSITION L=TAG(K) ;! CHAR ARRAY POSITION M=J ;! CHAR ARRAY POSITION OF NEW NAME 4: IF CH(L)=CH(M) THEN START ; ! PACKED WORDS MATCH M=M+1 ;! NEXT WORD OF NEW NAME IF M=CHP THEN START ; ! NAMES MATCH CHP=J ;! MOVE CHP BACK SINCE NAME ALREADY IN ->3 ; FINISH L=L+1 ;! NEXT WORD OF OLD NAME ->4 ; FINISH ; ! GO FOR NEXT WORD K=(K+1)&255 ;! NO MATCH SO TRY NEXT DICTIONARY POSITION IF K=I THEN START ; ! STARTING POSITION REACHED AGAIN FAULT(M'DICT',M'IONA',M'RY F',M'ULL ') STOP ; FINISH ->2 ; FINISH TAG(K)=J ;! STORE CHAR ARRAY POSITION OF NAME 3: AP=AP+1 ;! NEXT ANALYSIS RECORD POSITION A(AP)=K ;! STORE IDENTIFICATION NO OF NAME RESULT=1 ; ! SUCCESS END ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! INTEGERFN CNST ! RECOGNISE INTEGER AND LITERAL TEXT CONSTANTS INTEGER I,J,K I=T(TP) ;! FIRST CHAR IF I='M' AND T(TP+1)=''''+128 THEN START ; ! M-TYPE CONSTANT TP=TP+1 ;! IGNORE THE M I=T(TP) FINISH IF I=''''+128 THEN START ; ! START OF A LITERAL J=0 ;! TO ACCUMULATE LITERAL VALUE K=0 ;! CHARACTER COUNT 1: TP=TP+1 I=T(TP) ;! NEXT CHAR IF I¬='''' THEN START ; ! NOT END OF LITERAL J=J<<8!I&127 ;! PACK CHAR K=K+1 ;! COUNT CHAR ->1 ; FINISH TP=TP+1 ;! POINTER AFTER QUOTE IF K>4 THEN FAULT(M'STRI',M'NG T',M'OO L',M'ONG ') ->2 ; FINISH IF I<'0' OR I>'9' THEN RESULT=0 ; ! NOT A CONSTANT J=0 3: J=10*J+I-'0' ;! ACCUMULATE DECIMAL VALUE TP=TP+1 I=T(TP) ;! NEXT CHAR IF '0'<=I AND I<='9' THEN ->3 ; ! A DIGIT - STILL PART OF CONSTANT 2: AP=AP+1 ;! NEXT ANALYSIS RECORD POSITION A(AP)=J ;! FILL IN VALUE OF CONSTANT RESULT=1 ; ! SUCCESS END END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE SS ! COMPILE SOURCE STATEMENT ROUTINESPEC UI ROUTINESPEC SCCOND(INTEGERNAME LABEL) ROUTINESPEC SEXPR INTEGERFNSPEC FIND LABEL ROUTINESPEC CHECK ROUTINESPEC UNSET ROUTINESPEC PUSH START(INTEGER FLAG,LABEL) INTEGERFNSPEC BT NEXT INTEGERFNSPEC CT NEXT INTEGERFNSPEC WS NEXT ROUTINESPEC STORE TAG(INTEGER NAME,FORM,TYPE,DIM,LEV,AD) ROUTINESPEC DUMP(INTEGER OP,REG,BASE,DISP) ROUTINESPEC SKIP SEXPR ROUTINESPEC SKIP APP ROUTINESPEC RT ROUTINESPEC ARRAD ROUTINESPEC ENTER(INTEGER TYPE,ALLOC) ROUTINESPEC RETURN INTEGER I,J,K,L,M,N,P,Q,R,WS,LABEL I=A(AP) ;! ANALYSIS RECORD ENTRY AP=AP+1 ;! FOR FOLLOWING ENTRY WS=2 ;! SET WORKSPACE POINTER IF I=1 THEN ->10 ; ! UNCONDITIONAL INSTRUCTION IF I=2 THEN ->20 ; ! CONDITIONAL STATEMENT IF I=3 THEN ->30 ; ! LABEL IF I=4 THEN ->40 ; ! %FINISH IF I=5 THEN ->50 ; ! DECLARATIONS IF I=6 THEN ->60 ; ! ROUTINE/FN SPEC IF I=7 THEN ->70 ; ! %END IF I=8 THEN ->80 ; ! %BEGIN IF I=9 THEN ->90 ; ! %ENDOFPROGRAM RETURN ; ! <SEP> ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! UI 10: UI ;! COMPILE UNCONDITIONAL INSTRUCTION RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %IF . . . %THEN . . . %ELSE 20: SCCOND(I) ;! COMPILE CONDITION IF A(AP)=2 THEN START ; ! AP ON <UI> - JUMP INSTRUCTION AP=AP+2 ;! AP ON <ELSE> J=-1 ;! MARKER FOR 'JUMP' FINISH ELSE START ; ! NOT A JUMP IF A(AP)=3 THEN START ; ! %START IF A(AP+1)=1 THEN FAULT(M'%STA',M'RT %',M'ELSE',M' ? ') PUSH START(0,I) RETURN ; FINISH UI ;! COMPILE REMAINING UNCOND. INSTNS. J=0 ;! 'NOT JUMP' MARKER FINISH IF A(AP)=1 THEN START ; ! <ELSE>-CLAUSE PRESENT IF J=0 THEN START ; ! <UI> WAS NOT A JUMP J=BT NEXT ;! JUMP ROUND <ELSE>-CLAUSE <UI> DUMP('B',0,M'BT',J) FINISH IF I>=0 THEN BAT(I)=CA ; ! FILL IN LABEL ON <ELSE>-CLAUSE <UI> AP=AP+1 ;! AP ON <UI> IF A(AP)=3 THEN START ; ! %START PUSH START(1,J) RETURN ; FINISH UI ;! COMPILE REMAINING <UI>S I=J ;! JUMP AROUND LABEL FINISH IF I>=0 THEN BAT(I)=CA ; ! TO BRANCH ROUND THE UI RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! CONST: . . . 30: I=FIND LABEL ;! LOCATE/INSERT LABEL IN JUMP LIST IF I>=0 THEN START ; ! VALID LABEL IF BAT(I)>=0 THEN START WRITE(LABEL,1) SPACES(2) FAULT(M'LABE',M'L SE',M'T TW',M'ICE ') FINISH BAT(I)=CA ;! FILL IN LABEL ADDRESS FINISH SS ;! COMPILE STATEMENT AFTER LABEL RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %FINISH . . . 40: I=START(LEVEL) ;! LINK TO FIRST CELL IN START LIST IF I=0 THEN START ; ! NO CELLS IN LIST FAULT(M'SPUR',M'IOUS',M' %FI',M'NISH') RETURN ; FINISH J=TAG(I)&65535 ;! JUMP AROUND LABEL K=TAG(I)>>16 ;! BEFORE OR AFTER %ELSE MARKER START(LEVEL)=RETURN CELL(I) ;! POP UP CELL IF A(AP)=1 THEN START ; ! %ELSE PRESENT IF K=1 THEN FAULT(M'TWO ',M'%ELS',M'ES !',M' ') K=BT NEXT ;! JUMP AROUND <UI> DUMP('B',0,M'BT',K) IF J¬=65535 THEN BAT(J)=CA ; ! FILL IN LABEL ON <UI> IF NECESSARY AP=AP+1 ;! AP ON <UI> IF A(AP)=3 THEN START ; ! %START PUSH START(1,K) RETURN ; FINISH UI ;! COMPILE REMAINING <UI>S J=K ;! JUMP AROUND LABEL FINISH IF J¬=65535 THEN BAT(J)=CA ; ! FILL IN JUMP AROUND LABEL IF NECESSARY RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! DECLARATIONS 50: IF A(AP)=1 THEN START ; ! <ARR> = %ARRAY APP=AP ;! SAVE AP 51: AP=AP+2 ;! AP ON <NAMS> IF A(AP)=1 THEN ->51 ; ! SKIP DOWN TO END OF LIST OF NAMES AP=AP+1 ;! AP ON <+-¬> SEXPR ;! COMPILE EXPRESSION - LOWER BOUND DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) ;! STORE VALUE IN WORKSPACE SEXPR ;! COMPILE EXPRESSION - UPPER BOUND DUMP(M'LDA',M'ACC',M'ACC',1) ;! INCREMENT VALUE BY 1 IF A(AP)=1 THEN START ; ! 2-DIM ARRAYS DUMP(M'SUB',M'ACC',BR(LEVEL),WS-1) ;! PERFORM 2-DIM ARRAY DECLARATION CALCULATIONS DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) AP=AP+1 SEXPR ;! LOWER BOUND EXPR FOR 2ND DIM DUMP(M'MLT',M'ACC',BR(LEVEL),WS-1) DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) SEXPR ;! UPPER BOUND EXPR FOR 2ND DIM DUMP(M'LDA',M'ACC',M'ACC',1) DUMP(M'MLT',M'ACC',BR(LEVEL),WS-2) DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) WS=WS-4 ;! RESTORE WORKSPACE POINTER I=2 ;! NO OF DIMS FINISH ELSE START ; ! 1-DIM ARRAYS DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) WS=WS-2 ;! RESTORE WORKSPACE POINTER I=1 ;! NO OF DIMS FINISH J=2 ;! TAG FOR 'ARRAY' AP=APP ;! RESTORE AP TO BEFORE LIST OF NAMES FINISH ELSE START ; ! SCALAR DECLARATIONS I=0 ;! DIMS=0 FOR SCALARS J=0 ;! TAG FOR SCALAR FINISH 52: STORE TAG(A(AP+1),J,1,I,LEVEL,RAD(LEVEL)) ;! PUSHDOWN TAG FOR THIS NAME IF I=0 THEN RAD(LEVEL)=RAD(LEVEL)+1 ELSE START; ! ONE RELATIVE LOCATION FOR SCALARS IF I=1 THEN START ; ! 1-DIM ARRAYS DUMP(M'SUB',M'STP',BR(LEVEL),WS) DUMP(M'STR',M'STP',BR(LEVEL),RAD(LEVEL)) DUMP(M'ADD',M'STP',BR(LEVEL),WS+1) FINISH ELSE START ; ! 2-DIM ARRAYS DUMP(M'LOAD',M'ACC',BR(LEVEL),WS+1) DUMP(M'STR',M'ACC',BR(LEVEL),RAD(LEVEL)) DUMP(M'SUB',M'STP',BR(LEVEL),WS+2) DUMP(M'LDA',M'ACC',M'STP',0) DUMP(M'SUB',M'ACC',BR(LEVEL),WS) DUMP(M'STR',M'ACC',BR(LEVEL),RAD(LEVEL)+1) DUMP(M'ADD',M'STP',BR(LEVEL),WS+3) FINISH RAD(LEVEL)=RAD(LEVEL)+2 ;! 2 RELATIVE LOCATIONS FOR ARRAYS FINISH AP=AP+2 ;! AP ON <NAMS> IF A(AP)=1 THEN ->52 ; ! MORE NAMES IN LIST OF NAMES RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! RT SPEC? . . . 60: I=A(AP)-1 ;! ROUTINE/FN J=A(AP+1) ;! SPEC ? K=A(AP+2) ;! NAME OF ROUTIINE OR FN AP=AP+3 ;! AP ON <FPP> L=0 ;! PARAMETER COUNT M=10 ;! FIRST RELATIVE ADDRESS TO BE ALLOCATED 63: IF A(AP)=1 THEN START ; ! PARAMETERS PRESENT AP=AP+1 ;! AP ON <ARRN> IF A(AP)=1 THEN N=3 ELSE N=3-A(AP) ; ! SET TAG FOR PARAMETER FORM P=N<<28!1<<24!(LEVEL+1)<<16 ;! SET UP PATTERN FOR WHOLE TAG 62: L=L+1 ;! PARAMETER COUNT IF L>15 THEN START FAULT(M'TOO ',M'MANY',M' PAR',M'AMS ') ->61 ; FINISH ; ! IGNORE SUPERFLUOUS PARAMS PT(L)=P!M ;! STORE TAG FOR THIS PARAM PN(L)=A(AP+1) ;! STORE THE NAMES IDENT. NO IF N=3 THEN M=M+2 ELSE M=M+1 ; ! NEXT RELATIVE ADDRESS AP=AP+2 ;! AP ON <NAMS> IF A(AP)=1 THEN ->62 ; ! MORE NAMES IN LIST AP=AP+1 ;! AP ON <FPS> ->63 ; FINISH 61: N=LINK(K) ;! LINK TO TAG FOR NAME OF ROUTINE OR FN IF N=0 OR TAG(N)>>16&15<LEVEL THEN START ; ! NAME NOT SET OR SET AT LOWER LEVEL IF L>0 THEN START ; ! PARAMETERS PRESENT P=1 ;! PARAMETER COUNT Q=K ;! 'INSERT AFTER' POINTER 64: R=NEWCELL ;! PUSHDOWN TAG FOR PARAMETER TAG(R)=PT(P) LINK(R)=LINK(Q) PTC(P)=R ;! SAVE POINTER TO TAG CELL LINK(Q)=R Q=R ;! NEW VALUE FOR 'INSERT AFTER' POINTER P=P+1 ;! PARAMETER COUNT IF P<=L THEN ->64 ; ! MORE PARAMETERS YET FINISH STORE TAG(K,4,I,L,LEVEL,BT NEXT) ;! PUSHDOWN TAG FOR NAME OF ROUTINE OR FN IF LEVEL=0 THEN BAT(BTN-1)=K+65536 ; ! FLAG FOR EXTERNAL SPECS FINISH ELSE START ; ! NAME ALREADY SET AT THIS LEVEL IF J=2 AND TAG(N)>>28=4 THEN START ; ! STATEMENT NOT A SPEC & FORM OF NAME IS RT IF TAG(N)>>24&15¬=I THEN START PRINT NAME(K) FAULT(M'RT N',M'OT A',M'S SP',M'EC ') FINISH IF BAT(TAG(N)&65535)>=0 THEN START PRINT NAME(K) FAULT(M'RT A',M'PPEA',M'RS T',M'WICE') FINISH P=TAG(N)>>20&15 ;! NO OF PARAMS IN SPEC IF L¬=P THEN START FAULT(M'PARS',M' NOT',M' AS ',M'SPEC') IF L>P THEN L=P ; ! IGNORE SUPERFLUOUS PARAMS FINISH IF L>0 THEN START ; ! PARAMS PRESENT P=1 ;! PARAM COUNT Q=LINK(N) ;! LINK TO TAG OF FIRST PARAM 67: IF PT(P)!TAG(Q)&15<<20¬=TAG(Q) THEN START PRINT NAME(PN(P)) FAULT(M'PAR ',M'NOT ',M'AS S',M'PEC ') FINISH PTC(P)=Q ;! SAVE POINTER TO TAG CELL P=P+1 ;! PARAM COUNT Q=LINK(Q) ;! NEXT TAG CELL IF P<=L THEN ->67 ; ! MORE PARAMS FINISH FINISH ELSE START PRINT NAME(K) FAULT(M'NAME',M' SET',M' TWI',M'CE ') FINISH FINISH 68: IF J=2 THEN START ; ! STATEMENT NOT A SPEC BRT(LEVEL)=BT NEXT ;! BRANCH ROUND ROUTINE OR FN DUMP('B',0,M'BT',BRT(LEVEL)) BAT(TAG(LINK(K))&65535)=CA ;! FILL IN ADDRESS OF THIS ROUTINE OR FN IF LEVEL=15 THEN FAULT(M'TOO ',M'MANY',M' LEV',M'ELS ') C ELSE LEVEL=LEVEL+1 ; ! NEXT TEXTUAL LEVEL ENTER(I,M) IF L>0 THEN START ; ! PARAMS PRESENT P=1 ;! PARAM COUNT 69: I=PT(P) ;! PUSHDOWN TAGS FOR PARAMS IF I>>28=3 THEN STORE TAG(PN(P),3,1,0,LEVEL,PTC(P)) C ELSE STORE TAG(PN(P),I>>28,1,0,LEVEL,I&65535) ; ! TREAT ARRAYNAMES SPECIALLY P=P+1 IF P<=L THEN ->69 ; ! MORE PARAMS YET FINISH FINISH RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %END 70: CHECK ;! CHECK LABELS & START/FINISH BLOCKS COT(STAR(LEVEL))=RAD(LEVEL) ;! STORE STATIC ALLOCATION FOR THIS LEVEL UNSET ;! UNSET NAMES DECLARED AT THIS LEVEL CHP=CHPP(LEVEL) IF RTP(LEVEL)¬=0 THEN DUMP(M'STOP',0,0,0) ; ! %STOP FOR FNS RETURN ;! DUMP %RETURN CODE LEVEL=LEVEL-1 ;! DECREMENT TEXTUAL LEVEL COUNT IF LEVEL<1 THEN START ; ! NOT BACK AT OUTER LEVEL YET FAULT(M'EXCE',M'SS %',M'END ',M' ') ->71 ; FINISH ; ! TREAT AS %ENDOFPROGRAM BAT(BRT(LEVEL))=CA ;! FILL ADDR FOR BRANCH ROUND ROUTINE/FN RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %BEGIN 80: IF LEVEL¬=0 THEN START FAULT(M'%BEG',M'IN E',M'XTRA',M' ') ;! NO INTERNAL BLOCKS ALLOWED RETURN ; FINISH IF CA¬=0 OR RAD(0)¬=10 THEN START FAULT(M'%BEG',M'IN N',M'OT F',M'IRST') RETURN ; FINISH LEVEL=1 ;! TEXTUAL LEVEL COUNT TO 1 ENTER(-1,10) RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %ENDOFPROGRAM 90: CHECK ;! CHECK LABELS & START/FINISHES COT(STAR(LEVEL))=RAD(LEVEL) ;! FILL IN STATIC ALLOCATION FOR OUTER BLOCK UNSET ;! UNSET NAMES DECLARED AT THIS LEVEL IF LEVEL¬=1 THEN FAULT(M'TOO ',M'FEW ',M'%END',M'S ') 71: DUMP(M'STOP',0,0,0) ;! %STOP PRINT SYMBOL('B') ;! PRINT OUT BRANCH TABLE PRINT SYMBOL('T') PRINT SYMBOL(':') NEWLINE CA=0 93: IF CA¬=BTN THEN START DUMP('B',0,M'PRG',BAT(CA)) ;! BRANCH RELATIVE TO START OF PROGRAM ->93 ; FINISH PRINT SYMBOL('C') ;! PRINT OUT CONSTANT TABLE PRINT SYMBOL('T') PRINT SYMBOL(':') NEWLINE I=0 91: IF I¬=CTN THEN START WRITE(COT(I),10) NEWLINE I=I+1 ->91 ; FINISH PRINT SYMBOL(';') WRITE(FAULTS,1) ;! NUMBER OF PROGRAM FAULTS FAULT(M' FAU',M'LTS ',M'IN P',M'ROGM') STOP !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE UI ! COMPILE UNCONDITIONAL INSTRUCTION INTEGER I,J,K,L I=A(AP) ;! NEXT ANALYSIS RECORD ENTRY AP=AP+1 IF I=1 THEN ->10 ; ! ROUTINE CALL OR ASSIGNMENT STATEMENT IF I=2 THEN ->20 ; ! JUMP INSTRUCTION IF I=3 THEN ->30 ; ! %START IF I=4 THEN ->40 ; ! %RETURN IF I=5 THEN ->50 ; ! %RESULT= DUMP(M'STOP',0,0,0) ;! %STOP RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! NAME APP ASS 10: I=LINK(A(AP)) ;! POINTER TO NAME TAGS IF I=0 THEN START PRINT NAME(A(AP)) FAULT(M'NAME',M' NOT',M' SET',0) FINISH ELSE I=TAG(I) ; ! NAME TAGS OR ZERO TO AVOID DIAGNOSTICS J=AP ;! PRESERVE ANALYSIS RECORD POINTER AP=AP+1 ;! AP ON <APP> SKIP APP ;! SKIP TO <ASS> IF A(AP)=2 THEN START ; ! ROUTINE CALL IF I>>24=64 THEN START ; ! 'FORM/TYPE' IS ROUTINE AP=J ;! RESTORE AP TO <NAME> RT ;! CALL ROUTINE FINISH ELSE START IF I¬=0 THEN START PRINT NAME(A(J)) FAULT(M'NOT ',M'ROUT',M'INE ',M'NAME') FINISH FINISH AP=AP+1 ;! AP AFTER <UI> RETURN ; FINISH K=I>>28 ;! 'FORM' OF NAME IF K=4 THEN START PRINT NAME(A(J)) FAULT(M'NAME',M' NOT',M' A D',M'ESTN') ;! ROUTINE/FN FORM I=0 ;! CLEAR TAGS TO AVOID FURTHER DIAGNOSTIC FINISH AP=AP+1 ;! AP ON <+-¬> SEXPR IF I=0 THEN RETURN ; ! LHS NAME NOT SET IF K>=2 THEN START ; ! LHS AN ARRAY TYPE DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) ;! PRESERVE ACCUMMULATOR K=AP ;! PRESERVE AP AP=J ;! RESTORE INITIALANAL REC POINTER ARRAD ;! CALCULATE ARRAY ELEMENT ADDRESS WS=WS-1 ;! RESTORE WORKSPACE POINTER DUMP(M'LOAD',M'WK',BR(LEVEL),WS) ;! RESTORE ACCUMMULATOR DUMP(M'STR',M'WK',M'ACC',0) ;! DUMP ASSIGNMENT AP=K ;! RESTORE AP TO AFTER <UI> RETURN ; FINISH IF K=1 THEN START DUMP(M'LOAD',M'WK',BR(I>>16&15),I&65535);! INDIRECT ASSIGMENT DUMP(M'STR',M'ACC',M'WK',0) FINISH ELSE DUMP(M'STR',M'ACC',BR(I>>16&15),I&65535) IF A(J+1)=1 THEN START PRINT NAME(A(J)) FAULT(M'SCAL',M'AR H',M'AS P',M'ARAM') FINISH RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! -> CONST PRINT SYMBOL('B') ;! PRINT OUT BRANCH TABLE PRINT SYMBOL('T') PRINT SYMBOL(':') NEWLINE CA=0 93: IF CA¬=BTN THEN START DUMP('B',0,M'PRG',BAT(CA)) ;! BRANCH RELATIVE TO START OF PROGRAM ->93 ; FINISH PRINT SYMBOL('C') ;! PRINT OUT CONSTANT TABLE PRINT SYMBOL('T') PRINT SYMBOL(':') NEWLINE I=0 91: IF I¬=CTN THEN START WRITE(COT(I),10) NEWLINE I=I+1 ->91 ; FINISH PRINT SYMBOL(';') WRITE(FAULTS,1) ;! NUMBER OF PROGRAM FAULTS FAULT(M' FAU',M'LTS ',M'IN P',M'ROGM') STOP !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE UI ! COMPILE UNCONDITIONAL INSTRUCTION INTEGER I,J,K,L I=A(AP) ;! NEXT ANALYSIS RECORD ENTRY AP=AP+1 IF I=1 THEN ->10 ; ! ROUTINE CALL OR ASSIGNMENT STATEMENT IF I=2 THEN ->20 ; ! JUMP INSTRUCTION IF I=3 THEN ->30 ; ! %START IF I=4 THEN ->40 ; ! %RETURN IF I=5 THEN ->50 ; ! %RESULT= DUMP(M'STOP',0,0,0) ;! %STOP RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! NAME APP ASS 10: I=LINK(A(AP)) ;! POINTER TO NAME TAGS IF I=0 THEN START PRINT NAME(A(AP)) FAULT(M'NAME',M' NOT',M' SET',0) FINISH ELSE I=TAG(I) ; ! NAME TAGS OR ZERO TO AVOID DIAGNOSTICS J=AP ;! PRESERVE ANALYSIS RECORD POINTER AP=AP+1 ;! AP ON <APP> SKIP APP ;! SKIP TO <ASS> IF A(AP)=2 THEN START ; ! ROUTINE CALL IF I>>24=64 THEN START ; ! 'FORM/TYPE' IS ROUTINE AP=J ;! RESTORE AP TO <NAME> RT ;! CALL ROUTINE FINISH ELSE START IF I¬=0 THEN START PRINT NAME(A(J)) FAULT(M'NOT ',M'ROUT',M'INE ',M'NAME') FINISH FINISH AP=AP+1 ;! AP AFTER <UI> RETURN ; FINISH K=I>>28 ;! 'FORM' OF NAME IF K=4 THEN START PRINT NAME(A(J)) FAULT(M'NAME',M' NOT',M' A D',M'ESTN') ;! ROUTINE/FN FORM I=0 ;! CLEAR TAGS TO AVOID FURTHER DIAGNOSTIC FINISH AP=AP+1 ;! AP ON <+-¬> SEXPR IF I=0 THEN RETURN ; ! LHS NAME NOT SET IF K>=2 THEN START ; ! LHS AN ARRAY TYPE DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) ;! PRESERVE ACCUMMULATOR K=AP ;! PRESERVE AP AP=J ;! RESTORE INITIALANAL REC POINTER ARRAD ;! CALCULATE ARRAY ELEMENT ADDRESS WS=WS-1 ;! RESTORE WORKSPACE POINTER DUMP(M'LOAD',M'WK',BR(LEVEL),WS) ;! RESTORE ACCUMMULATOR DUMP(M'STR',M'WK',M'ACC',0) ;! DUMP ASSIGNMENT AP=K ;! RESTORE AP TO AFTER <UI> RETURN ; FINISH IF K=1 THEN START DUMP(M'LOAD',M'WK',BR(I>>16&15),I&65535);! INDIRECT ASSIGMENT DUMP(M'STR',M'ACC',M'WK',0) FINISH ELSE DUMP(M'STR',M'ACC',BR(I>>16&15),I&65535) IF A(J+1)=1 THEN START PRINT NAME(A(J)) FAULT(M'SCAL',M'AR H',M'AS P',M'ARAM') FINISH RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! -> CONST 20: DUMP('B',0,M'BT',FIND LABEL) ;! SCAN/INSERT JUMP LIST AND DUMP JUMP RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %START 30: FAULT(M'%STA',M'RT ?',M' ',M' ') ;! %START ALONE SHOULD NOT BE A SOURCE STATEMENT RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %RETURN 40: IF RTP(LEVEL)¬=0 THEN FAULT(M'%RET',M'URN ',M'CONT',M'EXT ') RETURN ;! DUMP %RETURN CODE - INCORRECT FOR FN RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! %RESULT= 50: I=RTP(LEVEL) ;! ROUTINE/FN TYPE IF I<=0 THEN FAULT(M'%RES',M'ULT ',M'CONT',M'EXT ') ; ! %BEGIN/%ROUTINE SEXPR ;! COMPILE RESULT EXPRESSION RETURN ;! LEAVE RESULT IN ACC & DUMP RETURN CODE END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE SEXPR ! COMPILE ARITHMETIC EXPRESSION ROUTINESPEC TORP ROUTINESPEC PSEVAL ROUTINESPEC EVAL(INTEGER P) INTEGER RPP,APP INTEGERARRAY RP,PT(1:32) ; ! REVERSE POLISH, POINTER/TYPE ARRAYS RPP=1 ;! RP POINTER TORP ;! EXPR TO REV POLISH IF SCF=1 THEN START ; ! PART OF A SIMPLE CONDITION SCF=0 ;! RESET FLAG COMP=A(AP) ;! COMPARATOR NUMBER IF A(AP+3)=0 AND A(AP+4)=2 THEN AP=AP+5 ELSE START AP=AP+1 ;! 2ND EXPR NON-ZERO TORP ;! 2ND EXPRESSION TO REVERSE POLISH RP(RPP)=10 ;! CODE FOR '-' I.E. (1ST-2ND) PT(RPP)=1 ;! FLAG=OPERATOR RPP=RPP+1 ;! INCREMENT RP POINTER FINISH FINISH APP=AP ;! SAVE FINAL ANAL REC POINTER PSEVAL ;! PSEUDO-EVALUATE EXPRESSION EVAL(RPP-1) ;! DUMP CODE FOR EXPR EVALUATION AP=APP ;! RESTORE FINAL ANAL REC POINTER ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE TORP ! TRANSFORM EXPRESSION TO REVERSE POLISH ROUTINESPEC STORE(INTEGER I,J) INTEGERARRAY OP(1:4) INTEGER OPP,I OPP=0 ;! OPERATOR STACK POINTER I=A(AP) ;! <+-¬> AP=AP+1 IF I=1 OR I=4 THEN ->1 ; ! + OR NULL I=I+9 ;! CODES FOR - & ¬ 3: OPP=OPP+1 ;! STACK OPERATOR OP(OPP)=I 1: I=A(AP) ;! <OPD> IF I=3 THEN START ; ! SUB-EXPRESSION AP=AP+1 ;! AP TO <+-¬> TORP ;! TRANSFORM SUB-EXPR TO REV POL FINISH ELSE START STORE(AP,0) ;! STORE ANAL REC POSITION OF OPERAND AP=AP+2 ;! AP ON <APP> OR AFTER <CNST> IF I=1 THEN SKIP APP ; ! OPERAND A NAME FINISH IF A(AP)=2 THEN START ; ! END OF <EXPR> AP=AP+1 ;! AP AFTER EXPRESSION 2: IF OPP=0 THEN RETURN ; ! OPERATOR STACK EMPTIED STORE(OP(OPP),1) ;! UNSTACK REMAINING OPERATORS OPP=OPP-1 ->2 ; FINISH I=A(AP+1) ;! <OP> AP=AP+2 ;! AP ON <EXPR> 4: IF OPP=0 OR PREC(I)>PREC(OP(OPP)) THEN ->3 ; ! OP STACK EMPTY OR NEW OP HIGHER PREC STORE(OP(OPP),1) ;! UNSTACK TOP OPERATOR OPP=OPP-1 ->4 ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE STORE(INTEGER I,J) ! STORE IN RP & PT ARRAYS, I=ANAL REC PTR , J= OP/OPD FLAG IF RPP>32 THEN START ; ! REV POL ARRAY FULL FAULT(M'EXPR',M' TOO',M' LON',M'G ') RPP=1 ;! IN ORDER TO CONTINUE FINISH RP(RPP)=I ;! STORE OP/OPD PT(RPP)=J ;! STORE FLAG RPP=RPP+1 ;! NEXT POSITION END END ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE PSEVAL ! PSEUDO-EVALUATION, CHECKING OPERANDS INTEGERARRAY PST(1:32) ; ! OPERAND POINTER STACK INTEGER PSTP,I,J,K PSTP=0 ;! PST POINTER I=1 ;! REV POL ARRAY POINTER 3: AP=RP(I) ;! ANAL REC POSITION OF OPERAND IF A(AP)=1 THEN START ; ! OPERAND A NAME J=LINK(A(AP+1)) ;! LINK TO TAG OF NAME IF J=0 THEN START PRINT NAME(A(AP+1)) FAULT(M'NAME',M' NOT',M' SET',0) K=0 ;! DUMMY TAG VALUE ->1 ; FINISH K=TAG(J) ;! TAG OF NAME J=K>>28 ;! 'FORM' OF NAME IF J>1 THEN START ; ! ARRAY OR ROUTINE/FN TYPE RP(I)=AP+1 ;! STORE ANAL REC POSITION OF <NAME> IF J=4 THEN START ; ! NAME IS ROUTINE/FN TYPE IF K>>24&15=0 THEN START PRINT NAME(A(AP+1)) FAULT(M'RT N',M'AME ',M'IN E',M'XPR ') K=0 ;! DUMMY TAG VALUE ->1 ; FINISH PT(I)=-1 ;! FLAG FOR FUNCTION FINISH ELSE PT(I)=-2 ; ! FLAG FOR ARRAY ->2 ; FINISH ; ! GO TO STACK POINTER IF A(AP+2)=1 THEN START PRINT NAME(A(AP+1)) FAULT(M'SCAL',M'AR H',M'AS P',M'ARAM') FINISH 1: RP(I)=K ;! STORE TAG OF NAME FOR SCALARS PT(I)=-3 ;! FLAG FOR SCALARS FINISH ELSE START ; ! OPERAND IS A <CNST> RP(I)=A(AP+1) ;! STORE VALUE OF CONSTANT PT(I)=-4 ;! FLAG FOR CONSTANTS FINISH 2: PSTP=PSTP+1 ;! STACK OPERAND POINTER 4: PST(PSTP)=I I=I+1 ;! REV POL ARRAY POINTER IF I<RPP THEN START ; ! NOT END OF REV POL YET IF PT(I)=0 THEN ->3 ; ! AN OPERAND IS NEXT IF RP(I)<=10 THEN START ; ! BINARY OPERATORS PSTP=PSTP-1 ;! PSEUDO-EVALUATE POINTERS PT(I)=PST(PSTP) ;! STACK POINTER TO RESULT FINISH ->4 ; FINISH END ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE EVAL(INTEGER P) ! DUMP CODE FOR EVALUATION OF EXPRESSION ROUTINESPEC OPN(INTEGER OP,L) INTEGER I,J,K I=PT(P) ;! POINTER/TYPE OF LAST REV POL ENTRY IF I<0 THEN START ; ! OPERAND OPN(0,P) ;! LOAD OPERAND RETURN ; FINISH J=RP(P) ;! OPERATOR K=P-1 ;! START OF 2ND OPERAND IF UCN(J)=1 THEN START ; ! UNARY OPERATOR IF PT(K)>=-2 THEN EVAL(K) ELSE OPN(0,K) ; ! EVAL IF NODE OTHERWISE LOAD OPERAND DUMP(OPR(J),M'ACC',0,0) ;! DUMP UNARY OPERATION RETURN ; FINISH IF PT(I)>=-2 THEN START ; ! FIRST OPERAND A NODE IF PT(K)>=-2 THEN START ; ! SECOND OPERAND A NODE EVAL(K) ;! EVALUATE 2ND OPERAND DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) ;! & STORE IT IN WORKSPACE EVAL(I) ;! EVALUATE 1ST OPERAND WS=WS-1 ;! RESTORE WORKSPACE POINTER DUMP(OPR(J),M'ACC',BR(LEVEL),WS) ;! DUMP OPERATION FINISH ELSE START ; ! 2ND OPERAND NOT A NODE EVAL(I) ;! EVALUATE 1ST OPERAND OPN(J,K) ;! OPERATION WITH 2ND OPERAND FINISH FINISH ELSE START ; ! 1ST OPERAND NOT A NODE IF PT(K)>=-2 THEN START ; ! 2ND OPERAND A NODE EVAL(K) ;! EVALUATE 2ND OPERAND IF UCN(J)=2 THEN START ; ! OPERATOR IS COMMUTATIVE OPN(J,I) ;! OPERATION WITH 1ST OPERAND RETURN ; FINISH DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) ;! STORE VALUE OF 2ND OPERAND IN WORKSPACE OPN(0,I) ;! LOAD 1ST OPERAND WS=WS-1 ;! RESTORE WORKSPACE POINTER DUMP(OPR(J),M'ACC',BR(LEVEL),WS) ;! DUMP OPERATION WITH 2ND OPERAND FINISH ELSE START ; ! 2ND OPERAND NOT A NODE OPN(0,I) ;! LOAD 1ST OPERAND OPN(J,K) ;! OPERATION WITH 2ND OPERAND FINISH FINISH RETURN ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE OPN(INTEGER OP,L) ! DUMP SIMPLE OPERATION, OP=OPERATOR, L=RP POSITION OF OPERAND INTEGER I,J I=PT(L) ;! KIND OF OPERAND AP=RP(L) ;! ANAL REC POINTER OR NAME TAGS IF I=-1 THEN START ; ! ROUTINE/FN TYPE RT ;! DUMP CALL ON FUNCTION RETURN ; FINISH IF I=-2 THEN START ; ! ARRAY ACCESS ARRAD ;! CALCULATE ARRAY ELEMENT ADDRESS DUMP(M'LOAD',M'ACC',M'ACC',0) ;! LOAD VALUE RETURN ; FINISH IF I=-3 THEN START ; ! SCALAR TYPE IF AP>>28=1 THEN START ; ! %NAME TYPE DUMP(M'LOAD',M'WK',BR(AP>>16&15),AP&65535) ;! LOAD INDIRECT DUMP(OPR(OP),M'ACC',M'WK',0) FINISH ELSE DUMP(OPR(OP),M'ACC',BR(AP>>16&15),AP&65535) RETURN ; FINISH IF OP¬=0 OR AP>65535 THEN START ; ! CONSTANT NOT 'LDA'-ABLE J=CT NEXT ;! NEXT HOLE IN CONSTANT TABLE COT(J)=AP ;! STORE VALUE DUMP(OPR(OP),M'ACC',M'CT',J) FINISH ELSE DUMP(M'LDA',M'ACC',0,AP) END END END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE SKIP SEXPR ! SKIP PAST <+-¬><OPD><EXPR> IN ANALYSIS RECORD, AP INITIALLY ON <+-¬> 1: AP=AP+2 ;! AP ON <OPD>+1 IF A(AP-1)=3 THEN SKIP SEXPR ELSE START ; ! SKIP SUB-EXPR ELSE <NAME> OR <CNST> AP=AP+1 ;! AP ON <APP> OR AFTER <CNST> IF A(AP-2)=1 THEN SKIP APP ; ! OPERAND IS A NAME FINISH AP=AP+1 ;! AP AFTER <EXPR> IF A(AP-1)=1 THEN ->1 ; ! MORE OPERANDS END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE SKIP APP ! SKIP PAST <APP> IN ANALYSIS RECORD 1: AP=AP+1 ;! POINTER TO <APP>+1 OR <EXPS>+1 IF A(AP-1)=1 THEN START ; ! EXPRESSIONS TO SKIP SKIP SEXPR ->1 ; FINISH END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE SCCOND(INTEGERNAME LABEL) ! COMPILE CONDITION I.E. <SC><COND>, LABEL SET FOR POSITION AFTER UI ROUTINESPEC SC ROUTINESPEC COND ROUTINESPEC STORE(INTEGER FT) INTEGER I,J,K,L,APP INTEGERARRAY CAP,LVL,TF,JMP,LBL(1:16) ; ! ANAL REC POINTERS, NESTING LEVEL, ;! TRUE/FALSE, JUMP & LABEL ARRAYS I=1 ;! INDEX TO ARRAYS L=0 ;! NESTING LEVEL SC ;! PROCESS <SC> COND ;! PROCESS <COND> APP=AP ;! PRESERVE FINAL ANAL REC POINTER L=-1 STORE(1) ;! PSEUDO-FALSE AT LEVEL -1 L=-2 STORE(2) ;! PSEUDO-TRUE AT LEVEL -2 K=I-1 ;! LAST POSITION FILLED IN IN ARRAYS I=1 2: J=I ;! FIND POSITIONS TO JUMP TO 1: J=J+1 ;! AFTER COMPARISONS IF LVL(J)>=LVL(I) OR TF(J)=TF(I) THEN ->1 ; ! SKIP HIGHER LEVELS ETC JMP(I)=J ;! JUMP TO COMPARISON POSITION J I=I+1 IF I<K THEN ->2 ; ! MORE JUMPS TO FILL IN YET IF A(AP)¬=2 THEN ->3 ; ! UI NOT A JUMP INSTRUCTION AP=AP+1 ;! TO <CONST> J=K-1 ;! LAST POSITION FILLED IN TF(J)=2 ;! SET AS 'TRUE' JMP(J)=J ;! SET JUMP AS THE UI JUMP LBL(J)=FIND LABEL ;! FILL IN BRANCH TABLE POSITION 3: I=1 ;! FILL IN PSEUDO-LABELS FOR INNER JUMPS 4: IF LBL(JMP(I))<0 THEN LBL(JMP(I))=BT NEXT ; ! NEXT BAT POSITION I=I+1 IF I<K THEN ->4 ; ! MORE TO FILL IN I=1 7: AP=CAP(I) ;! ANAL REC POINTER FOR 1ST EXPR OF COMP SCF=1 ;! SET FLAG FOR SEXPR SEXPR ;! TO EVALUATE (1ST - 2ND) IF TF(I)=1 THEN L=FALSE(COMP) ELSE L=TRUE(COMP) DUMP(L,M'ACC',M'BT',LBL(JMP(I))) ;! BRANCH TO REQUIRED POSITION IF LBL(I)>=0 AND (I¬=K-1 OR TF(I)=1) THEN BAT(LBL(I))=CA I=I+1 ;! FILL IN LABEL ADDRESS IF I<K THEN ->7 ; ! MORE COMPARISONS YET LABEL=LBL(K) ;! FINAL LABEL AP=APP ;! FINAL ANALYSIS RECORD POINTER ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE STORE(INTEGER FT) ! STORE LEVEL & TRUE/FALSE FLAG IF I>16 THEN START ; ! ARRAYS FULL FAULT(M'COND',M'N TO',M'O LO',M'NG ') I=1 ;! TO CONTINUE FINISH LVL(I)=L ;! SAVE NESTING LEVEL TF(I)=FT ;! SAVE TRUE/FALSE FLAG LBL(I)=-1 ;! SET 'LABEL NOT FILLED IN YET' FLAG I=I+1 ;! NEXT ARRAY POSITION END ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE SC AP=AP+1 IF A(AP-1)=2 THEN START L=L+1 ;! NESTING LEVEL UP 1 FOR SUB-CONDITION SC ;! PROCESS SUB-<SC> COND ;! PROCESS SUB-<COND> L=L-1 ;! NESTING LEVEL DOWN AFTER SUB-CONDITION FINISH ELSE START CAP(I)=AP ;! ANAL REC POINTER FOR SIMPLE COMPARISON SKIP SEXPR ;! SKIP 1ST EXPR OF COMPARISON AP=AP+1 ;! SKIP COMPARATOR SKIP SEXPR ;! SKIP 2ND EXPR FINISH END ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE COND ! PROCESS <COND> FOR SIMPLE COMPARISONS INTEGER I I=A(AP) ;! <COND> AP=AP+1 ;! AP ON <SC> IF I¬=3 THEN START ; ! NOT NULL ALTERNATIVE OF <COND> 1: STORE(I) ;! SAVE %AND OR %OR TYPE OF CONDITION SC ;! PROCESS <SC> AP=AP+1 ;! POINTER ON <ANDC>+1 OR <ORC>+1 IF A(AP-1)=1 THEN ->1 ; ! MORE %ANDS OR %ORS FINISH END END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE CHECK ! CHECK LABELS ALL SET & STARTS MATCH FINISHES INTEGER I,J I=JUMP(LEVEL) ;! POINTER TO JUMP LIST FOR THIS LEVEL 1: IF I¬=0 THEN START ; ! NO LABELS OR JUMPS USED AT THIS LEVEL IF BAT(TAG(I)&65535)<0 THEN START ; ! LABEL SET INCORRECTLY WRITE(TAG(I)>>16,1) ;! PRINT OUT LABEL NO OF LABEL NOT SET FAULT(M' LAB',M'EL N',M'OT S',M'ET ') FINISH I=RETURN CELL(I) ;! RETURN JUMP LIST CELL TO ASL ->1 ; FINISH I=START(LEVEL) ;! LINK TO START LIST 2: IF I¬=0 THEN START ; ! A CELL STILL IN LIST FAULT(M'%FIN',M'ISH ',M'MISS',M'ING ') I=RETURN CELL(I) ;! POP UP CELL ->2 ; FINISH END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE UNSET ! UNSET NAMES AND CHECK FOR MISSING ROUTINES INTEGER I,J,K I=NAME(LEVEL) ;! NAME LIST POINTER 1: IF I¬=0 THEN START ; ! UNSET NAMES DECLARED AT THIS LEVEL J=TAG(I) ;! NAME IDENT NO K=TAG(LINK(J)) ;! TAG WORD AT TOP OF LIST LINK(J)=RETURN CELL(LINK(J)) ;! POP UP CELL IF K>>28=4 THEN START ; ! ROUTINE/FN TYPE IF BAT(K&65535)<0 THEN START PRINT NAME(J) FAULT(M'ROUT',M'INE ',M'MISS',M'ING ') FINISH K=K>>20&15 ;! NO OF PARAMS 2: IF K¬=0 THEN START ; ! PARAMS PRESENT LINK(J)=RETURN CELL(LINK(J)) ;! POP UP CELLS K=K-1 ;! PARAM COUNT ->2 ; FINISH FINISH IF LINK(J)=0 THEN TAG(J)=0 ; ! A PREVIOUS DECLARATION OF SAME NAME I=RETURN CELL(I) ;! RETURN NAME LIST CELL ->1 ; FINISH END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE PUSH START(INTEGER FLAG,LABEL) ! PUSHDOWN START/FINISH BLOCK INFORMATION INTEGER I I=NEWCELL TAG(I)=FLAG<<16!LABEL&65535 ;! PACK FLAG & LABEL LINK(I)=START(LEVEL) ;! PUSH CELL DOWN START(LEVEL)=I ;! ONTO START LIST END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE ENTER(INTEGER TYPE,ALLOC) ! DUMP CODE FOR NEW LEVEL & INITIALISE LEVEL ARRAYS INTEGER I DUMP(M'STR',BR(LEVEL),M'STP',0) ;! ENTRY SEQUENCE DUMP(M'LDA',BR(LEVEL),M'STP',0) DUMP(M'STR',M'WK',M'STP',1) I=CT NEXT ;! STATIC ALLOCATION HOLE IN CONST TABLE DUMP(M'ADD',M'STP',M'CT',I) STAR(LEVEL)=I ;! REMEMBER POSITION OF HOLE JUMP(LEVEL)=0 ;! NO JUMPS AT NEW LEVEL YET NAME(LEVEL)=0 ;! NO NAMES AT NEW LEVEL YET RTP(LEVEL)=TYPE ;! BLOCK/ROUTINE/FN TYPE CHPP(LEVEL)=CHP ;! SAVE CHARACTER ARRAY POINTER START(LEVEL)=0 ;! NO START/FINISH BLOCKS YET RAD(LEVEL)=ALLOC ;! NEXT RELATIVE ADDRESS TO BE ASSIGNED END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE RETURN ! DUMP CODE FOR %RETURN DUMP(M'LDA',M'STP',BR(LEVEL),0) ;! RESTORE DIJKSTRA DISPLAY DUMP(M'LOAD',BR(LEVEL),M'STP',0) DUMP(M'LOAD',M'WK',M'STP',1) DUMP('B',0,M'WK',0) ;! BRANCH TO RETURN ADDRESS END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE RT ! DUMP CODE FOR A ROUTINE OR FUNCTION CALL INTEGER I,J,K,L,M,N,P I=LINK(A(AP)) ;! LINK TO TAG FOR NAME AP=AP+1 ;! AP ON <APP> J=TAG(I) ;! TAG OF NAME K=J>>20&15+1 ;! NO OF PARAMS +1 1: K=K-1 ;! COUNT PARAMS AP=AP+1 ;! AP ON <APP>+1 IF A(AP-1)=2 THEN START ; ! PARAMS ABSENT OR NO MORE TO PROCESS DUMP(M'BAL',M'WK',M'BT',J&65535) ;! DUMP BRANCH TO ROUTINE/FN IF K>0 THEN FAULT(M'TOO ',M'FEW ',M'PARA',M'MS ') RETURN ; FINISH IF K<=0 THEN START ; ! MORE PARAMS THAN SPEC IF K=0 THEN FAULT(M'TOO ',M'MANY',M' PAR',M'AMS ') ; ! ONLY MONITOR ONCE ->2 ; FINISH I=LINK(I) ;! LINK TO NEXT PARAM CELL L=TAG(I) ;! TAG OF PARAM IF L>>28=0 THEN START ; ! SCALAR VALUE SEXPR ;! COMPILE EXPRESSION ->3 ; FINISH IF A(AP)=4 AND A(AP+1)=1 THEN ->4 ; ! <+-¬> IS NULL & <OPD> IS A NAME 5: FAULT(M'NOT ',M'A NA',M'ME P',M'ARAM') 2: SKIP SEXPR ;! SKIP INVALID PARAM TO CONTINUE ->1 4: M=LINK(A(AP+2)) ;! LINK TO TAG FOR PARAM NAME IF M=0 THEN START PRINT NAME(A(AP+2)) FAULT(M'NAME',M' NOT',M' SET',M' ') ->2 ; FINISH N=TAG(M) ;! TAG OF PARAM NAME IF L>>28=1 THEN START ; ! PARAM IS SCALAR NAME TYPE IF N>>28=4 THEN START ; ! ACTUAL NAME IS ROUTINE/FN TYPE PRINT NAME(A(AP+2)) ->5 ; FINISH IF N>>28>=2 THEN START ; ! ACTUAL NAME IS AN ARRAY AP=AP+2 ;! AP ON <NAME> ARRAD ;! CALCULATE ARRAY ELEMENT ADDRESS AP=AP+1 ;! AP ON <EXPR>+1 - SHOULD BE <EXPS> IF A(AP-1)=1 THEN ->5 ; ! FURTHER OPERAND - INVALID ->3 ; FINISH IF A(AP+3)=1 THEN START ; ! <APP> NOT NULL PRINT NAME(A(AP+2)) FAULT(M'SCAL',M'AR H',M'AS P',M'ARAM') ->2 ; FINISH IF A(AP+4)=1 THEN ->5 ; ! FURTHER OPERANDS - INVALID IF N>>28=1 THEN P=M'LOAD' ELSE P=M'LDA' ; ! LOAD FOR NAME TYPE & LDA FOR VALUE TYPE DUMP(P,M'ACC',BR(N>>16&15),N&65535) FINISH ELSE START ; ! PARAM IS ARRAY NAME IF A(AP+3)¬=2 OR A(AP+4)¬=2 THEN ->5 ; ! <APP> NOT NULL OR MORE OPERANDS IF N>>28&2=0 THEN START ; ! 'FORM' OF ACTUAL IS NOT ARRAY PRINT NAME(A(AP+2)) FAULT(M'NOT ',M'AN A',M'RRAY',M' NME') ->2 ; FINISH IF N>>28=3 THEN START ; ! ACTUAL IS ARRAY NAME M=N&65535 ;! POINTER TO TAG CELL OF PARAM LIST N=TAG(M) ;! CORRECT TAG FOR PARAM FINISH IF N>>20&15¬=L>>20&15 THEN START ; ! DIMENSIONS DIFFERENT IF L>>20&15=0 THEN START ; ! FORMAL PARAM DIMENSION UNKNOWN L=TAG(I)!N&15<<20 ;! FILL FORMAL TAG WITH DIMENSION TAG(I)=L ;! OF ACTUAL PARAM FINISH ELSE START ; ! DIMENSION OF FORMAL KNOWN IF N>>20&15=0 THEN TAG(M)=TAG(M)!L&15<<20 ELSE START ;! FILL IN DIMENSION OF ACTUAL IF UNKNOWN PRINT NAME(A(AP+2)) FAULT(M'ARRA',M'Y DI',M'MENS',M'ION?') ->2 ; FINISH FINISH FINISH DUMP(M'LOAD',M'ACC',BR(N>>16&15),N&65535) IF L>>20&15¬=1 THEN START ; ! NOT 1-DIM ARRAY DUMP(M'STR',M'ACC',M'STP',L&65535) DUMP(M'LOAD',M'ACC',BR(N>>16&15),N&65535+1) L=L+1 FINISH FINISH AP=AP+5 ;! AP ON <EXPS> 3: DUMP(M'STR',M'ACC',M'STP',L&65535) ->1 END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE ARRAD ! DUMP CODE TO CALCULATE ARRAY ELEMENT ADDRESS INTEGER I,J,K,L L=A(AP) I=LINK(L) ;! LINK TO TAG FOR NAME OF ARRAY J=TAG(I) IF J>>28=3 THEN START ; ! NAME IS AN ARRAY NAME I=J&65535 ;! SUBSTITUTE CORRECT TAG VALUE J=TAG(I) FINISH AP=AP+2 ;! AP ON <APP>+1 IF A(AP-1)=1 THEN START ; ! INDEXES PRESENT SEXPR ;! COMPILE EXPR FOR FIRST INDEX AP=AP+1 ;! AP ON <EXPS>+1 IF A(AP-1)=1 THEN START ; ! 2ND INDEX PRESENT DUMP(M'STR',M'ACC',BR(LEVEL),WS NEXT) ;! STORE 1ST INDEX IN WORKSPACE SEXPR ;! COMPILE EXPR FOR 2ND INDEX IF A(AP)=1 THEN START ; ! 3RD INDEX PRESENT PRINT NAME(L) FAULT(M'TOO ',M'MANY',M' IND',M'EXES') SKIP APP ;! SKIP EXCESS INDEXES FINISH ELSE AP=AP+1 ; ! AP AFTER EXPRESSION DUMP(M'MLT',M'ACC',BR(J>>16&15),J&65535) WS=WS-1 ;! RESTORE WORKSPACE POINTER DUMP(M'ADD',M'ACC',BR(LEVEL),WS) DUMP(M'ADD',M'ACC',BR(J>>16&15),J&65535+1) K=2 ;! DIMENSION MARKER FINISH ELSE START ; ! ONLY ONE INDEX PRESENT DUMP(M'ADD',M'ACC',BR(J>>16&15),J&65535) K=1 ;! DIMENSION MARKER FINISH IF K¬=J>>20&15 THEN START ; ! DIMS FOUND DO NOT AGREE WITH TAG IF J>>20&15=0 THEN TAG(I)=TAG(I)!K<<20 ELSE C PRINT NAME(L) FAULT(M'ARRA',M'Y DI',M'MENS',M'ION?') ;! FILL IN DIMS IF UNKNOWN FINISH FINISH ELSE START PRINT NAME(L) FAULT(M'NO A',M'RRAY',M' IND',M'EXES') FINISH END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN BT NEXT ! ALLOCATE NEXT POSITION IN BRANCH TABLE IF BTN>1023 THEN START ; ! FULL FAULT(M'TOO ',M'MANY',M'LABE',M'LS ') BTN=0 ;! TRY TO CONTINUE FINISH BAT(BTN)=-1 ;! MARKER FOR ADDRESS NOT FILLED IN YET BTN=BTN+1 ;! NEXT POSITION RESULT=BTN-1 ; ! THIS POSITION END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN CT NEXT ! ALLOCATE NEXT POSITION IN CONSTANT TABLE IF CTN>1023 THEN START ; ! FULL FAULT(M'TOO ',M'MANY',M' CON',M'STS ') CTN=0 ;! TRY TO CONTINUE FINISH CTN=CTN+1 ;! NEXT POSITION RESULT=CTN-1 ; ! THIS POSITION END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN WS NEXT ! ALLOCATE NEXT WORK SPACE POSITION WS=WS+1 IF WS=11 THEN FAULT(M'COMP',M'ILER',M' WKS',M'PACE') RESULT=WS-1 END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN FIND LABEL ! CHECK & LOCATE OR INSERT LABEL IN JUMP LIST FOR THIS LEVEL INTEGER I,J LABEL=A(AP) ;! VALUE OF CONST AP=AP+1 ;! AFTER <CONST> IF LABEL>>16¬=0 THEN START ; ! INVALID LABEL NUMBER WRITE(LABEL,1) SPACES(2) FAULT(M'INVA',M'LID ',M'LABE',M'L ') RESULT=-1 ; ! 'FAULTY' RESULT FINISH I=JUMP(LEVEL) ;! JUMP LIST POINTER 1: IF I¬=0 THEN START ; ! SOMETHING IN LIST IF LABEL=TAG(I)>>16 THEN RESULT=TAG(I)&65535 ; ! LABEL ALREADY IN I=LINK(I) ;! NEXT CELL IN LIST ->1 ; FINISH I=NEWCELL ;! LABEL NOT IN LIST SO GET NEW CELL J=BT NEXT ;! GET NEXT BRANCH TABLE POSITION TAG(I)=LABEL<<16!J ;! FILL IN LIST ENTRY LINK(I)=JUMP(LEVEL) ;! PUSHDOWN ONTO JUMP LIST JUMP(LEVEL)=I ;! NEW JUMP LIST POINTER RESULT=J ; ! NEW BRANCH TABLE POSITION END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE STORE TAG(INTEGER NAM,FORM,TYPE,DIM,LEV,AD) ! STORE TAGS I.E. SET NAME & CHECK NOT SET ALREADY INTEGER M,N M=LINK(NAM) ;! POINTER TO EXISTING TAGS WORD FOR THIS IF M¬=0 AND LEV=TAG(M)>>16&15 AND FORM¬=4 THEN START PRINT NAME(NAM) FAULT(M'NAME',M' SET',M' TWI',M'CE ') RETURN ; FINISH N=NEWCELL ;! NEW CELL FOR TAGS TAG(N)=FORM<<28!TYPE<<24!DIM<<20!LEV<<16!AD ;! FILL IN TAGS LINK(N)=LINK(NAM) ;! PUSHDOWN ONTO TAGS LIST FOR THIS NAME LINK(NAM)=N N=NEWCELL TAG(N)=NAM ;! PUSHDOWN NEW CELL ONTO NAME LIST LINK(N)=NAME(LEVEL) ;! FOR NAMES DECLARED AT THIS LEVEL NAME(LEVEL)=N END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE DUMP(INTEGER OP,REG,BASE,DISP) ! PRINT OUT CURRENT ADDRESS, OPERATION MNEMONIC & OPERANDS ROUTINESPEC PMN(INTEGER I) INTEGER COM SPACES(10) COM=' ' PMN(OP) ;! OPERATOR MNEMONIC COM=',' PMN(REG) ;! REGISTER MNEMONIC IF DISP>=65536 THEN START PRINT SYMBOL(',') SPACES(7) PRINT NAME(DISP-65536) FINISH ELSE START IF BASE=M'BT' OR BASE=M'CT' OR BASE=M'PRG' THEN START PRINT SYMBOL(',') SPACES(7) FINISH PMN(BASE) ;! BASE MNEMONIC WRITE(DISP,1) ;! DISPLACEMENT FINISH NEWLINE CA=CA+1 ;! INCREMENT CURRENT ADDRESS COUNT ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE PMN(INTEGER I) ! PRINT MNEMONIC - CHARS INTO ONE WORD INTEGER J,K,L J=2 ;! AT LEAST TWO SPACES K=24 ;! FIRST SHIFT VALUE 1: L=I>>K&255 ;! UNPACK NEXT CHARACTER IF L=0 THEN J=J+1 ELSE PRINT SYMBOL(L) K=K-8 ;! NEXT SHIFT VALUE IF K>=0 THEN ->1 ; ! MORE CHARS POSSIBLY YET IF I=M'BT' OR I=M'CT' OR I=M'PRG' THEN C PRINT SYMBOL('+') ELSE START PRINT SYMBOL(COM) SPACES(J) ;! TO ALLIGN FIELDS CORRECTLY FINISH END END END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE FAULT(INTEGER A,B,C,D) ! MONITOR FAULT - A 'PRINT STRING' ROUTINE ROUTINESPEC OUT(INTEGER I) OUT(A) OUT(B) OUT(C) OUT(D) NEWLINE FAULTS=FAULTS+1 ;! INCREMENT FAULT COUNT ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ROUTINE OUT(INTEGER I) ! PRINT OUT PACKED CHARS PRINT SYMBOL(I>>24) PRINT SYMBOL(I>>16&255) PRINT SYMBOL(I>>8&255) PRINT SYMBOL(I&255) END END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN CH NEXT ! ALLOCATE NEXT POSITION IN 'CH' ARRAY IF CHP>512 THEN START ; ! CHARACTER ARRAY FULL FAULT(M'NAME',M'S TO',M'O LO',M'NG ') STOP ; FINISH CHP=CHP+1 RESULT=CHP-1 END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN NEWCELL ! ALLOCATE NEW CELL FOR LIST PROCESSING INTEGER I IF ASL=0 THEN START ; ! END OF AVAILABLE SPACE LIST FAULT(M'ASL ',M'EMPT',M'Y ',M' ') STOP ; FINISH I=ASL ;! POINTER TO TOP CELL OF ASL ASL=LINK(ASL) ;! ASL POINTER TO NEXT CELL DOWN TAG(I)=0 ;! CLEAR NEW CELL OUT LINK(I)=0 RESULT=I ; ! INDEX TO NEW CELL END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! INTEGERFN RETURN CELL(INTEGER I) ! DEALLOCATE CELL AND RETURN IT TO ASL INTEGER J J=LINK(I) ;! PRESENT LINK VALUE OF CELL LINK(I)=ASL ;! LINK TO TOP OF ASL ASL=I ;! ASL POINTER TO RETURNED CELL RESULT=J ; ! RETURN VALUE OF LINK END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ROUTINE PRINT NAME(INTEGER I) ! PRINT NAME FROM HASH POSITION INTEGER J,K,L,M J=TAG(I) ;! POINTER TO CH ARRAY K=CH(J) ;! LENGTH & FIRST 3 CHARS L=K>>24 ;! NUMBER OF CHARS IN NAME M=16 ;! FIRST SHIFT VALUE 1: PRINT SYMBOL(K>>M&255) L=L-1 IF L=0 THEN START SPACES(2) RETURN ; FINISH M=M-8 ;! NEXT SHIFT VALUE IF M<0 THEN START J=J+1 K=CH(J) ;! NEXT WORD OF CHARS M=24 FINISH ->1 END !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ENDOFPROGRAM