X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=compile.asm;h=3d5433ef5ff133ae51dfd033492fbe7336ce4f17;hb=5b7f593fcea545619f8afcc01099e433c84250a7;hp=1e76aeea96c355beec402cc9f59d3667526cbbad;hpb=c7bd2072c9a131bff7f03f36fefd65f7b6f60f02;p=rrq%2Frrqforth.git diff --git a/compile.asm b/compile.asm index 1e76aee..3d5433e 100644 --- a/compile.asm +++ b/compile.asm @@ -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,172 @@ 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 +p_number_LOOP: + dec rcx + jl p_number_DONE + lodsb + mov bl,al ; into bl + cmp bl,'0' + jl p_number_BAD + cmp bl,'9' + jg p_number_ALPHA + sub bl,'0' +p_number_CONSUME: + mov rax,rdi + mul qword [p_base_DFA] + add rax,rbx + mov rdi,rax + jmp p_number_LOOP +p_number_ALPHA: + cmp bl,'A' + jl p_number_BAD + cmp bl,'Z' + jg p_number_alpha + sub bl,'A'-10 + jmp p_number_CONSUME +p_number_alpha: + cmp bl,'a' + jl p_number_BAD + cmp bl,'z' + jg p_number_BAD + sub bl,'a'-10 + jmp p_number_CONSUME +p_number_BAD: + push qword 0 + popr rsi + next +p_number_DONE: + 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 on TOP + 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