TITLE "mp6.a - interpreter for a plotter language" ; plots as commanded by DATA, an external array of strings ; this version is an expansion of the code from MP4 and MP5 ; by Douglas Jones -- Nov 15, 2010 ; Note that this solution does not handle all possible ; problems, but that it does handle the issues explicitly ; mentioned in the written version of the assignment. ; This version completed Dec 1, 2010:w S START USE "hawk.macs" ; macros to make long conditional jumps ; (these might be useful addition to hawk.macs?) MACRO JLTU LABEL BGEU .+6 JUMP LABEL ENDMAC MACRO JGTU LABEL BLEU .+6 JUMP LABEL ENDMAC MACRO JGE LABEL BLT .+6 JUMP LABEL ENDMAC MACRO JNE LABEL BEQ .+6 JUMP LABEL ENDMAC MACRO JLE LABEL BGT .+6 JUMP LABEL ENDMAC MACRO JEQ LABEL BNE .+6 JUMP LABEL ENDMAC ; end of long conditional jump macros USE "monitor.h" USE "exceptions.h" EXT UNUSED EXT DATA SUBTITLE "Main Program" ; global variables COMMON EXCEPTION, EXSIZE ; local variables of main program DATAPTR = 0 ARSIZE = 4 ; the program starts here! START: LIL R2,UNUSED ; set up the stack LIL R1,DSPINI JSRS R1,R1 ; initialize the display ; --- begin aplication code ; optimizing the code brings this outside the loop LIL R3,EXCEPTION ; -- setup to handle exceptions STORE R2,R3,EXAR ; exception.exar = here LEA R4,MAINHAN STORE R4,R3,EXHAND ; exception.exhand = mainhan LIL R3,DATA ; p = data MAINLP: ; for (;;) { STORE R3,R2,DATAPTR ; -- save p LOADSCC R3,R3 ; s = *p -- parameter, pointer string BZS MAINQT ; if (s == NULL) break ; try { LIS R4,0 ; -- parameter x coord LIS R5,0 ; -- parameter y coord LIS R6,0 ; -- parameter a accumulator LIS R7,0 ; -- parameter null terminator ADDI R2,R2,ARSIZE JSR R1,INTERPRETER ; interpreter( s, 0, 0, 0, null ) ADDI R2,R2,-ARSIZE MAINHAN: ; } catch { nothing } LOAD R3,R2,DATAPTR ; -- recover p ADDSI R3,4 ; p++ BR MAINLP MAINQT: ; } ; --- end aplication code LIL R1,EXIT JSRS R1,R1 ; stop! SUBTITLE "Interpreter for funny strings" ; activation record for INTERPRETER ;RETAD = 0 STRING = 4 ; string pointer XCOORD = 8 ; x coordinate YCOORD = 12 ; y coordinate ACC = 16 ; a accumulator ENDCHAR = 20 ; the character expected at the end ARSIZE = 24 INTERPRETER: ; expects R3, s string pointer ; expects R4, x coordinate ; expects R5, y coordinate ; expects R6, a accumulator ; expects R7, endchar, the permitted terminator ; returns R3, s updated ; returns R6, a updated ; wipes out R4-8 ; call dspch for each char in string ; calls itself recursively to handle parentheses STORES R1,R2 STORE R7,R2,ENDCHAR INTERLP: ; for (;;) { LOADS R7,R3 ; -- get word holding char EXTB R7,R7,R3 ; char = *s ; -- through rest of loop, ; -- R3=s, R4=x, R5=y, R6=a, R7=char CMPI R7," " JLTU INTERQT ; if (char < ' ') break out of loop ADDSI R3,1 ; s++ -- delayed to here so won't skip nulls ; select (char) { CMPI R7,"z" JGTU INTELSE ; -- if (char > 'z') goto else case ADDI R8,R7,-"(" JLTU INTELSE ; -- if (char < '(') goto else case ; -- 83 cases remain LEA R1,INTTABLE ADDSL R8,R1,2 LOADS R1,R8 ; -- R1 = INTTABLE[R7] JUMPS R1 ALIGN 4 ; jump table for case select construct INTTABLE: ; ( ) * + , - . / W INTLPAR,INTRPAR,INTELSE,INTPLUS,INTELSE,INTMINS,INTELSE,INTELSE ; 0 1 2 3 4 5 6 7 W INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI,INTDIGI ; 8 9 : ; < = > ? W INTDIGI,INTDIGI,INTELSE,INTELSE,INTLT ,INTEQ ,INTGT ,INTELSE ; @ A B C D E F G W INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE ; H I J K L M N O W INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE ; P Q R S T U V W W INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE,INTELSE ; X Y Z [ \ ] ^ _ W INTELSE,INTELSE,INTELSE,INTLBRK,INTELSE,INTRBRK,INTELSE,INTELSE ; ` a b c d e f g W INTELSE,INTELSE,INTELSE,INTCLR ,INTDOWN,INTELSE,INTELSE,INTELSE ; h i j k l m n o W INTELSE,INTELSE,INTELSE,INTELSE,INTLEFT,INTELSE,INTELSE,INTELSE ; p q r s t u v w W INTELSE,INTELSE,INTRIGT,INTELSE,INTELSE,INTUP ,INTELSE,INTELSE ; x y z W INTX ,INTY ,INTZERO ; cases for MP5 ; -- R3=s, R4=x, R5=y, R6=a, R7=char INTCLR: ; case "c" LIS R6,0 ; a = 0 JUMP INTESAC ; break INTDIGI: ; cases "0" - "9" SL R6,1 ADDSL R6,R6,2 ; a = a * 10 ADDI R8,R7,-"0" ADD R6,R6,R8 ; a = a + (char - "0") JUMP INTESAC ; break INTX: ; case "x" MOVE R4,R6 ; x = a JUMP INTESAC ; break INTY: ; case "y" MOVE R5,R6 ; y = a JUMP INTESAC ; break INTPLUS: ; case "+" ADD R6,R4,R5 ; a = x+y JUMP INTESAC ; break INTMINS: ; case "-" SUB R6,R4,R5 ; a = x-y JUMP INTESAC ; break INTGT: ; case ">" TESTR R6 JLE INTESAC BR INTGELCOM ; if (a > 0) do common code INTEQ: ; case "=" TESTR R6 JNE INTESAC BR INTGELCOM ; if (a = 0) do common code INTLT: ; case "<" TESTR R6 JGE INTESAC ; if (a < 0) do common code INTGELCOM: ; common code for "<" "=" ">" skips LOADS R7,R3 ; -- get word holding char EXTB R7,R7,R3 ; char = *s JEQ THROW ; if (char = null) throw exception CMPI R7,")" JEQ THROW ; if (char = ")") throw exception CMPI R7,"(" JEQ THROW ; if (char = "(") throw exception ADDSI R3,1 ; s++ JUMP INTESAC ; break INTLBRK: ; case "[" -- skip forward over ] LIS R1,0 ; nest = 0 INTLBRLP: ; do { LOADS R7,R3 ; -- get word holding char EXTB R7,R7,R3 ; char = *s CMPI R7," " JLTU THROW ; if (char < ' ') throw exception ADDSI R3,1 ; s++ -- delayed past check for null CMPI R7,"[" BNE INTLBRB ADDSI R1,1 ; if (char = "[") nest ++; INTLBRB: CMPI R7,"]" BNE INTLBLB ADDSI R1,-1 ; if (char = "]") nest --; INTLBLB: TESTR R1 BGE INTLBRLP ; } until (nest < 0) JUMP INTESAC ; break INTRBRK: ; case "]" -- skip backward until [ LIS R1,0 ; nest = 0 ADDSI R3,-1 ; s-- -- s now points to this ] INTRBRLP: ; do { ADDSI R3,-1 ; s-- -- look at previous character LOADS R7,R3 ; -- get word holding char EXTB R7,R7,R3 ; char = *s CMPI R7," " JLTU THROW ; if (char < ' ') throw exception CMPI R7,"]" BNE INTRBLB ADDSI R1,1 ; if (char = "]") nest ++; INTRBLB: CMPI R7,"[" BNE INTRBRB ADDSI R1,-1 ; if (char = "[") nest --; INTRBRB: TESTR R1 BGE INTRBRLP ; } until (nest < 0) ADDSI R3,1 ; s++ -- we wanted to stop sooner! JUMP INTESAC ; break ; cases for MP4 ; -- R3=s, R4=x, R5=y, R6=a, R7=char INTRPAR: ; case ")" BR INTERQT ; break out of loop; INTZERO: ; case "z" LIS R4,0 ; x = 0 LIS R5,0 ; y = 0 JUMP INTESAC ; break INTUP: ; case "u" ADDSI R5,-1 ; y-- JUMP INTESAC ; break INTDOWN: ; case "d" ADDSI R5,1 ; y++ JUMP INTESAC ; break INTLEFT: ; case "l" ADDSI R4,-1 ; x-- JUMP INTESAC ; break INTRIGT: ; case "r" ADDSI R4,1 ; x++ JUMP INTESAC ; break INTLPAR: ; case "(" STORE R4,R2,XCOORD STORE R5,R2,YCOORD ; -- save coords through call LIS R7,")" ; -- parameter ADDI R2,R2,ARSIZE JSR R1,INTERPRETER ; s = interpreter( s, x, y, a, ")" ) ADDI R2,R2,-ARSIZE LOAD R4,R2,XCOORD LOAD R5,R2,YCOORD ; -- restore coords after call JUMP INTESAC ; break INTELSE: ; } else { STORE R3,R2,STRING STORE R4,R2,XCOORD STORE R5,R2,YCOORD STORE R6,R2,ACC ; -- save everything through calls MOVE R8,R7 MOVECC R3,R4 ; -- shove x param into place BNS THROW ; if (x < 0) throw exception MOVECC R4,R5 ; -- shove y param into place BNS THROW ; if (y < 0) throw exception ADDI R2,R2,ARSIZE LIL R1,DSPAT JSRS R1,R1 ; dspat( x,y ) MOVE R3,R8 ; -- recover saved char LIL R1,DSPCH JSRS R1,R1 ; dspch( char ) ADDI R2,R2,-ARSIZE LOAD R3,R2,STRING LOAD R4,R2,XCOORD LOAD R5,R2,YCOORD LOAD R6,R2,ACC ; -- restore everything after calls JUMP INTESAC ; break INTESAC = INTERLP ; } INTERQT: ; } -- R3=s, R4=x, R5=y, R6=a, R7=char LOAD R1,R2,ENDCHAR CMP R1,R7 BNE THROW ; if (char != endchar) throw exception LOADS R1,R2 JUMPS R1 ; return s and a THROW: LIL R3,EXCEPTION ; -- setup to throw exception LOAD R2,R3,EXAR ; here = exception.exar LOAD R1,R3,EXHAND ; exception.exhand = mainhan JUMPS R1 ; throw the exception END