X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=compile.asm;h=fe19b203620ee3dab25f407657704c588641fe20;hb=9b8fcf87eaed58b6dfabcf885f8eef5484643de6;hp=d06913876a00feab6e6a6a2d74815cc3166b1f7c;hpb=c7022e938a1d35c0929374616a871c2caba15598;p=rrq%2Frrqforth.git diff --git a/compile.asm b/compile.asm index d069138..fe19b20 100644 --- a/compile.asm +++ b/compile.asm @@ -8,10 +8,10 @@ ;; 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 @@ -22,19 +22,18 @@ 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 @@ -43,10 +42,37 @@ p_create_COPY: ;; ( 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" @@ -67,32 +93,56 @@ p_create_COPY: 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) - ;; ( -- chars* n ) - ;; Push the value of successor cell onto stack, and skip it + WORD p_literal_string,'S"',fasm,IMMEDIATE ;; " (fool emacs) + ;; ( -- char* n ) + ;; Save string on heap to make available at interpretation + ;; not for interactive use!! + cmp qword [p_state_DFA],0 + je p_literal_string_executing + 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 + mov rdi,qword [p_here_DFA] + mov qword [rdi],rcx + add rdi,8 +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 + +p_literal_string_executing: mov rax,qword [rsi] add rsi,8 push rsi @@ -100,16 +150,13 @@ p_create_COPY: 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 @@ -139,42 +186,56 @@ p_create_COPY: pushr rsi pop rcx ; ( -- chars* ) pop rsi ; ( -- ) - xor rdi,rdi + 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 rbx + dec rcx jl p_number_DONE + xor rax,rax ; clearing lodsb - mov bl,al ; into bl - cmp bl,'0' + cmp al,'0' jl p_number_BAD - cmp bl,'9' + cmp al,'9' jg p_number_ALPHA - sub bl,'0' + sub al,'0' p_number_CONSUME: + mov r8,rax mov rax,rdi - mul qword [p_base_DFA] - add rax,rbx + mul qword [p_base_DFA] ; uses rdx:rax + add rax,r8 mov rdi,rax jmp p_number_LOOP p_number_ALPHA: - cmp bl,'A' + cmp al,'A' jl p_number_BAD - cmp bl,'Z' + cmp al,'Z' jg p_number_alpha - sub bl,'A'-10 + sub al,'A'-10 jmp p_number_CONSUME p_number_alpha: - cmp bl,'a' + cmp al,'a' jl p_number_BAD - cmp bl,'z' + cmp al,'z' jg p_number_BAD - sub bl,'a'-10 + 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 @@ -184,30 +245,120 @@ p_number_DONE: dq 0,0 ; ( n chars* ) WORD p_evaluate_stream,'EVALUATE-STREAM' - ;; ( stream -- *?* flag ) + ;; ( stream* -- *?* flag ) ;; Execute the words from the given stream ;; returns 1 if stream ends and 0 if an unknown word is found + dq p_gtR ; Keep the stream on the return stack. +p_evaluate_stream_PROMPT: + dq p_verboseQ + dq p_get + BRANCH 0,p_evaluate_stream_LOOP + 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_read_word ; ( -- chars* n ) + dq p_Rget + dq p_read_word dq p_dup - BRANCH 0,p_evaluate_stream_END - 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 ; ( -- chars* n tfa/0 ) - dq p_execute ; ( -- chars* n tfa/0 ) - BRANCH ,p_evaluate_stream_LOOP + BRANCH 0,p_evaluate_stream_END ; branch if 0 on TOP + 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 + 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 0,p_evaluate_stream_BAD ; branch if 0 dq p_drop + 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 + dq p_stream_nchars + BRANCH 0,p_evaluate_stream_PROMPT BRANCH ,p_evaluate_stream_LOOP p_evaluate_stream_END: - dq p_literal - dq 1 + dq p_2drop + dq p_literal, 1 p_evaluate_stream_BAD: + 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,';',,IMMEDIATE + ;; ( -- ) + ;; Lay out p_exit, and set interpreting mode + dq p_left_bracket + dq p_literal, p_exit + dq p_comma + dq p_left_bracket + dq p_exit + + 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_open_file_quote,'OPEN-FILE"' + ;; ( "name" -- fd ) + dq p_double_quote + dq p_create + dq p_tfa2namez + dq p_literal,0 + dq p_literal,0 + dq sys_open + dq p_exit + + WORD p_load_file_quote,'LOAD-FILE"' + ;; ( "name" -- ) + ;; Create a word for the nominated file for a stream to, + ;; and store that stream pointer, then invoke evaluate-stream + dq p_open_file_quote ; fd + dq p_literal, 15000 ; buffer size + dq p_stream + dq p_dup + dq p_comma + dq p_evaluate_stream dq p_exit