altos/lisp: Rename progn to begin
[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                          'begin
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                                         ; (if <condition> <if-true>)
163                                         ; (if <condition> <if-true> <if-false)
164
165 (define if (macro (test args)
166                (cond ((null? (cdr args))
167                       (list
168                        cond
169                        (list test (car args)))
170                       )
171                      (else
172                       (list
173                        cond
174                        (list test (car args))
175                        (list 'else (cadr args))
176                        )
177                       )
178                      )
179                )
180      )
181
182 (if (> 3 2) 'yes)
183 (if (> 3 2) 'yes 'no)
184 (if (> 2 3) 'no 'yes)
185 (if (> 2 3) 'no)
186
187                                         ; define a set of local
188                                         ; variables and then evaluate
189                                         ; a list of sexprs
190                                         ;
191                                         ; (let (var-defines) sexprs)
192                                         ;
193                                         ; where var-defines are either
194                                         ;
195                                         ; (name value)
196                                         ;
197                                         ; or
198                                         ;
199                                         ; (name)
200                                         ;
201                                         ; e.g.
202                                         ;
203                                         ; (let ((x 1) (y)) (set! y (+ x 1)) y)
204
205 (define let (macro (vars exprs)
206                 ((lambda (make-names make-exprs make-nils)
207
208                                         ;
209                                         ; make the list of names in the let
210                                         ;
211
212                    (set! make-names (lambda (vars)
213                                       (cond ((not (null? vars))
214                                              (cons (car (car vars))
215                                                    (make-names (cdr vars))))
216                                             )
217                                       )
218                          )
219
220                                         ; the set of expressions is
221                                         ; the list of set expressions
222                                         ; pre-pended to the
223                                         ; expressions to evaluate
224
225                    (set! make-exprs (lambda (vars exprs)
226                                       (cond ((not (null? vars))
227                                              (cons
228                                               (list set
229                                                     (list quote
230                                                           (car (car vars))
231                                                           )
232                                                     (cond ((null? (cdr (car vars))) ())
233                                                           (else (cadr (car vars))))
234                                                     )
235                                               (make-exprs (cdr vars) exprs)
236                                               )
237                                              )
238                                             (exprs)
239                                             )
240                                       )
241                          )
242
243                                         ; the parameters to the lambda is a list
244                                         ; of nils of the right length
245
246                    (set! make-nils (lambda (vars)
247                                      (cond ((not (null? vars)) (cons () (make-nils (cdr vars))))
248                                            )
249                                      )
250                          )
251                                         ; prepend the set operations
252                                         ; to the expressions
253
254                    (set! exprs (make-exprs vars exprs))
255
256                                         ; build the lambda.
257
258                    (cons (cons 'lambda (cons (make-names vars) exprs))
259                          (make-nils vars)
260                          )
261                    )
262                  ()
263                  ()
264                  ()
265                  )
266                 )
267      )
268
269 (let ((x 1)) x)
270
271 (define let* let)
272                                         ; boolean operators
273
274 (define or (lexpr (l)
275                (let ((ret #f))
276                  (while (not (null? l))
277                    (cond ((car l) (set! ret #t) (set! l ()))
278                          ((set! l (cdr l)))))
279                  ret
280                  )
281                )
282      )
283
284                                         ; execute to resolve macros
285
286 (or #f #t)
287
288 (define and (lexpr (l)
289                (let ((ret #t))
290                  (while (not (null? l))
291                    (cond ((car l)
292                           (set! l (cdr l)))
293                          (#t
294                           (set! ret #f)
295                           (set! l ()))
296                          )
297                    )
298                  ret
299                  )
300                )
301      )
302
303                                         ; execute to resolve macros
304
305 (and #t #f)
306
307
308 (define append (lexpr (args)
309                       (let ((append-list (lambda (a b)
310                                            (cond ((null? a) b)
311                                                  (else (cons (car a) (append-list (cdr a) b)))
312                                                  )
313                                            )
314                                          )
315                             (append-lists (lambda (lists)
316                                             (cond ((null? lists) lists)
317                                                   ((null? (cdr lists)) (car lists))
318                                                   (else (append-list (car lists) (append-lists (cdr lists))))
319                                                   )
320                                             )
321                                           )
322                             )
323                         (append-lists args)
324                         )
325                       )
326   )
327
328 (append '(a b c) '(d e f) '(g h i))
329
330 (defun reverse (list)
331   (let ((result ()))
332     (while (not (null? list))
333       (set! result (cons (car list) result))
334       (set! list (cdr list))
335       )
336     result)
337   )
338
339 (reverse '(1 2 3))
340
341 (define list-tail
342   (lambda (x k)
343     (if (zero? k)
344         x
345       (list-tail (cdr x) (- k 1)))))
346
347 (list-tail '(1 2 3) 2)
348
349 (defun list-ref (x k) (car (list-tail x k)))
350
351 (list-ref '(1 2 3) 2)
352
353     
354                                         ; recursive equality
355
356 (defun equal? (a b)
357   (cond ((eq? a b) #t)
358         ((and (pair? a) (pair? b))
359          (and (equal? (car a) (car b))
360               (equal? (cdr a) (cdr b)))
361          )
362         (else #f)
363         )
364   )
365
366 (equal? '(a b c) '(a b c))
367 (equal? '(a b c) '(a b b))
368
369 (defun _member (obj list test?)
370   (if (null? list)
371       #f
372     (if (test? obj (car list))
373         list
374       (memq obj (cdr list)))))
375
376 (defun memq (obj list) (_member obj list eq?))
377
378 (memq 2 '(1 2 3))
379
380 (memq 4 '(1 2 3))
381
382 (defun memv (obj list) (_member obj list eqv?))
383
384 (memv 2 '(1 2 3))
385
386 (memv 4 '(1 2 3))
387
388 (defun member (obj list) (_member obj list equal?))
389
390 (member '(2) '((1) (2) (3)))
391
392 (member '(4) '((1) (2) (3)))
393
394 (defun _assoc (obj list test?)
395   (if (null? list)
396       #f
397     (if (test? obj (caar list))
398         (car list)
399       (_assoc obj (cdr list) test?)
400       )
401     )
402   )
403
404 (defun assq (obj list) (_assoc obj list eq?))
405 (defun assv (obj list) (_assoc obj list eqv?))
406 (defun assoc (obj list) (_assoc obj list equal?))
407
408 (assq 'a '((a 1) (b 2) (c 3)))
409 (assv 'b '((a 1) (b 2) (c 3)))
410 (assoc '(c) '((a 1) (b 2) ((c) 3)))
411
412 (define char? integer?)
413
414 (char? #\q)
415 (char? "h")
416
417 (defun char-upper-case? (c) (<= #\A c #\Z))
418
419 (char-upper-case? #\a)
420 (char-upper-case? #\B)
421 (char-upper-case? #\0)
422 (char-upper-case? #\space)
423
424 (defun char-lower-case? (c) (<= #\a c #\a))
425
426 (char-lower-case? #\a)
427 (char-lower-case? #\B)
428 (char-lower-case? #\0)
429 (char-lower-case? #\space)
430
431 (defun char-alphabetic? (c) (or (char-upper-case? c) (char-lower-case? c)))
432
433 (char-alphabetic? #\a)
434 (char-alphabetic? #\B)
435 (char-alphabetic? #\0)
436 (char-alphabetic? #\space)
437
438 (defun char-numeric? (c) (<= #\0 c #\9))
439
440 (char-numeric? #\a)
441 (char-numeric? #\B)
442 (char-numeric? #\0)
443 (char-numeric? #\space)
444
445 (defun char-whitespace? (c) (or (<= #\tab c #\return) (= #\space c)))
446
447 (char-whitespace? #\a)
448 (char-whitespace? #\B)
449 (char-whitespace? #\0)
450 (char-whitespace? #\space)
451
452 (defun char->integer (c) c)
453 (defun integer->char (c) char-integer)
454
455 (defun char-upcase (c) (if (char-lower-case? c) (+ c (- #\A #\a)) c))
456
457 (char-upcase #\a)
458 (char-upcase #\B)
459 (char-upcase #\0)
460 (char-upcase #\space)
461
462 (defun char-downcase (c) (if (char-upper-case? c) (+ c (- #\a #\A)) c))
463
464 (char-downcase #\a)
465 (char-downcase #\B)
466 (char-downcase #\0)
467 (char-downcase #\space)
468
469 (define string (lexpr (chars) (list->string chars)))
470
471 (display "apply\n")
472 (apply cons '(a b))
473
474 (define map (lexpr (proc lists)
475                    (let ((args (lambda (lists)
476                                  (if (null? lists) ()
477                                    (cons (caar lists) (args (cdr lists))))))
478                          (next (lambda (lists)
479                                  (if (null? lists) ()
480                                    (cons (cdr (car lists)) (next (cdr lists))))))
481                          (domap (lambda (lists)
482                                   (if (null? (car lists)) ()
483                                     (cons (apply proc (args lists)) (domap (next lists)))
484                                         )))
485                          )
486                      (domap lists))))
487
488 (map cadr '((a b) (d e) (g h)))
489
490 (define for-each (lexpr (proc lists)
491                         (apply map proc lists)
492                         #t))
493
494 (for-each display '("hello" " " "world" "\n"))
495
496 (define -string-ml (lambda (strings)
497                              (if (null? strings) ()
498                                (cons (string->list (car strings)) (-string-ml (cdr strings))))))
499
500 (define string-map (lexpr (proc strings)
501                           (list->string (apply map proc (-string-ml strings))))))
502
503 (string-map 1+ "HAL")
504
505 (define string-for-each (lexpr (proc strings)
506                                (apply for-each proc (-string-ml strings))))
507
508 (string-for-each write-char "IBM\n")
509
510 (define newline (lambda () (write-char #\newline)))
511
512 (newline)
513
514 (call-with-current-continuation
515  (lambda (exit)
516    (for-each (lambda (x)
517                (write "test" x)
518                (if (negative? x)
519                    (exit x)))
520              '(54 0 37 -3 245 19))
521    #t))
522
523 (define repeat (macro (count rest)
524                         (list
525                          let
526                          (list
527                           (list '__count__ count))
528                          (append
529                           (list
530                            while
531                            (list
532                             <=
533                             0
534                             (list
535                              set!
536                              '__count__
537                              (list
538                               -
539                               '__count__
540                               1))))
541                           rest))))
542
543 ;(define number->string (lexpr (arg opt)
544 ;                             (let ((base (if (null? opt) 10 (car opt)))
545                                         ;
546 ;
547