add DEPTH
[rrq/rrqforth.git] / compile.asm
index 1e76aeea96c355beec402cc9f59d3667526cbbad..71393bb31596e6d0e64c22be8316d192da238260 100644 (file)
@@ -4,14 +4,10 @@
        ;; The heap
        dq heap_start
        
-       ;; CREATE ( "[ \t\0]*([^ \t\0]+)" -- tfa )
-       ;; Skip leading whitespace and scan following non-whitespace
-       ;; as being a "word" to add into the current vocabulary. Add
-       ;; that word header, which consisits of:
        WORD p_create,'CREATE',fasm
+       ;; CREATE ( chars* n -- tfa )
+       ;; Add the pstring as a new word in the current wordlist.
        pushr rsi
-       push p_stdin_DFA        ; ( -- stream )
-       DOFORTH p_read_word     ; ( -- chars* n ) read next word
        mov rax,qword [p_wordlist_DFA] ; Current word list
        mov rax,[rax]           ; last word of current wordlist
        mov rbx,qword [p_here_DFA] 
@@ -51,26 +47,186 @@ p_create_COPY:
        mov qword [p_here_DFA],rax
        next
        
-       ;; DOES> ( -- )
-       ;; Change DOES offset of latest compilation word to current
-       ;; compilation address.
-       ;; LATEST @ TFA>DOES HERE @ OVER - SWAP !
-       WORD p_does,'DOES>',fasm
+       WORD p_comma,',',fasm
+       ;; ( v -- )
+       ;; Put cell 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
+       next
+       
+       WORD p_Ccomma,'C,',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
+       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
-       add rax,8
-       ;add rax,byte [rax]
-       add rax,1
-       mov rbx,[p_here_DFA]
+       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
        mov qword [rax+8],dodoes
        next
-       
-       WORD p_literal,'LIT',IMMEDIATE
-       dq p_create
-       dq p_does
-       dq p_get
-       dq p_exit
-       
-       WORD p_execute,'EXECUTE'
 
+       WORD p_literal,'LIT',fasm
+       ;; ( -- v )
+       ;; Push the value of successor cell onto stack, and skip it
+       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
+       mov rax,qword [rsi]
+       add rsi,8
+       push rsi
+       push rax
+       add rsi,rax
+       next
+
+;;; ========================================
+;;; The text interpreter
+
+       WORD p_state,'STATE',dovariable
+       ;; Interpretation state (0=interpreting, 1=compiling)
+       dq 0
+
+       WORD p_left_bracket,'[',fasm,IMMEDIATE
+       ;; ( -- )
+       ;; Change state to interpretation state.
+       mov qword[p_state_DFA],0
+       next
+
+       WORD p_right_bracket,']',fasm
+       ;; ( -- )
+       ;; Change state to compilation state.
+       mov qword[p_state_DFA],1
+       next
+
+       WORD p_base,'BASE',dovariable
+       dq 10
+
+       WORD p_decimal,'DECIMAL',fasm
+       ;; ( -- )
+       ;; Set BASE to 10
+       mov qword [p_base_DFA],10
+       next
+
+       WORD p_hex,'HEX',fasm
+       ;; ( -- )
+       ;; Set BASE to 16
+       mov qword [p_base_DFA],16
+       next
+
+       WORD p_number,'NUMBER',fasm
+       ;; ( chars* n -- [ 0 ]/[ v 1 ] )
+       pushr rsi
+       pop rcx                 ; ( -- chars* )
+       pop rsi                 ; ( -- )
+       xor rdi,rdi             ; value
+       mov rbx,1               ; sign (byte 0=0 means negative)
+       cmp qword [p_base_DFA],10
+       jne p_number_LOOP
+       cmp byte [rsi],'-'
+       jne p_number_LOOP
+       mov rbx,0
+       inc rsi
+       dec rcx
+       jle p_number_BAD
+p_number_LOOP:
+       dec rcx
+       jl p_number_DONE
+       xor rax,rax             ; clearing
+       lodsb
+       cmp al,'0'
+       jl p_number_BAD
+       cmp al,'9'
+       jg p_number_ALPHA
+       sub al,'0'
+p_number_CONSUME:
+       mov r8,rax
+       mov rax,rdi
+       mul qword [p_base_DFA]  ; uses rdx:rax
+       add rax,r8
+       mov rdi,rax
+       jmp p_number_LOOP
+p_number_ALPHA:
+       cmp al,'A'
+       jl p_number_BAD
+       cmp al,'Z'
+       jg p_number_alpha
+       sub al,'A'-10
+       jmp p_number_CONSUME
+p_number_alpha:
+       cmp al,'a'
+       jl p_number_BAD
+       cmp al,'z'
+       jg p_number_BAD
+       sub al,'a'-10
+       jmp p_number_CONSUME
+p_number_BAD:
+       push qword 0
+       popr rsi
+       next
+p_number_DONE:
+       cmp rbx,0
+       jne p_numper_POSITIVE
+       neg rdi
+p_numper_POSITIVE:
+       push rdi
+       push qword 1
+       popr rsi
+       next
+
+       WORD p_this_word,'THIS-WORD',dovariable
+       dq 0,0                  ; ( n chars* )
+
+       WORD p_evaluate_stream,'EVALUATE-STREAM'
+       ;; ( 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.
+p_evaluate_stream_LOOP:
+       dq p_Rget               ; ( -- stream*
+       dq p_read_word          ; ( -- chars* n )
+       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 ] )
+       BRANCH 0,p_evaluate_stream_NOTWORD ; branch if 0 on TOP
+       dq p_execute            ; consumes tfa
+       BRANCH ,p_evaluate_stream_LOOP
+p_evaluate_stream_NOTWORD:
+       dq p_drop               ; ( -- chars* n )
+       dq p_number             ; ( -- [ 0 ]/[ v 1 ] )
+       dq p_dup
+       BRANCH 0,p_evaluate_stream_BAD ; branch if 0
+       dq p_drop
+       BRANCH ,p_evaluate_stream_LOOP
+p_evaluate_stream_END:
+       dq p_2drop
+       dq p_literal
+       dq 1
+p_evaluate_stream_BAD:
+       dq p_Rgt                ; Discard the stream from the return stack
+       dq p_drop
+       dq p_exit