altos/lisp: Lots more scheme bits
[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 cadr (l) (car (cdr l)))
58
59 (defun caddr (l) (car (cdr (cdr l))))
60
61 (defun nth (list n)
62   (cond ((= n 0) (car list))
63         ((nth (cdr list) (1- n)))
64         )
65   )
66
67                                         ; simple math operators
68
69 (defun 1+ (x) (+ x 1))
70 (defun 1- (x) (- x 1))
71
72 (define zero? (macro (value rest)
73                      (list
74                       eq?
75                       value
76                       0)
77                      )
78   )
79
80 (zero? 1)
81 (zero? 0)
82 (zero? "hello")
83
84 (define positive? (macro (value rest)
85                          (list
86                           >
87                           value
88                           0)
89                          )
90   )
91
92 (positive? 12)
93 (positive? -12)
94
95 (define negative? (macro (value rest)
96                          (list
97                           <
98                           value
99                           0)
100                          )
101   )
102
103 (negative? 12)
104 (negative? -12)
105
106 (defun abs (x) (cond ((>= x 0) x)
107                      (else (- x)))
108        )
109
110 (abs 12)
111 (abs -12)
112
113 (define max (lexpr (first rest)
114                    (while (not (null? rest))
115                      (cond ((< first (car rest))
116                             (set! first (car rest)))
117                            )
118                      (set! rest (cdr rest))
119                      )
120                    first)
121   )
122
123 (max 1 2 3)
124 (max 3 2 1)
125
126 (define min (lexpr (first rest)
127                    (while (not (null? rest))
128                      (cond ((> first (car rest))
129                             (set! first (car rest)))
130                            )
131                      (set! rest (cdr rest))
132                      )
133                    first)
134   )
135
136 (min 1 2 3)
137 (min 3 2 1)
138
139 (defun even? (x) (zero? (% x 2)))
140
141 (even? 2)
142 (even? -2)
143 (even? 3)
144 (even? -1)
145
146 (defun odd? (x) (not (even? x)))
147
148 (odd? 2)
149 (odd? -2)
150 (odd? 3)
151 (odd? -1)
152
153 (define exact? number?)
154 (defun inexact? (x) #f)
155
156                                         ; (if <condition> <if-true>)
157                                         ; (if <condition> <if-true> <if-false)
158
159 (define if (macro (test args)
160                (cond ((null? (cdr args))
161                       (list
162                        cond
163                        (list test (car args)))
164                       )
165                      (else
166                       (list
167                        cond
168                        (list test (car args))
169                        (list 'else (cadr args))
170                        )
171                       )
172                      )
173                )
174      )
175
176 (if (> 3 2) 'yes)
177 (if (> 3 2) 'yes 'no)
178 (if (> 2 3) 'no 'yes)
179 (if (> 2 3) 'no)
180
181                                         ; define a set of local
182                                         ; variables and then evaluate
183                                         ; a list of sexprs
184                                         ;
185                                         ; (let (var-defines) sexprs)
186                                         ;
187                                         ; where var-defines are either
188                                         ;
189                                         ; (name value)
190                                         ;
191                                         ; or
192                                         ;
193                                         ; (name)
194                                         ;
195                                         ; e.g.
196                                         ;
197                                         ; (let ((x 1) (y)) (set! y (+ x 1)) y)
198
199 (define let (macro (vars exprs)
200                 ((lambda (make-names make-exprs make-nils)
201
202                                         ;
203                                         ; make the list of names in the let
204                                         ;
205
206                    (set! make-names (lambda (vars)
207                                       (cond ((not (null? vars))
208                                              (cons (car (car vars))
209                                                    (make-names (cdr vars))))
210                                             )
211                                       )
212                          )
213
214                                         ; the set of expressions is
215                                         ; the list of set expressions
216                                         ; pre-pended to the
217                                         ; expressions to evaluate
218
219                    (set! make-exprs (lambda (vars exprs)
220                                       (cond ((not (null? vars)) (cons
221                                                    (list set
222                                                          (list quote
223                                                                (car (car vars))
224                                                                )
225                                                          (cadr (car vars))
226                                                          )
227                                                    (make-exprs (cdr vars) exprs)
228                                                    )
229                                                   )
230                                             (exprs)
231                                             )
232                                       )
233                          )
234
235                                         ; the parameters to the lambda is a list
236                                         ; of nils of the right length
237
238                    (set! make-nils (lambda (vars)
239                                      (cond ((not (null? vars)) (cons () (make-nils (cdr vars))))
240                                            )
241                                      )
242                          )
243                                         ; prepend the set operations
244                                         ; to the expressions
245
246                    (set! exprs (make-exprs vars exprs))
247
248                                         ; build the lambda.
249
250                    (cons (cons 'lambda (cons (make-names vars) exprs))
251                          (make-nils vars)
252                          )
253                    )
254                  ()
255                  ()
256                  ()
257                  )
258                 )
259      )
260
261 (let ((x 1)) x)
262
263                                         ; boolean operators
264
265 (define or (lexpr (l)
266                (let ((ret #f))
267                  (while (not (null? l))
268                    (cond ((car l) (set! ret #t) (set! l ()))
269                          ((set! l (cdr l)))))
270                  ret
271                  )
272                )
273      )
274
275                                         ; execute to resolve macros
276
277 (or #f #t)
278
279 (define and (lexpr (l)
280                (let ((ret #t))
281                  (while (not (null? l))
282                    (cond ((car l)
283                           (set! l (cdr l)))
284                          (#t
285                           (set! ret #f)
286                           (set! l ()))
287                          )
288                    )
289                  ret
290                  )
291                )
292      )
293
294                                         ; execute to resolve macros
295
296 (and #t #f)
297
298
299 (define append (lexpr (args)
300                       (let ((append-list (lambda (a b)
301                                            (cond ((null? a) b)
302                                                  (else (cons (car a) (append-list (cdr a) b)))
303                                                  )
304                                            )
305                                          )
306                             (append-lists (lambda (lists)
307                                             (cond ((null? lists) lists)
308                                                   ((null? (cdr lists)) (car lists))
309                                                   (else (append-list (car lists) (append-lists (cdr lists))))
310                                                   )
311                                             )
312                                           )
313                             )
314                         (append-lists args)
315                         )
316                       )
317   )
318
319 (append '(a b c) '(d e f) '(g h i))
320
321 (defun reverse (list)
322   (let ((result ()))
323     (while (not (null? list))
324       (set! result (cons (car list) result))
325       (set! list (cdr list))
326       )
327     result)
328   )
329
330 (reverse '(1 2 3))
331
332 (define list-tail
333   (lambda (x k)
334     (if (zero? k)
335         x
336       (list-tail (cdr x) (- k 1)))))
337
338 (list-tail '(1 2 3) 2)
339                                         ; recursive equality
340
341 (defun equal? (a b)
342   (cond ((eq? a b) #t)
343         ((and (pair? a) (pair? b))
344          (and (equal? (car a) (car b))
345               (equal? (cdr a) (cdr b)))
346          )
347         (else #f)
348         )
349   )
350
351 (equal? '(a b c) '(a b c))
352 (equal? '(a b c) '(a b b))
353
354 ;(define number->string (lexpr (arg opt)
355 ;                             (let ((base (if (null? opt) 10 (car opt)))
356                                         ;
357 ;
358