altos/lisp: Fix some scheme compat issues
[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
18 (set (quote list) (lexpr (l) l))
19
20                                         ;
21                                         ; Define a variable without returning the value
22                                         ; Useful when defining functions to avoid
23                                         ; having lots of output generated
24                                         ;
25
26 (set (quote define) (macro (name val rest)
27                         (list
28                          'progn
29                          (list
30                           'set
31                           (list 'quote name)
32                           val)
33                          (list 'quote name)
34                          )
35                         )
36      )
37
38                                         ;
39                                         ; A slightly more convenient form
40                                         ; for defining lambdas.
41                                         ;
42                                         ; (defun <name> (<params>) s-exprs)
43                                         ;
44
45 (define defun (macro (name args exprs)
46                   (list
47                    define
48                    name
49                    (cons 'lambda (cons args exprs))
50                    )
51                   )
52      )
53
54                                         ; basic list accessors
55
56
57 (defun caar (l) (car (car l)))
58
59 (defun cadr (l) (car (cdr l)))
60
61 (defun caddr (l) (car (cdr (cdr l))))
62
63 (define list-tail (lambda (x k)
64                     (if (zero? k)
65                         x
66                       (list-tail (cdr x (- k 1)))
67                       )
68                     )
69   )
70
71 (define list-ref (lambda (x k)
72                    (car (list-tail x k))
73                    )
74   )
75
76                                         ; simple math operators
77
78 (defun 1+ (x) (+ x 1))
79 (defun 1- (x) (- x 1))
80
81 (define zero? (macro (value rest)
82                      (list
83                       eq?
84                       value
85                       0)
86                      )
87   )
88
89 (zero? 1)
90 (zero? 0)
91 (zero? "hello")
92
93 (define positive? (macro (value rest)
94                          (list
95                           >
96                           value
97                           0)
98                          )
99   )
100
101 (positive? 12)
102 (positive? -12)
103
104 (define negative? (macro (value rest)
105                          (list
106                           <
107                           value
108                           0)
109                          )
110   )
111
112 (negative? 12)
113 (negative? -12)
114
115 (defun abs (x) (cond ((>= x 0) x)
116                      (else (- x)))
117        )
118
119 (abs 12)
120 (abs -12)
121
122 (define max (lexpr (first rest)
123                    (while (not (null? rest))
124                      (cond ((< first (car rest))
125                             (set! first (car rest)))
126                            )
127                      (set! rest (cdr rest))
128                      )
129                    first)
130   )
131
132 (max 1 2 3)
133 (max 3 2 1)
134
135 (define min (lexpr (first rest)
136                    (while (not (null? rest))
137                      (cond ((> first (car rest))
138                             (set! first (car rest)))
139                            )
140                      (set! rest (cdr rest))
141                      )
142                    first)
143   )
144
145 (min 1 2 3)
146 (min 3 2 1)
147
148 (defun even? (x) (zero? (% x 2)))
149
150 (even? 2)
151 (even? -2)
152 (even? 3)
153 (even? -1)
154
155 (defun odd? (x) (not (even? x)))
156
157 (odd? 2)
158 (odd? -2)
159 (odd? 3)
160 (odd? -1)
161
162 (define exact? number?)
163 (defun inexact? (x) #f)
164
165                                         ; (if <condition> <if-true>)
166                                         ; (if <condition> <if-true> <if-false)
167
168 (define if (macro (test args)
169                (cond ((null? (cdr args))
170                       (list
171                        cond
172                        (list test (car args)))
173                       )
174                      (else
175                       (list
176                        cond
177                        (list test (car args))
178                        (list 'else (cadr args))
179                        )
180                       )
181                      )
182                )
183      )
184
185 (if (> 3 2) 'yes)
186 (if (> 3 2) 'yes 'no)
187 (if (> 2 3) 'no 'yes)
188 (if (> 2 3) 'no)
189
190                                         ; define a set of local
191                                         ; variables and then evaluate
192                                         ; a list of sexprs
193                                         ;
194                                         ; (let (var-defines) sexprs)
195                                         ;
196                                         ; where var-defines are either
197                                         ;
198                                         ; (name value)
199                                         ;
200                                         ; or
201                                         ;
202                                         ; (name)
203                                         ;
204                                         ; e.g.
205                                         ;
206                                         ; (let ((x 1) (y)) (set! y (+ x 1)) y)
207
208 (define let (macro (vars exprs)
209                 ((lambda (make-names make-exprs make-nils)
210
211                                         ;
212                                         ; make the list of names in the let
213                                         ;
214
215                    (set! make-names (lambda (vars)
216                                       (cond ((not (null? vars))
217                                              (cons (car (car vars))
218                                                    (make-names (cdr vars))))
219                                             )
220                                       )
221                          )
222
223                                         ; the set of expressions is
224                                         ; the list of set expressions
225                                         ; pre-pended to the
226                                         ; expressions to evaluate
227
228                    (set! make-exprs (lambda (vars exprs)
229                                       (cond ((not (null? vars))
230                                              (cons
231                                               (list set
232                                                     (list quote
233                                                           (car (car vars))
234                                                           )
235                                                     (cond ((null? (cdr (car vars))) ())
236                                                           (else (cadr (car vars))))
237                                                     )
238                                               (make-exprs (cdr vars) exprs)
239                                               )
240                                              )
241                                             (exprs)
242                                             )
243                                       )
244                          )
245
246                                         ; the parameters to the lambda is a list
247                                         ; of nils of the right length
248
249                    (set! make-nils (lambda (vars)
250                                      (cond ((not (null? vars)) (cons () (make-nils (cdr vars))))
251                                            )
252                                      )
253                          )
254                                         ; prepend the set operations
255                                         ; to the expressions
256
257                    (set! exprs (make-exprs vars exprs))
258
259                                         ; build the lambda.
260
261                    (cons (cons 'lambda (cons (make-names vars) exprs))
262                          (make-nils vars)
263                          )
264                    )
265                  ()
266                  ()
267                  ()
268                  )
269                 )
270      )
271
272 (let ((x 1)) x)
273
274 (define let* let)
275                                         ; boolean operators
276
277 (define or (lexpr (l)
278                (let ((ret #f))
279                  (while (not (null? l))
280                    (cond ((car l) (set! ret #t) (set! l ()))
281                          ((set! l (cdr l)))))
282                  ret
283                  )
284                )
285      )
286
287                                         ; execute to resolve macros
288
289 (or #f #t)
290
291 (define and (lexpr (l)
292                (let ((ret #t))
293                  (while (not (null? l))
294                    (cond ((car l)
295                           (set! l (cdr l)))
296                          (#t
297                           (set! ret #f)
298                           (set! l ()))
299                          )
300                    )
301                  ret
302                  )
303                )
304      )
305
306                                         ; execute to resolve macros
307
308 (and #t #f)
309
310
311 (define append (lexpr (args)
312                       (let ((append-list (lambda (a b)
313                                            (cond ((null? a) b)
314                                                  (else (cons (car a) (append-list (cdr a) b)))
315                                                  )
316                                            )
317                                          )
318                             (append-lists (lambda (lists)
319                                             (cond ((null? lists) lists)
320                                                   ((null? (cdr lists)) (car lists))
321                                                   (else (append-list (car lists) (append-lists (cdr lists))))
322                                                   )
323                                             )
324                                           )
325                             )
326                         (append-lists args)
327                         )
328                       )
329   )
330
331 (append '(a b c) '(d e f) '(g h i))
332
333 (defun reverse (list)
334   (let ((result ()))
335     (while (not (null? list))
336       (set! result (cons (car list) result))
337       (set! list (cdr list))
338       )
339     result)
340   )
341
342 (reverse '(1 2 3))
343
344 (define list-tail
345   (lambda (x k)
346     (if (zero? k)
347         x
348       (list-tail (cdr x) (- k 1)))))
349
350 (list-tail '(1 2 3) 2)
351
352 (defun list-ref (x k) (car (list-tail x k)))
353
354 (list-ref '(1 2 3) 2)
355
356     
357                                         ; recursive equality
358
359 (defun equal? (a b)
360   (cond ((eq? a b) #t)
361         ((and (pair? a) (pair? b))
362          (and (equal? (car a) (car b))
363               (equal? (cdr a) (cdr b)))
364          )
365         (else #f)
366         )
367   )
368
369 (equal? '(a b c) '(a b c))
370 (equal? '(a b c) '(a b b))
371
372 (defun _member (obj list test?)
373   (if (null? list)
374       #f
375     (if (test? obj (car list))
376         list
377       (memq obj (cdr list)))))
378
379 (defun memq (obj list) (_member obj list eq?))
380
381 (memq 2 '(1 2 3))
382
383 (memq 4 '(1 2 3))
384
385 (defun memv (obj list) (_member obj list eqv?))
386
387 (memv 2 '(1 2 3))
388
389 (memv 4 '(1 2 3))
390
391 (defun member (obj list) (_member obj list equal?))
392
393 (member '(2) '((1) (2) (3)))
394
395 (member '(4) '((1) (2) (3)))
396
397 (defun _assoc (obj list test?)
398   (if (null? list)
399       #f
400     (if (test? obj (caar list))
401         (car list)
402       (_assoc obj (cdr list) test?)
403       )
404     )
405   )
406
407 (defun assq (obj list) (_assoc obj list eq?))
408 (defun assv (obj list) (_assoc obj list eqv?))
409 (defun assoc (obj list) (_assoc obj list equal?))
410
411 (assq 'a '((a 1) (b 2) (c 3)))
412 (assv 'b '((a 1) (b 2) (c 3)))
413 (assoc '(c) '((a 1) (b 2) ((c) 3)))
414
415 (define char? integer?)
416
417 (char? #\q)
418 (char? "h")
419
420 (defun char-upper-case? (c) (<= #\A c #\Z))
421
422 (char-upper-case? #\a)
423 (char-upper-case? #\B)
424 (char-upper-case? #\0)
425 (char-upper-case? #\space)
426
427 (defun char-lower-case? (c) (<= #\a c #\a))
428
429 (char-lower-case? #\a)
430 (char-lower-case? #\B)
431 (char-lower-case? #\0)
432 (char-lower-case? #\space)
433
434 (defun char-alphabetic? (c) (or (char-upper-case? c) (char-lower-case? c)))
435
436 (char-alphabetic? #\a)
437 (char-alphabetic? #\B)
438 (char-alphabetic? #\0)
439 (char-alphabetic? #\space)
440
441 (defun char-numeric? (c) (<= #\0 c #\9))
442
443 (char-numeric? #\a)
444 (char-numeric? #\B)
445 (char-numeric? #\0)
446 (char-numeric? #\space)
447
448 (defun char-whitespace? (c) (or (<= #\tab c #\return) (= #\space c)))
449
450 (char-whitespace? #\a)
451 (char-whitespace? #\B)
452 (char-whitespace? #\0)
453 (char-whitespace? #\space)
454
455 (defun char->integer (c) c)
456 (defun integer->char (c) char-integer)
457
458 (defun char-upcase (c) (if (char-lower-case? c) (+ c (- #\A #\a)) c))
459
460 (char-upcase #\a)
461 (char-upcase #\B)
462 (char-upcase #\0)
463 (char-upcase #\space)
464
465 (defun char-downcase (c) (if (char-upper-case? c) (+ c (- #\a #\A)) c))
466
467 (char-downcase #\a)
468 (char-downcase #\B)
469 (char-downcase #\0)
470 (char-downcase #\space)
471
472 (define string (lexpr (chars) (list->string chars)))
473
474 (display "apply\n")
475 (apply cons '(a b))
476
477 (define map (lexpr (proc lists)
478                    (let ((args (lambda (lists)
479                                  (if (null? lists) ()
480                                    (cons (caar lists) (args (cdr lists))))))
481                          (next (lambda (lists)
482                                  (if (null? lists) ()
483                                    (cons (cdr (car lists)) (next (cdr lists))))))
484                          (domap (lambda (lists)
485                                   (if (null? (car lists)) ()
486                                     (cons (apply proc (args lists)) (domap (next lists)))
487                                         )))
488                          )
489                      (domap lists))))
490
491 (map cadr '((a b) (d e) (g h)))
492
493 (define for-each (lexpr (proc lists)
494                         (apply map proc lists)
495                         #t))
496
497 (for-each display '("hello" " " "world" "\n"))
498
499 (define -string-ml (lambda (strings)
500                              (if (null? strings) ()
501                                (cons (string->list (car strings)) (-string-ml (cdr strings))))))
502
503 (define string-map (lexpr (proc strings)
504                           (list->string (apply map proc (-string-ml strings))))))
505
506 (string-map 1+ "HAL")
507
508 (define string-for-each (lexpr (proc strings)
509                                (apply for-each proc (-string-ml strings))))
510
511 (string-for-each write-char "IBM\n")
512
513 (define newline (lambda () (write-char #\newline)))
514
515 (newline)
516
517 (call-with-current-continuation
518  (lambda (exit)
519    (for-each (lambda (x)
520                (write "test" x)
521                (if (negative? x)
522                    (exit x)))
523              '(54 0 37 -3 245 19))
524    #t))
525
526 ;(define number->string (lexpr (arg opt)
527 ;                             (let ((base (if (null? opt) 10 (car opt)))
528                                         ;
529 ;
530