bug fix ALLOT
[rrq/rrqforth.git] / compile.asm
index 71393bb31596e6d0e64c22be8316d192da238260..f723487f10e21d2db2aade7576dec84e4f65d392 100644 (file)
        ;; CREATE ( chars* n -- tfa )
        ;; Add the pstring as a new word in the current wordlist.
        pushr rsi
-       mov rax,qword [p_wordlist_DFA] ; Current word list
-       mov rax,[rax]           ; last word of current wordlist
+       mov rdx,qword [p_wordlist_DFA] ; Current word list
        mov rbx,qword [p_here_DFA] 
-       mov [rbx],rax           ; TFA of new word
+       mov rax,qword [rdx]     ; set up tfa linking to previous word
+       mov qword [rbx],rax     ; 
        mov qword [rbx+16],0    ; flags field
        ;; copy pname
        pop rcx                 ; n
        mov qword [rbx+24],rcx  ; PFA (length)
        pop rsi                 ; chars* (source)
        lea rdi,[rbx+32]        ; (dest)
-       ;; clear DF
+       cld
 p_create_COPY:
        movsb
        dec rcx
-       jge p_create_COPY
+       jg p_create_COPY
        mov byte [rdi],0        ; extra NUL
        inc rdi
        mov qword [rdi],rbx     ; pTFA
        add rdi,8
-       mov qword [rdi],rbx     ; OFF
+       mov qword [rdi],0       ; OFF
        add rdi,8
        mov qword [rbx+8],rdi   ; pCFA
+       mov qword [rdi],dovariable ; CFA
        add rdi,8
-       mov qword [rdi],dovalue ;CFA
-       add rdi,8
-       mov qword [rax],rbx     ; Install new word
        mov qword [p_here_DFA],rdi ; allocate the space
+       mov qword [rdx],rbx     ; Install new word (rdx still wordlist ptr)
        push rbx
        popr rsi
        next
 
-       WORD p_allot,'ALLOT',fasm
+       WORD p_allot,'ALLOT'
        ;; ( n -- )
        ;; Allocate n bytes on the heap
-       pop rax
-       add rax,qword [p_here_DFA]
-       mov qword [p_here_DFA],rax
-       next
+       dq p_here, p_swap, p_put_plus, p_return
        
-       WORD p_comma,',',fasm
-       ;; ( v -- )
-       ;; Put cell value onto the heap and advance "HERE"
+       WORD p_quote,"'"
+       ;; ( "word" -- cfa )
+       ;; Find the following word and push its cfa, or 0
+       dq p_input, p_get, p_read_word, p_find
+       BRANCH 0,p_quote_end
+       dq p_tfa2cfa
+p_quote_end:
+       dq p_return
+
+       WORD p_bracketed_quote,"[']",doforth,IMMEDIATE
+       ;; Compilation ( "word" -- cfa )
+       ;; Compile down " LIT value "
+       dq p_literal, p_literal, p_comma,p_quote, p_comma, p_return
+
+       WORD p_Ccomma,'C,',fasm
+       ;; ( c -- )
+       ;; Put byte value onto the heap and advance "HERE"
        mov rax,qword [p_here_DFA]
        pop rbx
-       mov qword [rax],rbx
-       add rax,8
-       mov qword [p_here_DFA],rax
+       mov byte [rax],bl
+       inc qword [p_here_DFA]
        next
-       
-       WORD p_Ccomma,'C,',fasm
+
+       WORD p_Wcomma,'W,',fasm
        ;; ( c -- )
        ;; Put byte value onto the heap and advance "HERE"
        mov rax,qword [p_here_DFA]
        pop rbx
-       mov byte [rax],bl
-       inc rax
-       mov qword [p_here_DFA],rax
+       mov word [rax],bx
+       add qword [p_here_DFA],2
        next
 
-       WORD p_does,'DOES>',fasm,IMMEDIATE
+       WORD p_Dcomma,'D,',fasm
+       ;; ( d -- )
+       ;; Put byte value onto the heap and advance "HERE"
+       mov rax,qword [p_here_DFA]
+       pop rbx
+       mov dword [rax],ebx
+       add qword [p_here_DFA],4
+       next
+
+       WORD p_comma,',',fasm
+       ;; ( v -- )
+       ;; Put byte value onto the heap and advance "HERE"
+       mov rax,qword [p_here_DFA]
+       pop rbx
+       mov qword [rax],rbx
+       add qword [p_here_DFA],8
+       next
+
+       WORD p_does,"DOES>",fasm,IMMEDIATE
        ;; ( -- )
