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