examples: lisp — pure-ww Lisp interpreter, REPL, in-process tests
Demo program that lives entirely on lib/* and libwwrt.a — no @symbol
FFI of its own. The interpreter sits in lispcore.ww (exports for the
test driver); lisp.ww is a 3-line entry that calls lispcore.repl().
Language surface: integers, floats, symbols, strings, lists, lambdas
with closures, define / set! / if / quote / let / begin, recursion
(fact / fib / ackermann / gcd), map / filter / reduce as user code.
REPL is line-buffered: each read tries to parse one top-level form,
asks for more on "unterminated list", evaluates and prints, then
shifts consumed bytes off the front of the buffer. Lookahead-aware —
the parser primes one extra token so we shift to L.curstart, not
L.pos, otherwise the first byte of the next form gets eaten.
lisp_test.ww exec'd as a regular binary (ww test drops -I in single-
file mode); 66 probes cover arithmetic, lists, closures, recursion,
errors. test_*.lisp drive the live REPL through `make demo`.
The wwstage cgen still mis-lowers a handful of patterns at this
shape of program — top-level array indexing, global-ptr deref,
two-level field stores, f64 routing through *T, alloc(structlit{})
for f64/str fields, (slice | E) returns, xs[i].kind chains, f64
compound assigns. Each workaround is annotated at its use site;
the full taxonomy is in examples/lisp/CLAUDE.md.
This commit is contained in:
167
examples/lisp/test_huge.lisp
Normal file
167
examples/lisp/test_huge.lisp
Normal file
@@ -0,0 +1,167 @@
|
||||
; test_huge.lisp — broad workout for the interpreter. Each section
|
||||
; defines a set of helpers and then exercises them, so the same
|
||||
; program touches arithmetic, list-building, closures, recursion,
|
||||
; tail calls, and a few short-loop computations.
|
||||
;
|
||||
; Run: cat test_huge.lisp | ./lisp
|
||||
; Profile: valgrind --tool=massif --pages-as-heap=yes ./lisp < test_huge.lisp
|
||||
|
||||
;; -- core helpers --------------------------------------------------------
|
||||
|
||||
(define inc (lambda (n) (+ n 1)))
|
||||
(define dec (lambda (n) (- n 1)))
|
||||
(define neg (lambda (n) (- 0 n)))
|
||||
(define abs (lambda (n) (if (< n 0) (- 0 n) n)))
|
||||
(define square (lambda (n) (* n n)))
|
||||
(define cube (lambda (n) (* n n n)))
|
||||
(define even? (lambda (n) (= 0 (mod n 2))))
|
||||
(define odd? (lambda (n) (not (even? n))))
|
||||
|
||||
;; -- list utilities ------------------------------------------------------
|
||||
|
||||
(define len (lambda (l)
|
||||
(if (null? l) 0 (+ 1 (len (cdr l))))))
|
||||
(define nth (lambda (l n)
|
||||
(if (= n 0) (car l) (nth (cdr l) (- n 1)))))
|
||||
(define last (lambda (l)
|
||||
(if (null? (cdr l)) (car l) (last (cdr l)))))
|
||||
(define reverse-onto (lambda (l acc)
|
||||
(if (null? l) acc (reverse-onto (cdr l) (cons (car l) acc)))))
|
||||
(define reverse (lambda (l) (reverse-onto l '())))
|
||||
(define append2 (lambda (a b)
|
||||
(if (null? a) b (cons (car a) (append2 (cdr a) b)))))
|
||||
(define map (lambda (f l)
|
||||
(if (null? l) '() (cons (f (car l)) (map f (cdr l))))))
|
||||
(define filter (lambda (p l)
|
||||
(if (null? l) '()
|
||||
(if (p (car l))
|
||||
(cons (car l) (filter p (cdr l)))
|
||||
(filter p (cdr l))))))
|
||||
(define reduce (lambda (f acc l)
|
||||
(if (null? l) acc (reduce f (f acc (car l)) (cdr l)))))
|
||||
(define iota (lambda (n)
|
||||
(if (= n 0) '() (cons n (iota (- n 1))))))
|
||||
(define range (lambda (n) (reverse (iota n))))
|
||||
|
||||
;; -- numeric helpers -----------------------------------------------------
|
||||
|
||||
(define max2 (lambda (a b) (if (> a b) a b)))
|
||||
(define min2 (lambda (a b) (if (< a b) a b)))
|
||||
(define max-list (lambda (l) (reduce max2 (car l) (cdr l))))
|
||||
(define min-list (lambda (l) (reduce min2 (car l) (cdr l))))
|
||||
(define sum (lambda (l) (reduce + 0 l)))
|
||||
(define product (lambda (l) (reduce * 1 l)))
|
||||
(define gcd (lambda (a b)
|
||||
(if (= b 0) a (gcd b (mod a b)))))
|
||||
(define lcm (lambda (a b) (/ (* a b) (gcd a b))))
|
||||
|
||||
;; -- recursive showpieces ------------------------------------------------
|
||||
|
||||
(define fact (lambda (n)
|
||||
(if (<= n 1) 1 (* n (fact (- n 1))))))
|
||||
(define fib (lambda (n)
|
||||
(if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))
|
||||
(define ack (lambda (m n)
|
||||
(if (= m 0) (+ n 1)
|
||||
(if (= n 0) (ack (- m 1) 1)
|
||||
(ack (- m 1) (ack m (- n 1)))))))
|
||||
|
||||
;; -- closures (let / let-over-lambda) -----------------------------------
|
||||
|
||||
(define adder (lambda (k) (lambda (x) (+ x k))))
|
||||
(define muller (lambda (k) (lambda (x) (* x k))))
|
||||
(define counter (lambda () (begin (define c 0) (lambda () (begin (set! c (+ c 1)) c)))))
|
||||
|
||||
(define add1 (adder 1))
|
||||
(define add10 (adder 10))
|
||||
(define add100 (adder 100))
|
||||
(define dbl (muller 2))
|
||||
(define triple (muller 3))
|
||||
|
||||
;; -- exercise the helpers -----------------------------------------------
|
||||
|
||||
(map inc '(1 2 3 4 5)) ; => (2 3 4 5 6)
|
||||
(map square '(1 2 3 4 5 6 7 8 9 10)) ; => (1 4 9 ... 100)
|
||||
(filter even? '(1 2 3 4 5 6 7 8 9 10)) ; => (2 4 6 8 10)
|
||||
(filter odd? (range 12)) ; => (1 3 5 7 9 11)
|
||||
(sum (range 100)) ; => 5050
|
||||
(sum (map square (range 10))) ; => 385
|
||||
(product '(1 2 3 4 5 6 7)) ; => 5040
|
||||
(max-list '(3 1 4 1 5 9 2 6 5 3 5)) ; => 9
|
||||
(min-list '(3 1 4 1 5 9 2 6 5 3 5)) ; => 1
|
||||
(len (range 50)) ; => 50
|
||||
(nth (range 30) 17) ; => 18
|
||||
(last (range 25)) ; => 25
|
||||
(reverse (range 8)) ; => (8 7 6 5 4 3 2 1)
|
||||
(append2 '(1 2 3) '(a b c)) ; => (1 2 3 a b c)
|
||||
(append2 (range 4) (reverse (range 4))) ; => (1 2 3 4 4 3 2 1)
|
||||
|
||||
;; -- gcd / lcm batch ----------------------------------------------------
|
||||
|
||||
(gcd 1024 768) ; => 256
|
||||
(gcd 12345 54321) ; => 3
|
||||
(gcd 1000003 1000033) ; => 1
|
||||
(lcm 12 18) ; => 36
|
||||
(lcm 7 11) ; => 77
|
||||
|
||||
;; -- factorials ----------------------------------------------------------
|
||||
|
||||
(fact 1) ; => 1
|
||||
(fact 5) ; => 120
|
||||
(fact 10) ; => 3628800
|
||||
(fact 15) ; => 1307674368000
|
||||
(fact 20) ; => 2432902008176640000
|
||||
|
||||
;; -- fibonacci (exponential — sized for ~few sec under massif) ---------
|
||||
|
||||
(fib 5) ; => 5
|
||||
(fib 10) ; => 55
|
||||
(fib 15) ; => 610
|
||||
(fib 18) ; => 2584
|
||||
|
||||
;; -- ackermann -----------------------------------------------------------
|
||||
|
||||
(ack 2 2) ; => 7
|
||||
(ack 2 4) ; => 11
|
||||
(ack 3 3) ; => 61
|
||||
|
||||
;; -- closure exercise ---------------------------------------------------
|
||||
|
||||
(add1 41) ; => 42
|
||||
(add10 92) ; => 102
|
||||
(add100 1) ; => 101
|
||||
(dbl 21) ; => 42
|
||||
(triple 14) ; => 42
|
||||
(map add10 '(1 2 3 4 5)) ; => (11 12 13 14 15)
|
||||
(map dbl (range 6)) ; => (2 4 6 8 10 12)
|
||||
|
||||
;; -- mixed pipeline (filter → map → reduce) -----------------------------
|
||||
|
||||
(define pipeline (lambda (l)
|
||||
(reduce + 0 (map square (filter even? l)))))
|
||||
(pipeline (range 10)) ; even squares 1..10 = 4+16+36+64+100 = 220
|
||||
(pipeline (range 20)) ; even squares 1..20
|
||||
(pipeline (range 30))
|
||||
|
||||
;; -- tail-recursive spin -------------------------------------------------
|
||||
|
||||
(define spin (lambda (n acc)
|
||||
(if (= n 0) acc (spin (- n 1) (+ acc 1)))))
|
||||
(spin 200 0) ; => 200
|
||||
(spin 500 0) ; => 500
|
||||
(spin 1000 0) ; => 1000
|
||||
|
||||
;; -- mutual-flavored recursion ------------------------------------------
|
||||
|
||||
(define ev? (lambda (n) (if (= n 0) #t (od? (- n 1)))))
|
||||
(define od? (lambda (n) (if (= n 0) #f (ev? (- n 1)))))
|
||||
(ev? 12) ; => #t
|
||||
(od? 13) ; => #t
|
||||
(ev? 27) ; => #f
|
||||
|
||||
;; -- final sanity -------------------------------------------------------
|
||||
|
||||
(+ (fact 6) (fib 14) (gcd 60 24)) ; 720 + 377 + 12 = 1109
|
||||
(reduce + 0 (map (lambda (n) (* n n)) (range 20))) ; 1+4+9+...+400 = 2870
|
||||
|
||||
"all done"
|
||||
Reference in New Issue
Block a user