-       ;; Change the "DOES offset" of latest compilation and assign
-       ;; it the "dodoes" execution semantics, 
-       mov rax,qword [p_wordlist_DFA] 
-       mov rax,[rax]           ; last word of current wordlist
+       ;; Change the "DOES offset" of most recent word and assign it
+       ;; the "dodoes" execution semantics that follows.
+       mov rax,qword [rsp]
+       mov rbx,rax
        tfa2does rax            ; *rax is the DOES offset field
-       ;; offset = qword [p_here_DFA]) - (rax+2*8)
-       mov rbx,qword [p_here_DFA]
-       sub rbx,rax
-       sub rbx,16
-       mov qword [rax],rbx
+       tfa2dfa rbx
+       mov rcx,qword [p_here_DFA]
+       sub rcx,rbx
+       mov qword [rax],rcx ; save offset from DFA to HERE
        mov qword [rax+8],dodoes
        next
 
        WORD p_literal,'LIT',fasm
        ;; ( -- v )
-       ;; Push the value of successor cell onto stack, and skip it
+       ;; Push the value of successor cell onto stack, and skip it.
+       ;; not for interactive use!!
        push qword [rsi]
        add rsi,8
        next
 
-       WORD p_literal_string,'S"',fasm
-                                     ;; " (fool emacs)
-       ;; ( -- chars* n )
-       ;; Push the value of successor cell onto stack, and skip it
+       WORD p_literal_string,'LIT-STRING',fasm
+       ;; ( -- char* n )
+       ;; Save NUL string length and pointer on heap to make
+       ;; available at interpretation. Not for interactive use!!
        mov rax,qword [rsi]
        add rsi,8
        push rsi
-       push rax
        add rsi,rax
+       dec rax
+       push rax
        next
 
-;;; ========================================
-;;; The text interpreter
 
+       WORD p_literal_string_compile,'S"',fasm,IMMEDIATE ;; " (fool emacs)
+       ;; ( "..." -- )
+       ;; Lay out a LIT-STRING and a NUL string with length
+       pushr rsi
+       mov rdi,qword [p_here_DFA]
+       mov qword [rdi],p_literal_string
+       add rdi,8
+       mov qword [p_here_DFA],rdi
+       DOFORTH p_double_quote
+       pop rcx
+       pop rsi
+       inc rcx                 ; include the terminating NUL in count
+       mov rdi,qword [p_here_DFA]
+       mov qword [rdi],rcx
+       add rdi,8
+       cld
+p_literal_string_copy:
+       dec rcx
+       jl p_literal_string_copied
+       movsb
+       jmp p_literal_string_copy
+p_literal_string_copied:
+       mov qword [p_here_DFA],rdi
+       popr rsi
+       next
+       
        WORD p_state,'STATE',dovariable
        ;; Interpretation state (0=interpreting, 1=compiling)
        dq 0
 
        WORD p_left_bracket,'[',fasm,IMMEDIATE
        ;; ( -- )
-       ;; Change state to interpretation state.
+       ;; Change state to interpreting state.
        mov qword[p_state_DFA],0
        next
 
@@ -172,6 +223,8 @@ p_number_ALPHA:
        cmp al,'Z'
        jg p_number_alpha
        sub al,'A'-10
+       cmp rax,qword [p_base_DFA]
+       jge p_number_BAD
        jmp p_number_CONSUME
 p_number_alpha:
        cmp al,'a'
@@ -179,6 +232,8 @@ p_number_alpha:
        cmp al,'z'
        jg p_number_BAD
        sub al,'a'-10
+       cmp rax,qword [p_base_DFA]
+       jge p_number_BAD
        jmp p_number_CONSUME
 p_number_BAD:
        push qword 0
@@ -194,6 +249,10 @@ p_numper_POSITIVE:
        popr rsi
        next
 
+       WORD p_input,'INPUT',dovariable
+       ;; The current input stream for evaluate-stream
+       dq 0
+
        WORD p_this_word,'THIS-WORD',dovariable
        dq 0,0                  ; ( n chars* )
 
@@ -201,32 +260,121 @@ p_numper_POSITIVE:
        ;; ( stream* -- *?* flag )
        ;; Execute the words from the given stream
        ;; returns 1 if stream ends and 0 if an unknown word is found
-       dq p_ltR                ; Keep the stream on the return stack.
+       dq p_input, p_get, p_gtR ; save old stream on R-stack
+       dq p_input, p_put
+p_evaluate_stream_PROMPT:
+       dq p_verboseQ, p_get
+       BRANCH 0,p_evaluate_stream_LOOP
+       dq p_depth, p_dot
+       dq p_literal_string
+       STRING '> '
+       dq p_tell
+       dq p_input, p_get
+       dq p_clear_stream
 p_evaluate_stream_LOOP:
