⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interpreter.inc

📁 This a basic compiler for MSP430
💻 INC
📖 第 1 页 / 共 5 页
字号:
x_while_00:
        call    #eval_expr                   ; evaluate test expression
        bis.w   r14, r15
        cmp.w   #0, r15                      ; result is zero?
        jnz     term                         ; ...no, continue loop
        add.w   #6, sp                       ; ...yes, drop loop type, tp, and lp
        mov.w   #T_WEND, r11                 ; search for a matching WEND
        call    #find_control_match
        jnc     while_without_matching_end_while_error
        mov.b   @tp+, r4
        jmp     term

; WEND
x_wend:
        cmp.w   #T_WHILE, @sp                ; is control structure WHILE?
        jnz     end_while_without_while_error; ...no, report error
        mov.w   2(sp), lp                    ; ...yes, restore context to that following WHILE
        mov.w   4(sp), tp
        mov.b   -1(tp), r4
        jmp     x_while_00                   ; re-evaluate expression

; REPEAT ... UNTIL cond
x_repeat:
        push.w  tp                           ; stack interpreter's context
        push.w  lp
        push.w  #T_REPEAT                    ; indicate that this is a REPEAT loop
        jmp     term                         ; ensure that statement is correctly terminated

x_until:
        cmp.w   #T_REPEAT, @sp               ; control structure is REPEAT?
        jnz     until_without_repeat_error   ; ...no, report error
        call    #eval_expr                   ; ...yes, evaluate control expression
        bis.w   r14, r15
        cmp.w   #0, r15                      ; result is true (non-zero)?
        jnz     x_until_10                   ; ...yes, exit the repeat loop
        mov.w   2(sp), lp                    ; ...no, restore interpreter context
        mov.w   4(sp), tp
        mov.b   -1(tp), r4                   ; prime R4 with character following REPEAT
        jmp     term                         ; ensure that statement is correctly terminated
x_until_10:
        add.w   #6, sp                       ; remove REPEAT context
        jmp     term                         ; ensure that statement is correctly terminated

; EXIT FOR
x_exit_for:
        call    #end_of_statement            ; anything after EXIT FOR?
        jnz     syntax_error                 ; ...yes, syntax error
        mov.w   #T_FOR, r11                  ; ...no, find a matching FOR loop
        jmp     x_exit_10

; EXIT REPEAT
x_exit_repeat:
        call    #end_of_statement            ; anything after EXIT REPEAT?
        jnz     syntax_error                 ; ...yes, syntax error
        mov.w   #T_REPEAT, r11               ; ...no, find a matching REPEAT loop
        jmp     x_exit_10

; EXIT WHILE
x_exit_while:
        call    #end_of_statement            ; anything after EXIT WHILE?
        jnz     syntax_error                 ; ...yes, syntax error
        mov.w   #T_WHILE, r11                ; ...no, find a matching WHILE loop

x_exit_10:
        cmp.w   @sp, r11                     ; matched structure?
        jz      x_exit_30                    ; ...yes, transfer control out of loop
        cmp.w   #T_END, @sp                  ; searched whole stack?
        jz      exit_not_in_loop_error       ; ...yes, not found so emit invalid exit
        cmp.w   #T_GOSUB, @sp
        jz      exit_not_in_loop_error
        cmp.w   #T_RESUME, @sp
        jz      exit_not_in_loop_error
        add.w   #6, sp                       ; 6 bytes are stacked for WHILE/REPEAT loops
        cmp.w   #T_FOR, @sp
        jnz     x_exit_10
        add.w   #6, sp                       ; 12 bytes are stacked for a FOR loop
        jmp     x_exit_10

x_exit_30:
        cmp.w   #T_WHILE, r11                ; WHILE-WEND loop?
        jnz     x_exit_40
        mov.w   #T_WEND, r11                 ; search for a matching WEND
x_exit_40:
        cmp.w   #T_FOR, r11                  ; FOR-NEXT loop?
        jnz     x_exit_50
        mov.w   #T_NEXT, r11                 ; search for a matching NEXT
x_exit_50:
        cmp.w   #T_REPEAT, r11               ; REPEAT-UNTIL loop?
        jnz     x_exit_60
        mov.w   #T_UNTIL, r11                ; search for a matching UNTIL
x_exit_60:
        mov.w   2(sp), lp                    ; get token pointer and line pointer of
        mov.w   4(sp), tp                    ; token immediately following WHILE/REPEAT/FOR
        call    #find_control_match
        jnc     exit_not_in_loop_error
        mov.b   @tp+, r4
        add.w   #6, sp                       ; remove structure parameters from stack
        cmp.w   #T_NEXT, r11                 ; FOR-NEXT loop stores a bit more context
        jnz     term
        add.w   #6, sp
        jmp     term

find_control_match:
        push.w  lp                           ; save line pointer for error message if we can't find the endpoint
        push.w  #T_END                       ; push delimiter
