436da3dc423a26253d0207cba2df69320c0dbbd6
[fw/altos] / src / lisp / ao_lisp_const.lisp
1 ;
2 ; Copyright © 2016 Keith Packard <keithp@keithp.com>
3 ;
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.
8 ;
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.
13 ;
14 ; Lisp code placed in ROM
15
16                                         ; return a list containing all of the arguments
17 (def (quote list) (lexpr (l) l))
18
19 (def (quote def!)
20      (macro (name value rest)
21             (list
22              def
23              (list quote name)
24              value)
25             )
26      )
27
28 (begin
29  (def! append
30    (lexpr (args)
31           ((lambda (append-list append-lists)
32              (set! append-list
33                    (lambda (a b)
34                      (cond ((null? a) b)
35                            (else (cons (car a) (append-list (cdr a) b)))
36                            )
37                      )
38                    )
39              (set! append-lists
40                    (lambda (lists)
41                      (cond ((null? lists) lists)
42                            ((null? (cdr lists)) (car lists))
43                            (else (append-list (car lists) (append-lists (cdr lists))))
44                            )
45                      )
46                    )
47              (append-lists args)
48              ) () ())
49           )
50    )
51  'append)
52
53 (append '(a b c) '(d e f) '(g h i))
54
55                                         ; boolean operators
56
57 (begin
58  (def! or
59    (macro (l)
60           (def! _or
61             (lambda (l)
62               (cond ((null? l) #f)
63                     ((null? (cdr l))
64                      (car l))
65                     (else
66                      (list
67                       cond
68                       (list
69                        (car l))
70                       (list
71                        'else
72                        (_or (cdr l))
73                        )
74                       )
75                      )
76                     )
77               )
78             )
79           (_or l)))
80  'or)
81
82                                         ; execute to resolve macros
83
84 (or #f #t)
85
86 (begin
87  (def! and
88    (macro (l)
89           (def! _and
90             (lambda (l)
91               (cond ((null? l) #t)
92                     ((null? (cdr l))
93                      (car l))
94                     (else
95                      (list
96                       cond
97                       (list
98                        (car l)
99                        (_and (cdr l))
100                        )
101                       )
102                      )
103                     )
104               )
105             )
106           (_and l)))
107  'and)
108
109                                         ; execute to resolve macros
110
111 (and #t #f)
112
113 (begin
114  (def! quasiquote
115    (macro (x rest)
116           (def! constant?
117                                         ; A constant value is either a pair starting with quote,
118                                         ; or anything which is neither a pair nor a symbol
119
120             (lambda (exp)
121               (cond ((pair? exp)
122                      (eq? (car exp) 'quote)
123                      )
124                     (else
125                      (not (symbol? exp))
126                      )
127                     )
128               )
129             )
130           (def! combine-skeletons
131             (lambda (left right exp)
132               (cond
133                ((and (constant? left) (constant? right)) 
134                 (cond ((and (eqv? (eval left) (car exp))
135                             (eqv? (eval right) (cdr exp)))
136                        (list 'quote exp)
137                        )
138                       (else
139                        (list 'quote (cons (eval left) (eval right)))
140                        )
141                       )
142                 )
143                ((null? right)
144                 (list 'list left)
145                 )
146                ((and (pair? right) (eq? (car right) 'list))
147                 (cons 'list (cons left (cdr right)))
148                 )
149                (else
150                 (list 'cons left right)
151                 )
152                )
153               )
154             )
155
156           (def! expand-quasiquote
157             (lambda (exp nesting)
158               (cond
159
160                                         ; non cons -- constants
161                                         ; themselves, others are
162                                         ; quoted
163
164                ((not (pair? exp)) 
165                 (cond ((constant? exp)
166                        exp
167                        )
168                       (else
169                        (list 'quote exp)
170                        )
171                       )
172                 )
173
174                                         ; check for an unquote exp and
175                                         ; add the param unquoted
176
177                ((and (eq? (car exp) 'unquote) (= (length exp) 2))
178                 (cond ((= nesting 0)
179                        (car (cdr exp))
180                        )
181                       (else
182                        (combine-skeletons ''unquote 
183                                           (expand-quasiquote (cdr exp) (- nesting 1))
184                                           exp))
185                       )
186                 )
187
188                                         ; nested quasi-quote --
189                                         ; construct the right
190                                         ; expression
191
192                ((and (eq? (car exp) 'quasiquote) (= (length exp) 2))
193                 (combine-skeletons ''quasiquote 
194                                    (expand-quasiquote (cdr exp) (+ nesting 1))
195                                    exp))
196
197                                         ; check for an
198                                         ; unquote-splicing member,
199                                         ; compute the expansion of the
200                                         ; value and append the rest of
201                                         ; the quasiquote result to it
202
203                ((and (pair? (car exp))
204                      (eq? (car (car exp)) 'unquote-splicing)
205                      (= (length (car exp)) 2))
206                 (cond ((= nesting 0)
207                        (list 'append (car (cdr (car exp)))
208                              (expand-quasiquote (cdr exp) nesting))
209                        )
210                       (else
211                        (combine-skeletons (expand-quasiquote (car exp) (- nesting 1))
212                                           (expand-quasiquote (cdr exp) nesting)
213                                           exp))
214                       )
215                 )
216
217                                         ; for other lists, just glue
218                                         ; the expansion of the first
219                                         ; element to the expansion of
220                                         ; the rest of the list
221
222                (else (combine-skeletons (expand-quasiquote (car exp) nesting)
223                                         (expand-quasiquote (cdr exp) nesting)
224                                         exp)
225                      )
226                )
227               )
228             )
229           (expand-quasiquote x 0)
230           )
231    )
232  'quasiquote)
233                                         ;
234                                         ; Define a variable without returning the value
235                                         ; Useful when defining functions to avoid
236                                         ; having lots of output generated.
237                                         ;
238                                         ; Also accepts the alternate
239                                         ; form for defining lambdas of
240                                         ; (define (name x y z) sexprs ...) 
241                                         ;
242
243 (def! define
244       (macro (first rest)
245                                         ; check for alternate lambda definition form
246
247              (cond ((list? first)
248                     (set! rest
249                           (append
250                            (list
251                             'lambda
252                             (cdr first))
253                            rest))
254                     (set! first (car first))
255                     )
256                    (else
257                     (set! rest (car rest))
258                     )
259                    )
260              `(begin
261                (def (quote ,first) ,rest)
262                (quote ,first))
263              )
264       )
265
266                                         ; basic list accessors
267
268 (define (caar l) (car (car l)))
269
270 (define (cadr l) (car (cdr l)))
271
272 (define (cdar l) (cdr (car l)))
273
274 (define (caddr l) (car (cdr (cdr l))))
275
276 (define (list-tail x k)
277   (if (zero? k)
278       x
279     (list-tail (cdr x (- k 1)))
280     )
281   )
282
283 (define (list-ref x k)
284   (car (list-tail x k))
285   )
286
287                                         ; (if <condition> <if-true>)
288                                         ; (if <condition> <if-true> <if-false)
289
290 (define if
291   (macro (test args)
292          (cond ((null? (cdr args))
293                 `(cond (,test ,(car args)))
294                 )
295                (else
296                 `(cond (,test ,(car args))
297                        (else ,(cadr args)))
298                 )
299                )
300          )
301   )
302
303 (if (> 3 2) 'yes)
304 (if (> 3 2) 'yes 'no)
305 (if (> 2 3) 'no 'yes)
306 (if (> 2 3) 'no)
307
308                                         ; simple math operators
309
310 (define zero? (macro (value rest) `(eq? ,value 0)))
311
312 (zero? 1)
313 (zero? 0)
314 (zero? "hello")
315
316 (define positive? (macro (value rest) `(> ,value 0)))
317
318 (positive? 12)
319 (positive? -12)
320
321 (define negative? (macro (value rest) `(< ,value 0)))
322
323 (negative? 12)
324 (negative? -12)
325
326 (define (abs x) (if (>= x 0) x (- x)))
327
328 (abs 12)
329 (abs -12)
330
331 (define max (lexpr (first rest)
332                    (while (not (null? rest))
333                      (cond ((< first (car rest))
334                             (set! first (car rest)))
335                            )
336                      (set! rest (cdr rest))
337                      )
338                    first)
339   )
340
341 (max 1 2 3)
342 (max 3 2 1)
343
344 (define min (lexpr (first rest)
345                    (while (not (null? rest))
346                      (cond ((> first (car rest))
347                             (set! first (car rest)))
348                            )
349                      (set! rest (cdr rest))
350                      )
351                    first)
352   )
353
354 (min 1 2 3)
355 (min 3 2 1)
356
357 (define (even? x) (zero? (% x 2)))
358
359 (even? 2)
360 (even? -2)
361 (even? 3)
362 (even? -1)
363
364 (define (odd? x) (not (even? x)))
365
366 (odd? 2)
367 (odd? -2)
368 (odd? 3)
369 (odd? -1)
370
371
372                                         ; define a set of local
373                                         ; variables all at once and
374                                         ; then evaluate a list of
375                                         ; sexprs
376                                         ;
377                                         ; (let (var-defines) sexprs)
378                                         ;
379                                         ; where var-defines are either
380                                         ;
381                                         ; (name value)
382                                         ;
383                                         ; or
384                                         ;
385                                         ; (name)
386                                         ;
387                                         ; e.g.
388                                         ;
389                                         ; (let ((x 1) (y)) (set! y (+ x 1)) y)
390
391 (define let
392   (macro (vars exprs)
393          (define (make-names vars)
394            (cond ((not (null? vars))
395                   (cons (car (car vars))
396                         (make-names (cdr vars))))
397                  (else ())
398                  )
399            )
400
401                                         ; the parameters to the lambda is a list
402                                         ; of nils of the right length
403
404          (define (make-vals vars)
405            (cond ((not (null? vars))
406                   (cons (cond ((null? (cdr (car vars))) ())
407                               (else
408                                (car (cdr (car vars))))
409                               )
410                         (make-vals (cdr vars))))
411                  (else ())
412                  )
413            )
414                                         ; prepend the set operations
415                                         ; to the expressions
416
417                                         ; build the lambda.
418
419          `((lambda ,(make-names vars) ,@exprs) ,@(make-vals vars))
420          )
421      )
422                    
423
424 (let ((x 1) (y)) (set! y 2) (+ x y))
425
426                                         ; define a set of local
427                                         ; variables one at a time and
428                                         ; then evaluate a list of
429                                         ; sexprs
430                                         ;
431                                         ; (let* (var-defines) sexprs)
432                                         ;
433                                         ; where var-defines are either
434                                         ;
435                                         ; (name value)
436                                         ;
437                                         ; or
438                                         ;
439                                         ; (name)
440                                         ;
441                                         ; e.g.
442                                         ;
443                                         ; (let* ((x 1) (y)) (set! y (+ x 1)) y)
444
445 (define let*
446   (macro (vars exprs)
447
448                                         ;
449                                         ; make the list of names in the let
450                                         ;
451
452          (define (make-names vars)
453            (cond ((not (null? vars))
454                   (cons (car (car vars))
455                         (make-names (cdr vars))))
456                  (else ())
457                  )
458            )
459
460                                         ; the set of expressions is
461                                         ; the list of set expressions
462                                         ; pre-pended to the
463                                         ; expressions to evaluate
464
465          (define (make-exprs vars exprs)
466            (cond ((null? vars) exprs)
467                  (else
468                   (cons
469                    (list set
470                          (list quote
471                                (car (car vars))
472                                )
473                          (cond ((null? (cdr (car vars))) ())
474                                (else (cadr (car vars))))
475                          )
476                    (make-exprs (cdr vars) exprs)
477                    )
478                   )
479                  )
480            )
481
482                                         ; the parameters to the lambda is a list
483                                         ; of nils of the right length
484
485          (define (make-nils vars)
486            (cond ((null? vars) ())
487                  (else (cons () (make-nils (cdr vars))))
488                  )
489            )
490                                         ; build the lambda.
491
492          `((lambda ,(make-names vars) ,@(make-exprs vars exprs)) ,@(make-nils vars))
493          )
494      )
495
496 (let* ((x 1) (y x)) (+ x y))
497
498 (define when (macro (test l) `(cond (,test ,@l))))
499
500 (when #t (write 'when))
501
502 (define unless (macro (test l) `(cond ((not ,test) ,@l))))
503
504 (unless #f (write 'unless))
505
506 (define (reverse list)
507   (let ((result ()))
508     (while (not (null? list))
509       (set! result (cons (car list) result))
510       (set! list (cdr list))
511       )
512     result)
513   )
514
515 (reverse '(1 2 3))
516
517 (define (list-tail x k)
518   (if (zero? k)
519       x
520     (list-tail (cdr x) (- k 1))))
521
522 (list-tail '(1 2 3) 2)
523
524 (define (list-ref x k) (car (list-tail x k)))
525
526 (list-ref '(1 2 3) 2)
527     
528                                         ; recursive equality
529
530 (define (equal? a b)
531   (cond ((eq? a b) #t)
532         ((and (pair? a) (pair? b))
533          (and (equal? (car a) (car b))
534               (equal? (cdr a) (cdr b)))
535          )
536         (else #f)
537         )
538   )
539
540 (equal? '(a b c) '(a b c))
541 (equal? '(a b c) '(a b b))
542
543 (define member (lexpr (obj list test?)
544                       (cond ((null? list)
545                              #f
546                              )
547                             (else
548                              (if (null? test?) (set! test? equal?) (set! test? (car test?)))
549                              (if (test? obj (car list))
550                                  list
551                                (member obj (cdr list) test?))
552                              )
553                             )
554                       )
555   )
556
557 (member '(2) '((1) (2) (3)))
558
559 (member '(4) '((1) (2) (3)))
560
561 (define (memq obj list) (member obj list eq?))
562
563 (memq 2 '(1 2 3))
564
565 (memq 4 '(1 2 3))
566
567 (memq '(2) '((1) (2) (3)))
568
569 (define (memv obj list) (member obj list eqv?))
570
571 (memv 2 '(1 2 3))
572
573 (memv 4 '(1 2 3))
574
575 (memv '(2) '((1) (2) (3)))
576
577 (define (_assoc obj list test?)
578   (if (null? list)
579       #f
580     (if (test? obj (caar list))
581         (car list)
582       (_assoc obj (cdr list) test?)
583       )
584     )
585   )
586
587 (define (assq obj list) (_assoc obj list eq?))
588 (define (assv obj list) (_assoc obj list eqv?))
589 (define (assoc obj list) (_assoc obj list equal?))
590
591 (assq 'a '((a 1) (b 2) (c 3)))
592 (assv 'b '((a 1) (b 2) (c 3)))
593 (assoc '(c) '((a 1) (b 2) ((c) 3)))
594
595 (define char? integer?)
596
597 (char? #\q)
598 (char? "h")
599
600 (define (char-upper-case? c) (<= #\A c #\Z))
601
602 (char-upper-case? #\a)
603 (char-upper-case? #\B)
604 (char-upper-case? #\0)
605 (char-upper-case? #\space)
606
607 (define (char-lower-case? c) (<= #\a c #\a))
608
609 (char-lower-case? #\a)
610 (char-lower-case? #\B)
611 (char-lower-case? #\0)
612 (char-lower-case? #\space)
613
614 (define (char-alphabetic? c) (or (char-upper-case? c) (char-lower-case? c)))
615
616 (char-alphabetic? #\a)
617 (char-alphabetic? #\B)
618 (char-alphabetic? #\0)
619 (char-alphabetic? #\space)
620
621 (define (char-numeric? c) (<= #\0 c #\9))
622
623 (char-numeric? #\a)
624 (char-numeric? #\B)
625 (char-numeric? #\0)
626 (char-numeric? #\space)
627
628 (define (char-whitespace? c) (or (<= #\tab c #\return) (= #\space c)))
629
630 (char-whitespace? #\a)
631 (char-whitespace? #\B)
632 (char-whitespace? #\0)
633 (char-whitespace? #\space)
634
635 (define (char->integer c) c)
636 (define (integer->char c) char-integer)
637
638 (define (char-upcase c) (if (char-lower-case? c) (+ c (- #\A #\a)) c))
639
640 (char-upcase #\a)
641 (char-upcase #\B)
642 (char-upcase #\0)
643 (char-upcase #\space)
644
645 (define (char-downcase c) (if (char-upper-case? c) (+ c (- #\a #\A)) c))
646
647 (char-downcase #\a)
648 (char-downcase #\B)
649 (char-downcase #\0)
650 (char-downcase #\space)
651
652 (define string (lexpr (chars) (list->string chars)))
653
654 (display "apply\n")
655 (apply cons '(a b))
656
657 (define map
658   (lexpr (proc lists)
659          (define (args lists)
660            (cond ((null? lists) ())
661                  (else
662                   (cons (caar lists) (args (cdr lists)))
663                   )
664                  )
665            )
666          (define (next lists)
667            (cond ((null? lists) ())
668                  (else
669                   (cons (cdr (car lists)) (next (cdr lists)))
670                   )
671                  )
672            )
673          (define (domap lists)
674            (cond ((null? (car lists)) ())
675                  (else
676                   (cons (apply proc (args lists)) (domap (next lists)))
677                   )
678                  )
679            )
680          (domap lists)
681          )
682   )
683
684 (map cadr '((a b) (d e) (g h)))
685
686 (define for-each (lexpr (proc lists)
687                         (apply map proc lists)
688                         #t))
689
690 (for-each display '("hello" " " "world" "\n"))
691
692 (define _string-ml (lambda (strings)
693                              (if (null? strings) ()
694                                (cons (string->list (car strings)) (_string-ml (cdr strings))))))
695
696 (define string-map (lexpr (proc strings)
697                           (list->string (apply map proc (_string-ml strings))))))
698
699 (string-map (lambda (x) (+ 1 x)) "HAL")
700
701 (define string-for-each (lexpr (proc strings)
702                                (apply for-each proc (_string-ml strings))))
703
704 (string-for-each write-char "IBM\n")
705
706 (define newline (lambda () (write-char #\newline)))
707
708 (newline)
709
710 (call-with-current-continuation
711  (lambda (exit)
712    (for-each (lambda (x)
713                (write "test" x)
714                (if (negative? x)
715                    (exit x)))
716              '(54 0 37 -3 245 19))
717    #t))
718
719
720                                         ; `q -> (quote q)
721                                         ; `(q) -> (append (quote (q)))
722                                         ; `(a ,(+ 1 2)) -> (append (quote (a)) (list (+ 1 2)))
723                                         ; `(a ,@(list 1 2 3) -> (append (quote (a)) (list 1 2 3))
724
725
726
727 `(hello ,(+ 1 2) ,@(list 1 2 3) `foo)
728
729 (define repeat (macro (count rest)
730                        `(let ((__count__ ,count))
731                           (while (<= 0 (set! __count__ (- __count__ 1))) ,@rest))))
732
733 (repeat 2 (write 'hello))
734 (repeat 3 (write 'goodbye))
735
736 (define case (macro (test l)
737                     (let* ((_unarrow
738                                         ; construct the body of the
739                                         ; case, dealing with the
740                                         ; lambda version ( => lambda)
741                             
742                             (lambda (l)
743                               (cond ((null? l) l)
744                                     ((eq? (car l) '=>) `(( ,(cadr l) __key__)))
745                                     (else l))))
746                            (_case (lambda (l)
747
748                                         ; Build the case elements, which is
749                                         ; simply a list of cond clauses
750
751                                     (cond ((null? l) ())
752
753                                         ; else case
754
755                                           ((eq? (caar l) 'else)
756                                            `((else ,@(_unarrow (cdr (car l))))))
757
758                                         ; regular case
759                                           
760                                           (else
761                                            (cons
762                                             `((eqv? ,(caar l) __key__)
763                                               ,@(_unarrow (cdr (car l))))
764                                             (_case (cdr l)))
765                                            )
766                                           ))))
767
768                                         ; now construct the overall
769                                         ; expression, using a lambda
770                                         ; to hold the computed value
771                                         ; of the test expression
772
773                       `((lambda (__key__)
774                           (cond ,@(_case l))) ,test))))
775
776 (case 12 (1 "one") (2 "two") (3 => (lambda (x) (write "the value is" x))) (12 "twelve") (else "else"))
777
778 ;(define number->string (lexpr (arg opt)
779 ;                             (let ((base (if (null? opt) 10 (car opt)))
780                                         ;
781 ;
782