-       dq p_Rget               ; ( -- stream*
-       dq p_read_word          ; ( -- chars* n )
+       dq p_input, p_get
+       dq p_read_word
        dq p_dup
        BRANCH 0,p_evaluate_stream_END ; branch if 0 on TOP
-       dq p_2dup               ; ( -- chars* n chars* n )
-       dq p_this_word          ; ( -- chars* n chars* n p )
-       dq p_2put               ; ( -- chars* n )
-       dq p_find               ; ( -- [ chars* n 0 ]/[ tfa ] )
-       dq p_dup                ; ( -- [ chars* n 0 0 ]/[ tfa tfa ] )
+       dq p_2dup, p_this_word, p_2put
+       dq p_find
+       dq p_dup
        BRANCH 0,p_evaluate_stream_NOTWORD ; branch if 0 on TOP
-       dq p_execute            ; consumes tfa
-       BRANCH ,p_evaluate_stream_LOOP
+       dq p_state
+       dq p_get
+       BRANCH 0,p_evaluate_stream_INTERPRET
+       dq p_dup
+       dq p_tfa2flags_get
+       dq p_literal, 1 ; the immediate bit
+       dq p_and
+       BRANCH 0,p_evaluate_stream_COMPILE
+p_evaluate_stream_INTERPRET:
+       dq p_tfa2cfa
+       dq p_execute
+       BRANCH ,p_evaluate_stream_AFTER
+p_evaluate_stream_COMPILE:
+       dq p_tfa2cfa
+       dq p_comma
+       BRANCH ,p_evaluate_stream_AFTER
 p_evaluate_stream_NOTWORD:
-       dq p_drop               ; ( -- chars* n )
-       dq p_number             ; ( -- [ 0 ]/[ v 1 ] )
+       dq p_drop
+       dq p_number
        dq p_dup
        BRANCH 0,p_evaluate_stream_BAD ; branch if 0
        dq p_drop
+       dq p_state, p_get
+       BRANCH 0,p_evaluate_stream_AFTER ; branch if 0
+       dq p_literal, p_literal
+       dq p_comma, p_comma
+p_evaluate_stream_AFTER:
+       dq p_input, p_get
+       dq p_stream_nchars
+       BRANCH 0,p_evaluate_stream_PROMPT
        BRANCH ,p_evaluate_stream_LOOP
 p_evaluate_stream_END:
        dq p_2drop
-       dq p_literal
-       dq 1
+       dq p_literal, 1
 p_evaluate_stream_BAD:
-       dq p_Rgt                ; Discard the stream from the return stack
-       dq p_drop
-       dq p_exit
+       dq p_Rgt, p_input, p_put ; restore previous stream
+       dq p_literal,0, p_state, p_put ; set interactive mode
+       dq p_return
+
+       WORD p_colon,':'
+       ;; ( -- )
+       ;; Read next word as a new word into current wordlist, set it
+       ;; to be a doforth word, and set compiling mode.
+       dq p_literal, doforth
+       dq p_input, p_get
+       dq p_read_word
+       dq p_create
+       dq p_tfa2cfa
+       dq p_put
+       dq p_right_bracket
+       dq p_return
+
+       WORD p_semicolon,';',,IMMEDIATE
+       ;; ( -- )
+       ;; Lay out p_return, and set interpreting mode
+       dq p_literal, p_return, p_comma, p_left_bracket, p_return
+
+       WORD p_immediate,'IMMEDIATE',fasm,IMMEDIATE
+       ;; ( -- )
+       ;; Set "immediate flag" of the word being defined
+       mov rax,qword [p_wordlist_DFA]
+       mov rax,qword [rax]     ; tfa of most recent word
+       mov qword [rax+16],1    ; set the flags field to 1
+       next
+
+       WORD p_load_buffer_size,'LOAD-BUFFER-SIZE',dovariable
+       ;; ( -- a )
+       ;; The buffer size (in bytes) used by LOAD-FILE
+       dq 15000
+       
+       WORD p_open_file,'OPEN-FILE',fasm
+       ;; ( chaz* n -- fd )
+       ;; Open the nominated file
+       pushr rsi
+       add rsp,8 ; drop n ... assuming NUL-ended string
+       push qword 0
+       push qword 0
+       DOFORTH sys_open
+       popr rsi
+       next
+
+       WORD p_load_file,'LOAD-FILE'
+       ;; ( chaz* n -- )
+       dq p_open_file
+       dq p_dup, p_0less
+       BRANCH 1,p_load_file_badfile
+       dq p_load_buffer_size, p_get
+       dq p_stream, p_dup, p_gtR
+       dq p_evaluate_stream
+       dq p_Rgt, p_unstream
+       BRANCH ,p_load_file_exit
+p_load_file_badfile:
+       dq p_literal_string
+       STRING '** open file error: '
+       dq p_tell, p_dot, p_nl, p_emit
+       dq p_literal,1
+p_load_file_exit:
+       dq p_return