find_control_match_00:
        cmp.w   #T_WHILE, r4                 ; start of a WHILE-WEND?
        jz      open_control
        cmp.w   #T_FOR, r4                   ; start of a FOR-NEXT?
        jz      open_control
        cmp.w   #T_REPEAT, r4                ; start of a REPEAT-UNTIL?
        jz      open_control
        cmp.w   #T_END, @sp                  ; everything closed?
        jnz     find_control_match_10
        cmp.w   r4, r11                      ; matched the terminator we're looking for?
        jnz     find_control_match_10        ; no, try other terminators
        add.w   #4, sp                       ; remove T_END and lp from stack
        setc
        ret                                  ; return with LP and TP set appropriately and C=1

find_control_match_10:
        cmp.w   #T_NEXT, r4                  ; close FOR-NEXT structure?
        jz      close_for                    ; yes
        cmp.w   #T_WEND, r4                  ; close WHILE-WEND structure?
        jz      close_while                  ; yes
        cmp.w   #T_UNTIL, r4                 ; close REPEAT-UNTIL structure?
        jz      close_repeat                 ; yes
        jmp     open_control_00              ; no, consider next token

open_control:
        push.w  r4
open_control_00:
        cmp.b   #0, r4
        mov.b   @tp+, r4
        jnz     find_control_match_00
        cmp.w   #0, lp
        jz      unterminated_structure
        mov.w   @lp, lp
        mov.w   lp, tp
        add.w   #4, tp
        mov.b   @tp+, r4
        jmp     find_control_match_00
close_for:
        pop.w   r15
        cmp.w   #T_FOR, r15
        jnz     next_without_for_error
        jmp     open_control_00
close_while:
        pop.w   r15
        cmp.w   #T_WHILE, r15
        jnz     end_while_without_while_error
        jmp     open_control_00
close_repeat:
        pop.w   r15
        cmp.w   #T_REPEAT, r15
        jnz     until_without_repeat_error
        jmp     open_control_00

; Clear unclosed structures from stack
unterminated_structure:
        mov.w   @sp, r4                      ; get the structure which is unterminated
unterminated_structure_10:
        pop.w   r15
        cmp.w   #T_END, r15
        jnz     unterminated_structure_10
        pop.w   lp
        clrc
        ret

; END
x_end:
        call    #end_of_statement            ; anything after EXIT REPEAT?
        jnz     syntax_error                 ; ...yes, syntax error
        mov.w   #END_OF_RAM, sp              ; FIXME
        jmp     ready                        ; ended, so terminate

; FOR var = init TO final
x_for:
        call    #is_letter
        jnc     syntax_error
        mov.b   @tp+, r7
        cmp.w   #T_EQ, r7
        jnz     syntax_error
        sub.w   #'A', r4
        add.w   r4, r4
        add.w   r4, r4
        mov.w   r4, r11
        call    #get_eval_expr
        mov.w   r14, vars(r11)
        mov.w   r15, vars+2(r11)
        cmp.w   #T_TO, r4
        jnz     syntax_error
        call    #get_eval_expr
        push.w  r15                          ; limit           +10
        push.w  r14                          ;                 +8
        push.w  r11                          ; variable offset +6
        push.w  tp                           ; token pointer   +4
        push.w  lp                           ;                 +2
        push.w  #T_FOR
        jmp     term

x_next:
        cmp.w   #T_FOR, @sp                  ; is control structure FOR?
        jnz     next_without_for_error       ; ...no, report error
        mov.w   6(sp), r11                   ; pointer to variable
        add.w   #1, vars(r11)                ; increment variable
        addc.w  #0, vars+2(r11)
        mov.w   8(sp), r14                   ; get limit
        mov.w   10(sp), r15
        sub.w   vars(r11), r14               ; subtract current value
        subc.w  vars+2(r11), r15
        jnc     x_next_terminate_loop        ; if passed limit, terminate loop
        mov.w   4(sp), tp                    ; restore context
        mov.w   2(sp), lp
        mov.b   -1(tp), r4
        jmp     term                         ; continue with loop
x_next_terminate_loop:
        add.w   #6*2, sp                     ; remove FOR context
        jmp     term                         ; continue with statement after NEXT

; ON BREAK stmt
; ON X GOTO l1, l2, ... ELSE ...
x_on:
        cmp.w   #T_BREAK, r4                 ; check for ON BREAK
        jz      x_on_break
        call    #eval_expr                   ; evaluate control expression X
        mov.w   r14, r11
        cmp.w   #T_GOTO, r4                  ; require GOTO
        jnz     syntax_error
x_on_goto_00:
        mov.b   @tp+, r4                     ; get token after GOTO
        cmp.b   #0, r4                       ; on end of statement, continue execution
        jz      term
        cmp.b   #':', r4
        jz      term
        cmp.b   #T_ELSE, r4                  ; got to end of list without a match, but have an ELSE?
        jz      x_if_10                      ; ...yes, treat ELSE like IF's THEN allowing e.g. ELSE 100 or ELSE PRINT Y
        call    #eval_expr                   ; evaluate line number
        sub.w   #1, r11                      ; this label index matches control expression?
        jz      x_goto_00                    ; yes
        cmp.b   #',', r4                     ; more in the list
        jz      x_on_goto_00                 ; yep, try to match another
        cmp.b   #T_ELSE, r4                  ; got to end of list without a match, but have an ELSE?
        jz      x_if_10                      ; ...yes, treat ELSE like IF's THEN allowing e.g. ELSE 100 or ELSE PRINT Y
	jmp     term
