2 ; Copyright © 2016 Keith Packard <keithp@keithp.com>
4 ; This program is free software; you can redistribute it and/or modify
5 ; it under the terms of the GNU General Public License as published by
6 ; the Free Software Foundation, either version 2 of the License, or
7 ; (at your option) any later version.
9 ; This program is distributed in the hope that it will be useful, but
10 ; WITHOUT ANY WARRANTY; without even the implied warranty of
11 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ; General Public License for more details.
14 ; Lisp code placed in ROM
16 (def (quote _?_) (lambda (a b) (cond ((eq? a b) a) (else (exit)))))
18 ; return a list containing all of the arguments
19 (def (quote list) (lambda l l))
36 (else (cons (car a) (append-list (cdr a) b)))
43 (cond ((null? lists) lists)
44 ((null? (cdr lists)) (car lists))
45 (else (append-list (car lists) (append-lists (cdr lists))))
54 (append '(a b c) '(d e f) '(g h i))
83 ; execute to resolve macros
112 ; execute to resolve macros
122 ((and (pair? a) (pair? b))
123 (and (equal? (car a) (car b))
124 (equal? (cdr a) (cdr b)))
126 ((and (vector? a) (vector? b) (= (vector-length a) (vector-length b)))
129 (equal? (vector-ref a i)
145 (_?_ (equal? '(a b c) '(a b c)) #t)
146 (_?_ (equal? '(a b c) '(a b b)) #f)
147 (_?_ (equal? #(1 2 3) #(1 2 3)) #t)
148 (_?_ (equal? #(1 2 3) #(4 5 6)) #f)
150 (def (quote _??_) (lambda (a b) (cond ((equal? a b) a) (else (exit)))))
156 ; A constant value is either a pair starting with quote,
157 ; or anything which is neither a pair nor a symbol
161 (eq? (car exp) 'quote)
169 (def! combine-skeletons
170 (lambda (left right exp)
172 ((and (constant? left) (constant? right))
173 (cond ((and (eqv? (eval left) (car exp))
174 (eqv? (eval right) (cdr exp)))
178 (list 'quote (cons (eval left) (eval right)))
185 ((and (pair? right) (eq? (car right) 'list))
186 (cons 'list (cons left (cdr right)))
189 (list 'cons left right)
195 (def! expand-quasiquote
196 (lambda (exp nesting)
199 ; non cons -- constants
200 ; themselves, others are
204 (cond ((constant? exp)
213 ; check for an unquote exp and
214 ; add the param unquoted
216 ((and (eq? (car exp) 'unquote) (= (length exp) 2))
221 (combine-skeletons ''unquote
222 (expand-quasiquote (cdr exp) (- nesting 1))
227 ; nested quasi-quote --
228 ; construct the right
231 ((and (eq? (car exp) 'quasiquote) (= (length exp) 2))
232 (combine-skeletons ''quasiquote
233 (expand-quasiquote (cdr exp) (+ nesting 1))
237 ; unquote-splicing member,
238 ; compute the expansion of the
239 ; value and append the rest of
240 ; the quasiquote result to it
242 ((and (pair? (car exp))
243 (eq? (car (car exp)) 'unquote-splicing)
244 (= (length (car exp)) 2))
246 (list 'append (car (cdr (car exp)))
247 (expand-quasiquote (cdr exp) nesting))
250 (combine-skeletons (expand-quasiquote (car exp) (- nesting 1))
251 (expand-quasiquote (cdr exp) nesting)
256 ; for other lists, just glue
257 ; the expansion of the first
258 ; element to the expansion of
259 ; the rest of the list
261 (else (combine-skeletons (expand-quasiquote (car exp) nesting)
262 (expand-quasiquote (cdr exp) nesting)
268 (def! result (expand-quasiquote x 0))
275 ; Define a variable without returning the value
276 ; Useful when defining functions to avoid
277 ; having lots of output generated.
279 ; Also accepts the alternate
280 ; form for defining lambdas of
281 ; (define (name x y z) sexprs ...)
286 (macro (first . rest)
287 ; check for alternate lambda definition form
296 (set! first (car first))
299 (set! rest (car rest))
302 (def! result `(,begin
303 (,def (,quote ,first) ,rest)
312 ; basic list accessors
314 (define (caar l) (car (car l)))
316 (_??_ (caar '((1 2 3) (4 5 6))) 1)
318 (define (cadr l) (car (cdr l)))
320 (_??_ (cadr '(1 2 3 4 5 6)) 2)
322 (define (cdar l) (cdr (car l)))
324 (_??_ (cdar '((1 2) (3 4))) '(2))
326 (define (cddr l) (cdr (cdr l)))
328 (_??_ (cddr '(1 2 3)) '(3))
330 (define (caddr l) (car (cdr (cdr l))))
332 (_??_ (caddr '(1 2 3 4)) 3)
334 ; (if <condition> <if-true>)
335 ; (if <condition> <if-true> <if-false)
339 (cond ((null? (cdr args))
340 `(cond (,test ,(car args)))
343 `(cond (,test ,(car args))
350 (_??_ (if (> 3 2) 'yes) 'yes)
351 (_??_ (if (> 3 2) 'yes 'no) 'yes)
352 (_??_ (if (> 2 3) 'no 'yes) 'yes)
353 (_??_ (if (> 2 3) 'no) #f)
355 ; simple math operators
357 (define zero? (macro (value) `(eq? ,value 0)))
361 (_??_ (zero? "hello") #f)
363 (define positive? (macro (value) `(> ,value 0)))
365 (_??_ (positive? 12) #t)
366 (_??_ (positive? -12) #f)
368 (define negative? (macro (value) `(< ,value 0)))
370 (_??_ (negative? 12) #f)
371 (_??_ (negative? -12) #t)
373 (define (abs x) (if (>= x 0) x (- x)))
378 (define max (lambda (first . rest)
379 (while (not (null? rest))
380 (cond ((< first (car rest))
381 (set! first (car rest)))
383 (set! rest (cdr rest))
391 (define min (lambda (first . rest)
392 (while (not (null? rest))
393 (cond ((> first (car rest))
394 (set! first (car rest)))
396 (set! rest (cdr rest))
404 (define (even? x) (zero? (% x 2)))
411 (define (odd? x) (not (even? x)))
418 (_??_ (list-tail '(1 2 3 . 4) 3) 4)
420 (define (list-ref x k)
421 (car (list-tail x k))
424 (_??_ (list-ref '(1 2 3 4) 3) 4)
426 (define (list-set! x k v)
427 (set-car! (list-tail x k) v)
430 (list-set! (list 1 2 3) 1 4)
432 ; define a set of local
433 ; variables all at once and
434 ; then evaluate a list of
437 ; (let (var-defines) sexprs)
439 ; where var-defines are either
449 ; (let ((x 1) (y)) (set! y (+ x 1)) y)
452 (macro (vars . exprs)
453 (define (make-names vars)
454 (cond ((not (null? vars))
455 (cons (car (car vars))
456 (make-names (cdr vars))))
461 ; the parameters to the lambda is a list
462 ; of nils of the right length
464 (define (make-vals vars)
465 (cond ((not (null? vars))
466 (cons (cond ((null? (cdr (car vars))) ())
468 (car (cdr (car vars))))
470 (make-vals (cdr vars))))
474 ; prepend the set operations
479 `((lambda ,(make-names vars) ,@exprs) ,@(make-vals vars))
484 (_??_ (let ((x 1) (y)) (set! y 2) (+ x y)) 3)
486 ; define a set of local
487 ; variables one at a time and
488 ; then evaluate a list of
491 ; (let* (var-defines) sexprs)
493 ; where var-defines are either
503 ; (let* ((x 1) (y)) (set! y (+ x 1)) y)
506 (macro (vars . exprs)
509 ; make the list of names in the let
512 (define (make-names vars)
513 (cond ((not (null? vars))
514 (cons (car (car vars))
515 (make-names (cdr vars))))
520 ; the set of expressions is
521 ; the list of set expressions
523 ; expressions to evaluate
525 (define (make-exprs vars exprs)
526 (cond ((null? vars) exprs)
533 (cond ((null? (cdr (car vars))) ())
534 (else (cadr (car vars))))
536 (make-exprs (cdr vars) exprs)
542 ; the parameters to the lambda is a list
543 ; of nils of the right length
545 (define (make-nils vars)
546 (cond ((null? vars) ())
547 (else (cons () (make-nils (cdr vars))))
552 `((lambda ,(make-names vars) ,@(make-exprs vars exprs)) ,@(make-nils vars))
556 (_??_ (let* ((x 1) (y x)) (+ x y)) 2)
558 (define when (macro (test . l) `(cond (,test ,@l))))
560 (_??_ (when #t (+ 1 2)) 3)
561 (_??_ (when #f (+ 1 2)) #f)
563 (define unless (macro (test . l) `(cond ((not ,test) ,@l))))
565 (_??_ (unless #f (+ 2 3)) 5)
566 (_??_ (unless #t (+ 2 3)) #f)
568 (define (reverse list)
572 (_r (cdr old) (cons (car old) new))
578 (_??_ (reverse '(1 2 3)) '(3 2 1))
585 (_m (- a 1) (cons b x))
596 (_??_ (make-list 10 'a) '(a a a a a a a a a a))
598 (_??_ (make-list 10) '(#f #f #f #f #f #f #f #f #f #f))
600 (define member (lambda (obj list . test?)
605 (if (null? test?) (set! test? equal?) (set! test? (car test?)))
606 (if (test? obj (car list))
608 (member obj (cdr list) test?))
614 (_??_ (member '(2) '((1) (2) (3))) '((2) (3)))
616 (_??_ (member '(4) '((1) (2) (3))) #f)
618 (define (memq obj list) (member obj list eq?))
620 (_??_ (memq 2 '(1 2 3)) '(2 3))
622 (_??_ (memq 4 '(1 2 3)) #f)
624 (_??_ (memq '(2) '((1) (2) (3))) #f)
626 (define (memv obj list) (member obj list eqv?))
628 (_??_ (memv 2 '(1 2 3)) '(2 3))
630 (_??_ (memv 4 '(1 2 3)) #f)
632 (_??_ (memv '(2) '((1) (2) (3))) #f)
634 (define (assoc obj list . compare)
636 (set! compare equal?)
637 (set! compare (car compare))
641 (if (compare obj (caar list))
643 (assoc obj (cdr list) compare)
648 (define (assq obj list) (assoc obj list eq?))
649 (define (assv obj list) (assoc obj list eqv?))
651 (_??_ (assq 'a '((a 1) (b 2) (c 3))) '(a 1))
652 (_??_ (assv 'b '((a 1) (b 2) (c 3))) '(b 2))
653 (_??_ (assoc '(c) '((a 1) (b 2) ((c) 3))) '((c) 3))
655 (define char? integer?)
657 (_??_ (char? #\q) #t)
658 (_??_ (char? "h") #f)
660 (define (char-upper-case? c) (<= #\A c #\Z))
662 (_??_ (char-upper-case? #\a) #f)
663 (_??_ (char-upper-case? #\B) #t)
664 (_??_ (char-upper-case? #\0) #f)
665 (_??_ (char-upper-case? #\space) #f)
667 (define (char-lower-case? c) (<= #\a c #\a))
669 (_??_ (char-lower-case? #\a) #t)
670 (_??_ (char-lower-case? #\B) #f)
671 (_??_ (char-lower-case? #\0) #f)
672 (_??_ (char-lower-case? #\space) #f)
674 (define (char-alphabetic? c) (or (char-upper-case? c) (char-lower-case? c)))
676 (_??_ (char-alphabetic? #\a) #t)
677 (_??_ (char-alphabetic? #\B) #t)
678 (_??_ (char-alphabetic? #\0) #f)
679 (_??_ (char-alphabetic? #\space) #f)
681 (define (char-numeric? c) (<= #\0 c #\9))
683 (_??_ (char-numeric? #\a) #f)
684 (_??_ (char-numeric? #\B) #f)
685 (_??_ (char-numeric? #\0) #t)
686 (_??_ (char-numeric? #\space) #f)
688 (define (char-whitespace? c) (or (<= #\tab c #\return) (= #\space c)))
690 (_??_ (char-whitespace? #\a) #f)
691 (_??_ (char-whitespace? #\B) #f)
692 (_??_ (char-whitespace? #\0) #f)
693 (_??_ (char-whitespace? #\space) #t)
695 (define char->integer (macro (v) v))
696 (define integer->char char->integer)
698 (define (char-upcase c) (if (char-lower-case? c) (+ c (- #\A #\a)) c))
700 (_??_ (char-upcase #\a) #\A)
701 (_??_ (char-upcase #\B) #\B)
702 (_??_ (char-upcase #\0) #\0)
703 (_??_ (char-upcase #\space) #\space)
705 (define (char-downcase c) (if (char-upper-case? c) (+ c (- #\a #\A)) c))
707 (_??_ (char-downcase #\a) #\a)
708 (_??_ (char-downcase #\B) #\b)
709 (_??_ (char-downcase #\0) #\0)
710 (_??_ (char-downcase #\space) #\space)
712 (define (digit-value c)
713 (if (char-numeric? c)
718 (_??_ (digit-value #\1) 1)
719 (_??_ (digit-value #\a) #f)
721 (define string (lambda chars (list->string chars)))
723 (_??_ (string #\a #\b #\c) "abc")
725 (_??_ (apply cons '(a b)) '(a . b))
728 (lambda (proc . lists)
730 (cond ((null? lists) ())
732 (cons (caar lists) (_a (cdr lists)))
737 (cond ((null? lists) ())
739 (cons (cdr (car lists)) (_n (cdr lists)))
744 (cond ((null? (car lists)) ())
746 (cons (apply proc (_a lists)) (_m (_n lists)))
754 (_??_ (map cadr '((a b) (d e) (g h))) '(b e h))
757 (lambda (proc . lists)
759 (cond ((null? (car lists)) #t)
761 (apply proc (map car lists))
770 (for-each display '("hello" " " "world" "\n"))
772 (define (newline) (write-char #\newline))
776 (call-with-current-continuation
778 (for-each (lambda (x)
782 '(54 0 37 -3 245 19))
787 ; `(q) -> (append (quote (q)))
788 ; `(a ,(+ 1 2)) -> (append (quote (a)) (list (+ 1 2)))
789 ; `(a ,@(list 1 2 3) -> (append (quote (a)) (list 1 2 3))
793 (_??_ `(hello ,(+ 1 2) ,@(list 1 2 3) `foo) '(hello 3 1 2 3 (quasiquote foo)))
797 (macro (count . rest)
798 (define counter '__count__)
800 (set! counter (car count))
801 (set! count (cadr count))
807 (while (< ,counter __max__)
809 (set! ,counter (+ ,counter 1))
815 (repeat 2 (write 'hello))
816 (repeat (x 3) (write 'goodbye x))
820 ; construct the body of the
821 ; case, dealing with the
822 ; lambda version ( => lambda)
826 ((eq? (car l) '=>) `(( ,(cadr l) __key__)))
830 ; Build the case elements, which is
831 ; simply a list of cond clauses
839 ((eq? (caar l) 'else)
840 `((else ,@(_unarrow (cdr (car l))))))
846 `((eqv? ,(caar l) __key__)
847 ,@(_unarrow (cdr (car l))))
853 ; now construct the overall
854 ; expression, using a lambda
855 ; to hold the computed value
856 ; of the test expression
859 (cond ,@(_case l))) ,test)
863 (_??_ (case 1 (1 "one") (2 "two") (3 => (lambda (x) (write "the value is" x))) (12 "twelve") (else "else")) "one")
864 (_??_ (case 2 (1 "one") (2 "two") (3 => (lambda (x) (write "the value is" x))) (12 "twelve") (else "else")) "two")
865 (_??_ (case 3 (1 "one") (2 "two") (3 => (lambda (x) (write "the value is" x) "three")) (12 "twelve") (else "else")) "three")
866 (_??_ (case 4 (1 "one") (2 "two") (3 => (lambda (x) (write "the value is" x))) (12 "twelve") (else "else")) "else")
867 (_??_ (case 12 (1 "one") (2 "two") (3 => (lambda (x) (write "the value is" x))) (12 "twelve") (else "else")) "twelve")
870 (macro (vars test . cmds)
874 (if (null? (cddr (car v)))
876 (cons `(set! ,(caar v) ,(caddr (car v)))
882 `(let ,(map (lambda (v) (list (car v) (cadr v))) vars)
883 (while (not ,(car test))
899 (_??_ (do ((vec (make-vector 5))
902 (vector-set! vec i i)) #(0 1 2 3 4))