shithub: femtolisp

Download patch

ref: ed2b11a8ac69cd8296aa0910f2f08c5f2cab2752
parent: 21dd64045484411ef9c9f218c1490fd02c02b3fd
author: Jeff Bezanson <[email protected]>
date: Fri Feb 17 12:38:10 EST 2012

some cleanup

--- /dev/null
+++ b/femtolisp/.gitignore
@@ -1,0 +1,4 @@
+/*.o
+/*.do
+/*.a
+/flisp
--- a/femtolisp/100x100.lsp
+++ /dev/null
@@ -1,1 +1,0 @@
-'#0=(#198=(#197=(#196=(#195=(#194=(#193=(#192=(#191=(#190=(#189=(#188=(#187=(#186=(#185=(#184=(#183=(#182=(#181=(#180=(#179=(#178=(#177=(#176=(#175=(#174=(#173=(#172=(#171=(#170=(#169=(#168=(#167=(#166=(#165=(#164=(#163=(#162=(#161=(#160=(#159=(#158=(#157=(#156=(#155=(#154=(#153=(#152=(#151=(#150=(#149=(#148=(#147=(#146=(#145=(#144=(#143=(#142=(#141=(#140=(#139=(#138=(#137=(#136=(#135=(#134=(#133=(#132=(#131=(#130=(#129=(#128=(#127=(#126=(#125=(#124=(#123=(#122=(#121=(#120=(#119=(#118=(#117=(#116=(#115=(#114=(#113=(#112=(#111=(#110=(#109=(#108=(#107=(#106=(#105=(#104=(#103=(#102=(#101=(#100=(#0# . #1=(#9999=(#9998=(#9997=(#9996=(#9995=(#9994=(#9993=(#9992=(#9991=(#9990=(#9989=(#9988=(#9987=(#9986=(#9985=(#9984=(#9983=(#9982=(#9981=(#9980=(#9979=(#9978=(#9977=(#9976=(#9975=(#9974=(#9973=(#9972=(#9971=(#9970=(#9969=(#9968=(#9967=(#9966=(#9965=(#9964=(#9963=(#9962=(#9961=(#9960=(#9959=(#9958=(#9957=(#9956=(#9955=(#9954=(#9953=(#9952=(#9951=(#9950=(#9949=(#9948=(#9947=(#9946=(#9945=(#9944=(#9943=(#9942=(#9941=(#9940=(#9939=(#9938=(#9937=(#9936=(#9935=(#9934=(#9933=(#9932=(#9931=(#9930=(#9929=(#9928=(#9927=(#9926=(#9925=(#9924=(#9923=(#9922=(#9921=(#9920=(#9919=(#9918=(#9917=(#9916=(#9915=(#9914=(#9913=(#9912=(#9911=(#9910=(#9909=(#9908=(#9907=(#9906=(#9905=(#9904=(#9903=(#9902=(#9901=(#1# . #2=(#9900=(#9899=(#9898=(#9897=(#9896=(#9895=(#9894=(#9893=(#9892=(#9891=(#9890=(#9889=(#9888=(#9887=(#9886=(#9885=(#9884=(#9883=(#9882=(#9881=(#9880=(#9879=(#9878=(#9877=(#9876=(#9875=(#9874=(#9873=(#9872=(#9871=(#9870=(#9869=(#9868=(#9867=(#9866=(#9865=(#9864=(#9863=(#9862=(#9861=(#9860=(#9859=(#9858=(#9857=(#9856=(#9855=(#9854=(#9853=(#9852=(#9851=(#9850=(#9849=(#9848=(#9847=(#9846=(#9845=(#9844=(#9843=(#9842=(#9841=(#9840=(#9839=(#9838=(#9837=(#9836=(#9835=(#9834=(#9833=(#9832=(#9831=(#9830=(#9829=(#9828=(#9827=(#9826=(#9825=(#9824=(#9823=(#9822=(#9821=(#9820=(#9819=(#9818=(#9817=(#9816=(#9815=(#9814=(#9813=(#9812=(#9811=(#9810=(#9809=(#9808=(#9807=(#9806=(#9805=(#9804=(#9803=(#9802=(#2# . #3=(#9801=(#9800=(#9799=(#9798=(#9797=(#9796=(#9795=(#9794=(#9793=(#9792=(#9791=(#9790=(#9789=(#9788=(#9787=(#9786=(#9785=(#9784=(#9783=(#9782=(#9781=(#9780=(#9779=(#9778=(#9777=(#9776=(#9775=(#9774=(#9773=(#9772=(#9771=(#9770=(#9769=(#9768=(#9767=(#9766=(#9765=(#9764=(#9763=(#9762=(#9761=(#9760=(#9759=(#9758=(#9757=(#9756=(#9755=(#9754=(#9753=(#9752=(#9751=(#9750=(#9749=(#9748=(#9747=(#9746=(#9745=(#9744=(#9743=(#9742=(#9741=(#9740=(#9739=(#9738=(#9737=(#9736=(#9735=(#9734=(#9733=(#9732=(#9731=(#9730=(#9729=(#9728=(#9727=(#9726=(#9725=(#9724=(#9723=(#9722=(#9721=(#9720=(#9719=(#9718=(#9717=(#9716=(#9715=(#9714=(#9713=(#9712=(#9711=(#9710=(#9709=(#9708=(#9707=(#9706=(#9705=(#9704=(#9703=(#3# . #4=(#9702=(#9701=(#9700=(#9699=(#9698=(#9697=(#9696=(#9695=(#9694=(#9693=(#9692=(#9691=(#9690=(#9689=(#9688=(#9687=(#9686=(#9685=(#9684=(#9683=(#9682=(#9681=(#9680=(#9679=(#9678=(#9677=(#9676=(#9675=(#9674=(#9673=(#9672=(#9671=(#9670=(#9669=(#9668=(#9667=(#9666=(#9665=(#9664=(#9663=(#9662=(#9661=(#9660=(#9659=(#9658=(#9657=(#9656=(#9655=(#9654=(#9653=(#9652=(#9651=(#9650=(#9649=(#9648=(#9647=(#9646=(#9645=(#9644=(#9643=(#9642=(#9641=(#9640=(#9639=(#9638=(#9637=(#9636=(#9635=(#9634=(#9633=(#9632=(#9631=(#9630=(#9629=(#9628=(#9627=(#9626=(#9625=(#9624=(#9623=(#9622=(#9621=(#9620=(#9619=(#9618=(#9617=(#9616=(#9615=(#9614=(#9613=(#9612=(#9611=(#9610=(#9609=(#9608=(#9607=(#9606=(#9605=(#9604=(#4# . #5=(#9603=(#9602=(#9601=(#9600=(#9599=(#9598=(#9597=(#9596=(#9595=(#9594=(#9593=(#9592=(#9591=(#9590=(#9589=(#9588=(#9587=(#9586=(#9585=(#9584=(#9583=(#9582=(#9581=(#9580=(#9579=(#9578=(#9577=(#9576=(#9575=(#9574=(#9573=(#9572=(#9571=(#9570=(#9569=(#9568=(#9567=(#9566=(#9565=(#9564=(#9563=(#9562=(#9561=(#9560=(#9559=(#9558=(#9557=(#9556=(#9555=(#9554=(#9553=(#9552=(#9551=(#9550=(#9549=(#9548=(#9547=(#9546=(#9545=(#9544=(#9543=(#9542=(#9541=(#9540=(#9539=(#9538=(#9537=(#9536=(#9535=(#9534=(#9533=(#9532=(#9531=(#9530=(#9529=(#9528=(#9527=(#9526=(#9525=(#9524=(#9523=(#9522=(#9521=(#9520=(#9519=(#9518=(#9517=(#9516=(#9515=(#9514=(#9513=(#9512=(#9511=(#9510=(#9509=(#9508=(#9
\ No newline at end of file
--- a/femtolisp/Makefile
+++ b/femtolisp/Makefile
@@ -22,7 +22,7 @@
 default: release test
 
 test:
-	./flisp unittest.lsp
+	cd tests && ../flisp unittest.lsp
 
 %.o: %.c
 	$(CC) $(SHIPFLAGS) -c $< -o $@
--- a/femtolisp/bq.scm
+++ /dev/null
@@ -1,122 +1,0 @@
-(define (bq-process2 x d)
-  (define (splice-form? x)
-    (or (and (pair? x) (or (eq? (car x) 'unquote-splicing)
-			   (eq? (car x) 'unquote-nsplicing)
-			   (and (eq? (car x) 'unquote)
-				(length> x 2))))
-	(eq? x 'unquote)))
-  ;; bracket without splicing
-  (define (bq-bracket1 x)
-    (if (and (pair? x) (eq? (car x) 'unquote))
-	(if (= d 0)
-	    (cadr x)
-	    (list cons ''unquote
-		  (bq-process2 (cdr x) (- d 1))))
-	(bq-process2 x d)))
-  (define (bq-bracket x)
-    (cond ((atom? x)  (list list (bq-process2 x d)))
-	  ((eq? (car x) 'unquote)
-	   (if (= d 0)
-	       (cons list (cdr x))
-	       (list list (list cons ''unquote
-				(bq-process2 (cdr x) (- d 1))))))
-	  ((eq? (car x) 'unquote-splicing)
-	   (if (= d 0)
-	       (list 'copy-list (cadr x))
-	       (list list (list list ''unquote-splicing
-				(bq-process2 (cadr x) (- d 1))))))
-	  ((eq? (car x) 'unquote-nsplicing)
-	   (if (= d 0)
-	       (cadr x)
-	       (list list (list list ''unquote-nsplicing
-				(bq-process2 (cadr x) (- d 1))))))
-	  (else  (list list (bq-process2 x d)))))
-  (cond ((symbol? x)  (list 'quote x))
-	((vector? x)
-	 (let ((body (bq-process2 (vector->list x) d)))
-	   (if (eq? (car body) list)
-	       (cons vector (cdr body))
-	       (list apply vector body))))
-        ((atom? x)  x)
-        ((eq? (car x) 'quasiquote)
-	 (list list ''quasiquote (bq-process2 (cadr x) (+ d 1))))
-        ((eq? (car x) 'unquote)
-	 (if (and (= d 0) (length= x 2))
-	     (cadr x)
-	     (list cons ''unquote (bq-process2 (cdr x) (- d 1)))))
-	((or (> d 0) (not (any splice-form? x)))
-         (let ((lc    (lastcdr x))
-               (forms (map bq-bracket1 x)))
-           (if (null? lc)
-               (cons list forms)
-	       (if (null? (cdr forms))
-		   (list cons (car forms) (bq-process2 lc d))
-		   (nconc (cons list* forms) (list (bq-process2 lc d)))))))
-	(else
-	 (let loop ((p x) (q ()))
-	   (cond ((null? p) ;; proper list
-		  (cons 'nconc (reverse! q)))
-		 ((pair? p)
-		  (cond ((eq? (car p) 'unquote)
-			 ;; (... . ,x)
-			 (cons 'nconc
-			       (nreconc q
-					(if (= d 0)
-					    (cdr p)
-					    (list (list list ''unquote)
-						  (bq-process2 (cdr p)
-							       (- d 1)))))))
-			(else
-			 (loop (cdr p) (cons (bq-bracket (car p)) q)))))
-		 (else
-		  ;; (... . x)
-		  (cons 'nconc (reverse! (cons (bq-process2 p d) q)))))))))
-
-#|
-tests
-
-> ``(,a ,,a ,b ,@b ,,@b)
-`(,a ,1 ,b ,@b (unquote 2 3))
-> `(,a ,1 ,b ,@b (unquote 2 3))
-(1 1 (2 3) 2 3 2 3)
-
-(define a 1)
-
-(bq-process2 '`(,a (unquote unquote a)) 0)
-
-(define b '(unquote a))
-(define unquote 88)
-(bq-process2 '``(,a ,,,@b) 0)
-; etc. => (1 88 1)
-
-(define b '(a a))
-(bq-process2 '``(,a ,,,@b) 0)
-; etc. => (1 1 1)
-|#
-
-;; minimal version with no optimizations, vectors, or dotted lists
-(define (bq-process0 x d)
-  (define (bq-bracket x)
-    (cond ((and (pair? x) (eq? (car x) 'unquote))
-	   (if (= d 0)
-	       (cons list (cdr x))
-	       (list list (list cons ''unquote
-				(bq-process0 (cdr x) (- d 1))))))
-	  ((and (pair? x) (eq? (car x) 'unquote-splicing))
-	   (if (= d 0)
-	       (list 'copy-list (cadr x))
-	       (list list (list list ''unquote-splicing
-				(bq-process0 (cadr x) (- d 1))))))
-	  (else  (list list (bq-process0 x d)))))
-  (cond ((symbol? x)  (list 'quote x))
-        ((atom? x)    x)
-        ((eq? (car x) 'quasiquote)
-	 (list list ''quasiquote (bq-process0 (cadr x) (+ d 1))))
-        ((eq? (car x) 'unquote)
-	 (if (and (= d 0) (length= x 2))
-	     (cadr x)
-	     (list cons ''unquote (bq-process0 (cdr x) (- d 1)))))
-	(else
-	 (cons 'nconc (map bq-bracket x)))))
-
-#t
--- a/femtolisp/color.lsp
+++ /dev/null
@@ -1,89 +1,0 @@
-; -*- scheme -*-
-
-; dictionaries ----------------------------------------------------------------
-(define (dict-new) ())
-
-(define (dict-extend dl key value)
-  (cond ((null? dl)              (list (cons key value)))
-        ((equal? key (caar dl))  (cons (cons key value) (cdr dl)))
-        (else (cons (car dl) (dict-extend (cdr dl) key value)))))
-
-(define (dict-lookup dl key)
-  (cond ((null? dl)              ())
-        ((equal? key (caar dl))  (cdar dl))
-        (else (dict-lookup (cdr dl) key))))
-
-(define (dict-keys dl) (map car dl))
-
-; graphs ----------------------------------------------------------------------
-(define (graph-empty) (dict-new))
-
-(define (graph-connect g n1 n2)
-  (dict-extend
-   (dict-extend g n2 (cons n1 (dict-lookup g n2)))
-   n1
-   (cons n2 (dict-lookup g n1))))
-
-(define (graph-adjacent? g n1 n2) (member n2 (dict-lookup g n1)))
-
-(define (graph-neighbors g n) (dict-lookup g n))
-
-(define (graph-nodes g) (dict-keys g))
-
-(define (graph-add-node g n1) (dict-extend g n1 ()))
-
-(define (graph-from-edges edge-list)
-  (if (null? edge-list)
-      (graph-empty)
-    (graph-connect (graph-from-edges (cdr edge-list))
-                   (caar edge-list)
-                   (cdar edge-list))))
-
-; graph coloring --------------------------------------------------------------
-(define (node-colorable? g coloring node-to-color color-of-node)
-  (not (member
-        color-of-node
-        (map
-         (lambda (n)
-           (let ((color-pair (assq n coloring)))
-             (if (pair? color-pair) (cdr color-pair) ())))
-         (graph-neighbors g node-to-color)))))
-
-(define (try-each f lst)
-  (if (null? lst) #f
-      (let ((ret (f (car lst))))
-	(if ret ret (try-each f (cdr lst))))))
-
-(define (color-node g coloring colors uncolored-nodes color)
-  (cond
-   ((null? uncolored-nodes) coloring)
-   ((node-colorable? g coloring (car uncolored-nodes) color)
-    (let ((new-coloring
-           (cons (cons (car uncolored-nodes) color) coloring)))
-      (try-each (lambda (c)
-                  (color-node g new-coloring colors (cdr uncolored-nodes) c))
-                colors)))))
-
-(define (color-graph g colors)
-  (if (null? colors)
-      (and (null? (graph-nodes g)) ())
-      (color-node g () colors (graph-nodes g) (car colors))))
-
-(define (color-pairs pairs colors)
-  (color-graph (graph-from-edges pairs) colors))
-
-; queens ----------------------------------------------------------------------
-(define (can-attack x y)
-  (let ((x1 (mod x 5))
-        (y1 (truncate (/ x 5)))
-        (x2 (mod y 5))
-        (y2 (truncate (/ y 5))))
-    (or (= x1 x2) (= y1 y2) (= (abs (- y2 y1)) (abs (- x2 x1))))))
-
-(define (generate-5x5-pairs)
-  (let ((result ()))
-    (dotimes (x 25)
-      (dotimes (y 25)
-        (if (and (not (= x y)) (can-attack x y))
-            (set! result (cons (cons x y) result)) ())))
-    result))
--- a/femtolisp/cps.lsp
+++ /dev/null
@@ -1,308 +1,0 @@
-; -*- scheme -*-
-(define (begin->cps forms k)
-  (cond ((atom? forms)       `(,k ,forms))
-        ((null? (cdr forms))  (cps- (car forms) k))
-        (#t (let ((_ (gensym)))   ; var to bind ignored value
-	      (cps- (car forms) `(lambda (,_)
-				   ,(begin->cps (cdr forms) k)))))))
-
-(define-macro (lambda/cc args body)
-  `(cons 'lambda/cc (lambda ,args ,body)))
-
-; a utility used at run time to dispatch a call with or without
-; the continuation argument, depending on the function
-(define (funcall/cc f k . args)
-  (if (and (pair? f) (eq (car f) 'lambda/cc))
-      (apply (cdr f) (cons k args))
-      (k (apply f args))))
-(define *funcall/cc-names*
-  (list->vector
-   (map (lambda (i) (symbol (string 'funcall/cc- i)))
-        (iota 6))))
-(define-macro (def-funcall/cc-n args)
-  (let ((name (aref *funcall/cc-names* (length args))))
-    `(define (,name f k ,@args)
-       (if (and (pair? f) (eq (car f) 'lambda/cc))
-           ((cdr f) k ,@args)
-	   (k (f ,@args))))))
-(def-funcall/cc-n ())
-(def-funcall/cc-n (a0))
-(def-funcall/cc-n (a0 a1))
-(def-funcall/cc-n (a0 a1 a2))
-(def-funcall/cc-n (a0 a1 a2 a3))
-(def-funcall/cc-n (a0 a1 a2 a3 a4))
-
-(define (rest->cps xformer form k argsyms)
-  (let ((el (car form)))
-    (if (or (atom? el) (constant? el))
-        (xformer (cdr form) k (cons el argsyms))
-      (let ((g (gensym)))
-        (cps- el `(lambda (,g)
-                    ,(xformer (cdr form) k (cons g argsyms))))))))
-
-(define (make-funcall/cc head ke args)
-  (let ((n (length args)))
-    (if (< n 6)
-        `(,(aref *funcall/cc-names* n) ,head ,ke ,@args)
-      `(funcall/cc ,head ,ke ,@args))))
-
-; (f x) => (cps- f `(lambda (F) ,(cps- x `(lambda (X) (F ,k X)))))
-(define (app->cps form k argsyms)
-  (cond ((atom? form)
-         (let ((r (reverse argsyms)))
-           (make-funcall/cc (car r) k (cdr r))))
-        (#t (rest->cps app->cps form k argsyms))))
-
-; (+ x) => (cps- x `(lambda (X) (,k (+ X))))
-(define (builtincall->cps form k)
-  (prim->cps (cdr form) k (list (car form))))
-(define (prim->cps form k argsyms)
-  (cond ((atom? form) `(,k ,(reverse argsyms)))
-        (#t           (rest->cps prim->cps form k argsyms))))
-
-(define *top-k* (gensym))
-(set-top-level-value! *top-k* identity)
-
-(define (cps form)
-  (η-reduce
-   (β-reduce
-    (expand
-     (cps- (expand form) *top-k*)))))
-(define (cps- form k)
-  (let ((g (gensym)))
-    (cond ((or (atom? form) (constant? form))
-           `(,k ,form))
-
-          ((eq (car form) 'lambda)
-           `(,k (lambda/cc ,(cons g (cadr form)) ,(cps- (caddr form) g))))
-
-          ((eq (car form) 'begin)
-           (begin->cps (cdr form) k))
-
-          ((eq (car form) 'if)
-           (let ((test (cadr form))
-                 (then (caddr form))
-                 (else (cadddr form)))
-             (if (atom? k)
-                 (cps- test `(lambda (,g)
-                               (if ,g
-                                   ,(cps- then k)
-                                 ,(cps- else k))))
-               `(let ((,g ,k))
-                  ,(cps- form g)))))
-
-          ((eq (car form) 'and)
-           (cond ((atom? (cdr  form)) `(,k #t))
-                 ((atom? (cddr form)) (cps- (cadr form) k))
-                 (#t
-                  (if (atom? k)
-                      (cps- (cadr form)
-                            `(lambda (,g)
-                               (if ,g ,(cps- `(and ,@(cddr form)) k)
-                                 (,k ,g))))
-                    `(let ((,g ,k))
-                       ,(cps- form g))))))
-
-          ((eq (car form) 'or)
-           (cond ((atom? (cdr  form)) `(,k #f))
-                 ((atom? (cddr form)) (cps- (cadr form) k))
-                 (#t
-                  (if (atom? k)
-                      (cps- (cadr form)
-                            `(lambda (,g)
-                               (if ,g (,k ,g)
-                                 ,(cps- `(or ,@(cddr form)) k))))
-                    `(let ((,g ,k))
-                       ,(cps- form g))))))
-
-          ((eq (car form) 'while)
-           (let ((test (cadr form))
-                 (body (caddr form))
-                 (lastval (gensym)))
-             (cps- (expand
-                    `(let ((,lastval #f))
-                       ((label ,g (lambda ()
-                                    (if ,test
-                                        (begin (set! ,lastval ,body)
-                                               (,g))
-                                      ,lastval))))))
-                   k)))
-
-          ((eq (car form) 'set!)
-           (let ((var (cadr form))
-                 (E   (caddr form)))
-             (cps- E `(lambda (,g) (,k (set! ,var ,g))))))
-
-          ((eq (car form) 'reset)
-           `(,k ,(cps- (cadr form) *top-k*)))
-
-          ((eq (car form) 'shift)
-           (let ((v (cadr form))
-                 (E (caddr form))
-                 (val (gensym)))
-             `(let ((,v (lambda/cc (,g ,val) (,g (,k ,val)))))
-                ,(cps- E *top-k*))))
-
-          ((eq (car form) 'without-delimited-continuations)
-           `(,k ,(cadr form)))
-
-          ((and (constant? (car form))
-                (builtin? (eval (car form))))
-           (builtincall->cps form k))
-
-          ; ((lambda (...) body) ...)
-          ((and (pair? (car form))
-                (eq (caar form) 'lambda))
-           (let ((largs (cadr (car form)))
-                 (lbody (caddr (car form))))
-             (cond ((null? largs)   ; ((lambda () body))
-                    (cps- lbody k))
-                   ((symbol? largs) ; ((lambda x body) args...)
-                    (cps- `((lambda (,largs) ,lbody) (list ,@(cdr form))) k))
-                   (#t
-                    (cps- (cadr form) `(lambda (,(car largs))
-                                         ,(cps- `((lambda ,(cdr largs) ,lbody)
-                                                  ,@(cddr form))
-                                                k)))))))
-
-          (#t
-           (app->cps form k ())))))
-
-; (lambda (args...) (f args...)) => f
-; but only for constant, builtin f
-(define (η-reduce form)
-  (cond ((or (atom? form) (constant? form)) form)
-        ((and (eq (car form) 'lambda)
-              (let ((body (caddr form))
-                    (args (cadr form)))
-                (and (pair? body)
-                     (equal? (cdr body) args)
-                     (constant? (car (caddr form))))))
-         (car (caddr form)))
-        (#t (map η-reduce form))))
-
-(define (contains x form)
-  (or (eq form x)
-      (any (lambda (p) (contains x p)) form)))
-
-(define (β-reduce form)
-  (if (or (atom? form) (constant? form))
-      form
-      (β-reduce- (map β-reduce form))))
-
-(define (β-reduce- form)
-        ; ((lambda (f) (f arg)) X) => (X arg)
-  (cond ((and (length= form 2)
-              (pair? (car form))
-              (eq (caar form) 'lambda)
-              (let ((args (cadr (car form)))
-                    (body (caddr (car form))))
-                (and (pair? body) (pair? args)
-                     (length= body 2)
-                     (length= args 1)
-                     (eq (car body) (car args))
-                     (not (eq (cadr body) (car args)))
-                     (symbol? (cadr body)))))
-         `(,(cadr form)
-           ,(cadr (caddr (car form)))))
-
-        ; (identity x) => x
-        ((eq (car form) *top-k*)
-         (cadr form))
-
-        ; uncurry:
-        ; ((lambda (p1) ((lambda (args...) body) exprs...)) s) =>
-        ; ((lambda (p1 args...) body) s exprs...)
-        ; where exprs... doesn't contain p1
-        ((and (length= form 2)
-              (pair? (car form))
-              (eq (caar form) 'lambda)
-              (or (atom? (cadr form)) (constant? (cadr form)))
-              (let ((args (cadr (car form)))
-                    (s (cadr form))
-                    (body (caddr (car form))))
-                (and (pair? args) (length= args 1)
-                     (pair? body)
-                     (pair? (car body))
-                     (eq (caar body) 'lambda)
-                     (let ((innerargs (cadr (car body)))
-                           (innerbody (caddr (car body)))
-                           (params (cdr body)))
-                       (and (not (contains (car args) params))
-                            `((lambda ,(cons (car args) innerargs)
-                                ,innerbody)
-                              ,s
-                              ,@params)))))))
-
-        (#t form)))
-
-(define-macro (with-delimited-continuations . code)
-  (cps `((lambda () ,@code))))
-
-(define-macro (define-generator form . body)
-  (let ((ko  (gensym))
-        (cur (gensym))
-	(name (car form))
-	(args (cdr form)))
-    `(define (,name ,@args)
-       (let ((,ko  #f)
-             (,cur #f))
-         (lambda ()
-           (with-delimited-continuations
-            (if ,ko (,ko ,cur)
-              (reset
-               (let ((yield
-                      (lambda (v)
-                        (shift yk
-                               (begin (set! ,ko  yk)
-                                      (set! ,cur v))))))
-                 ,@body)))))))))
-
-; a test case
-(define-generator (range-iterator lo hi)
-  ((label loop
-          (lambda (i)
-            (if (< hi i)
-                'done
-              (begin (yield i)
-                     (loop (+ 1 i))))))
-   lo))
-
-; example from Chung-chieh Shan's paper
-(assert (equal?
-         (with-delimited-continuations
-          (cons 'a (reset (cons 'b (shift f (cons 1 (f (f (cons 'c ())))))))))
-         '(a 1 b b c)))
-
-#t
-
-#|
-todo:
-* tag lambdas that accept continuation arguments, compile computed
-  calls to calls to funcall/cc that does the right thing for both
-  cc-lambdas and normal lambdas
-
-* handle dotted arglists in lambda
-
-- optimize constant functions, e.g. (funcall/cc-0 #:g65 (lambda (#:g58) 'done))
-
-- implement CPS version of apply
-
-- use fewer gensyms
-
- here's an alternate way to transform a while loop:
-
- (let ((x 0))
-   (while (< x 10)
-     (begin (print x) (set! x (+ 1 x)))))
- =>
-  (let ((x 0))
-    (reset
-     (let ((l #f))
-       (let ((k (shift k (k k))))
-         (if (< x 10)
-             (begin (set! l (begin (print x)
-                                   (set! x (+ 1 x))))
-                    (k k))
-           l)))))
-|#
--- /dev/null
+++ b/femtolisp/examples/bq.scm
@@ -1,0 +1,122 @@
+(define (bq-process2 x d)
+  (define (splice-form? x)
+    (or (and (pair? x) (or (eq? (car x) 'unquote-splicing)
+			   (eq? (car x) 'unquote-nsplicing)
+			   (and (eq? (car x) 'unquote)
+				(length> x 2))))
+	(eq? x 'unquote)))
+  ;; bracket without splicing
+  (define (bq-bracket1 x)
+    (if (and (pair? x) (eq? (car x) 'unquote))
+	(if (= d 0)
+	    (cadr x)
+	    (list cons ''unquote
+		  (bq-process2 (cdr x) (- d 1))))
+	(bq-process2 x d)))
+  (define (bq-bracket x)
+    (cond ((atom? x)  (list list (bq-process2 x d)))
+	  ((eq? (car x) 'unquote)
+	   (if (= d 0)
+	       (cons list (cdr x))
+	       (list list (list cons ''unquote
+				(bq-process2 (cdr x) (- d 1))))))
+	  ((eq? (car x) 'unquote-splicing)
+	   (if (= d 0)
+	       (list 'copy-list (cadr x))
+	       (list list (list list ''unquote-splicing
+				(bq-process2 (cadr x) (- d 1))))))
+	  ((eq? (car x) 'unquote-nsplicing)
+	   (if (= d 0)
+	       (cadr x)
+	       (list list (list list ''unquote-nsplicing
+				(bq-process2 (cadr x) (- d 1))))))
+	  (else  (list list (bq-process2 x d)))))
+  (cond ((symbol? x)  (list 'quote x))
+	((vector? x)
+	 (let ((body (bq-process2 (vector->list x) d)))
+	   (if (eq? (car body) list)
+	       (cons vector (cdr body))
+	       (list apply vector body))))
+        ((atom? x)  x)
+        ((eq? (car x) 'quasiquote)
+	 (list list ''quasiquote (bq-process2 (cadr x) (+ d 1))))
+        ((eq? (car x) 'unquote)
+	 (if (and (= d 0) (length= x 2))
+	     (cadr x)
+	     (list cons ''unquote (bq-process2 (cdr x) (- d 1)))))
+	((or (> d 0) (not (any splice-form? x)))
+         (let ((lc    (lastcdr x))
+               (forms (map bq-bracket1 x)))
+           (if (null? lc)
+               (cons list forms)
+	       (if (null? (cdr forms))
+		   (list cons (car forms) (bq-process2 lc d))
+		   (nconc (cons list* forms) (list (bq-process2 lc d)))))))
+	(else
+	 (let loop ((p x) (q ()))
+	   (cond ((null? p) ;; proper list
+		  (cons 'nconc (reverse! q)))
+		 ((pair? p)
+		  (cond ((eq? (car p) 'unquote)
+			 ;; (... . ,x)
+			 (cons 'nconc
+			       (nreconc q
+					(if (= d 0)
+					    (cdr p)
+					    (list (list list ''unquote)
+						  (bq-process2 (cdr p)
+							       (- d 1)))))))
+			(else
+			 (loop (cdr p) (cons (bq-bracket (car p)) q)))))
+		 (else
+		  ;; (... . x)
+		  (cons 'nconc (reverse! (cons (bq-process2 p d) q)))))))))
+
+#|
+tests
+
+> ``(,a ,,a ,b ,@b ,,@b)
+`(,a ,1 ,b ,@b (unquote 2 3))
+> `(,a ,1 ,b ,@b (unquote 2 3))
+(1 1 (2 3) 2 3 2 3)
+
+(define a 1)
+
+(bq-process2 '`(,a (unquote unquote a)) 0)
+
+(define b '(unquote a))
+(define unquote 88)
+(bq-process2 '``(,a ,,,@b) 0)
+; etc. => (1 88 1)
+
+(define b '(a a))
+(bq-process2 '``(,a ,,,@b) 0)
+; etc. => (1 1 1)
+|#
+
+;; minimal version with no optimizations, vectors, or dotted lists
+(define (bq-process0 x d)
+  (define (bq-bracket x)
+    (cond ((and (pair? x) (eq? (car x) 'unquote))
+	   (if (= d 0)
+	       (cons list (cdr x))
+	       (list list (list cons ''unquote
+				(bq-process0 (cdr x) (- d 1))))))
+	  ((and (pair? x) (eq? (car x) 'unquote-splicing))
+	   (if (= d 0)
+	       (list 'copy-list (cadr x))
+	       (list list (list list ''unquote-splicing
+				(bq-process0 (cadr x) (- d 1))))))
+	  (else  (list list (bq-process0 x d)))))
+  (cond ((symbol? x)  (list 'quote x))
+        ((atom? x)    x)
+        ((eq? (car x) 'quasiquote)
+	 (list list ''quasiquote (bq-process0 (cadr x) (+ d 1))))
+        ((eq? (car x) 'unquote)
+	 (if (and (= d 0) (length= x 2))
+	     (cadr x)
+	     (list cons ''unquote (bq-process0 (cdr x) (- d 1)))))
+	(else
+	 (cons 'nconc (map bq-bracket x)))))
+
+#t
--- /dev/null
+++ b/femtolisp/examples/cps.lsp
@@ -1,0 +1,308 @@
+; -*- scheme -*-
+(define (begin->cps forms k)
+  (cond ((atom? forms)       `(,k ,forms))
+        ((null? (cdr forms))  (cps- (car forms) k))
+        (#t (let ((_ (gensym)))   ; var to bind ignored value
+	      (cps- (car forms) `(lambda (,_)
+				   ,(begin->cps (cdr forms) k)))))))
+
+(define-macro (lambda/cc args body)
+  `(cons 'lambda/cc (lambda ,args ,body)))
+
+; a utility used at run time to dispatch a call with or without
+; the continuation argument, depending on the function
+(define (funcall/cc f k . args)
+  (if (and (pair? f) (eq (car f) 'lambda/cc))
+      (apply (cdr f) (cons k args))
+      (k (apply f args))))
+(define *funcall/cc-names*
+  (list->vector
+   (map (lambda (i) (symbol (string 'funcall/cc- i)))
+        (iota 6))))
+(define-macro (def-funcall/cc-n args)
+  (let ((name (aref *funcall/cc-names* (length args))))
+    `(define (,name f k ,@args)
+       (if (and (pair? f) (eq (car f) 'lambda/cc))
+           ((cdr f) k ,@args)
+	   (k (f ,@args))))))
+(def-funcall/cc-n ())
+(def-funcall/cc-n (a0))
+(def-funcall/cc-n (a0 a1))
+(def-funcall/cc-n (a0 a1 a2))
+(def-funcall/cc-n (a0 a1 a2 a3))
+(def-funcall/cc-n (a0 a1 a2 a3 a4))
+
+(define (rest->cps xformer form k argsyms)
+  (let ((el (car form)))
+    (if (or (atom? el) (constant? el))
+        (xformer (cdr form) k (cons el argsyms))
+      (let ((g (gensym)))
+        (cps- el `(lambda (,g)
+                    ,(xformer (cdr form) k (cons g argsyms))))))))
+
+(define (make-funcall/cc head ke args)
+  (let ((n (length args)))
+    (if (< n 6)
+        `(,(aref *funcall/cc-names* n) ,head ,ke ,@args)
+      `(funcall/cc ,head ,ke ,@args))))
+
+; (f x) => (cps- f `(lambda (F) ,(cps- x `(lambda (X) (F ,k X)))))
+(define (app->cps form k argsyms)
+  (cond ((atom? form)
+         (let ((r (reverse argsyms)))
+           (make-funcall/cc (car r) k (cdr r))))
+        (#t (rest->cps app->cps form k argsyms))))
+
+; (+ x) => (cps- x `(lambda (X) (,k (+ X))))
+(define (builtincall->cps form k)
+  (prim->cps (cdr form) k (list (car form))))
+(define (prim->cps form k argsyms)
+  (cond ((atom? form) `(,k ,(reverse argsyms)))
+        (#t           (rest->cps prim->cps form k argsyms))))
+
+(define *top-k* (gensym))
+(set-top-level-value! *top-k* identity)
+
+(define (cps form)
+  (η-reduce
+   (β-reduce
+    (expand
+     (cps- (expand form) *top-k*)))))
+(define (cps- form k)
+  (let ((g (gensym)))
+    (cond ((or (atom? form) (constant? form))
+           `(,k ,form))
+
+          ((eq (car form) 'lambda)
+           `(,k (lambda/cc ,(cons g (cadr form)) ,(cps- (caddr form) g))))
+
+          ((eq (car form) 'begin)
+           (begin->cps (cdr form) k))
+
+          ((eq (car form) 'if)
+           (let ((test (cadr form))
+                 (then (caddr form))
+                 (else (cadddr form)))
+             (if (atom? k)
+                 (cps- test `(lambda (,g)
+                               (if ,g
+                                   ,(cps- then k)
+                                 ,(cps- else k))))
+               `(let ((,g ,k))
+                  ,(cps- form g)))))
+
+          ((eq (car form) 'and)
+           (cond ((atom? (cdr  form)) `(,k #t))
+                 ((atom? (cddr form)) (cps- (cadr form) k))
+                 (#t
+                  (if (atom? k)
+                      (cps- (cadr form)
+                            `(lambda (,g)
+                               (if ,g ,(cps- `(and ,@(cddr form)) k)
+                                 (,k ,g))))
+                    `(let ((,g ,k))
+                       ,(cps- form g))))))
+
+          ((eq (car form) 'or)
+           (cond ((atom? (cdr  form)) `(,k #f))
+                 ((atom? (cddr form)) (cps- (cadr form) k))
+                 (#t
+                  (if (atom? k)
+                      (cps- (cadr form)
+                            `(lambda (,g)
+                               (if ,g (,k ,g)
+                                 ,(cps- `(or ,@(cddr form)) k))))
+                    `(let ((,g ,k))
+                       ,(cps- form g))))))
+
+          ((eq (car form) 'while)
+           (let ((test (cadr form))
+                 (body (caddr form))
+                 (lastval (gensym)))
+             (cps- (expand
+                    `(let ((,lastval #f))
+                       ((label ,g (lambda ()
+                                    (if ,test
+                                        (begin (set! ,lastval ,body)
+                                               (,g))
+                                      ,lastval))))))
+                   k)))
+
+          ((eq (car form) 'set!)
+           (let ((var (cadr form))
+                 (E   (caddr form)))
+             (cps- E `(lambda (,g) (,k (set! ,var ,g))))))
+
+          ((eq (car form) 'reset)
+           `(,k ,(cps- (cadr form) *top-k*)))
+
+          ((eq (car form) 'shift)
+           (let ((v (cadr form))
+                 (E (caddr form))
+                 (val (gensym)))
+             `(let ((,v (lambda/cc (,g ,val) (,g (,k ,val)))))
+                ,(cps- E *top-k*))))
+
+          ((eq (car form) 'without-delimited-continuations)
+           `(,k ,(cadr form)))
+
+          ((and (constant? (car form))
+                (builtin? (eval (car form))))
+           (builtincall->cps form k))
+
+          ; ((lambda (...) body) ...)
+          ((and (pair? (car form))
+                (eq (caar form) 'lambda))
+           (let ((largs (cadr (car form)))
+                 (lbody (caddr (car form))))
+             (cond ((null? largs)   ; ((lambda () body))
+                    (cps- lbody k))
+                   ((symbol? largs) ; ((lambda x body) args...)
+                    (cps- `((lambda (,largs) ,lbody) (list ,@(cdr form))) k))
+                   (#t
+                    (cps- (cadr form) `(lambda (,(car largs))
+                                         ,(cps- `((lambda ,(cdr largs) ,lbody)
+                                                  ,@(cddr form))
+                                                k)))))))
+
+          (#t
+           (app->cps form k ())))))
+
+; (lambda (args...) (f args...)) => f
+; but only for constant, builtin f
+(define (η-reduce form)
+  (cond ((or (atom? form) (constant? form)) form)
+        ((and (eq (car form) 'lambda)
+              (let ((body (caddr form))
+                    (args (cadr form)))
+                (and (pair? body)
+                     (equal? (cdr body) args)
+                     (constant? (car (caddr form))))))
+         (car (caddr form)))
+        (#t (map η-reduce form))))
+
+(define (contains x form)
+  (or (eq form x)
+      (any (lambda (p) (contains x p)) form)))
+
+(define (β-reduce form)
+  (if (or (atom? form) (constant? form))
+      form
+      (β-reduce- (map β-reduce form))))
+
+(define (β-reduce- form)
+        ; ((lambda (f) (f arg)) X) => (X arg)
+  (cond ((and (length= form 2)
+              (pair? (car form))
+              (eq (caar form) 'lambda)
+              (let ((args (cadr (car form)))
+                    (body (caddr (car form))))
+                (and (pair? body) (pair? args)
+                     (length= body 2)
+                     (length= args 1)
+                     (eq (car body) (car args))
+                     (not (eq (cadr body) (car args)))
+                     (symbol? (cadr body)))))
+         `(,(cadr form)
+           ,(cadr (caddr (car form)))))
+
+        ; (identity x) => x
+        ((eq (car form) *top-k*)
+         (cadr form))
+
+        ; uncurry:
+        ; ((lambda (p1) ((lambda (args...) body) exprs...)) s) =>
+        ; ((lambda (p1 args...) body) s exprs...)
+        ; where exprs... doesn't contain p1
+        ((and (length= form 2)
+              (pair? (car form))
+              (eq (caar form) 'lambda)
+              (or (atom? (cadr form)) (constant? (cadr form)))
+              (let ((args (cadr (car form)))
+                    (s (cadr form))
+                    (body (caddr (car form))))
+                (and (pair? args) (length= args 1)
+                     (pair? body)
+                     (pair? (car body))
+                     (eq (caar body) 'lambda)
+                     (let ((innerargs (cadr (car body)))
+                           (innerbody (caddr (car body)))
+                           (params (cdr body)))
+                       (and (not (contains (car args) params))
+                            `((lambda ,(cons (car args) innerargs)
+                                ,innerbody)
+                              ,s
+                              ,@params)))))))
+
+        (#t form)))
+
+(define-macro (with-delimited-continuations . code)
+  (cps `((lambda () ,@code))))
+
+(define-macro (define-generator form . body)
+  (let ((ko  (gensym))
+        (cur (gensym))
+	(name (car form))
+	(args (cdr form)))
+    `(define (,name ,@args)
+       (let ((,ko  #f)
+             (,cur #f))
+         (lambda ()
+           (with-delimited-continuations
+            (if ,ko (,ko ,cur)
+              (reset
+               (let ((yield
+                      (lambda (v)
+                        (shift yk
+                               (begin (set! ,ko  yk)
+                                      (set! ,cur v))))))
+                 ,@body)))))))))
+
+; a test case
+(define-generator (range-iterator lo hi)
+  ((label loop
+          (lambda (i)
+            (if (< hi i)
+                'done
+              (begin (yield i)
+                     (loop (+ 1 i))))))
+   lo))
+
+; example from Chung-chieh Shan's paper
+(assert (equal?
+         (with-delimited-continuations
+          (cons 'a (reset (cons 'b (shift f (cons 1 (f (f (cons 'c ())))))))))
+         '(a 1 b b c)))
+
+#t
+
+#|
+todo:
+* tag lambdas that accept continuation arguments, compile computed
+  calls to calls to funcall/cc that does the right thing for both
+  cc-lambdas and normal lambdas
+
+* handle dotted arglists in lambda
+
+- optimize constant functions, e.g. (funcall/cc-0 #:g65 (lambda (#:g58) 'done))
+
+- implement CPS version of apply
+
+- use fewer gensyms
+
+ here's an alternate way to transform a while loop:
+
+ (let ((x 0))
+   (while (< x 10)
+     (begin (print x) (set! x (+ 1 x)))))
+ =>
+  (let ((x 0))
+    (reset
+     (let ((l #f))
+       (let ((k (shift k (k k))))
+         (if (< x 10)
+             (begin (set! l (begin (print x)
+                                   (set! x (+ 1 x))))
+                    (k k))
+           l)))))
+|#
--- /dev/null
+++ b/femtolisp/examples/rule30.lsp
@@ -1,0 +1,25 @@
+; -*- scheme -*-
+
+(define (rule30-step b)
+  (let ((L (ash b -1))
+	(R (ash b 1)))
+    (let ((~b (lognot b))
+	  (~L (lognot L))
+	  (~R (lognot R)))
+      (logior (logand  L ~b ~R)
+	      (logand ~L  b  R)
+	      (logand ~L  b ~R)
+	      (logand ~L ~b  R)))))
+
+(define (bin-draw s)
+  (string.map (lambda (c) (case c
+			    (#\1 #\#)
+			    (#\0 #\ )
+			    (else c)))
+	      s))
+
+(for-each (lambda (n)
+	    (begin
+	      (princ (bin-draw (string.lpad (number->string n 2) 63 #\0)))
+	      (newline)))
+	  (nestlist rule30-step (uint64 0x0000000080000000) 32))
--- a/femtolisp/perf.lsp
+++ /dev/null
@@ -1,37 +1,0 @@
-(load "test.lsp")
-
-(princ "colorgraph: ")
-(load "tcolor.lsp")
-
-(princ "fib(34): ")
-(assert (equal? (time (fib 34)) 5702887))
-(princ "yfib(32): ")
-(assert (equal? (time (yfib 32)) 2178309))
-
-(princ "sort: ")
-(set! r (map-int (lambda (x) (mod (+ (* x 9421) 12345) 1024)) 1000))
-(time (simple-sort r))
-
-(princ "expand: ")
-(time (dotimes (n 5000) (expand '(dotimes (i 100) body1 body2))))
-
-(define (my-append . lsts)
-  (cond ((null? lsts) ())
-        ((null? (cdr lsts)) (car lsts))
-        (else (letrec ((append2 (lambda (l d)
-				  (if (null? l) d
-				      (cons (car l)
-					    (append2 (cdr l) d))))))
-		(append2 (car lsts) (apply my-append (cdr lsts)))))))
-
-(princ "append: ")
-(set! L (map-int (lambda (x) (map-int identity 20)) 20))
-(time (dotimes (n 1000) (apply my-append L)))
-
-(path.cwd "ast")
-(princ "p-lambda: ")
-(load "rpasses.lsp")
-(define *input* (load "datetimeR.lsp"))
-(time (set! *output* (compile-ish *input*)))
-(assert (equal? *output* (load "rpasses-out.lsp")))
-(path.cwd "..")
--- a/femtolisp/rule30.lsp
+++ /dev/null
@@ -1,25 +1,0 @@
-; -*- scheme -*-
-
-(define (rule30-step b)
-  (let ((L (ash b -1))
-	(R (ash b 1)))
-    (let ((~b (lognot b))
-	  (~L (lognot L))
-	  (~R (lognot R)))
-      (logior (logand  L ~b ~R)
-	      (logand ~L  b  R)
-	      (logand ~L  b ~R)
-	      (logand ~L ~b  R)))))
-
-(define (bin-draw s)
-  (string.map (lambda (c) (case c
-			    (#\1 #\#)
-			    (#\0 #\ )
-			    (else c)))
-	      s))
-
-(for-each (lambda (n)
-	    (begin
-	      (princ (bin-draw (string.lpad (number->string n 2) 63 #\0)))
-	      (newline)))
-	  (nestlist rule30-step (uint64 0x0000000080000000) 32))
--- a/femtolisp/site/doc
+++ /dev/null
@@ -1,62 +1,0 @@
-1. Syntax
-
-symbols
-numbers
-conses and vectors
-comments
-special prefix tokens: ' ` , ,@ ,.
-other read macros: #. #' #\ #< #n= #n# #: #ctor
-builtins
-
-2. Data and execution models
-
-3. Primitive functions
-
-eq atom not set prog1 progn
-symbolp numberp builtinp consp vectorp boundp
-+ - * / <
-apply eval
-
-4. Special forms
-
-quote if lambda macro while label cond and or
-
-5. Data structures
-
-cons car cdr rplaca rplacd list
-alloc vector aref aset length
-
-6. Other functions
-
-read, print, princ, load, exit
-equal, compare
-gensym
-
-7. Exceptions
-
-trycatch raise
-
-8. Cvalues
-
-introduction
-type representations
-constructors
-access
-memory management concerns
-ccall
-
-
-If deliberate 50% heap utilization seems wasteful, consider:
-
-- malloc has per-object overhead. for small allocations you might use
-  much more space than you think.
-- any non-moving memory manager (whether malloc or a collector) can
-  waste arbitrary amounts of memory through fragmentation.
-
-With a copying collector, you agree to give up 50% of your memory
-up front, in exchange for significant benefits:
-
-- really fast allocation
-- heap compaction, improving locality and possibly speeding up computation
-- collector performance O(1) in number of dead objects, essential for
-  maximal performance on generational workloads
--- a/femtolisp/site/doc.html
+++ /dev/null
@@ -1,428 +1,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
-<title>femtoLisp</title>
-</head>
-<body bgcolor="#fcfcfc">    <!-"#fcfcc8">
-<img src="flbanner.jpg">
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-<h1>0. Argument</h1>
-This Lisp has the following characteristics and goals:
-
-<ul>
-<li>Lisp-1 evaluation rule (ala Scheme)
-<li>Self-evaluating lambda (i.e. <tt>'(lambda (x) x)</tt> is callable)
-<li>Full Common Lisp-style macros
-<li>Dotted lambda lists for rest arguments (ala Scheme)
-<li>Symbols have one binding
-<li>Builtin functions are constants
-<li><em>All</em> values are printable and readable
-<li>Case-sensitive symbol names
-<li>Only the minimal core built-in (i.e. written in C), but
-    enough to provide a practical level of performance
-<li>Very short (but not necessarily simple...) implementation
-<li>Generally use Common Lisp operator names
-<li>Nothing excessively weird or fancy
-</ul>
-
-<h1>1. Syntax</h1>
-<h2>1.1. Symbols</h2>
-Any character string can be a symbol name, including the empty string. In
-general, text between whitespace is read as a symbol except in the following
-cases:
-<ul>
-<li>The text begins with <tt>#</tt>
-<li>The text consists of a single period <tt>.</tt>
-<li>The text contains one of the special characters <tt>()[]';`,\|</tt>
-<li>The text is a valid number
-<li>The text is empty
-</ul>
-In these cases the symbol can be written by surrounding it with <tt>| |</tt>
-characters, or by escaping individual characters within the symbol using
-backslash <tt>\</tt>. Note that <tt>|</tt> and <tt>\</tt> must always be
-preceded with a backslash when writing a symbol name.
-
-<h2>1.2. Numbers</h2>
-
-A number consists of an optional + or - sign followed by one of the following
-sequences:
-<ul>
-<li><tt>NNN...</tt> where N is a decimal digit
-<li><tt>0xNNN...</tt> where N is a hexadecimal digit
-<li><tt>0NNN...</tt> where N is an octal digit
-</ul>
-femtoLisp provides 30-bit integers, and it is an error to write a constant
-less than -2<sup>29</sup> or greater than 2<sup>29</sup>-1.
-
-<h2>1.3. Conses and vectors</h2>
-
-The text <tt>(a b c)</tt> parses to the structure
-<tt>(cons a (cons b (cons c nil)))</tt> where a, b, and c are arbitrary
-expressions.
-<p>
-The text <tt>(a . b)</tt> parses to the structure
-<tt>(cons a b)</tt> where a and b are arbitrary expressions.
-<p>
-The text <tt>()</tt> reads as the symbol <tt>nil</tt>.
-<p>
-The text <tt>[a b c]</tt> parses to a vector of expressions a, b, and c.
-The syntax <tt>#(a b c)</tt> has the same meaning.
-
-
-<h2>1.4. Comments</h2>
-
-Text between a semicolon <tt>;</tt> and the next end-of-line is skipped.
-Text between <tt>#|</tt> and <tt>|#</tt> is also skipped.
-
-<h2>1.5. Prefix tokens</h2>
-
-There are five special prefix tokens which parse as follows:<p>
-<tt>'a</tt> is equivalent to <tt>(quote a)</tt>.<br>
-<tt>`a</tt> is equivalent to <tt>(backquote a)</tt>.<br>
-<tt>,a</tt> is equivalent to <tt>(*comma* a)</tt>.<br>
-<tt>,@a</tt> is equivalent to <tt>(*comma-at* a)</tt>.<br>
-<tt>,.a</tt> is equivalent to <tt>(*comma-dot* a)</tt>.
-
-
-<h2>1.6. Other read macros</h2>
-
-femtoLisp provides a few "read macros" that let you accomplish interesting
-tricks for textually representing data structures.
-
-<table border=1>
-<tr>
-<td>sequence<td>meaning
-<tr>
-<td><tt>#.e</tt><td>evaluate expression <tt>e</tt> and behave as if e's
-  value had been written in place of e
-<tr>
-<td><tt>#\c</tt><td><tt>c</tt> is a character; read as its Unicode value
-<tr>
-<td><tt>#n=e</tt><td>read <tt>e</tt> and label it as <tt>n</tt>, where n
-  is a decimal number
-<tr>
-<td><tt>#n#</tt><td>read as the identically-same value previously labeled
-  <tt>n</tt>
-<tr>
-<td><tt>#:gNNN or #:NNN</tt><td>read a gensym. NNN is a hexadecimal
-  constant. future occurrences of the same <tt>#:</tt> sequence will read to
-  the identically-same gensym
-<tr>
-<td><tt>#sym(...)</tt><td>reads to the result of evaluating
-  <tt>(apply sym '(...))</tt>
-<tr>
-<td><tt>#&lt;</tt><td>triggers an error
-<tr>
-<td><tt>#'</tt><td>ignored; provided for compatibility
-<tr>
-<td><tt>#!</tt><td>single-line comment, for script execution support
-<tr>
-<td><tt>"str"</tt><td>UTF-8 character string; may contain newlines.
-  <tt>\</tt> is the escape character. All C escape sequences are supported, plus
-  <tt>\u</tt> and <tt>\U</tt> for unicode values.
-</table>
-When a read macro involves persistent state (e.g. label assignments), that
-state is valid only within the closest enclosing call to <tt>read</tt>.
-
-
-<h2>1.7. Builtins</h2>
-
-Builtin functions are represented as opaque constants. Every builtin
-function is the value of some constant symbol, so the builtin <tt>eq</tt>,
-for example, can be written as <tt>#.eq</tt> ("the value of symbol eq").
-Note that <tt>eq</tt> itself is still an ordinary symbol, except that its
-value cannot be changed.
-<p>
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-
-<h1>2. Data and execution models</h1>
-
-
-
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-
-<h1>3. Primitive functions</h1>
-
-
-eq atom not set prog1 progn
-symbolp numberp builtinp consp vectorp boundp
-+ - * / <
-apply eval
-
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-<h1>4. Special forms</h1>
-
-quote if lambda macro while label cond and or
-
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-<h1>5. Data structures</h1>
-
-cons car cdr rplaca rplacd list
-alloc vector aref aset length
-
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-<h1>6. Other functions</h1>
-
-read print princ load exit
-equal compare
-gensym
-
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-<h1>7. Exceptions</h1>
-
-trycatch raise
-
-
-<table border=0 width="100%" cellpadding=0 cellspacing=0>
-<tr><td bgcolor="#2d3f5f" height=4></table>
-
-<h1>8. Cvalues</h1>
-
-<h2>8.1. Introduction</h2>
-
-femtoLisp allows you to use the full range of C data types on
-dynamically-typed Lisp values. The motivation for this feature is that
-useful
-interpreters must provide a large library of routines in C for dealing
-with "real world" data like text and packed numeric arrays, and I would
-rather not write yet another such library. Instead, all the
-required data representations and primitives are provided so that such
-features could be implemented in, or at least described in, Lisp.
-<p>
-The cvalues capability makes it easier to call C from Lisp by providing
-ways to construct whatever arguments your C routines might require, and ways
-to decipher whatever values your C routines might return. Here are some
-things you can do with cvalues:
-<ul>
-<li>Call native C functions from Lisp without wrappers
-<li>Wrap C functions in pure Lisp, automatically inheriting some degree
-  of type safety
-<li>Use Lisp functions as callbacks from C code
-<li>Use the Lisp garbage collector to reclaim malloc'd storage
-<li>Annotate C pointers with size information for bounds checking or
-  serialization
-<li>Attach symbolic type information to a C data structure, allowing it to
-  inherit Lisp services such as printing a readable representation
-<li>Add datatypes like strings to Lisp
-<li>Use more efficient represenations for your Lisp programs' data
-</ul>
-<p>
-femtoLisp's "cvalues" is inspired in part by Python's "ctypes" package.
-Lisp doesn't really have first-class types the way Python does, but it does
-have values, hence my version is called "cvalues".
-
-<h2>8.2. Type representations</h2>
-
-The core of cvalues is a language for describing C data types as
-symbolic expressions:
-
-<ul>
-<li>Primitive types are symbols <tt>int8, uint8, int16, uint16, int32, uint32,
-int64, uint64, char, wchar, long, ulong, float, double, void</tt>
-<li>Arrays <tt>(array TYPE SIZE)</tt>, where TYPE is another C type and
-SIZE is either a Lisp number or a C ulong. SIZE can be omitted to
-represent incomplete C array types like "int a[]". As in C, the size may
-only be omitted for the top level of a nested array; all array
-<em>element</em> types
-must have explicit sizes. Examples:
-<ul>
-  <tt>int a[][2][3]</tt> is <tt>(array (array (array int32 3) 2))</tt><br>
-  <tt>int a[4][]</tt> would be <tt>(array (array int32) 4)</tt>, but this is
-  invalid.
-</ul>
-<li>Pointer <tt>(pointer TYPE)</tt>
-<li>Struct <tt>(struct ((NAME TYPE) (NAME TYPE) ...))</tt>
-<li>Union <tt>(union ((NAME TYPE) (NAME TYPE) ...))</tt>
-<li>Enum <tt>(enum (NAME NAME ...))</tt>
-<li>Function <tt>(c-function RET-TYPE (ARG-TYPE ARG-TYPE ...))</tt>
-</ul>
-
-A cvalue can be constructed using <tt>(c-value TYPE arg)</tt>, where
-<tt>arg</tt> is some Lisp value. The system will try to convert the Lisp
-value to the specified type. In many cases this will work better if some
-components of the provided Lisp value are themselves cvalues.
-
-<p>
-Note the function type is called "c-function" to avoid confusion, since
-functions are such a prevalent concept in Lisp.
-
-<p>
-The function <tt>sizeof</tt> returns the size (in bytes) of a cvalue or a
-c type. Every cvalue has a size, but incomplete types will cause
-<tt>sizeof</tt> to raise an error. The function <tt>typeof</tt> returns
-the type of a cvalue.
-
-<p>
-You are probably wondering how 32- and 64-bit integers are constructed from
-femtoLisp's 30-bit integers. The answer is that larger integers are
-constructed from multiple Lisp numbers 16 bits at a time, in big-endian
-fashion. In fact, the larger numeric types are the only cvalues
-types whose constructors accept multiple arguments. Examples:
-<ul>
-<pre>
-(c-value 'int32 0xdead 0xbeef)         ; make 0xdeadbeef
-(c-value 'uint64 0x1001 0x8000 0xffff) ; make 0x000010018000ffff
-</pre>
-</ul>
-As you can see, missing zeros are padded in from the left.
-
-
-<h2>8.3. Constructors</h2>
-
-For convenience, a specialized constructor is provided for each
-class of C type (primitives, pointer, array, struct, union, enum,
-and c-function).
-For example:
-<ul>
-<pre>
-(uint32 0xcafe 0xd00d)
-(int32 -4)
-(char #\w)
-(array 'int8 [1 1 2 3 5 8])
-</pre>
-</ul>
-
-These forms can be slightly less efficient than <tt>(c-value ...)</tt>
-because in many cases they will allocate a new type for the new value.
-For example, the fourth expression must create the type
-<tt>(array int8 6)</tt>.
-
-<p>
-Notice that calls to these constructors strongly resemble
-the types of the values they create. This relationship can be expressed
-formally as follows:
-
-<pre>
-(define (c-allocate type)
-  (if (atom type)
-      (apply (eval type) ())
-      (apply (eval (car type)) (cdr type))))
-</pre>
-
-This function produces an instance of the given type by
-invoking the appropriate constructor. Primitive types (whose representations
-are symbols) can be constructed with zero arguments. For other types,
-the only required arguments are those present in the type representation.
-Any arguments after those are initializers. Using
-<tt>(cdr type)</tt> as the argument list provides only required arguments,
-so the value you get will not be initialized.
-
-<p>
-The builtin <tt>c-value</tt> function is similar to this one, except that it
-lets you pass initializers.
-
-<p>
-Cvalue constructors are generally permissive; they do the best they
-can with whatever you pass in. For example:
-
-<ul>
-<pre>
-(c-value '(array int8 1))      ; ok, full type provided
-(c-value '(array int8))        ; error, no size information
-(c-value '(array int8) [0 1])  ; ok, size implied by initializer
-</pre>
-</ul>
-
-<p>
-ccopy, c2lisp
-
-<h2>8.4. Pointers, arrays, and strings</h2>
-
-Pointer types are provided for completeness and C interoperability, but
-they should not generally be used from Lisp. femtoLisp doesn't know
-anything about a pointer except the raw address and the (alleged) type of the
-value it points to. Arrays are much more useful. They behave like references
-as in C, but femtoLisp tracks their sizes and performs bounds checking.
-
-<p>
-Arrays are used to allocate strings. All strings share
-the incomplete array type <tt>(array char)</tt>:
-
-<pre>
-> (c-value '(array char) [#\h #\e #\l #\l #\o])
-"hello"
-
-> (sizeof that)
-5
-</pre>
-
-<tt>sizeof</tt> reveals that the size is known even though it is not
-reflected in the type (as is always the case with incomplete array types).
-
-<p>
-Since femtoLisp tracks the sizes of all values, there is no need for NUL
-terminators. Strings are just arrays of bytes, and may contain zero bytes
-throughout. However, C functions require zero-terminated strings. To
-solve this problem, femtoLisp allocates magic strings that actually have
-space for one more byte than they appear to. The hidden extra byte is
-always zero. This guarantees that a C function operating on the string
-will never overrun its allocated space.
-
-<p>
-Such magic strings are produced by double-quoted string literals, and by
-any explicit string-constructing function (such as <tt>string</tt>).
-
-<p>
-Unfortunately you still need to be careful, because it is possible to
-allocate a non-magic character array with no terminator. The "hello"
-string above is an example of this, since it was constructed from an
-explicit vector of characters.
-Such an array would cause problems if passed to a function expecting a
-C string.
-
-<p>
-deref
-
-<h2>8.5. Access</h2>
-
-cref,cset,byteref,byteset,ccopy
-
-<h2>8.6. Memory management concerns</h2>
-
-autorelease
-
-
-<h2>8.7. Guest functions</h2>
-
-Functions written in C but designed to operate on Lisp values are
-known here as "guest functions". Although they are foreign, they live in
-Lisp's house and so live by its rules. Guest functions are what you
-use to write interpreter extensions, for example to implement a function
-like <tt>assoc</tt> in C for performance.
-
-<p>
-Guest functions must have a particular signature:
-<pre>
-value_t func(value_t *args, uint32_t nargs);
-</pre>
-Guest functions must also be aware of the femtoLisp API and garbage
-collector.
-
-
-<h2>8.8. Native functions</h2>
-
-</body>
-</html>
binary files a/femtolisp/site/flbanner.jpg /dev/null differ
binary files a/femtolisp/site/flbanner.xcf /dev/null differ
binary files a/femtolisp/site/flbanner2.jpg /dev/null differ
--- a/femtolisp/site/index.html
+++ /dev/null
@@ -1,206 +1,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
-<title>femtoLisp</title>
-</head>
-<body>
-<h1>femtoLisp</h1>
-<hr>
-femtoLisp is an elegant Lisp implementation. Its goal is to be a
-reasonably efficient and capable interpreter with the shortest, simplest
-code possible. As its name implies, it is small (10<sup>-15</sup>).
-Right now it is just 1000 lines of C (give or take). It would make a great
-teaching example, or a useful system anywhere a very small Lisp is wanted.
-It is also a useful basis for developing other interpreters or related
-languages.
-
-
-<h2>The language implemented</h2>
-
-femtoLisp tries to be a generic, simple Lisp dialect, influenced by McCarthy's
-original.
-
-<ul>
-<li>Types: cons, symbol, 30-bit integer, builtin function
-<li>Self-evaluating lambda, macro, and label forms
-<li>Full Common Lisp-style macros
-<li>Case-sensitive symbol names
-<li>Scheme-style evaluation rule where any expression may appear in head
-    position as long as it evaluates to a callable
-<li>Scheme-style formal argument lists (dotted lists for varargs)
-<li>Transparent closure representation <tt>(lambda args body . env)</tt>
-<li>A lambda body may contain only one form. Use explicit <tt>progn</tt> for
-    multiple forms. Included macros, however, allow <tt>defun</tt>,
-    <tt>let</tt>, etc. to accept multiple body forms.
-<li>Builtin function names are constants and cannot be redefined.
-<li>Symbols have one binding, as in Scheme.
-</ul>
-<b>Builtin special forms:</b><br>
-<tt>quote, cond, if, and, or, lambda, macro, label, while, progn, prog1</tt>
-<p>
-<b>Builtin functions:</b><br>
-<tt>eq, atom, not, symbolp, numberp, boundp, cons, car, cdr,
-    read, eval, print, load, set, 
-    +, -, *, /, &lt;, apply, rplaca, rplacd</tt>
-<p>
-<b>Included library functions and macros:</b><br>
-<tt>
-setq, setf, defmacro, defun, define, let, let*, labels, dotimes,
-macroexpand-1, macroexpand, backquote,
-
-null, consp, builtinp, self-evaluating-p, listp, eql, equal, every, any,
-when, unless,
-
-=, !=, &gt;, &lt;=, &gt;=, compare, mod, abs, identity,
-
-list, list*, length, last, nthcdr, lastcdr, list-ref, reverse, nreverse,
-assoc, member, append, nconc, copy-list, copy-tree, revappend, nreconc,
-
-mapcar, filter, reduce, map-int,
-
-symbol-plist, set-symbol-plist, put, get
-</tt>
-<p>
-<a href="system.lsp">system.lsp</a>
-
-
-<h2>The implementation</h2>
-
-<ul>
-<li>Compacting copying garbage collector (<tt>O(1)</tt> in number of dead
-    objects)
-<li>Tagged pointers for efficient type checking and fast integers
-<li>Tail-recursive evaluator (tail calls use no stack space)
-<li>Minimally-consing <tt>apply</tt>
-<li>Interactive and script execution modes
-</ul>
-<p>
-<a href="lisp.c">lisp.c</a>
-
-
-<h2>femtoLisp2</h2>
-
-This version includes robust reading and printing capabilities for
-circular structures and escaped symbol names. It adds read and print support
-for the Common Lisp read-macros <tt>#., #n#,</tt> and <tt>#n=</tt>.
-This allows builtins to be printed in a readable fashion as e.g.
-"<tt>#.eq</tt>".
-<p>
-The net result is that the interpreter achieves a highly satisfying property
-of closure under I/O. In other words, every representable Lisp value can be
-read and printed.
-<p>
-The traditional builtin <tt>label</tt> provides a purely-functional,
-non-circular way
-to write an anonymous recursive function. In femtoLisp2 you can
-achieve the same effect "manually" using nothing more than the reader:
-<br>
-<tt>#0=(lambda (x) (if (&lt;= x 0) 1 (* x (#0# (- x 1)))))</tt>
-<p>
-femtoLisp2 has the following extra features and optimizations:
-<ul>
-<li> builtin functions <tt>error, exit,</tt> and <tt>princ</tt>
-<li> read support for backquote expressions
-<li> delayed environment consing
-<li> collective allocation of cons chains
-</ul>
-Those two optimizations are a Big Deal.
-<p>
-<a href="lisp2.c">lisp2.c</a> (uses <a href="flutils.c">flutils.c</a>)
-
-
-<h2>Performance</h2>
-
-femtoLisp's performance is surprising. It is faster than most
-interpreters, and it is usually within a factor of 2-5 of compiled CLISP.
-
-<table border=1>
-<tr>
-<td colspan=3><center><b>solve 5 queens problem 100x</b></center></td>
-<tr>
-<td>          <td>interpreted<td>compiled
-<tr>
-<td>CLISP     <td>4.02 sec   <td>0.68 sec
-<tr>
-<td>femtoLisp2<td>2.62 sec   <td>2.03 sec**
-<tr>
-<td>femtoLisp <td>6.02 sec   <td>5.64 sec**
-<tr>
-
-<td colspan=3><center><b>recursive fib(34)</b></center></td>
-<tr>
-<td>          <td>interpreted<td>compiled
-<tr>
-<td>CLISP     <td>23.12 sec  <td>4.04 sec
-<tr>
-<td>femtoLisp2<td>4.71 sec   <td>n/a
-<tr>
-<td>femtoLisp <td>7.25 sec   <td>n/a
-<tr>
-
-</table>
-** femtoLisp is not a compiler; in this context "compiled" means macros
-were pre-expanded.
-
-
-<h2>"Installation"</h2>
-
-Here is a <a href="Makefile">Makefile</a>. Type <tt>make</tt> to build
-femtoLisp, <tt>make NAME=lisp2</tt> to build femtoLisp2.
-
-
-<h2>Tail recursion</h2>
-The femtoLisp evaluator is tail-recursive, following the idea in
-<a href="http://library.readscheme.org/servlets/cite.ss?pattern=Ste-76b">
-Lambda: The Ultimate Declarative</a> (should be required reading
-for all schoolchildren).
-<p>
-The femtoLisp source provides a simple concrete example showing why a function
-call is best viewed as a "renaming plus goto" rather than as a set of stack
-operations.
-<p>
-Here is the non-tail-recursive evaluator code to evaluate the body of a
-lambda (function), from <a href="lisp-nontail.c">lisp-nontail.c</a>:
-<pre>
-        PUSH(*lenv);    // preserve environment on stack
-        lenv = &amp;Stack[SP-1];
-        v = eval(*body, lenv);
-        POP();
-        return v;
-</pre>
-(Note that because of the copying garbage collector, values are referenced
-through relocatable handles.)
-<p>
-Superficially, the call to <tt>eval</tt> is not a tail call, because work
-remains after it returns&mdash;namely, popping the environment off the stack.
-In other words, the control stack must be saved and restored to allow us to
-eventually restore the environment stack. However, restoring the environment
-stack is the <i>only</i> work to be done. Yet after this point the old
-environment is not used! So restoring the environment stack isn't
-necessary, therefore restoring the control stack isn't either.
-<p>
-This perspective makes proper tail recursion seem like more than an
-alternate design or optimization. It seems more correct.
-<p>
-Here is the corrected, tail-recursive version of the code:
-<pre>
-        SP = saveSP;    // restore stack completely
-        e = *body;      // reassign arguments
-        *penv = *lenv;
-        goto eval_top;
-</pre>
-<tt>penv</tt> is a pointer to the old environment, which we overwrite.
-(Notice that the variable <tt>penv</tt> does not even appear in the first code
-example.)
-So where is the environment saved and restored, if not here? The answer
-is that the burden is shifted to the caller; a caller to <tt>eval</tt> must
-expect that its environment might be overwritten, and take steps to save it
-if it will be needed further after the call. In practice, this means
-the environment is saved and restored around the evaluation of
-arguments, rather than around function applications. Hence <tt>(f x)</tt>
-might be a tail call to <tt>f</tt>, but <tt>(+ y (f x))</tt> is not.
-
-</body>
-</html>
--- a/femtolisp/tcolor.lsp
+++ /dev/null
@@ -1,16 +1,0 @@
-; -*- scheme -*-
-; color for performance
-
-(load "color.lsp")
-
-; 100x color 5 queens
-(define Q (generate-5x5-pairs))
-(define (ct)
-  (set! C (color-pairs Q '(a b c d e)))
-  (dotimes (n 99) (color-pairs Q '(a b c d e))))
-(time (ct))
-(assert (equal? C
-		'((23 . a) (9 . a) (22 . b) (17 . d) (14 . d) (8 . b) (21 . e)
-		  (19 . b) (16 . c) (13 . c) (11 . b) (7 . e) (24 . c) (20 . d)
-		  (18 . e) (15 . a) (12 . a) (10 . e) (6 . d) (5 . c) (4 . e)
-		  (3 . d) (2 . c) (0 . b) (1 . a))))
--- a/femtolisp/test.lsp
+++ /dev/null
@@ -1,294 +1,0 @@
-; -*- scheme -*-
-
-; make label self-evaluating, but evaluating the lambda in the process
-;(defmacro labl (name f)
-;  (list list ''labl (list 'quote name) f))
-
-(define-macro (labl name f)
-  `(let (,name) (set! ,name ,f)))
-
-;(define (reverse lst)
-;  ((label rev-help (lambda (lst result)
-;                     (if (null? lst) result
-;                       (rev-help (cdr lst) (cons (car lst) result)))))
-;   lst ()))
-
-(define (append- . lsts)
-  ((label append-h
-          (lambda (lsts)
-            (cond ((null? lsts) ())
-                  ((null? (cdr lsts)) (car lsts))
-                  (#t ((label append2 (lambda (l d)
-					(if (null? l) d
-					    (cons (car l)
-						  (append2 (cdr l) d)))))
-		       (car lsts) (append-h (cdr lsts)))))))
-   lsts))
-
-;(princ 'Hello '| | 'world! "\n")
-;(filter (lambda (x) (not (< x 0))) '(1 -1 -2 5 10 -8 0))
-(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
-;(princ (time (fib 34)) "\n")
-;(dotimes (i 20000) (map-int (lambda (x) (list 'quote x)) 8))
-;(dotimes (i 40000) (append '(a b) '(1 2 3 4) () '(c) () '(5 6)))
-;(dotimes (i 80000) (list 1 2 3 4 5))
-;(set! a (map-int identity 10000))
-;(dotimes (i 200) (rfoldl cons () a))
-
-#|
-(define-macro (dotimes var . body)
-  (let ((v   (car var))
-        (cnt (cadr var)))
-    `(let ((,v 0))
-       (while (< ,v ,cnt)
-         (prog1
-             ,(cons 'begin body)
-           (set! ,v (+ ,v 1)))))))
-
-(define (map-int f n)
-  (if (<= n 0)
-      ()
-      (let ((first (cons (f 0) ())))
-	((label map-int-
-		(lambda (acc i n)
-		  (if (= i n)
-		      first
-		      (begin (set-cdr! acc (cons (f i) ()))
-			     (map-int- (cdr acc) (+ i 1) n)))))
-	 first 1 n))))
-|#
-
-(define-macro (labl name fn)
-  `((lambda (,name) (set! ,name ,fn)) ()))
-
-(define (square x) (* x x))
-(define (expt b p)
-  (cond ((= p 0) 1)
-        ((= b 0) 0)
-        ((even? p) (square (expt b (div0 p 2))))
-        (#t (* b (expt b (- p 1))))))
-
-(define (gcd a b)
-  (cond ((= a 0) b)
-        ((= b 0) a)
-        ((< a b)  (gcd a (- b a)))
-        (#t       (gcd b (- a b)))))
-
-; like eval-when-compile
-(define-macro (literal expr)
-  (let ((v (eval expr)))
-    (if (self-evaluating? v) v (list quote v))))
-
-(define (cardepth l)
-  (if (atom? l) 0
-      (+ 1 (cardepth (car l)))))
-
-(define (nestlist f zero n)
-  (if (<= n 0) ()
-      (cons zero (nestlist f (f zero) (- n 1)))))
-
-(define (mapl f . lsts)
-  ((label mapl-
-          (lambda (lsts)
-            (if (null? (car lsts)) ()
-		(begin (apply f lsts) (mapl- (map cdr lsts))))))
-   lsts))
-
-; test to see if a symbol begins with :
-(define (keywordp s)
-  (and (>= s '|:|) (<= s '|:~|)))
-
-; swap the cars and cdrs of every cons in a structure
-(define (swapad c)
-  (if (atom? c) c
-      (set-cdr! c (K (swapad (car c))
-		     (set-car! c (swapad (cdr c)))))))
-
-(define (without x l)
-  (filter (lambda (e) (not (eq e x))) l))
-
-(define (conscount c)
-  (if (pair? c) (+ 1
-                   (conscount (car c))
-                   (conscount (cdr c)))
-      0))
-
-;  _ Welcome to
-; (_ _ _ |_ _ |  . _ _ 2
-; | (-||||_(_)|__|_)|_)
-; ==================|==
-
-;[` _ ,_ |-  | . _  2
-;| (/_||||_()|_|_\|)
-;                 | 
-
-(define-macro (while- test . forms)
-  `((label -loop- (lambda ()
-                    (if ,test
-                        (begin ,@forms
-                               (-loop-))
-			())))))
-
-; this would be a cool use of thunking to handle 'finally' clauses, but
-; this code doesn't work in the case where the user manually re-raises
-; inside a catch block. one way to handle it would be to replace all
-; their uses of 'raise' with '*_try_finally_raise_*' which calls the thunk.
-; (try expr
-;      (catch (TypeError e) . exprs)
-;      (catch (IOError e) . exprs)
-;      (finally . exprs))
-(define-macro (try expr . forms)
-  (let ((final (f-body (cdr (or (assq 'finally forms) '(())))))
-        (body (foldr
-               ; create a function to check for and handle one exception
-               ; type, and pass off control to the next when no match
-               (lambda (catc next)
-                 (let ((var    (cadr (cadr catc)))
-                       (extype (caadr catc))
-                       (todo   (f-body (cddr  catc))))
-                   `(lambda (,var)
-                      (if (or (eq ,var ',extype)
-                              (and (pair? ,var)
-                                   (eq (car ,var) ',extype)))
-                          ,todo
-                        (,next ,var)))))
-
-               ; default function; no matches so re-raise
-               '(lambda (e) (begin (*_try_finally_thunk_*) (raise e)))
-
-               ; make list of catch forms
-               (filter (lambda (f) (eq (car f) 'catch)) forms))))
-    `(let ((*_try_finally_thunk_* (lambda () ,final)))
-       (prog1 (attempt ,expr ,body)
-         (*_try_finally_thunk_*)))))
-
-(define Y
-  (lambda (f)
-    ((lambda (h)
-       (f (lambda (x) ((h h) x))))
-     (lambda (h)
-       (f (lambda (x) ((h h) x)))))))
-
-(define yfib
-  (Y (lambda (fib)
-       (lambda (n)
-         (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))))
-
-;(defun tt () (time (dotimes (i 500000) (* 0x1fffffff 1) )))
-;(tt)
-;(tt)
-;(tt)
-
-(define-macro (accumulate-while cnd what . body)
-  (let ((acc (gensym)))
-    `(let ((,acc (list ())))
-       (cdr
-	(prog1 ,acc
-	 (while ,cnd
-		(begin (set! ,acc
-			     (cdr (set-cdr! ,acc (cons ,what ()))))
-		       ,@body)))))))
-
-(define-macro (accumulate-for var lo hi what . body)
-  (let ((acc   (gensym)))
-    `(let ((,acc (list ())))
-       (cdr
-	(prog1 ,acc
-	 (for ,lo ,hi
-	      (lambda (,var)
-		(begin (set! ,acc
-			     (cdr (set-cdr! ,acc (cons ,what ()))))
-		       ,@body))))))))
-
-(define (map-indexed f lst)
-  (if (atom? lst) lst
-    (let ((i 0))
-      (accumulate-while (pair? lst) (f (car lst) i)
-                        (begin (set! lst (cdr lst))
-                               (set! i (1+ i)))))))
-
-(define (string.findall haystack needle . offs)
-  (define (sub h n offs lst)
-    (let ((i (string.find h n offs)))
-      (if i
-	  (sub h n (string.inc h i) (cons i lst))
-	  (reverse! lst))))
-  (sub haystack needle (if (null? offs) 0 (car offs)) ()))
-
-(let ((*profiles* (table)))
-  (set! profile
-	(lambda (s)
-	  (let ((f (top-level-value s)))
-	    (put! *profiles* s (cons 0 0))
-	    (set-top-level-value! s
-	     (lambda args
-	       (define tt (get *profiles* s))
-	       (define count (car tt))
-	       (define time  (cdr tt))
-	       (define t0 (time.now))
-	       (define v (apply f args))
-	       (set-cdr! tt (+ time (- (time.now) t0)))
-	       (set-car! tt (+ count 1))
-	       v)))))
-  (set! show-profiles
-	(lambda ()
-	  (define pr (filter (lambda (x) (> (cadr x) 0))
-			     (table.pairs *profiles*)))
-	  (define width (+ 4
-			   (apply max
-				  (map (lambda (x)
-					 (length (string x)))
-				       (cons 'Function
-					     (map car pr))))))
-	  (princ (string.rpad "Function" width #\ )
-		 "#Calls     Time (seconds)")
-	  (newline)
-	  (princ (string.rpad "--------" width #\ )
-		 "------     --------------")
-	  (newline)
-	  (for-each
-	   (lambda (p)
-	     (princ (string.rpad (string (caddr p)) width #\ )
-		    (string.rpad (string (cadr p)) 11 #\ )
-		    (car p))
-	     (newline))
-	   (simple-sort (map (lambda (l) (reverse (to-proper l)))
-			     pr)))))
-  (set! clear-profiles
-	(lambda ()
-	  (for-each (lambda (k)
-		      (put! *profiles* k (cons 0 0)))
-		    (table.keys *profiles*)))))
-
-#;(for-each profile
-	  '(emit encode-byte-code const-to-idx-vec
-	    index-of lookup-sym in-env? any every
-	    compile-sym compile-if compile-begin
-	    compile-arglist expand builtin->instruction
-	    compile-app separate nconc get-defined-vars
-	    compile-in compile compile-f delete-duplicates
-	    map length> length= count filter append
-	    lastcdr to-proper reverse reverse! list->vector
-	    table.foreach list-head list-tail assq memq assoc member
-	    assv memv nreconc bq-process))
-
-(define (filt1 pred lst)
-  (define (filt1- pred lst accum)
-    (if (null? lst) accum
-	(if (pred (car lst))
-	    (filt1- pred (cdr lst) (cons (car lst) accum))
-	    (filt1- pred (cdr lst) accum))))
-  (filt1- pred lst ()))
-
-(define (filto pred lst (accum ()))
-  (if (atom? lst) accum
-      (if (pred (car lst))
-	  (filto pred (cdr lst) (cons (car lst) accum))
-	  (filto pred (cdr lst) accum))))
-
-; (pairwise? p a b c d) == (and (p a b) (p b c) (p c d))
-(define (pairwise? pred . args)
-  (or (null? args)
-      (let f ((a (car args)) (d (cdr args)))
-	(or (null? d)
-	    (and (pred a (car d)) (f (car d) (cdr d)))))))
--- /dev/null
+++ b/femtolisp/tests/100x100.lsp
@@ -1,0 +1,1 @@
+'#0=(#198=(#197=(#196=(#195=(#194=(#193=(#192=(#191=(#190=(#189=(#188=(#187=(#186=(#185=(#184=(#183=(#182=(#181=(#180=(#179=(#178=(#177=(#176=(#175=(#174=(#173=(#172=(#171=(#170=(#169=(#168=(#167=(#166=(#165=(#164=(#163=(#162=(#161=(#160=(#159=(#158=(#157=(#156=(#155=(#154=(#153=(#152=(#151=(#150=(#149=(#148=(#147=(#146=(#145=(#144=(#143=(#142=(#141=(#140=(#139=(#138=(#137=(#136=(#135=(#134=(#133=(#132=(#131=(#130=(#129=(#128=(#127=(#126=(#125=(#124=(#123=(#122=(#121=(#120=(#119=(#118=(#117=(#116=(#115=(#114=(#113=(#112=(#111=(#110=(#109=(#108=(#107=(#106=(#105=(#104=(#103=(#102=(#101=(#100=(#0# . #1=(#9999=(#9998=(#9997=(#9996=(#9995=(#9994=(#9993=(#9992=(#9991=(#9990=(#9989=(#9988=(#9987=(#9986=(#9985=(#9984=(#9983=(#9982=(#9981=(#9980=(#9979=(#9978=(#9977=(#9976=(#9975=(#9974=(#9973=(#9972=(#9971=(#9970=(#9969=(#9968=(#9967=(#9966=(#9965=(#9964=(#9963=(#9962=(#9961=(#9960=(#9959=(#9958=(#9957=(#9956=(#9955=(#9954=(#9953=(#9952=(#9951=(#9950=(#9949=(#9948=(#9947=(#9946=(#9945=(#9944=(#9943=(#9942=(#9941=(#9940=(#9939=(#9938=(#9937=(#9936=(#9935=(#9934=(#9933=(#9932=(#9931=(#9930=(#9929=(#9928=(#9927=(#9926=(#9925=(#9924=(#9923=(#9922=(#9921=(#9920=(#9919=(#9918=(#9917=(#9916=(#9915=(#9914=(#9913=(#9912=(#9911=(#9910=(#9909=(#9908=(#9907=(#9906=(#9905=(#9904=(#9903=(#9902=(#9901=(#1# . #2=(#9900=(#9899=(#9898=(#9897=(#9896=(#9895=(#9894=(#9893=(#9892=(#9891=(#9890=(#9889=(#9888=(#9887=(#9886=(#9885=(#9884=(#9883=(#9882=(#9881=(#9880=(#9879=(#9878=(#9877=(#9876=(#9875=(#9874=(#9873=(#9872=(#9871=(#9870=(#9869=(#9868=(#9867=(#9866=(#9865=(#9864=(#9863=(#9862=(#9861=(#9860=(#9859=(#9858=(#9857=(#9856=(#9855=(#9854=(#9853=(#9852=(#9851=(#9850=(#9849=(#9848=(#9847=(#9846=(#9845=(#9844=(#9843=(#9842=(#9841=(#9840=(#9839=(#9838=(#9837=(#9836=(#9835=(#9834=(#9833=(#9832=(#9831=(#9830=(#9829=(#9828=(#9827=(#9826=(#9825=(#9824=(#9823=(#9822=(#9821=(#9820=(#9819=(#9818=(#9817=(#9816=(#9815=(#9814=(#9813=(#9812=(#9811=(#9810=(#9809=(#9808=(#9807=(#9806=(#9805=(#9804=(#9803=(#9802=(#2# . #3=(#9801=(#9800=(#9799=(#9798=(#9797=(#9796=(#9795=(#9794=(#9793=(#9792=(#9791=(#9790=(#9789=(#9788=(#9787=(#9786=(#9785=(#9784=(#9783=(#9782=(#9781=(#9780=(#9779=(#9778=(#9777=(#9776=(#9775=(#9774=(#9773=(#9772=(#9771=(#9770=(#9769=(#9768=(#9767=(#9766=(#9765=(#9764=(#9763=(#9762=(#9761=(#9760=(#9759=(#9758=(#9757=(#9756=(#9755=(#9754=(#9753=(#9752=(#9751=(#9750=(#9749=(#9748=(#9747=(#9746=(#9745=(#9744=(#9743=(#9742=(#9741=(#9740=(#9739=(#9738=(#9737=(#9736=(#9735=(#9734=(#9733=(#9732=(#9731=(#9730=(#9729=(#9728=(#9727=(#9726=(#9725=(#9724=(#9723=(#9722=(#9721=(#9720=(#9719=(#9718=(#9717=(#9716=(#9715=(#9714=(#9713=(#9712=(#9711=(#9710=(#9709=(#9708=(#9707=(#9706=(#9705=(#9704=(#9703=(#3# . #4=(#9702=(#9701=(#9700=(#9699=(#9698=(#9697=(#9696=(#9695=(#9694=(#9693=(#9692=(#9691=(#9690=(#9689=(#9688=(#9687=(#9686=(#9685=(#9684=(#9683=(#9682=(#9681=(#9680=(#9679=(#9678=(#9677=(#9676=(#9675=(#9674=(#9673=(#9672=(#9671=(#9670=(#9669=(#9668=(#9667=(#9666=(#9665=(#9664=(#9663=(#9662=(#9661=(#9660=(#9659=(#9658=(#9657=(#9656=(#9655=(#9654=(#9653=(#9652=(#9651=(#9650=(#9649=(#9648=(#9647=(#9646=(#9645=(#9644=(#9643=(#9642=(#9641=(#9640=(#9639=(#9638=(#9637=(#9636=(#9635=(#9634=(#9633=(#9632=(#9631=(#9630=(#9629=(#9628=(#9627=(#9626=(#9625=(#9624=(#9623=(#9622=(#9621=(#9620=(#9619=(#9618=(#9617=(#9616=(#9615=(#9614=(#9613=(#9612=(#9611=(#9610=(#9609=(#9608=(#9607=(#9606=(#9605=(#9604=(#4# . #5=(#9603=(#9602=(#9601=(#9600=(#9599=(#9598=(#9597=(#9596=(#9595=(#9594=(#9593=(#9592=(#9591=(#9590=(#9589=(#9588=(#9587=(#9586=(#9585=(#9584=(#9583=(#9582=(#9581=(#9580=(#9579=(#9578=(#9577=(#9576=(#9575=(#9574=(#9573=(#9572=(#9571=(#9570=(#9569=(#9568=(#9567=(#9566=(#9565=(#9564=(#9563=(#9562=(#9561=(#9560=(#9559=(#9558=(#9557=(#9556=(#9555=(#9554=(#9553=(#9552=(#9551=(#9550=(#9549=(#9548=(#9547=(#9546=(#9545=(#9544=(#9543=(#9542=(#9541=(#9540=(#9539=(#9538=(#9537=(#9536=(#9535=(#9534=(#9533=(#9532=(#9531=(#9530=(#9529=(#9528=(#9527=(#9526=(#9525=(#9524=(#9523=(#9522=(#9521=(#9520=(#9519=(#9518=(#9517=(#9516=(#9515=(#9514=(#9513=(#9512=(#9511=(#9510=(#9509=(#9508=(#9
\ No newline at end of file
--- /dev/null
+++ b/femtolisp/tests/color.lsp
@@ -1,0 +1,89 @@
+; -*- scheme -*-
+
+; dictionaries ----------------------------------------------------------------
+(define (dict-new) ())
+
+(define (dict-extend dl key value)
+  (cond ((null? dl)              (list (cons key value)))
+        ((equal? key (caar dl))  (cons (cons key value) (cdr dl)))
+        (else (cons (car dl) (dict-extend (cdr dl) key value)))))
+
+(define (dict-lookup dl key)
+  (cond ((null? dl)              ())
+        ((equal? key (caar dl))  (cdar dl))
+        (else (dict-lookup (cdr dl) key))))
+
+(define (dict-keys dl) (map car dl))
+
+; graphs ----------------------------------------------------------------------
+(define (graph-empty) (dict-new))
+
+(define (graph-connect g n1 n2)
+  (dict-extend
+   (dict-extend g n2 (cons n1 (dict-lookup g n2)))
+   n1
+   (cons n2 (dict-lookup g n1))))
+
+(define (graph-adjacent? g n1 n2) (member n2 (dict-lookup g n1)))
+
+(define (graph-neighbors g n) (dict-lookup g n))
+
+(define (graph-nodes g) (dict-keys g))
+
+(define (graph-add-node g n1) (dict-extend g n1 ()))
+
+(define (graph-from-edges edge-list)
+  (if (null? edge-list)
+      (graph-empty)
+    (graph-connect (graph-from-edges (cdr edge-list))
+                   (caar edge-list)
+                   (cdar edge-list))))
+
+; graph coloring --------------------------------------------------------------
+(define (node-colorable? g coloring node-to-color color-of-node)
+  (not (member
+        color-of-node
+        (map
+         (lambda (n)
+           (let ((color-pair (assq n coloring)))
+             (if (pair? color-pair) (cdr color-pair) ())))
+         (graph-neighbors g node-to-color)))))
+
+(define (try-each f lst)
+  (if (null? lst) #f
+      (let ((ret (f (car lst))))
+	(if ret ret (try-each f (cdr lst))))))
+
+(define (color-node g coloring colors uncolored-nodes color)
+  (cond
+   ((null? uncolored-nodes) coloring)
+   ((node-colorable? g coloring (car uncolored-nodes) color)
+    (let ((new-coloring
+           (cons (cons (car uncolored-nodes) color) coloring)))
+      (try-each (lambda (c)
+                  (color-node g new-coloring colors (cdr uncolored-nodes) c))
+                colors)))))
+
+(define (color-graph g colors)
+  (if (null? colors)
+      (and (null? (graph-nodes g)) ())
+      (color-node g () colors (graph-nodes g) (car colors))))
+
+(define (color-pairs pairs colors)
+  (color-graph (graph-from-edges pairs) colors))
+
+; queens ----------------------------------------------------------------------
+(define (can-attack x y)
+  (let ((x1 (mod x 5))
+        (y1 (truncate (/ x 5)))
+        (x2 (mod y 5))
+        (y2 (truncate (/ y 5))))
+    (or (= x1 x2) (= y1 y2) (= (abs (- y2 y1)) (abs (- x2 x1))))))
+
+(define (generate-5x5-pairs)
+  (let ((result ()))
+    (dotimes (x 25)
+      (dotimes (y 25)
+        (if (and (not (= x y)) (can-attack x y))
+            (set! result (cons (cons x y) result)) ())))
+    result))
--- /dev/null
+++ b/femtolisp/tests/perf.lsp
@@ -1,0 +1,37 @@
+(load "test.lsp")
+
+(princ "colorgraph: ")
+(load "tcolor.lsp")
+
+(princ "fib(34): ")
+(assert (equal? (time (fib 34)) 5702887))
+(princ "yfib(32): ")
+(assert (equal? (time (yfib 32)) 2178309))
+
+(princ "sort: ")
+(set! r (map-int (lambda (x) (mod (+ (* x 9421) 12345) 1024)) 1000))
+(time (simple-sort r))
+
+(princ "expand: ")
+(time (dotimes (n 5000) (expand '(dotimes (i 100) body1 body2))))
+
+(define (my-append . lsts)
+  (cond ((null? lsts) ())
+        ((null? (cdr lsts)) (car lsts))
+        (else (letrec ((append2 (lambda (l d)
+				  (if (null? l) d
+				      (cons (car l)
+					    (append2 (cdr l) d))))))
+		(append2 (car lsts) (apply my-append (cdr lsts)))))))
+
+(princ "append: ")
+(set! L (map-int (lambda (x) (map-int identity 20)) 20))
+(time (dotimes (n 1000) (apply my-append L)))
+
+(path.cwd "ast")
+(princ "p-lambda: ")
+(load "rpasses.lsp")
+(define *input* (load "datetimeR.lsp"))
+(time (set! *output* (compile-ish *input*)))
+(assert (equal? *output* (load "rpasses-out.lsp")))
+(path.cwd "..")
--- /dev/null
+++ b/femtolisp/tests/tcolor.lsp
@@ -1,0 +1,16 @@
+; -*- scheme -*-
+; color for performance
+
+(load "color.lsp")
+
+; 100x color 5 queens
+(define Q (generate-5x5-pairs))
+(define (ct)
+  (set! C (color-pairs Q '(a b c d e)))
+  (dotimes (n 99) (color-pairs Q '(a b c d e))))
+(time (ct))
+(assert (equal? C
+		'((23 . a) (9 . a) (22 . b) (17 . d) (14 . d) (8 . b) (21 . e)
+		  (19 . b) (16 . c) (13 . c) (11 . b) (7 . e) (24 . c) (20 . d)
+		  (18 . e) (15 . a) (12 . a) (10 . e) (6 . d) (5 . c) (4 . e)
+		  (3 . d) (2 . c) (0 . b) (1 . a))))
--- /dev/null
+++ b/femtolisp/tests/test.lsp
@@ -1,0 +1,294 @@
+; -*- scheme -*-
+
+; make label self-evaluating, but evaluating the lambda in the process
+;(defmacro labl (name f)
+;  (list list ''labl (list 'quote name) f))
+
+(define-macro (labl name f)
+  `(let (,name) (set! ,name ,f)))
+
+;(define (reverse lst)
+;  ((label rev-help (lambda (lst result)
+;                     (if (null? lst) result
+;                       (rev-help (cdr lst) (cons (car lst) result)))))
+;   lst ()))
+
+(define (append- . lsts)
+  ((label append-h
+          (lambda (lsts)
+            (cond ((null? lsts) ())
+                  ((null? (cdr lsts)) (car lsts))
+                  (#t ((label append2 (lambda (l d)
+					(if (null? l) d
+					    (cons (car l)
+						  (append2 (cdr l) d)))))
+		       (car lsts) (append-h (cdr lsts)))))))
+   lsts))
+
+;(princ 'Hello '| | 'world! "\n")
+;(filter (lambda (x) (not (< x 0))) '(1 -1 -2 5 10 -8 0))
+(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
+;(princ (time (fib 34)) "\n")
+;(dotimes (i 20000) (map-int (lambda (x) (list 'quote x)) 8))
+;(dotimes (i 40000) (append '(a b) '(1 2 3 4) () '(c) () '(5 6)))
+;(dotimes (i 80000) (list 1 2 3 4 5))
+;(set! a (map-int identity 10000))
+;(dotimes (i 200) (rfoldl cons () a))
+
+#|
+(define-macro (dotimes var . body)
+  (let ((v   (car var))
+        (cnt (cadr var)))
+    `(let ((,v 0))
+       (while (< ,v ,cnt)
+         (prog1
+             ,(cons 'begin body)
+           (set! ,v (+ ,v 1)))))))
+
+(define (map-int f n)
+  (if (<= n 0)
+      ()
+      (let ((first (cons (f 0) ())))
+	((label map-int-
+		(lambda (acc i n)
+		  (if (= i n)
+		      first
+		      (begin (set-cdr! acc (cons (f i) ()))
+			     (map-int- (cdr acc) (+ i 1) n)))))
+	 first 1 n))))
+|#
+
+(define-macro (labl name fn)
+  `((lambda (,name) (set! ,name ,fn)) ()))
+
+(define (square x) (* x x))
+(define (expt b p)
+  (cond ((= p 0) 1)
+        ((= b 0) 0)
+        ((even? p) (square (expt b (div0 p 2))))
+        (#t (* b (expt b (- p 1))))))
+
+(define (gcd a b)
+  (cond ((= a 0) b)
+        ((= b 0) a)
+        ((< a b)  (gcd a (- b a)))
+        (#t       (gcd b (- a b)))))
+
+; like eval-when-compile
+(define-macro (literal expr)
+  (let ((v (eval expr)))
+    (if (self-evaluating? v) v (list quote v))))
+
+(define (cardepth l)
+  (if (atom? l) 0
+      (+ 1 (cardepth (car l)))))
+
+(define (nestlist f zero n)
+  (if (<= n 0) ()
+      (cons zero (nestlist f (f zero) (- n 1)))))
+
+(define (mapl f . lsts)
+  ((label mapl-
+          (lambda (lsts)
+            (if (null? (car lsts)) ()
+		(begin (apply f lsts) (mapl- (map cdr lsts))))))
+   lsts))
+
+; test to see if a symbol begins with :
+(define (keywordp s)
+  (and (>= s '|:|) (<= s '|:~|)))
+
+; swap the cars and cdrs of every cons in a structure
+(define (swapad c)
+  (if (atom? c) c
+      (set-cdr! c (K (swapad (car c))
+		     (set-car! c (swapad (cdr c)))))))
+
+(define (without x l)
+  (filter (lambda (e) (not (eq e x))) l))
+
+(define (conscount c)
+  (if (pair? c) (+ 1
+                   (conscount (car c))
+                   (conscount (cdr c)))
+      0))
+
+;  _ Welcome to
+; (_ _ _ |_ _ |  . _ _ 2
+; | (-||||_(_)|__|_)|_)
+; ==================|==
+
+;[` _ ,_ |-  | . _  2
+;| (/_||||_()|_|_\|)
+;                 | 
+
+(define-macro (while- test . forms)
+  `((label -loop- (lambda ()
+                    (if ,test
+                        (begin ,@forms
+                               (-loop-))
+			())))))
+
+; this would be a cool use of thunking to handle 'finally' clauses, but
+; this code doesn't work in the case where the user manually re-raises
+; inside a catch block. one way to handle it would be to replace all
+; their uses of 'raise' with '*_try_finally_raise_*' which calls the thunk.
+; (try expr
+;      (catch (TypeError e) . exprs)
+;      (catch (IOError e) . exprs)
+;      (finally . exprs))
+(define-macro (try expr . forms)
+  (let ((final (f-body (cdr (or (assq 'finally forms) '(())))))
+        (body (foldr
+               ; create a function to check for and handle one exception
+               ; type, and pass off control to the next when no match
+               (lambda (catc next)
+                 (let ((var    (cadr (cadr catc)))
+                       (extype (caadr catc))
+                       (todo   (f-body (cddr  catc))))
+                   `(lambda (,var)
+                      (if (or (eq ,var ',extype)
+                              (and (pair? ,var)
+                                   (eq (car ,var) ',extype)))
+                          ,todo
+                        (,next ,var)))))
+
+               ; default function; no matches so re-raise
+               '(lambda (e) (begin (*_try_finally_thunk_*) (raise e)))
+
+               ; make list of catch forms
+               (filter (lambda (f) (eq (car f) 'catch)) forms))))
+    `(let ((*_try_finally_thunk_* (lambda () ,final)))
+       (prog1 (attempt ,expr ,body)
+         (*_try_finally_thunk_*)))))
+
+(define Y
+  (lambda (f)
+    ((lambda (h)
+       (f (lambda (x) ((h h) x))))
+     (lambda (h)
+       (f (lambda (x) ((h h) x)))))))
+
+(define yfib
+  (Y (lambda (fib)
+       (lambda (n)
+         (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))))
+
+;(defun tt () (time (dotimes (i 500000) (* 0x1fffffff 1) )))
+;(tt)
+;(tt)
+;(tt)
+
+(define-macro (accumulate-while cnd what . body)
+  (let ((acc (gensym)))
+    `(let ((,acc (list ())))
+       (cdr
+	(prog1 ,acc
+	 (while ,cnd
+		(begin (set! ,acc
+			     (cdr (set-cdr! ,acc (cons ,what ()))))
+		       ,@body)))))))
+
+(define-macro (accumulate-for var lo hi what . body)
+  (let ((acc   (gensym)))
+    `(let ((,acc (list ())))
+       (cdr
+	(prog1 ,acc
+	 (for ,lo ,hi
+	      (lambda (,var)
+		(begin (set! ,acc
+			     (cdr (set-cdr! ,acc (cons ,what ()))))
+		       ,@body))))))))
+
+(define (map-indexed f lst)
+  (if (atom? lst) lst
+    (let ((i 0))
+      (accumulate-while (pair? lst) (f (car lst) i)
+                        (begin (set! lst (cdr lst))
+                               (set! i (1+ i)))))))
+
+(define (string.findall haystack needle . offs)
+  (define (sub h n offs lst)
+    (let ((i (string.find h n offs)))
+      (if i
+	  (sub h n (string.inc h i) (cons i lst))
+	  (reverse! lst))))
+  (sub haystack needle (if (null? offs) 0 (car offs)) ()))
+
+(let ((*profiles* (table)))
+  (set! profile
+	(lambda (s)
+	  (let ((f (top-level-value s)))
+	    (put! *profiles* s (cons 0 0))
+	    (set-top-level-value! s
+	     (lambda args
+	       (define tt (get *profiles* s))
+	       (define count (car tt))
+	       (define time  (cdr tt))
+	       (define t0 (time.now))
+	       (define v (apply f args))
+	       (set-cdr! tt (+ time (- (time.now) t0)))
+	       (set-car! tt (+ count 1))
+	       v)))))
+  (set! show-profiles
+	(lambda ()
+	  (define pr (filter (lambda (x) (> (cadr x) 0))
+			     (table.pairs *profiles*)))
+	  (define width (+ 4
+			   (apply max
+				  (map (lambda (x)
+					 (length (string x)))
+				       (cons 'Function
+					     (map car pr))))))
+	  (princ (string.rpad "Function" width #\ )
+		 "#Calls     Time (seconds)")
+	  (newline)
+	  (princ (string.rpad "--------" width #\ )
+		 "------     --------------")
+	  (newline)
+	  (for-each
+	   (lambda (p)
+	     (princ (string.rpad (string (caddr p)) width #\ )
+		    (string.rpad (string (cadr p)) 11 #\ )
+		    (car p))
+	     (newline))
+	   (simple-sort (map (lambda (l) (reverse (to-proper l)))
+			     pr)))))
+  (set! clear-profiles
+	(lambda ()
+	  (for-each (lambda (k)
+		      (put! *profiles* k (cons 0 0)))
+		    (table.keys *profiles*)))))
+
+#;(for-each profile
+	  '(emit encode-byte-code const-to-idx-vec
+	    index-of lookup-sym in-env? any every
+	    compile-sym compile-if compile-begin
+	    compile-arglist expand builtin->instruction
+	    compile-app separate nconc get-defined-vars
+	    compile-in compile compile-f delete-duplicates
+	    map length> length= count filter append
+	    lastcdr to-proper reverse reverse! list->vector
+	    table.foreach list-head list-tail assq memq assoc member
+	    assv memv nreconc bq-process))
+
+(define (filt1 pred lst)
+  (define (filt1- pred lst accum)
+    (if (null? lst) accum
+	(if (pred (car lst))
+	    (filt1- pred (cdr lst) (cons (car lst) accum))
+	    (filt1- pred (cdr lst) accum))))
+  (filt1- pred lst ()))
+
+(define (filto pred lst (accum ()))
+  (if (atom? lst) accum
+      (if (pred (car lst))
+	  (filto pred (cdr lst) (cons (car lst) accum))
+	  (filto pred (cdr lst) accum))))
+
+; (pairwise? p a b c d) == (and (p a b) (p b c) (p c d))
+(define (pairwise? pred . args)
+  (or (null? args)
+      (let f ((a (car args)) (d (cdr args)))
+	(or (null? d)
+	    (and (pred a (car d)) (f (car d) (cdr d)))))))
--- /dev/null
+++ b/femtolisp/tests/torture.scm
@@ -1,0 +1,24 @@
+(define ones (map (lambda (x) 1) (iota 1000000)))
+
+(write (apply + ones))
+(newline)
+
+(define (big n)
+  (if (<= n 0)
+      0
+      `(+ 1 1 1 1 1 1 1 1 1 1 ,(big (- n 1)))))
+
+(define nst (big 100000))
+
+(write (eval nst))
+(newline)
+
+(define longg (cons '+ ones))
+(write (eval longg))
+(newline)
+
+(define (f x)
+  (begin (write x)
+	 (newline)
+	 (f (+ x 1))
+	 0))
--- /dev/null
+++ b/femtolisp/tests/torus.lsp
@@ -1,0 +1,48 @@
+; -*- scheme -*-
+(define (maplist f l)
+  (if (null? l) ()
+    (cons (f l) (maplist f (cdr l)))))
+
+; produce a beautiful, toroidal cons structure
+; make m copies of a CDR-circular list of length n, and connect corresponding
+; conses in CAR-circular loops
+; replace maplist 'identity' with 'copy-tree' for rapdily exploding memory use
+(define (torus m n)
+  (let* ((l (map-int identity n))
+         (g l)
+         (prev g))
+    (dotimes (i (- m 1))
+      (set! prev g)
+      (set! g (maplist identity g))
+      (set-cdr! (last-pair prev) prev))
+    (set-cdr! (last-pair g) g)
+    (let ((a l)
+          (b g))
+      (dotimes (i n)
+        (set-car! a b)
+        (set! a (cdr a))
+        (set! b (cdr b))))
+    l))
+
+(define (cyl m n)
+  (let* ((l (map-int identity n))
+         (g l))
+    (dotimes (i (- m 1))
+      (set! g (maplist identity g)))
+    (let ((a l)
+          (b g))
+      (dotimes (i n)
+        (set-car! a b)
+        (set! a (cdr a))
+        (set! b (cdr b))))
+    l))
+
+(time (begin (print (torus 100 100)) ()))
+;(time (dotimes (i 1) (load "100x100.lsp")))
+; with ltable
+; printing time: 0.415sec
+; reading time: 0.165sec
+
+; with ptrhash
+; printing time: 0.081sec
+; reading time: 0.0264sec
--- /dev/null
+++ b/femtolisp/tests/unittest.lsp
@@ -1,0 +1,274 @@
+; -*- scheme -*-
+(define-macro (assert-fail expr . what)
+  `(assert (trycatch (begin ,expr #f)
+		     (lambda (e) ,(if (null? what) #t
+				      `(eq? (car e) ',(car what)))))))
+
+(define (every-int n)
+  (list (fixnum n) (int8 n) (uint8 n) (int16 n) (uint16 n) (int32 n) (uint32 n)
+        (int64 n) (uint64 n)))
+
+(define (every-sint n)
+  (list (fixnum n) (int8 n) (int16 n) (int32 n) (int64 n)))
+
+(define (each f l)
+  (if (atom? l) ()
+      (begin (f (car l))
+	     (each f (cdr l)))))
+
+(define (each^2 f l m)
+  (each (lambda (o) (each (lambda (p) (f o p)) m)) l))
+
+(define (test-lt a b)
+  (each^2 (lambda (neg pos)
+            (begin
+              (eval `(assert (= -1 (compare ,neg ,pos))))
+              (eval `(assert (=  1 (compare ,pos ,neg))))))
+          a
+          b))
+
+(define (test-eq a b)
+  (each^2 (lambda (a b)
+            (begin
+              (eval `(assert (= 0 (compare ,a ,b))))))
+          a
+          b))
+
+(test-lt (every-sint -1) (every-int 1))
+(test-lt (every-int 0) (every-int 1))
+(test-eq (every-int 88) (every-int 88))
+(test-eq (every-sint -88) (every-sint -88))
+
+(define (test-square a)
+  (each (lambda (i) (eval `(assert (>= (* ,i ,i) 0))))
+        a))
+
+(test-square (every-sint -67))
+(test-square (every-int 3))
+(test-square (every-int 0x80000000))
+(test-square (every-sint 0x80000000))
+(test-square (every-sint -0x80000000))
+
+(assert (= (* 128 0x02000001) 0x100000080))
+
+(assert (= (/ 1) 1))
+(assert (= (/ -1) -1))
+(assert (= (/ 2.0) 0.5))
+
+(assert (= (- 4999950000 4999941999) 8001))
+
+(assert (not (eqv? 10 #\newline)))
+(assert (not (eqv? #\newline 10)))
+
+; tricky cases involving INT_MIN
+(assert (< (- #uint32(0x80000000)) 0))
+(assert (> (- #int32(0x80000000)) 0))
+(assert (< (- #uint64(0x8000000000000000)) 0))
+(assert (> (- #int64(0x8000000000000000)) 0))
+
+(assert (not (equal? #int64(0x8000000000000000) #uint64(0x8000000000000000))))
+(assert (equal? (+ #int64(0x4000000000000000) #int64(0x4000000000000000))
+		#uint64(0x8000000000000000)))
+(assert (equal? (* 2 #int64(0x4000000000000000))
+		#uint64(0x8000000000000000)))
+
+(assert (equal? (uint64 (double -123)) #uint64(0xffffffffffffff85)))
+
+(assert (equal? (string 'sym #byte(65) #wchar(945) "blah") "symA\u03B1blah"))
+
+; NaNs
+(assert (equal? +nan.0 +nan.0))
+(assert (not (= +nan.0 +nan.0)))
+(assert (not (= +nan.0 -nan.0)))
+(assert (equal? (< +nan.0 3) (> 3 +nan.0)))
+(assert (equal? (< +nan.0 (double 3)) (> (double 3) +nan.0)))
+(assert (equal? (< +nan.0 3) (> (double 3) +nan.0)))
+(assert (equal? (< +nan.0 (double 3)) (> 3 +nan.0)))
+(assert (equal? (< +nan.0 3) (< +nan.0 (double 3))))
+(assert (equal? (> +nan.0 3) (> +nan.0 (double 3))))
+(assert (equal? (< 3 +nan.0) (> +nan.0 (double 3))))
+(assert (equal? (> 3 +nan.0) (> (double 3) +nan.0)))
+(assert (not (>= +nan.0 +nan.0)))
+
+; -0.0 etc.
+(assert (not (equal? 0.0 0)))
+(assert (equal? 0.0 0.0))
+(assert (not (equal? -0.0 0.0)))
+(assert (not (equal? -0.0 0)))
+(assert (not (eqv? 0.0 0)))
+(assert (not (eqv? -0.0 0)))
+(assert (not (eqv? -0.0 0.0)))
+(assert (= 0.0 -0.0))
+
+; this crashed once
+(for 1 10 (lambda (i) 0))
+
+; failing applications
+(assert-fail ((lambda (x) x) 1 2))
+(assert-fail ((lambda (x) x)))
+(assert-fail ((lambda (x y . z) z) 1))
+(assert-fail (car 'x) type-error)
+(assert-fail gjegherqpfdf___trejif unbound-error)
+
+; long argument lists
+(assert (= (apply + (iota 100000)) 4999950000))
+(define ones (map (lambda (x) 1) (iota 80000)))
+(assert (= (eval `(if (< 2 1)
+		      (+ ,@ones)
+		      (+ ,@(cdr ones))))
+	   79999))
+
+(define MAX_ARGS 255)
+
+(define as (apply list* (map-int (lambda (x) (gensym)) (+ MAX_ARGS 1))))
+(define f (compile `(lambda ,as ,(lastcdr as))))
+(assert (equal? (apply f (iota (+ MAX_ARGS 0))) `()))
+(assert (equal? (apply f (iota (+ MAX_ARGS 1))) `(,MAX_ARGS)))
+(assert (equal? (apply f (iota (+ MAX_ARGS 2))) `(,MAX_ARGS ,(+ MAX_ARGS 1))))
+
+(define as (apply list* (map-int (lambda (x) (gensym)) (+ MAX_ARGS 100))))
+(define ff (compile `(lambda ,as (set! ,(car (last-pair as)) 42)
+			     ,(car (last-pair as)))))
+(assert (equal? (apply ff (iota (+ MAX_ARGS 100))) 42))
+(define ff (compile `(lambda ,as (set! ,(car (last-pair as)) 42)
+			     (lambda () ,(car (last-pair as))))))
+(assert (equal? ((apply ff (iota (+ MAX_ARGS 100)))) 42))
+
+(define as (map-int (lambda (x) (gensym)) 1000))
+(define f (compile `(lambda ,as ,(car (last-pair as)))))
+(assert (equal? (apply f (iota 1000)) 999))
+
+(define as (apply list* (map-int (lambda (x) (gensym)) 995)))
+(define f (compile `(lambda ,as ,(lastcdr as))))
+(assert (equal? (apply f (iota 994))  '()))
+(assert (equal? (apply f (iota 995))  '(994)))
+(assert (equal? (apply f (iota 1000)) '(994 995 996 997 998 999)))
+
+; optional arguments
+(assert (equal? ((lambda ((b 0)) b)) 0))
+(assert (equal? ((lambda (a (b 2)) (list a b)) 1) '(1 2)))
+(assert (equal? ((lambda (a (b 2)) (list a b)) 1 3) '(1 3)))
+(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1) '(1 2 3)))
+(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1 8) '(1 8 3)))
+(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1 8 9) '(1 8 9)))
+(assert (equal? ((lambda ((x 0) . r) (list x r))) '(0 ())))
+(assert (equal? ((lambda ((x 0) . r) (list x r)) 1 2 3) '(1 (2 3))))
+
+; keyword arguments
+(assert (keyword? kw:))
+(assert (not (keyword? 'kw)))
+(assert (not (keyword? ':)))
+(assert (equal? ((lambda (x (a 2) (b: a) . r) (list x a b r)) 1 0 8 4 5)
+		'(1 0 0 (8 4 5))))
+(assert (equal? ((lambda (x (a 2) (b: a) . r) (list x a b r)) 0 b: 3 1)
+		'(0 2 3 (1))))
+(define (keys4 (a: 8) (b: 3) (c: 7) (d: 6)) (list a b c d))
+(assert (equal? (keys4 a: 10) '(10 3 7 6)))
+(assert (equal? (keys4 b: 10) '(8 10 7 6)))
+(assert (equal? (keys4 c: 10) '(8 3 10 6)))
+(assert (equal? (keys4 d: 10) '(8 3 7 10)))
+(assert-fail (keys4 e: 10))   ; unsupported keyword
+(assert-fail (keys4 a: 1 b:)) ; keyword with no argument
+
+; cvalues and arrays
+(assert (equal? (typeof "") '(array byte)))
+(assert-fail (aref #(1) 3) bounds-error)
+(define iarr (array 'int64 32 16 8 7 1))
+(assert (equal? (aref iarr 0) 32))
+(assert (equal? (aref iarr #int8(3)) 7))
+
+; gensyms
+(assert (gensym? (gensym)))
+(assert (not (gensym? 'a)))
+(assert (not (eq? (gensym) (gensym))))
+(assert (not (equal? (string (gensym)) (string (gensym)))))
+(let ((gs (gensym))) (assert (eq? gs gs)))
+
+; eof object
+(assert (eof-object? (eof-object)))
+(assert (not (eof-object? 1)))
+(assert (not (eof-object? 'a)))
+(assert (not (eof-object? '())))
+(assert (not (eof-object? #f)))
+(assert (not (null? (eof-object))))
+(assert (not (builtin? (eof-object))))
+(assert (not (function? (eof-object))))
+
+; ok, a couple end-to-end tests as well
+(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
+(assert (equal? (fib 20) 6765))
+
+(load "color.lsp")
+(assert (equal? (color-pairs (generate-5x5-pairs) '(a b c d e))
+		'((23 . a) (9 . a) (22 . b) (17 . d) (14 . d) (8 . b) (21 . e)
+		  (19 . b) (16 . c) (13 . c) (11 . b) (7 . e) (24 . c) (20 . d)
+		  (18 . e) (15 . a) (12 . a) (10 . e) (6 . d) (5 . c) (4 . e)
+		  (3 . d) (2 . c) (0 . b) (1 . a))))
+
+; hashing strange things
+(assert (equal?
+	 (hash '#0=(1 1 #0# . #0#))
+	 (hash '#1=(1 1 #1# 1 1 #1# . #1#))))
+
+(assert (not (equal?
+	      (hash '#0=(1 1 #0# . #0#))
+	      (hash '#1=(1 2 #1# 1 1 #1# . #1#)))))
+
+(assert (equal?
+	 (hash '#0=((1 . #0#) . #0#))
+	 (hash '#1=((1 . #1#) (1 . #1#) . #1#))))
+
+(assert (not (equal?
+	      (hash '#0=((1 . #0#) . #0#))
+	      (hash '#1=((2 . #1#) (1 . #1#) . #1#)))))
+
+(assert (not (equal?
+	      (hash '#0=((1 . #0#) . #0#))
+	      (hash '#1=((1 . #1#) (2 . #1#) . #1#)))))
+
+(assert (equal?
+	 (hash '(#0=(#0#) 0))
+	 (hash '(#1=(((((#1#))))) 0))))
+
+(assert (not (equal?
+	      (hash '(#0=(#0#) 0))
+	      (hash '(#1=(((((#1#))))) 1)))))
+
+(assert (equal?
+	 (hash #0=[1 [2 [#0#]] 3])
+	 (hash #1=[1 [2 [[1 [2 [#1#]] 3]]] 3])))
+
+(assert (not (equal?
+	      (hash #0=[1 [2 [#0#]] 3])
+	      (hash #1=[1 [2 [[5 [2 [#1#]] 3]]] 3]))))
+
+(assert (equal?
+	 (hash #0=[1 #0# [2 [#0#]] 3])
+	 (hash #1=[1 #1# [2 [[1 #1# [2 [#1#]] 3]]] 3])))
+
+(assert (not (equal?
+	      (hash #0=[1 #0# [2 [#0#]] 3])
+	      (hash #1=[6 #1# [2 [[1 #1# [2 [#1#]] 3]]] 3]))))
+
+(assert (equal?
+	 (hash [1 [2 [[1 1 [2 [1]] 3]]] 3])
+	 (hash [1 [2 [[1 1 [2 [1]] 3]]] 3])))
+
+(assert (not (equal?
+	      (hash [6 1 [2 [[3 1 [2 [1]] 3]]] 3])
+	      (hash [6 1 [2 [[1 1 [2 [1]] 3]]] 3]))))
+
+(assert (equal? (hash '#0=(1 . #0#))
+		(hash '#1=(1 1 . #1#))))
+
+(assert (not (equal? (hash '#0=(1 1 . #0#))
+		     (hash '#1=(1 #0# . #1#)))))
+
+(assert (not (equal? (hash (iota 10))
+		     (hash (iota 20)))))
+
+(assert (not (equal? (hash (iota 41))
+		     (hash (iota 42)))))
+
+(princ "all tests pass\n")
+#t
binary files a/femtolisp/tiny/lisp /dev/null differ
binary files a/femtolisp/tiny/lisp2 /dev/null differ
binary files a/femtolisp/tiny/lispf /dev/null differ
--- a/femtolisp/torture.scm
+++ /dev/null
@@ -1,24 +1,0 @@
-(define ones (map (lambda (x) 1) (iota 1000000)))
-
-(write (apply + ones))
-(newline)
-
-(define (big n)
-  (if (<= n 0)
-      0
-      `(+ 1 1 1 1 1 1 1 1 1 1 ,(big (- n 1)))))
-
-(define nst (big 100000))
-
-(write (eval nst))
-(newline)
-
-(define longg (cons '+ ones))
-(write (eval longg))
-(newline)
-
-(define (f x)
-  (begin (write x)
-	 (newline)
-	 (f (+ x 1))
-	 0))
--- a/femtolisp/torus.lsp
+++ /dev/null
@@ -1,48 +1,0 @@
-; -*- scheme -*-
-(define (maplist f l)
-  (if (null? l) ()
-    (cons (f l) (maplist f (cdr l)))))
-
-; produce a beautiful, toroidal cons structure
-; make m copies of a CDR-circular list of length n, and connect corresponding
-; conses in CAR-circular loops
-; replace maplist 'identity' with 'copy-tree' for rapdily exploding memory use
-(define (torus m n)
-  (let* ((l (map-int identity n))
-         (g l)
-         (prev g))
-    (dotimes (i (- m 1))
-      (set! prev g)
-      (set! g (maplist identity g))
-      (set-cdr! (last-pair prev) prev))
-    (set-cdr! (last-pair g) g)
-    (let ((a l)
-          (b g))
-      (dotimes (i n)
-        (set-car! a b)
-        (set! a (cdr a))
-        (set! b (cdr b))))
-    l))
-
-(define (cyl m n)
-  (let* ((l (map-int identity n))
-         (g l))
-    (dotimes (i (- m 1))
-      (set! g (maplist identity g)))
-    (let ((a l)
-          (b g))
-      (dotimes (i n)
-        (set-car! a b)
-        (set! a (cdr a))
-        (set! b (cdr b))))
-    l))
-
-(time (begin (print (torus 100 100)) ()))
-;(time (dotimes (i 1) (load "100x100.lsp")))
-; with ltable
-; printing time: 0.415sec
-; reading time: 0.165sec
-
-; with ptrhash
-; printing time: 0.081sec
-; reading time: 0.0264sec
--- a/femtolisp/unittest.lsp
+++ /dev/null
@@ -1,274 +1,0 @@
-; -*- scheme -*-
-(define-macro (assert-fail expr . what)
-  `(assert (trycatch (begin ,expr #f)
-		     (lambda (e) ,(if (null? what) #t
-				      `(eq? (car e) ',(car what)))))))
-
-(define (every-int n)
-  (list (fixnum n) (int8 n) (uint8 n) (int16 n) (uint16 n) (int32 n) (uint32 n)
-        (int64 n) (uint64 n)))
-
-(define (every-sint n)
-  (list (fixnum n) (int8 n) (int16 n) (int32 n) (int64 n)))
-
-(define (each f l)
-  (if (atom? l) ()
-      (begin (f (car l))
-	     (each f (cdr l)))))
-
-(define (each^2 f l m)
-  (each (lambda (o) (each (lambda (p) (f o p)) m)) l))
-
-(define (test-lt a b)
-  (each^2 (lambda (neg pos)
-            (begin
-              (eval `(assert (= -1 (compare ,neg ,pos))))
-              (eval `(assert (=  1 (compare ,pos ,neg))))))
-          a
-          b))
-
-(define (test-eq a b)
-  (each^2 (lambda (a b)
-            (begin
-              (eval `(assert (= 0 (compare ,a ,b))))))
-          a
-          b))
-
-(test-lt (every-sint -1) (every-int 1))
-(test-lt (every-int 0) (every-int 1))
-(test-eq (every-int 88) (every-int 88))
-(test-eq (every-sint -88) (every-sint -88))
-
-(define (test-square a)
-  (each (lambda (i) (eval `(assert (>= (* ,i ,i) 0))))
-        a))
-
-(test-square (every-sint -67))
-(test-square (every-int 3))
-(test-square (every-int 0x80000000))
-(test-square (every-sint 0x80000000))
-(test-square (every-sint -0x80000000))
-
-(assert (= (* 128 0x02000001) 0x100000080))
-
-(assert (= (/ 1) 1))
-(assert (= (/ -1) -1))
-(assert (= (/ 2.0) 0.5))
-
-(assert (= (- 4999950000 4999941999) 8001))
-
-(assert (not (eqv? 10 #\newline)))
-(assert (not (eqv? #\newline 10)))
-
-; tricky cases involving INT_MIN
-(assert (< (- #uint32(0x80000000)) 0))
-(assert (> (- #int32(0x80000000)) 0))
-(assert (< (- #uint64(0x8000000000000000)) 0))
-(assert (> (- #int64(0x8000000000000000)) 0))
-
-(assert (not (equal? #int64(0x8000000000000000) #uint64(0x8000000000000000))))
-(assert (equal? (+ #int64(0x4000000000000000) #int64(0x4000000000000000))
-		#uint64(0x8000000000000000)))
-(assert (equal? (* 2 #int64(0x4000000000000000))
-		#uint64(0x8000000000000000)))
-
-(assert (equal? (uint64 (double -123)) #uint64(0xffffffffffffff85)))
-
-(assert (equal? (string 'sym #byte(65) #wchar(945) "blah") "symA\u03B1blah"))
-
-; NaNs
-(assert (equal? +nan.0 +nan.0))
-(assert (not (= +nan.0 +nan.0)))
-(assert (not (= +nan.0 -nan.0)))
-(assert (equal? (< +nan.0 3) (> 3 +nan.0)))
-(assert (equal? (< +nan.0 (double 3)) (> (double 3) +nan.0)))
-(assert (equal? (< +nan.0 3) (> (double 3) +nan.0)))
-(assert (equal? (< +nan.0 (double 3)) (> 3 +nan.0)))
-(assert (equal? (< +nan.0 3) (< +nan.0 (double 3))))
-(assert (equal? (> +nan.0 3) (> +nan.0 (double 3))))
-(assert (equal? (< 3 +nan.0) (> +nan.0 (double 3))))
-(assert (equal? (> 3 +nan.0) (> (double 3) +nan.0)))
-(assert (not (>= +nan.0 +nan.0)))
-
-; -0.0 etc.
-(assert (not (equal? 0.0 0)))
-(assert (equal? 0.0 0.0))
-(assert (not (equal? -0.0 0.0)))
-(assert (not (equal? -0.0 0)))
-(assert (not (eqv? 0.0 0)))
-(assert (not (eqv? -0.0 0)))
-(assert (not (eqv? -0.0 0.0)))
-(assert (= 0.0 -0.0))
-
-; this crashed once
-(for 1 10 (lambda (i) 0))
-
-; failing applications
-(assert-fail ((lambda (x) x) 1 2))
-(assert-fail ((lambda (x) x)))
-(assert-fail ((lambda (x y . z) z) 1))
-(assert-fail (car 'x) type-error)
-(assert-fail gjegherqpfdf___trejif unbound-error)
-
-; long argument lists
-(assert (= (apply + (iota 100000)) 4999950000))
-(define ones (map (lambda (x) 1) (iota 80000)))
-(assert (= (eval `(if (< 2 1)
-		      (+ ,@ones)
-		      (+ ,@(cdr ones))))
-	   79999))
-
-(define MAX_ARGS 255)
-
-(define as (apply list* (map-int (lambda (x) (gensym)) (+ MAX_ARGS 1))))
-(define f (compile `(lambda ,as ,(lastcdr as))))
-(assert (equal? (apply f (iota (+ MAX_ARGS 0))) `()))
-(assert (equal? (apply f (iota (+ MAX_ARGS 1))) `(,MAX_ARGS)))
-(assert (equal? (apply f (iota (+ MAX_ARGS 2))) `(,MAX_ARGS ,(+ MAX_ARGS 1))))
-
-(define as (apply list* (map-int (lambda (x) (gensym)) (+ MAX_ARGS 100))))
-(define ff (compile `(lambda ,as (set! ,(car (last-pair as)) 42)
-			     ,(car (last-pair as)))))
-(assert (equal? (apply ff (iota (+ MAX_ARGS 100))) 42))
-(define ff (compile `(lambda ,as (set! ,(car (last-pair as)) 42)
-			     (lambda () ,(car (last-pair as))))))
-(assert (equal? ((apply ff (iota (+ MAX_ARGS 100)))) 42))
-
-(define as (map-int (lambda (x) (gensym)) 1000))
-(define f (compile `(lambda ,as ,(car (last-pair as)))))
-(assert (equal? (apply f (iota 1000)) 999))
-
-(define as (apply list* (map-int (lambda (x) (gensym)) 995)))
-(define f (compile `(lambda ,as ,(lastcdr as))))
-(assert (equal? (apply f (iota 994))  '()))
-(assert (equal? (apply f (iota 995))  '(994)))
-(assert (equal? (apply f (iota 1000)) '(994 995 996 997 998 999)))
-
-; optional arguments
-(assert (equal? ((lambda ((b 0)) b)) 0))
-(assert (equal? ((lambda (a (b 2)) (list a b)) 1) '(1 2)))
-(assert (equal? ((lambda (a (b 2)) (list a b)) 1 3) '(1 3)))
-(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1) '(1 2 3)))
-(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1 8) '(1 8 3)))
-(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1 8 9) '(1 8 9)))
-(assert (equal? ((lambda ((x 0) . r) (list x r))) '(0 ())))
-(assert (equal? ((lambda ((x 0) . r) (list x r)) 1 2 3) '(1 (2 3))))
-
-; keyword arguments
-(assert (keyword? kw:))
-(assert (not (keyword? 'kw)))
-(assert (not (keyword? ':)))
-(assert (equal? ((lambda (x (a 2) (b: a) . r) (list x a b r)) 1 0 8 4 5)
-		'(1 0 0 (8 4 5))))
-(assert (equal? ((lambda (x (a 2) (b: a) . r) (list x a b r)) 0 b: 3 1)
-		'(0 2 3 (1))))
-(define (keys4 (a: 8) (b: 3) (c: 7) (d: 6)) (list a b c d))
-(assert (equal? (keys4 a: 10) '(10 3 7 6)))
-(assert (equal? (keys4 b: 10) '(8 10 7 6)))
-(assert (equal? (keys4 c: 10) '(8 3 10 6)))
-(assert (equal? (keys4 d: 10) '(8 3 7 10)))
-(assert-fail (keys4 e: 10))   ; unsupported keyword
-(assert-fail (keys4 a: 1 b:)) ; keyword with no argument
-
-; cvalues and arrays
-(assert (equal? (typeof "") '(array byte)))
-(assert-fail (aref #(1) 3) bounds-error)
-(define iarr (array 'int64 32 16 8 7 1))
-(assert (equal? (aref iarr 0) 32))
-(assert (equal? (aref iarr #int8(3)) 7))
-
-; gensyms
-(assert (gensym? (gensym)))
-(assert (not (gensym? 'a)))
-(assert (not (eq? (gensym) (gensym))))
-(assert (not (equal? (string (gensym)) (string (gensym)))))
-(let ((gs (gensym))) (assert (eq? gs gs)))
-
-; eof object
-(assert (eof-object? (eof-object)))
-(assert (not (eof-object? 1)))
-(assert (not (eof-object? 'a)))
-(assert (not (eof-object? '())))
-(assert (not (eof-object? #f)))
-(assert (not (null? (eof-object))))
-(assert (not (builtin? (eof-object))))
-(assert (not (function? (eof-object))))
-
-; ok, a couple end-to-end tests as well
-(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
-(assert (equal? (fib 20) 6765))
-
-(load "color.lsp")
-(assert (equal? (color-pairs (generate-5x5-pairs) '(a b c d e))
-		'((23 . a) (9 . a) (22 . b) (17 . d) (14 . d) (8 . b) (21 . e)
-		  (19 . b) (16 . c) (13 . c) (11 . b) (7 . e) (24 . c) (20 . d)
-		  (18 . e) (15 . a) (12 . a) (10 . e) (6 . d) (5 . c) (4 . e)
-		  (3 . d) (2 . c) (0 . b) (1 . a))))
-
-; hashing strange things
-(assert (equal?
-	 (hash '#0=(1 1 #0# . #0#))
-	 (hash '#1=(1 1 #1# 1 1 #1# . #1#))))
-
-(assert (not (equal?
-	      (hash '#0=(1 1 #0# . #0#))
-	      (hash '#1=(1 2 #1# 1 1 #1# . #1#)))))
-
-(assert (equal?
-	 (hash '#0=((1 . #0#) . #0#))
-	 (hash '#1=((1 . #1#) (1 . #1#) . #1#))))
-
-(assert (not (equal?
-	      (hash '#0=((1 . #0#) . #0#))
-	      (hash '#1=((2 . #1#) (1 . #1#) . #1#)))))
-
-(assert (not (equal?
-	      (hash '#0=((1 . #0#) . #0#))
-	      (hash '#1=((1 . #1#) (2 . #1#) . #1#)))))
-
-(assert (equal?
-	 (hash '(#0=(#0#) 0))
-	 (hash '(#1=(((((#1#))))) 0))))
-
-(assert (not (equal?
-	      (hash '(#0=(#0#) 0))
-	      (hash '(#1=(((((#1#))))) 1)))))
-
-(assert (equal?
-	 (hash #0=[1 [2 [#0#]] 3])
-	 (hash #1=[1 [2 [[1 [2 [#1#]] 3]]] 3])))
-
-(assert (not (equal?
-	      (hash #0=[1 [2 [#0#]] 3])
-	      (hash #1=[1 [2 [[5 [2 [#1#]] 3]]] 3]))))
-
-(assert (equal?
-	 (hash #0=[1 #0# [2 [#0#]] 3])
-	 (hash #1=[1 #1# [2 [[1 #1# [2 [#1#]] 3]]] 3])))
-
-(assert (not (equal?
-	      (hash #0=[1 #0# [2 [#0#]] 3])
-	      (hash #1=[6 #1# [2 [[1 #1# [2 [#1#]] 3]]] 3]))))
-
-(assert (equal?
-	 (hash [1 [2 [[1 1 [2 [1]] 3]]] 3])
-	 (hash [1 [2 [[1 1 [2 [1]] 3]]] 3])))
-
-(assert (not (equal?
-	      (hash [6 1 [2 [[3 1 [2 [1]] 3]]] 3])
-	      (hash [6 1 [2 [[1 1 [2 [1]] 3]]] 3]))))
-
-(assert (equal? (hash '#0=(1 . #0#))
-		(hash '#1=(1 1 . #1#))))
-
-(assert (not (equal? (hash '#0=(1 1 . #0#))
-		     (hash '#1=(1 #0# . #1#)))))
-
-(assert (not (equal? (hash (iota 10))
-		     (hash (iota 20)))))
-
-(assert (not (equal? (hash (iota 41))
-		     (hash (iota 42)))))
-
-(princ "all tests pass\n")
-#t