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:
7
SPEC.md
7
SPEC.md
@@ -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
3
fn.sl
@@ -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
2
nob.sl
@@ -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
|
||||
|
||||
@@ -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 !
|
||||
|
||||
@@ -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
|
||||
|
||||
125
stdlib/core.sl
125
stdlib/core.sl
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
16
stdlib/io.sl
16
stdlib/io.sl
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user