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