standardized the system of stack effect comments and updated/corrected the existing comments in stdlib and added some that were lacking

This commit is contained in:
IgorCielniak
2026-02-05 21:36:03 +01:00
parent 2d06358e24
commit 5fb36ac9bc
11 changed files with 128 additions and 110 deletions

View File

@@ -21,6 +21,13 @@ This document reflects the implementation that ships in this repository today (`
- **Lists** `[` begins a list literal, `]` ends it. The compiler captures the intervening stack segment into a freshly `mmap`'d buffer that stores `(len followed by qword items)`, drops the captured values, and pushes the buffer address. Users must `munmap` the buffer when done.
- **Token customization** Immediate words can call `add-token` or `add-token-chars` to teach the reader about new multi-character tokens. `fn.sl` uses this in combination with token hooks to recognize `foo(1, 2)` syntax.
### Stack-effect comments
- **Location and prefix** Public words in `stdlib/` (and most user code should) document its stack effect with a line comment directly above the definition: `#word_name …`.
- **Before/after form** Use `[before] -> [after]`, where each side is a comma-separated list. Items sitting to the left of `|` are deeper in the stack; the segment to the right of `|` runs all the way to the current top-of-stack. Omit the `|` only when a side is empty (`[*]`).
- **Tail sentinel** `*` represents the untouched rest of the stack. By convention it is always the first entry on each side so readers can quickly see which values are consumed/produced.
- **Alternatives** Separate multiple outcomes with `||`. Each branch repeats the `[before] -> [after]` structure (e.g., `#read_file [*, path | len] -> [*, addr | len] || [*, tag | neg_errno]`).
- **Examples** `#dup [* | x] -> [*, x | x]` means a word consumes the top value `x` and returns two copies with the newest copy at TOS; `#arr_pop [* | arr] -> [*, arr | x]` states that the array pointer remains just below the popped element. This notation keeps stack order resonably easy to read and grep.
## 4. Runtime Model
- **Stacks** `r12` holds the data stack pointer, `r13` the return stack pointer. Both live in `.bss` buffers sized by `DSTK_BYTES`/`RSTK_BYTES` (default 64 KiB each). `stdlib/core.sl` implements all standard stack shuffles, arithmetic, comparisons, boolean ops, `@`/`!`, `c@`/`c!`, and return-stack transfers (`>r`, `r>`, `rdrop`, `rpick`).
- **Calling convention** Words call each other using the System V ABI. `extern` words marshal arguments into registers before `call symbol`, then push results back onto the data stack. Integer results come from `rax`; floating results come from `xmm0` and are copied into a qword slot.

3
fn.sl
View File

@@ -1,4 +1,5 @@
word call-syntax-rewrite # ( fnameToken -- handled )
#call-syntax-rewrite [* | fnameToken] -> [* | handled]
word call-syntax-rewrite
dup token-lexeme identifier? 0 == if drop 0 exit end
peek-token dup nil? if drop drop 0 exit end
dup token-lexeme "(" string= 0 == if drop drop 0 exit end

2
nob.sl
View File

@@ -2,7 +2,7 @@ import stdlib/stdlib.sl
import stdlib/linux.sl
import stdlib/mem.sl
# sh ( cmd_addr cmd_len -- exit_code | neg_errno )
# sh [*, cmd_addr | cmd_len ] -> [* | exit_code ]
word sh
swap
>r # save cmd_addr

View File

@@ -11,7 +11,7 @@
import mem.sl
# : arr_new ( cap -- arr )
#arr_new [* | cap] -> [* | arr]
# Create a new array with given initial capacity (minimum 1)
word arr_new
dup 1 < if drop 1 end
@@ -22,21 +22,21 @@ word arr_new
nip
end
# : arr_len ( arr -- len )
#arr_len [* | arr] -> [* | len]
word arr_len @ end
# : arr_cap ( arr -- cap )
#arr_cap [* | arr] -> [* | cap]
word arr_cap 8 + @ end
# : arr_data ( arr -- ptr )
#arr_data [* | arr] -> [* | ptr]
word arr_data 16 + @ end
# : arr_free ( arr -- )
#arr_free [* | arr] -> [*]
word arr_free
dup arr_cap 8 * 24 + free
end
# Helper: copy n qwords from src to dst (dst src n --)
# Helper: copy n qwords from src to dst [*, dst, src | n] -> [*]
word arr_copy_elements
while dup 0 > do
over @ 3 pick swap ! # dst = *src
@@ -47,7 +47,7 @@ word arr_copy_elements
drop 2drop
end
# : arr_reserve ( cap arr -- arr )
#arr_reserve [*, cap | arr] -> [* | arr]
# Ensures capacity >= cap; returns (possibly moved) arr pointer.
word arr_reserve
swap dup 1 < if drop 1 end swap # reqcap arr
@@ -77,7 +77,7 @@ word arr_reserve
end
end
# : arr_push ( x arr -- arr )
#arr_push [*, x | arr] -> [* | arr]
# Push element onto array, growing if needed
word arr_push
dup arr_len over arr_cap >= if
@@ -94,27 +94,26 @@ word arr_push
dup @ 1 + over swap !
end
# : arr_pop ( arr -- x arr )
#arr_pop [* | arr] -> [*, arr | x]
# Pop element from array (returns 0 if empty)
word arr_pop
dup arr_len 0 == if
0 swap
0
else
# Decrement len
dup @ 1 - over swap !
# Get element at new len position
dup arr_data over arr_len 8 * + @
swap
end
end
# : arr_get ( i arr -- x )
#arr_get [*, i | arr] -> [* | x]
# Get element at index i
word arr_get
arr_data swap 8 * + @
end
# : arr_set ( x i arr -- )
#arr_set [*, x, i | arr] -> [*]
# Set element at index i to x
word arr_set
arr_data swap 8 * + swap !

View File

@@ -9,7 +9,7 @@
# Allocation: mmap; free: munmap.
# Growth: allocate new block, copy elements, munmap old block.
# : arr_new ( cap -- arr )
#arr_new [* | cap] -> [* | arr]
:asm arr_new {
mov r14, [r12] ; requested cap
cmp r14, 1
@@ -42,7 +42,7 @@
}
;
# : arr_len ( arr -- len )
#arr_len [* | arr] -> [* | len]
:asm arr_len {
mov rax, [r12]
mov rax, [rax]
@@ -51,7 +51,7 @@
}
;
# : arr_cap ( arr -- cap )
#arr_cap [* | arr] -> [* | cap]
:asm arr_cap {
mov rax, [r12]
mov rax, [rax + 8]
@@ -60,7 +60,7 @@
}
;
# : arr_data ( arr -- ptr )
#arr_data [* | arr] -> [* | ptr]
:asm arr_data {
mov rax, [r12]
mov rax, [rax + 16]
@@ -69,7 +69,7 @@
}
;
# : arr_free ( arr -- )
#arr_free [* | arr] -> [*]
:asm arr_free {
mov rbx, [r12] ; base
mov rcx, [rbx + 8] ; cap
@@ -84,7 +84,7 @@
}
;
# : arr_reserve ( cap arr -- arr )
#arr_reserve [*, cap | arr] -> [* | arr]
# Ensures capacity >= cap; returns (possibly moved) arr pointer.
:asm arr_reserve {
mov rbx, [r12] ; arr
@@ -151,7 +151,7 @@
}
;
# : arr_push ( x arr -- arr )
#arr_push [*, x | arr] -> [* | arr]
:asm arr_push {
mov rbx, [r12] ; arr
mov rcx, [rbx] ; len
@@ -227,7 +227,7 @@
}
;
# : arr_pop ( arr -- x arr )
#arr_pop [* | arr] -> [*, arr | x]
:asm arr_pop {
mov rbx, [r12] ; arr
mov rcx, [rbx] ; len

View File

@@ -2,6 +2,7 @@
# persistent: resb 64
# push the addr of it
#mem [*] -> [* | ptr]
:asm mem {
lea rax, [rel persistent]
sub r12, 8
@@ -9,7 +10,7 @@
}
;
# : argc ( -- n )
#argc [*] -> [* | n]
:asm argc {
extern sys_argc
mov rax, [rel sys_argc]
@@ -19,7 +20,7 @@
}
;
# : argv ( -- ptr )
#argv [*] -> [* | ptr]
:asm argv {
extern sys_argv
mov rax, [rel sys_argv]
@@ -29,7 +30,7 @@
}
;
# : argv@ ( n -- ptr )
#argv@ [* | n] -> [* | ptr]
:asm argv@ {
extern sys_argv
mov rbx, [r12] ; n
@@ -40,7 +41,7 @@
}
;
# : c@ ( addr -- byte )
#c@ [* | addr] -> [* | byte]
:asm c@ {
mov rax, [r12] ; get address from stack
movzx rax, byte [rax] ; load byte at address, zero-extend to rax
@@ -49,7 +50,7 @@
}
;
# : c! ( byte addr -- )
#c! [*, byte | addr] -> [*]
:asm c! {
mov rax, [r12] ; get address from stack
add r12, 8 ; pop address
@@ -60,7 +61,7 @@
}
;
# : r@ ( -- x )
#r@ [*] -> [* | x]
:asm r@ {
mov rax, [r13] ; get value from return stack
sub r12, 8 ; make room on data stack
@@ -69,7 +70,7 @@
}
;
# : dup ( x -- x x )
#dup [* | x] -> [*, x | x]
:asm dup {
mov rax, [r12] ; get top of stack
sub r12, 8 ; make room
@@ -77,13 +78,13 @@
}
;
# : drop ( x -- )
#drop [* | x] -> [*]
:asm drop {
add r12, 8 ; remove top of stack
}
;
# : over ( x1 x2 -- x1 x2 x1 )
#over [*, x1 | x2] -> [*, x1, x2 | x1]
:asm over {
mov rax, [r12 + 8] ; get second item
sub r12, 8 ; make room
@@ -91,7 +92,7 @@
}
;
# : swap ( x1 x2 -- x2 x1 )
#swap [*, x1 | x2] -> [*, x2 | x1]
:asm swap {
mov rax, [r12] ; get top
mov rbx, [r12 + 8] ; get second
@@ -100,7 +101,7 @@
}
;
# : rot ( x1 x2 x3 -- x2 x3 x1 )
#rot [*, x1, x2 | x3] -> [*, x2, x3 | x1]
:asm rot {
mov rax, [r12] ; x3 (top)
mov rbx, [r12 + 8] ; x2
@@ -111,7 +112,7 @@
}
;
# : -rot ( x1 x2 x3 -- x3 x1 x2 )
#-rot [*, x1, x2 | x3] -> [*, x3, x1 | x2]
:asm -rot {
mov rax, [r12] ; x3 (top)
mov rbx, [r12 + 8] ; x2
@@ -122,7 +123,7 @@
}
;
# : nip ( x1 x2 -- x2 )
#nip [*, x1 | x2] -> [* | x2]
:asm nip {
mov rax, [r12] ; get top
add r12, 8 ; drop lower
@@ -130,7 +131,7 @@
}
;
# : tuck ( x1 x2 -- x2 x1 x2 )
#tuck [*, x1 | x2] -> [*, x2, x1 | x2]
:asm tuck {
mov rax, [r12] ; x2 (top)
mov rbx, [r12 + 8] ; x1
@@ -141,7 +142,7 @@
}
;
# : 2dup ( x1 x2 -- x1 x2 x1 x2 )
#2dup [*, x1 | x2] -> [*, x1, x2, x1 | x2]
:asm 2dup {
mov rax, [r12] ; b (top)
mov rbx, [r12 + 8] ; a
@@ -152,13 +153,13 @@
}
;
# : 2drop ( x1 x2 -- )
#2drop [*, x1 | x2] -> [*]
:asm 2drop {
add r12, 16 ; remove two items
}
;
# : 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 )
#2swap [*, x1, x2, x3 | x4] -> [*, x3, x4, x1 | x2]
:asm 2swap {
mov rax, [r12] ; d (top)
mov rbx, [r12 + 8] ; c
@@ -171,7 +172,7 @@
}
;
# : 2over ( x1 x2 x3 x4 -- x3 x4 x1 x2 x3 x4 )
#2over [*, x1, x2, x3 | x4] -> [*, x3, x4, x1, x2, x3 | x4]
:asm 2over {
mov rax, [r12 + 16] ; b
mov rbx, [r12 + 24] ; a
@@ -182,7 +183,7 @@
}
;
# : + ( x1 x2 -- x3 )
#+ [*, x1 | x2] -> [* | x3]
:asm + {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -190,7 +191,7 @@
}
;
# : - ( x1 x2 -- x3 )
#- [*, x1 | x2] -> [* | x3]
:asm - {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -198,7 +199,7 @@
}
;
# : * ( x1 x2 -- x3 )
#* [*, x1 | x2] -> [* | x3]
:asm * {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -207,7 +208,7 @@
}
;
# : / ( x1 x2 -- x3 )
#/ [*, x1 | x2] -> [* | x3]
:asm / {
mov rbx, [r12] ; divisor
add r12, 8 ; pop
@@ -218,7 +219,7 @@
}
;
# : % ( x1 x2 -- x3 )
#% [*, x1 | x2] -> [* | x3]
:asm % {
mov rbx, [r12] ; divisor
add r12, 8 ; pop
@@ -229,7 +230,7 @@
}
;
# : == ( x1 x2 -- flag )
#== [*, x1 | x2] -> [* | flag]
:asm == {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -241,7 +242,7 @@
}
;
# : != ( x1 x2 -- flag )
#!= [*, x1 | x2] -> [* | flag]
:asm != {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -253,7 +254,7 @@
}
;
# : < ( x1 x2 -- flag )
#< [*, x1 | x2] -> [* | flag]
:asm < {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -265,7 +266,7 @@
}
;
# : > ( x1 x2 -- flag )
#> [*, x1 | x2] -> [* | flag]
:asm > {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -277,7 +278,7 @@
}
;
# : <= ( x1 x2 -- flag )
#<= [*, x1 | x2] -> [* | flag]
:asm <= {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -289,7 +290,7 @@
}
;
# : >= ( x1 x2 -- flag )
#>= [*, x1 | x2] -> [* | flag]
:asm >= {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -301,7 +302,7 @@
}
;
# : @ ( addr -- x )
#@ [* | addr] -> [* | x]
:asm @ {
mov rax, [r12] ; get address
mov rax, [rax] ; load value
@@ -309,7 +310,7 @@
}
;
# : ! ( x addr -- )
#! [*, x | addr] -> [*]
:asm ! {
mov rax, [r12] ; get value (TOS)
add r12, 8 ; pop value
@@ -319,7 +320,7 @@
}
;
# : mmap ( addr len prot flags fd offset -- addr )
#mmap [*, addr, len, prot, flags, fd | offset] -> [* | addr]
:asm mmap {
mov r9, [r12] ; offset
add r12, 8
@@ -339,7 +340,7 @@
}
;
# : munmap ( addr len -- res )
#munmap [*, addr | len] -> [* | res]
:asm munmap {
mov rsi, [r12] ; len
add r12, 8
@@ -352,7 +353,7 @@
}
;
# : exit ( code -- )
#exit [* | code] -> [*]
:asm exit {
mov rdi, [r12] ; exit code
add r12, 8
@@ -361,7 +362,7 @@
}
;
# : and ( x1 x2 -- flag )
#and [*, x1 | x2] -> [* | flag]
:asm and {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -377,7 +378,7 @@
}
;
# : or ( x1 x2 -- flag )
#or [*, x1 | x2] -> [* | flag]
:asm or {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -393,7 +394,7 @@
}
;
# : not ( x -- flag )
#not [* | x] -> [* | flag]
:asm not {
mov rax, [r12] ; get value
test rax, rax
@@ -403,7 +404,7 @@
}
;
# : >r ( x -- )
#>r [* | x] -> [*]
:asm >r {
mov rax, [r12] ; get value
add r12, 8 ; pop
@@ -412,7 +413,7 @@
}
;
# : r> ( -- x )
#r> [*] -> [* | x]
:asm r> {
mov rax, [r13] ; get value from return stack
add r13, 8 ; pop return stack
@@ -421,13 +422,13 @@
}
;
# : rdrop ( -- )
#rdrop [*] -> [*]
:asm rdrop {
add r13, 8 ; pop return stack
}
;
# : pick ( n -- x )
#pick [* | n] -> [* | x]
:asm pick {
mov rcx, [r12] ; get index
add r12, 8 ; pop
@@ -437,7 +438,7 @@
}
;
# : rpick ( n -- x )
#rpick [* | n] -> [* | x]
:asm rpick {
mov rcx, [r12] ; get index
add r12, 8 ; pop
@@ -447,7 +448,7 @@
}
;
# : neg ( x -- -x )
#neg [* | x] -> [* | -x]
:asm neg {
mov rax, [r12] ; get value
neg rax ; arithmetic negation
@@ -455,7 +456,7 @@
}
;
# : abs ( x -- |x| )
#abs [* | x] -> [* | |x|]
:asm abs {
mov rax, [r12] ; get value
test rax, rax ; check sign
@@ -466,7 +467,7 @@
}
;
# : bitnot ( 0|1 -- 1|0 )
#bitnot [* | bool] -> [* | bool]
:asm bitnot {
mov rax, [r12] ; get value
xor rax, 1 ; flip lowest bit
@@ -474,7 +475,7 @@
}
;
# : band ( x1 x2 -- x3 )
#band [*, x1 | x2] -> [* | x3]
:asm band {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -482,7 +483,7 @@
}
;
# : bor ( x1 x2 -- x3 )
#bor [*, x1 | x2] -> [* | x3]
:asm bor {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -490,7 +491,7 @@
}
;
# : bxor ( x1 x2 -- x3 )
#bxor [*, x1 | x2] -> [* | x3]
:asm bxor {
mov rax, [r12] ; get top
add r12, 8 ; pop
@@ -498,13 +499,13 @@
}
;
# : bnot ( x -- x )
#bnot [* | x] -> [* | x]
:asm bnot {
not qword [r12] ; bitwise not
}
;
# : shl ( x1 x2 -- x3 )
#shl [*, x1 | x2] -> [* | x3]
:asm shl {
mov rcx, [r12] ; shift count
add r12, 8 ; pop
@@ -512,7 +513,7 @@
}
;
# : sal ( x1 x2 -- x3 )
#sal [*, x1 | x2] -> [* | x3]
:asm sal {
mov rcx, [r12] ; shift count
add r12, 8 ; pop
@@ -520,7 +521,7 @@
}
;
# : shr ( x1 x2 -- x3 )
#shr [*, x1 | x2] -> [* | x3]
:asm shr {
mov rcx, [r12] ; shift count
add r12, 8 ; pop
@@ -528,7 +529,7 @@
}
;
# : sar ( x1 x2 -- x3 )
#sar [*, x1 | x2] -> [* | x3]
:asm sar {
mov rcx, [r12] ; shift count
add r12, 8 ; pop
@@ -536,7 +537,7 @@
}
;
# : rol ( x1 x2 -- x3 )
#rol [*, x1 | x2] -> [* | x3]
:asm rol {
mov rcx, [r12] ; shift count
add r12, 8 ; pop
@@ -544,7 +545,7 @@
}
;
# : ror ( x1 x2 -- x3 )
#ror [*, x1 | x2] -> [* | x3]
:asm ror {
mov rcx, [r12] ; shift count
add r12, 8 ; pop
@@ -552,19 +553,19 @@
}
;
# : inc ( x -- x+1 )
#inc [* | x] -> [* | x+1]
:asm inc {
inc qword [r12]
}
;
# : dec ( x -- x-1 )
#dec [* | x] -> [* | x-1]
:asm dec {
dec qword [r12]
}
;
# : min ( x1 x2 -- x3 )
#min [*, x1 | x2] -> [* | x3]
:asm min {
mov rax, [r12] ; x2
add r12, 8 ; pop
@@ -575,7 +576,7 @@
}
;
# : max ( x1 x2 -- x3 )
#max [*, x1 | x2] -> [* | x3]
:asm max {
mov rax, [r12] ; x2
add r12, 8 ; pop
@@ -586,7 +587,7 @@
}
;
# : clamp ( x lo hi -- y )
#clamp [*, x, lo | hi] -> [* | y]
:asm clamp {
mov rax, [r12] ; hi
mov rbx, [r12 + 8] ; lo
@@ -600,7 +601,7 @@
}
;
# : time ( -- t )
#time [*] -> [* | t]
:asm time {
mov rax, 201 ; syscall: time
xor rdi, rdi
@@ -611,7 +612,7 @@
}
;
# : rand ( -- n )
#rand [*] -> [* | n]
:asm rand {
lea rbx, [rel persistent]
mov rax, [rbx] ; state

View File

@@ -1,7 +1,7 @@
import stdlib.sl
import io.sl
# : dump ( n -- )
#dump [* | n] -> [*]
# dump takes the firts element from the stack
# and prints that much consequent elements
@@ -28,7 +28,7 @@ word rdump
drop
end
# : int3 ( -- )
#int3 [*] -> [*]
:asm int3 {
int3
}

View File

@@ -1,8 +1,8 @@
# L2 IO Primitives
# : read_file ( path_addr path_len -- addr len | 0 0 )
#read_file [*, path_addr | path_len] -> [*, addr | len] || [*, tag | neg_errno]
# Reads the file at the given path (pointer+length, not null-terminated),
# returns (addr len) of mapped file, or (0 0) on error.
# returns (addr len) of mapped file, or (tag neg_errno) on error.
:asm read_file {
; stack: path_addr (NOS), path_len (TOS)
@@ -79,7 +79,7 @@
}
;
# : write_file ( path_ptr path_len buf_ptr buf_len -- bytes_written | neg_errno )
#write_file [*, path_ptr, path_len, buf_ptr | buf_len] -> [* | bytes_written] || [* | neg_errno]
:asm write_file {
; stack: path_addr, path_len, buf_addr, buf_len (TOS)
mov r13, [r12] ; buf_len
@@ -132,7 +132,7 @@
}
;
# : read_stdin ( max_len -- addr len | neg_errno 0 )
#read_stdin [* | max_len] -> [*, addr | len] || [*, tag | neg_errno]
:asm read_stdin {
; stack: max_len
mov r14, [r12] ; max_len
@@ -268,7 +268,7 @@
}
;
# : write_buf ( addr len -- )
#write_buf [*, addr | len] -> [*]
:asm write_buf (effects string-io) {
mov rdx, [r12] ; len
mov rsi, [r12 + 8] ; addr
@@ -280,7 +280,7 @@
}
;
# : ewrite_buf ( addr len -- )
#ewrite_buf [*, addr | len] -> [*]
:asm ewrite_buf (effects string-io) {
mov rdx, [r12] ; len
mov rsi, [r12 + 8] ; addr
@@ -292,7 +292,7 @@
}
;
# : putc ( char -- )
#putc [* | char] -> [*]
:asm putc {
mov rax, [r12]
add r12, 8
@@ -306,7 +306,7 @@
}
;
# : puti ( int -- )
#puti [* | int] -> [*]
:asm puti {
mov rax, [r12] ; get int
add r12, 8 ; pop

View File

@@ -2,7 +2,7 @@
# Provides syscall constants and helpers for L2 programs
# swap impl is provided so this can be used without the need for stdlib
# : ___linux_swap ( x1 x2 -- x2 x1 )
#___linux_swap [*, x1 | x2] -> [*, x2 | x1]
:asm ___linux_swap {
mov rax, [r12] ; get top
mov rbx, [r12 + 8] ; get second

View File

@@ -1,5 +1,6 @@
import stdlib.sl
#alloc [* | size] -> [* | addr]
word alloc
0 # addr hint (NULL)
swap # size
@@ -11,11 +12,13 @@ word alloc
swap drop
end
#free [*, addr | size] -> [*]
word free
munmap drop
end
word memcpy #(dst_addr src_addr len -- dst_addr len)
#memcpy [*, dst_addr, src_addr | len] -> [*, dst_addr | len]
word memcpy
dup
>r
swap
@@ -40,7 +43,8 @@ word memcpy #(dst_addr src_addr len -- dst_addr len)
r> dup -rot - swap
end
word memset #( value len addr -- )
#memset [*, value, len | addr] -> [*]
word memset
swap
0 swap for
-rot swap 2 pick + 2dup swap ! 1 + -rot swap
@@ -48,13 +52,15 @@ word memset #( value len addr -- )
2drop drop
end
word memdump #( len addr -- addr )
#memdump [*, len | addr] -> [* | addr]
word memdump
for
dup c@ puti cr 1 +
end
end
word realloc #( addr old_len new_len -- new_addr )
#realloc [*, addr, old_len | new_len] -> [* | new_addr]
word realloc
2 pick swap alloc
rot rot swap
memcpy

View File

@@ -1,10 +1,10 @@
# : strcmp ( addr len addr len -- bool addr len addr len)
#strcmp [*, addr, len, addr | len] -> [*, addr, len, addr, len | bool]
word strcmp
3 pick 2 pick @ swap @ ==
end
# : strconcat ( addr len addr len -- addr len)
#strconcat [*, addr, len, addr | len] -> [*, addr | len]
word strconcat
0 pick 3 pick +
dup
@@ -31,7 +31,7 @@ word strconcat
rdrop rdrop rdrop
end
# : strlen ( addr -- len )
#strlen [* | addr] -> [* | len]
# for null terminated strings
word strlen
0 swap # len addr
@@ -42,7 +42,8 @@ word strlen
drop # drop addr, leave len
end
word digitsN>num # ( d_{n-1} ... d0 n -- value ), digits bottom=MSD, top=LSD, length on top (MSD-most significant digit, LSD-least significant digit)
#digitsN>num [*, d_{n-1}, d0 | n] -> [* | value]
word digitsN>num # digits bottom=MSD, top=LSD, length on top (MSD-most significant digit, LSD-least significant digit)
0 swap # place accumulator below length
for # loop n times using the length on top
r@ pick # fetch next digit starting from MSD (uses loop counter as index)
@@ -52,7 +53,8 @@ word digitsN>num # ( d_{n-1} ... d0 n -- value ), digits bottom=MSD, top=LSD, l
end
end
# : toint (addr len -- int ) converts a string to an int
#toint [*, addr | len] -> [* | int]
# converts a string to an int
word toint
swap
over 0 swap
@@ -75,7 +77,8 @@ word toint
rdrop rdrop
end
# : count_digits ( int -- int) returns the amount of digits of an int
#count_digits [* | int] -> [* | int]
# returns the amount of digits of an int
word count_digits
0
swap
@@ -85,7 +88,8 @@ word count_digits
drop
end
# : tostr ( int -- addr len ) the function allocates a buffer to remember to free it
#tostr [* | int] -> [*, addr | len]
# the function allocates a buffer, remember to free it
word tostr
dup
count_digits