--- /dev/null
+// stdio.asm: WORD p_fdemit,'FDEMIT'
+
+anchor:p_fdemit[]
+
+=== Word: FDEMIT
+
+....
+Data stack: ( c fd -- )
+....
+
+"FDEMIT" is a function word that puts the given character code to the
+given file descriptor. The character is the least significant byte of
+the data stack cell.
+
--- /dev/null
+// stdio.asm: WORD p_fdtell,'FDTELL'
+
+anchor:p_fdtell[]
+
+=== Word: FDTELL
+....
+Data stack: ( char* n fd -- )
+....
+
+"FDTELL" is a function word that prints a string to the given file
+descriptor.
--- /dev/null
+// compile.asm: WORD p_load_buffer_size,'LOAD-BUFFER-SIZE',dovariable
+
+anchor:p_load_buffer_size[]
+
+=== Word: LOAD-BUFFER-SIZE
+
+....
+data stack: ( -- a )
+....
+
+"LOAD-BUFFER-SIZE" is a variable word telling the buffer size in bytes
+that <<p_load_file,LOAD-FILE>> should use.
--- /dev/null
+// compile.asm: WORD p_load_file,'LOAD-FILE'
+
+anchor:p_load_file[]
+
+=== Word: LOAD-FILE
+
+....
+data stack: ( chaz* -- * 0/1 )
+....
+
+"LOAD-FILE" is a function word that evaluates a text file. It opens a
+file via xref:p_open_file[OPEN-FILE] and sets up a stream with a
+buffer of <<p_load_buffer_size,LOAD-BUFFER-SIZE>> bytes for
+reading it. The stream is passed to
+<<p_evaluate_stream,EVALUATE-STREAM>> for processing its words. Upon
+its return the file is closed and the stream memory is reclaimed, and
+then the function returns whatever
+<<p_evaluate_stream,EVALUATE-STREAM>> returns.
+++ /dev/null
-// compile.asm: WORD p_load_file_quote,'LOAD-FILE"'
-
-anchor:p_load_file_quote[]
-
-=== Word: LOAD-FILE"
-
-....
-data stack: ( "name" -- )
-....
-
-"LOAD-FILE"" is a function word that opens a file via
-xref:p_open_file_quote[OPEN-FILE"], allocates a stream buffer of 15000
-bytes for reading it, saves the stream pointer as value for the newly
-created filename variable, and then it invokes
-xref:p_evaluate_stream[EVALUATE-STREAM] for processing the file.
--- /dev/null
+// compile.asm: WORD p_open_file,'OPEN-FILE'
+
+anchor:p_open_file[]
+
+=== Word: OPEN-FILE
+
+....
+Data stack: ( chaz* -- fd )
+....
+
+"OPEN-FILE" is a function word that opens the file named by the zero
+terminated character string and returns the file descriptor, or if
+less than 0, the system call error code.
--- /dev/null
+// stack.asm: WORD p_rbp, 'RSP',fasm
+
+anchor:p_rbp[]
+
+=== Word: RSP
+
+....
+Data stack: ( -- a )
+....
+
+"RSP" is a function word that pushes the return stack pointer value
+onto the data stack.
--- /dev/null
+// stack.asm: WORD p_rbpn, 'R[n]',fasm
+
+anchor:p_rbpn[]
+
+=== Word: R[n]
+
+....
+Data stack: ( n -- a )
+....
+
+"R[n]" is a function word that pushes the address for the n:th cell on
+the top return stack value onto the data stack.
+
+====
+.Defintion concept for R[n]
+****
+( n -- a ) : R[n] 8 * RSP + ;
+****
+====
<<p_pad,PAD>>, and there is a limit of 1024 characters.
At the end of the stream READ-WORD returns 0 length.
+
+.Whitespace
+[caption='Special syntax {counter:syntax}: ']
+====
+All character codes less or equal to 32 are regarded as "whitespace".
+====
+
+.Rest-of-line comment
+[caption='Special syntax {counter:syntax}: ']
+====
+The "#" character following whitespace starts a line comment and the
+rest of the line is ignored. Note that this is also recognised with
+<<p_lparen,parethesis commenting>>.
+====
+++ /dev/null
-// stack.asm: WORD p_rsp, 'R[n]',fasm
-
-anchor:p_rsp[]
-
-=== Word: R[n]
-
-....
-Data stack: ( n -- a )
-....
-
-"R[n]" is a function word that pushes the address for the n:th cell on
-the top return stack value onto the data stack.
==== File descriptor backed STREAM
+
A file descriptor backed STREAM gains a buffer of the given size
prefixed by a 32 byte STREAM header of the following layout:
-// stdio.asm: WORD p_tell,'TELL',fasm
+// stdio.asm: WORD p_tell,'TELL'
anchor:p_tell[]
--- /dev/null
+// stdio.asm: WORD p_unstream,'UNSTREAM',fasm
+
+anchor:p_unstream[]
+
+=== Word: UNSTREAM
+....
+Data stack: ( stream* -- )
+....
+
+"UNSTREAM" is a function word that releases the memory allocated for a
+stream, and closes the associated file if it's a file stream.
+
+==== File descriptor backed stream
+
+This kind of stream has the stream header as a prefix within the
+allocated memory. Thus, stream* is the base address for the memory to
+reclaim, and the size of this is determined from the cell at (stream*
++ 16) plus the 32 bytes head itself.
+
+==== Memory block backed STREAM
+
+This kind of stream has a separate header which points at the memory
+area to reclaim. The cell at stream* is the base address, and the cell
+at (stream* + 16) is its size.
popr rsi
next
- WORD p_allot,'ALLOT',fasm
+ WORD p_allot,'ALLOT'
;; ( n -- )
;; Allocate n bytes on the heap
- pop rax
- add qword [p_here_DFA],rax
- next
+ dq p_here, p_put_plus, p_exit
- WORD p_quote,"'",fasm
+ WORD p_quote,"'"
;; ( "word" -- cfa )
;; Find the following word and push its cfa, or 0
- pushr rsi
- DOFORTH p_input, p_get, 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
+ dq p_input, p_get, p_read_word, p_find
+ BRANCH 0,p_quote_end
+ dq p_tfa2cfa
p_quote_end:
- popr rsi
- next
+ dq p_exit
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
+ ;; Compile down " LIT value "
+ dq p_literal, p_literal, p_comma,p_quote, p_comma, p_exit
- WORD p_comma,',',fasm
+ WORD p_comma,','
;; ( 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
+ dq p_here, p_put, p_literal, 8, p_here, p_put_plus, p_exit
- WORD p_Ccomma,'C,',fasm
+ WORD p_Ccomma,'C,'
;; ( 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
+ dq p_here, p_Cput, p_literal, 1, p_here, p_put_plus, p_exit
WORD p_does,"DOES>",fasm,IMMEDIATE
;; ( -- )
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
+ dq p_literal, p_exit, p_comma, p_left_bracket, p_exit
WORD p_immediate,'IMMEDIATE',fasm,IMMEDIATE
;; ( -- )
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_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* -- fd )
+ ;; Open the nominated file
+ pushr rsi
+ push qword 0
+ push qword 0
+ DOFORTH sys_open
+ popr rsi
+ next
- 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
+ WORD p_load_file,'LOAD-FILE'
+ ;; ( chaz* -- )
+ 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_exit
cat <<EOF >> gdbinit
commands $((NBR+1))
print (void*) \$rsp
-print (((char*)(*(((void**)\$rax)-2)))+32)
print (void*) \$rsi
+print (char*)((*((void**)(*((void**)\$rsi)-16)))+32)
end
EOF
macro BRANCH zero,label {
if zero in <0>
dq p_zero_branch
+ else if zero in <1>
+ dq p_true_branch
else
dq p_branch
end if
include::separator.adoc[]
include::adoc/p_false.adoc[]
include::separator.adoc[]
+include::adoc/p_fdemit.adoc[]
+include::separator.adoc[]
+include::adoc/p_fdtell.adoc[]
+include::separator.adoc[]
include::adoc/p_find.adoc[]
include::separator.adoc[]
include::adoc/p_forth.adoc[]
include::separator.adoc[]
include::adoc/p_literal_string.adoc[]
include::separator.adoc[]
-include::adoc/p_load_file_quote.adoc[]
+include::adoc/p_load_buffer_size.adoc[]
+include::separator.adoc[]
+include::adoc/p_load_file.adoc[]
include::separator.adoc[]
include::adoc/p_lparen.adoc[]
include::separator.adoc[]
include::separator.adoc[]
include::adoc/p_number.adoc[]
include::separator.adoc[]
-include::adoc/p_open_file_quote.adoc[]
+include::adoc/p_open_file.adoc[]
include::separator.adoc[]
include::adoc/p_or.adoc[]
include::separator.adoc[]
include::separator.adoc[]
include::adoc/p_quote.adoc[]
include::separator.adoc[]
+include::adoc/p_rbp.adoc[]
+include::separator.adoc[]
+include::adoc/p_rbpn.adoc[]
+include::separator.adoc[]
include::adoc/p_read_stream_char.adoc[]
include::separator.adoc[]
include::adoc/p_read_word.adoc[]
include::separator.adoc[]
include::adoc/p_rot.adoc[]
include::separator.adoc[]
-include::adoc/p_rsp.adoc[]
-include::separator.adoc[]
include::adoc/p_semicolon.adoc[]
include::separator.adoc[]
include::adoc/p_setup_signals.adoc[]
include::separator.adoc[]
include::adoc/p_unequal.adoc[]
include::separator.adoc[]
+include::adoc/p_unstream.adoc[]
+include::separator.adoc[]
include::adoc/p_verboseQ.adoc[]
include::separator.adoc[]
include::adoc/p_within.adoc[]
;;; Words for stack manipulations
+ WORD p_dsp,'D[n]',fasm
+ ;; ( n -- a )
+ ;; Push the address of the n:th cell below n onto the stack
+ pop rax
+ shl rax,3
+ add rax,rsp
+ push rax
+ next
+
WORD p_depth,'DEPTH',fasm
;; ( -- v )
;; Push stack depth (before push)
push qword [rbp]
next
- WORD p_rsp,'R[n]',fasm
+ WORD p_rbp,'RSP',fasm
+ ;; Push the return stack pointer to the data stack
+ push rbp
+ next
+
+ WORD p_rbpn,'R[n]',fasm
;; ( n -- a )
;; push the address of the n:th cell on the return stack
mov rax,qword [rsp]
push rax
jmp exit
+ WORD p_unstream,'UNSTREAM',fasm
+ ;; ( stream -- )
+ ;; Release mmap-ed memory
+ pushr rsi
+ mov rax,qword [rsp]
+ mov rbx,qword [rax+8]
+ cmp rbx,0
+ jl p_unstream_incore
+ ;; unstream fd stream
+ push rbx
+ DOFORTH sys_close
+ pop rax
+ mov rax,qword [rsp]
+ push qword [rax+16]
+ add qword [rax+16],32
+ DOFORTH sys_munmap
+ pop rax
+ popr rsi
+ next
+p_unstream_incore:
+ mov rbx,qword [rax+16]
+ mov rax,qword [rax]
+ mov qword [rsp],rax
+ push rbx
+ DOFORTH sys_munmap
+ pop rax
+ popr rsi
+ next
+
WORD p_clear_stream,'CLEAR-STREAM',fasm
;; ( stream -- )
- ;; Clear buffer of input stream
+ ;; "Clear" the stream by moving its "current position" to the
+ ;; "fill position".
pop rax
mov rbx,qword [rax+16] ; copy fill
mov qword [rax+24],rbx ; into current
push rax
p_read_word_skipblanks:
- FORTH
- dq p_dup
- dq p_read_stream_char
- ENDFORTH
+ DOFORTH p_dup, p_read_stream_char
pop rbx
cmp bl,0
jl p_read_word_nomore
cmp bl,' '
jle p_read_word_skipblanks
-
+ cmp bl,'#'
+ je p_read_word_skipline
p_read_word_readword:
;; ( buffer length stream )
mov rax,qword [rsp+16]
mov rcx,qword [rsp+8]
mov [rax+rcx],bl
inc qword [rsp+8]
- FORTH
- dq p_dup
- dq p_read_stream_char
- ENDFORTH
+ DOFORTH p_dup, p_read_stream_char
pop rbx
cmp bl,0
jl p_read_word_nomore
popr rsi
next
+p_read_word_skipline:
+ DOFORTH p_dup, p_read_stream_char
+ pop rbx
+ cmp bl,0
+ jl p_read_word_nomore
+ cmp bl,10 ; newline
+ je p_read_word_skipblanks
+ jmp p_read_word_skipline
+
WORD p_double_quote,'"',fasm ;; " (fool emacs)
;; ( -- char* n )
;; Scan to double quote in stream buffer, putting the string
jmp p_double_quote_loop
p_double_quote_endquote:
p_double_quote_endstream:
- mov qword [rdi],0
lea rdi,[p_pad_DFA]
add rdi,qword [rsp]
+ mov byte [rdi],0
;; copy PAD string into new temp object
inc qword [rsp]
DOFORTH p_str2temp
popr rsi
next
- WORD p_tell,'TELL',fasm
+ WORD p_fdtell,'FDTELL',
+ ;; ( chars* n fd -- )
+ ;; Write n bytes from chars* to fd
+ dq p_rot, p_rot, sys_write, p_drop, p_exit
+
+ WORD p_tell,'TELL'
;; ( chars* n -- )
;; Write n bytes from chars* to stdout
- pushr rsi
- pop rbx
- pop rax
- push 1
- push rax
- push rbx
- DOFORTH sys_write
- pop rax
- popr rsi
- next
+ dq p_literal,1,p_fdtell, p_exit
- WORD p_emit,'EMIT',fasm
+ WORD p_fdemit,'FDEMIT'
+ ;; ( c fd -- )
+ ;; Write byte to fd
+ dq p_literal,1, p_dsp, p_literal,1, sys_write, p_2drop, p_exit
+
+ WORD p_emit,'EMIT'
;; ( c -- )
;; Write byte to stdout
- pushr rsi
- mov rax,rsp
- push 1
- push rax
- push 1
- DOFORTH sys_write
- pop rax ; ignore return value
- pop rax ; drop input data
- popr rsi
- next
+ dq p_literal,1, p_fdemit, p_exit
WORD p_nl,'NL',dovalue
;; ( -- c )
xref:p_gtR[>R] {nbsp}
xref:p_Rget[R@] {nbsp}
xref:p_Rgt[R>] {nbsp}
-<<p_rsp,R[n]>> {nbsp}
+<<p_rbpn,R[n]>> {nbsp}
xref:data_stack[DATA-STACK] {nbsp}
xref:return_stack[RETURN-STACK] {nbsp}
xref:p_exit[EXIT] {nbsp}
xref:p_false[FALSE] {nbsp}
+xref:p_fdemit[FDEMIT] {nbsp}
+xref:p_fdtell[FDTELL] {nbsp}
xref:p_find[FIND] {nbsp}
xref:p_forth[FORTH] {nbsp}
xref:p_input[INPUT] {nbsp}
xref:p_literal[LIT] {nbsp}
-xref:p_load_file_quote[LOAD-FILE"] {nbsp}
+xref:p_load_buffer_size[LOAD-BUFFER-SIZE] {nbsp}
+xref:p_load_file[LOAD-FILE] {nbsp}
xref:p_args[MAIN-ARGS] {nbsp}
xref:p_malloc[MALLOC] {nbsp}
xref:p_not[NOT] {nbsp}
xref:p_number[NUMBER] {nbsp}
-xref:p_open_file_quote[OPEN-FILE"] {nbsp}
+xref:p_open_file[OPEN-FILE] {nbsp}
xref:p_or[OR] {nbsp}
xref:p_over[OVER] {nbsp}
xref:p_realloc[REALLOC] {nbsp}
xref:p_roll[ROLL] {nbsp}
xref:p_rot[ROT] {nbsp}
+xref:p_rbp[RSP] {nbsp}
xref:p_sp[SP] {nbsp}
xref:p_state[STATE] {nbsp}
xref:p_true[TRUE] {nbsp}
xref:p_tuck[TUCK] {nbsp}
+xref:p_unstream[UNSTREAM] {nbsp}
+
xref:p_verboseQ[VERBOSE?] {nbsp}
xref:p_within[WITHIN] {nbsp}