diff --git a/desk/lib/core.fs b/desk/lib/core.fs new file mode 100644 index 0000000..475df59 --- /dev/null +++ b/desk/lib/core.fs @@ -0,0 +1,26 @@ +( North core stdlib ) +( Composite definitions layered on top of the interpreter primitives. ) +( Load interactively with INCLUDE /lib/core or via the test harness. ) +( Uses paren comments throughout so the file can be flattened to a single ) +( line for tooling that does not preserve newlines. ) + +( ---- Comparison shorthands ---- ) + +: <= ( a b -- f ) > NOT ; +: >= ( a b -- f ) < NOT ; +: 0<> ( n -- f ) 0= NOT ; +: U<= ( a b -- f ) U> NOT ; +: U>= ( a b -- f ) U< NOT ; + +( ---- Range test: true iff lo <= n < hi ---- ) + +: WITHIN ( n lo hi -- f ) >R OVER <= SWAP R> < AND ; + +( ---- Numeric convenience ---- ) + +: SQUARED ( n -- n*n ) DUP * ; +: CUBED ( n -- n*n*n ) DUP SQUARED * ; + +( ---- Fetch and print: classic Forth debug helper ---- ) + +: ? ( addr -- ) @ . ; diff --git a/tests/test-north.sh b/tests/test-north.sh index f81939a..cdc4b11 100644 --- a/tests/test-north.sh +++ b/tests/test-north.sh @@ -4,6 +4,7 @@ # Later: convert to in-Urbit threads LIB="desk/lib/north.hoon" +CORE="desk/lib/core.fs" PASS=0 FAIL=0 # Forth TRUE = max direct atom in Vere64 (2^63-1 = 0x7fff.ffff.ffff.ffff) @@ -11,6 +12,11 @@ FAIL=0 T="9.223.372.036.854.775.807" F=0 +# Flatten core.fs into a single-line tape literal, escaping backslash and quote +# so it can be embedded inside a hoon "..." tape. Paren comments in core.fs +# survive the newline-to-space collapse (unlike \ line comments would). +CORE_SRC=$(sed 's|\\|\\\\|g; s|"|\\"|g' "$CORE" | tr '\n' ' ') + north-eval() { local raw raw=$( (echo "=>"; cat "$LIB"; echo "$1") | ~/bin/urbit eval 2>&1 ) @@ -955,6 +961,41 @@ check "DEFER IS re" "d-stack:(eval (parse \": sq dup * ; : double 2 * ; DEFER f # Mutual recursion via DEFER: even?/odd? ping-pong (drop arg before returning result) check "DEFER mutual" "d-stack:(eval (parse \"DEFER is-even : is-odd dup 0 = IF drop 0 EXIT THEN 1- is-even ; : is-even-impl dup 0 = IF drop 1 EXIT THEN 1- is-odd ; ' is-even-impl IS is-even 4 is-even\") *north)" "~[1]" +echo "" +echo "=== Core stdlib (desk/lib/core.fs) ===" + +# Comparison shorthands +check "<= less" "d-stack:(eval (parse \"$CORE_SRC 3 5 <=\") *north)" "~[$T]" +check "<= equal" "d-stack:(eval (parse \"$CORE_SRC 5 5 <=\") *north)" "~[$T]" +check "<= greater" "d-stack:(eval (parse \"$CORE_SRC 7 5 <=\") *north)" "~[$F]" +check ">= less" "d-stack:(eval (parse \"$CORE_SRC 3 5 >=\") *north)" "~[$F]" +check ">= equal" "d-stack:(eval (parse \"$CORE_SRC 5 5 >=\") *north)" "~[$T]" +check ">= greater" "d-stack:(eval (parse \"$CORE_SRC 7 5 >=\") *north)" "~[$T]" +check "0<> zero" "d-stack:(eval (parse \"$CORE_SRC 0 0<>\") *north)" "~[$F]" +check "0<> nonzero" "d-stack:(eval (parse \"$CORE_SRC 7 0<>\") *north)" "~[$T]" +check "U<= less" "d-stack:(eval (parse \"$CORE_SRC 3 5 U<=\") *north)" "~[$T]" +check "U<= equal" "d-stack:(eval (parse \"$CORE_SRC 5 5 U<=\") *north)" "~[$T]" +check "U<= greater" "d-stack:(eval (parse \"$CORE_SRC 7 5 U<=\") *north)" "~[$F]" +check "U>= less" "d-stack:(eval (parse \"$CORE_SRC 3 5 U>=\") *north)" "~[$F]" +check "U>= equal" "d-stack:(eval (parse \"$CORE_SRC 5 5 U>=\") *north)" "~[$T]" +check "U>= greater" "d-stack:(eval (parse \"$CORE_SRC 7 5 U>=\") *north)" "~[$T]" + +# WITHIN: true iff lo <= n < hi +check "WITHIN low" "d-stack:(eval (parse \"$CORE_SRC 5 5 10 WITHIN\") *north)" "~[$T]" +check "WITHIN mid" "d-stack:(eval (parse \"$CORE_SRC 7 5 10 WITHIN\") *north)" "~[$T]" +check "WITHIN high" "d-stack:(eval (parse \"$CORE_SRC 10 5 10 WITHIN\") *north)" "~[$F]" +check "WITHIN under" "d-stack:(eval (parse \"$CORE_SRC 4 5 10 WITHIN\") *north)" "~[$F]" +check "WITHIN over" "d-stack:(eval (parse \"$CORE_SRC 11 5 10 WITHIN\") *north)" "~[$F]" + +# Numeric helpers +check "SQUARED 0" "d-stack:(eval (parse \"$CORE_SRC 0 SQUARED\") *north)" "~[0]" +check "SQUARED 7" "d-stack:(eval (parse \"$CORE_SRC 7 SQUARED\") *north)" "~[49]" +check "CUBED 0" "d-stack:(eval (parse \"$CORE_SRC 0 CUBED\") *north)" "~[0]" +check "CUBED 3" "d-stack:(eval (parse \"$CORE_SRC 3 CUBED\") *north)" "~[27]" + +# ? fetch-and-print: allot a cell, store 42, then ? prints it via output buffer +check "? prints" "output.buffers:(eval (parse \"$CORE_SRC 1 ALLOT 42 0 ! 0 ?\") *north)" '"42 "' + echo "" echo "=== Results ===" echo "Passed: $PASS Failed: $FAIL"