x_on_break:
        mov.w   tp, &break_tp
        mov.w   lp, &break_lp
        jmp     x_rem

; IF expr THEN [stmt | number]
; IF expr [THEN] stmt
x_if:
        call    #eval_expr                   ; evaluate control expr
        bis.w   r14, r15                     ; controlling expression is false?
        cmp.w   #0, r15
        jz      x_rem                        ; ...yes, skip whole line
        cmp.w   #T_THEN, r4                  ; THEN?
        jnz     chrgot                       ; ...no, THEN is omitted, so next is a statement
x_if_10:
        mov.b   @tp+, r4                     ; get token following THEN
        call    #is_digit                    ; is it a digit?
        jc      x_goto                       ; ...yes, assume it's a line number and use GOTO
        jmp     chrgot

; INPUT [#channel, ] [string,] var [, string], var...
x_input:
        mov.w   #1, r15                      ; default to channel 1 if no channel number given
        call    #select_channel
        cmp.w   #'#', r4                     ; channel number being specified?
        jnz     x_input_10                   ; ...no, so just use default
        call    #get_eval_expr               ; evaluate the channel number
        mov.w   r14, r15                     ; only use the low 16 bits of the channel number
        call    #select_channel              ; select the channel, error if it's bad
x_input_00:
	call	#check_comma                 ; a comma must come next
x_input_10:
        cmp.b   #'"', r4                     ; string?
	jnz     x_input_20                   ; ...no, it must be a variable
	call    #print_quoted_string         ; print the prompt string
	call	#check_comma                 ; a comma must come next
	jmp     x_input_30                   ; do the input
x_input_20:
        mov.w   #'?', r15                    ; default prompt is just '?'
	call    #print_char
x_input_30:
	call	#varptr                      ; get variable we're inputting
	cmp.w   #4, r15                      ; only allow READ on word variables
	jnz     syntax_error
x_input_35:
	mov.w   r14, r11                     ; save for later use
	call    #get_string                  ; read the input to ramtop
	mov.w   &ramtop, r10                 ; get ready to parse input
x_input_40:
	mov.b   @r10+, r4                    ; get character from input buffer
	cmp.b   #' ', r4                     ; space?
	jz      x_input_40                   ; ...yes, skip them
	cmp.b   #0, r4                       ; nothing on line?
	jz      x_input_50                   ; ...no, try again
	call    #is_digit                    ; leading digit?
	jnc     x_input_50                   ; ...no, print bad data error and try again
        push.w  tp                           ; save interpreter's token pointer
	mov.w   r10, tp                      ; prepare to parse number from buffer
	call    #read_int                    ; do the parsing
	mov.w   r14, @r11                    ; store read value
	mov.w   r15, 2(r11)
	pop.w   tp                           ; restore interpreter's token pointer
	mov.b   -1(tp), r4                   ; refresh context
	call    #end_of_statement            ; end of statement looming?
	jz      term                         ; ...yes, execute next statement
	jmp     x_input_00
x_input_50:
	mov.w   #bad_input_error_message, r15; print bad input error
	call    #print_message
        mov.w   #'?', r15                    ; repeat default prompt
	call    #print_char
	jmp     x_input_35                   ; try again

; PRINT expr [, | ;] expr...
x_print:
        mov.w   #0, r11                      ; r11 is "hold CR" flag
        mov.w   #1, r15                      ; default to channel 1 if no channel number given
        call    #select_channel
        cmp.w   #'#', r4                     ; channel number being specified?
        jnz     x_print_02                   ; ...no, so just use default
        call    #get_eval_expr               ; evaluate the channel number
        mov.w   r14, r15                     ; only use the low 16 bits of the channel number
        call    #select_channel              ; select the channel, error if it's bad
        jmp     x_print_50                   ; see if ',' or anything terminates the statement early
x_print_00:
	mov.b	#9, r15                      ; print tab on ','
	call	#print_char
x_print_01:
        mov.b   @tp+, r4                     ; get next token
x_print_02:
        cmp.w   #T_AT, r4                    ; AT?
        jnz     x_print_03                   ; ...no, continue to decode it
        call    #get_eval_expr               ; evaluate positional expression
        call    #print_at                    ; position cursor
        jmp     x_print_40                   ; deal with terminators
x_print_03:
        cmp.b   #'"', r4                     ; printing a string?
        jne     x_print_20                   ; ...no, continue to decode it
	call    #print_quoted_string         ; print the string
        jmp     x_print_35                   ; continue parsing
x_print_10:
        mov.b   @tp+, r4                     ; get next token

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -