;; 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
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
add rdi,8
- mov qword [rdi],dovalue ;CFA
+ mov qword [rdi],dovariable ; 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
;; ( n -- )
;; Allocate n bytes on the heap
pop rax
- add rax,qword [p_here_DFA]
- mov qword [p_here_DFA],rax
+ add qword [p_here_DFA],rax
next
+ WORD p_quote,"'",fasm
+ ;; ( "word" -- cfa )
+ ;; Find the following word and push its cfa, or 0
+ pushr rsi
+ DOFORTH p_stdin, p_read_word, p_find
+ cmp qword[rsp],0
+ jne p_quote_tfa
+ add rsp,16
+ mov qword[rsp],0
+ jmp p_quote_end
+p_quote_tfa:
+ mov rax,qword [rsp]
+ tfa2cfa rax
+ mov qword [rsp],rax
+p_quote_end:
+ popr rsi
+ next
+
+ WORD p_bracketed_quote,"[']",doforth,IMMEDIATE
+ ;; Compilation ( "word" -- cfa )
+ ;; Find the following word and push its cfa, or 0
+ dq p_literal
+ dq p_literal
+ dq p_comma
+ dq p_quote
+ dq p_comma
+ dq p_exit
+
WORD p_comma,',',fasm
;; ( v -- )
;; Put cell value onto the heap and advance "HERE"
mov qword [p_here_DFA],rax
next
- WORD p_does,'DOES>',fasm,IMMEDIATE
+ 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)
- ;; Compilation: ( "..." -- )
- ;; Interpretation: ( -- char* n )
+ ;; ( -- char* n )
;; Save string on heap to make available at interpretation
- cmp qword [p_state_DFA],0
- je p_literal_string_interpret
- ;; compilation mode: read stream until \" onto the heap
- pushr rsi
- mov rdi,[p_here_DFA]
- lea rbx,[p_literal_string_CFA]
- mov qword [rdi],rbx
- add rdi,8
- pop rbx
- mov qword [rdi],rbx
- add rdi,8
- cmp rbx,0
- je p_literal_string_end
- lea rsi,[p_pad_DFA]
-p_literal_string_copy:
- lodsb
- stosb
- dec rbx
- jg p_literal_string_copy
-p_literal_string_end:
- mov qword [p_here_DFA],rdi
- popr rsi
- next
-
-p_literal_string_interpret:
+ ;; not for interactive use!!
mov rax,qword [rsi]
add rsi,8
push rsi
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.
+ ;; Change state to interpreting state.
mov qword[p_state_DFA],0
next
;; ( 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_gtR ; Keep the stream on the return stack.
p_evaluate_stream_PROMPT:
- dq p_depth, p_dot, p_literal_string
- STRING ' > '
- dq p_tell, p_Rget, p_clear_stream
+ dq p_depth
+ dq p_dot
+ dq p_literal_string
+ STRING '> '
+ dq p_tell
+ dq p_Rget
+ dq p_clear_stream
p_evaluate_stream_LOOP:
- dq p_Rget, p_read_word, p_dup
+ dq p_Rget
+ dq p_read_word
+ dq p_dup
BRANCH 0,p_evaluate_stream_END ; branch if 0 on TOP
- dq p_2dup, p_this_word, p_2put, p_find, p_dup
+ dq p_2dup
+ dq p_this_word
+ dq p_2put
+ dq p_find
+ dq p_dup
BRANCH 0,p_evaluate_stream_NOTWORD ; branch if 0 on TOP
- dq p_state, p_get
+ dq p_state
+ dq p_get
+ BRANCH 0,p_evaluate_stream_INTERPRET
+ dq p_dup
+ dq p_cfa2flags_get
+ dq p_literal, 1
+ dq p_and
+ dq p_not
BRANCH 0,p_evaluate_stream_INTERPRET
dq p_comma
BRANCH ,p_evaluate_stream_AFTER
dq p_execute
BRANCH ,p_evaluate_stream_AFTER
p_evaluate_stream_NOTWORD:
- dq p_drop, p_number
+ dq p_drop
+ dq p_number
BRANCH 0,p_evaluate_stream_BAD ; branch if 0
+ dq p_state
+ dq 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_Rget,p_stream_nchars
+ dq p_Rget
+ dq p_stream_nchars
BRANCH 0,p_evaluate_stream_PROMPT
BRANCH ,p_evaluate_stream_LOOP
p_evaluate_stream_END:
- dq p_2drop, p_literal, 1
+ dq p_2drop
+ dq p_literal, 1
p_evaluate_stream_BAD:
- dq p_Rgt, p_drop, p_exit
+ dq p_Rgt
+ dq p_drop
+ dq p_exit
+
+ 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_stdin
+ dq p_read_word
+ dq p_create
+ dq p_tfa2cfa
+ dq p_put
+ dq p_right_bracket
+ dq p_exit
+
+ WORD p_semicolon,';'
+ ;; ( -- )
+ ;; Lay out p_exit, and set interpreting mode
+ dq p_left_bracket
+ dq p_literal, p_exit
+ dq p_comma
+
+ 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