altos/scheme: Add ports. Split scheme code up.
[fw/altos] / src / scheme / ao_scheme_basic_syntax.scheme
1 ;
2 ; Copyright © 2018 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 ; Basic syntax placed in ROM
15
16 (def (quote _?_) (lambda (a b) (cond ((eq? a b) a) (else (exit 1)))))
17
18 (def (quote list) (lambda l l))
19
20 (def (quote def!)
21      (macro (a b)
22             (list
23              def
24              (list quote a)
25              b)
26             )
27      )
28
29 (begin
30  (def! append
31    (lambda args
32           (def! _a
33             (lambda (a b)
34               (cond ((null? a) b)
35                     (else (cons (car a) (_a (cdr a) b)))
36                     )
37               )
38             )
39             
40           (def! _b
41             (lambda (l)
42               (cond ((null? l) l)
43                     ((null? (cdr l)) (car l))
44                     (else (_a (car l) (_b (cdr l))))
45                     )
46               )
47             )
48           (_b args)
49           )
50    )
51  'append)
52
53 (append '(a) '(b))
54
55
56                                         ;
57                                         ; Define a variable without returning the value
58                                         ; Useful when defining functions to avoid
59                                         ; having lots of output generated.
60                                         ;
61                                         ; Also accepts the alternate
62                                         ; form for defining lambdas of
63                                         ; (define (name x y z) sexprs ...) 
64                                         ;
65
66 (begin
67  (def! define
68    (macro (a . b)
69                                         ; check for alternate lambda definition form
70
71           (cond ((pair? a)
72                  (set! b
73                        (cons
74                         lambda
75                         (cons (cdr a) b)))
76                  (set! a (car a))
77                  )
78                 (else
79                  (set! b (car b))
80                  )
81                 )
82           (cons begin
83                 (cons
84                  (cons def
85                        (cons (cons quote (cons a '()))
86                              (cons b '())
87                              )
88                        )
89                  (cons
90                   (cons quote (cons a '()))
91                   '())
92                  )
93                 )
94           )
95    )
96  'define
97  )
98                                         ; boolean operators
99
100 (define or
101   (macro a
102     (def! b
103       (lambda (a)
104         (cond ((null? a) #f)
105               ((null? (cdr a))
106                (car a))
107               (else
108                (list
109                 cond
110                 (list
111                  (car a))
112                 (list
113                  'else
114                  (b (cdr a))
115                  )
116                 )
117                )
118               )
119         )
120       )
121     (b a)))
122
123                                         ; execute to resolve macros
124
125 (_?_ (or #f #t) #t)
126
127 (define and
128   (macro a
129     (def! b
130       (lambda (a)
131         (cond ((null? a) #t)
132               ((null? (cdr a))
133                (car a))
134               (else
135                (list
136                 cond
137                 (list
138                  (car a)
139                  (b (cdr a))
140                  )
141                 )
142                )
143               )
144         )
145       )
146     (b a)
147     )
148   )
149
150                                         ; execute to resolve macros
151
152 (_?_ (and #t #f) #f)
153
154                                         ; (if <condition> <if-true>)
155                                         ; (if <condition> <if-true> <if-false)
156
157 (define if
158   (macro (a . b)
159     (cond ((null? (cdr b))
160            (list cond (list a (car b)))
161                 )
162           (else
163            (list cond
164                  (list a (car b))
165                  (list 'else (car (cdr b)))
166                  )
167            )
168           )
169     )
170   )
171
172 (_?_ (if (> 3 2) 'yes) 'yes)
173 (_?_ (if (> 3 2) 'yes 'no) 'yes)
174 (_?_ (if (> 2 3) 'no 'yes) 'yes)
175 (_?_ (if (> 2 3) 'no) #f)
176
177 (define letrec
178   (macro (a . b)
179
180                                         ;
181                                         ; make the list of names in the let
182                                         ;
183
184          (define (_a a)
185            (cond ((not (null? a))
186                   (cons (car (car a))
187                         (_a (cdr a))))
188                  (else ())
189                  )
190            )
191
192                                         ; the set of expressions is
193                                         ; the list of set expressions
194                                         ; pre-pended to the
195                                         ; expressions to evaluate
196
197          (define (_b a b)
198            (cond ((null? a) b)
199                  (else
200                   (cons
201                    (list set
202                          (list quote
203                                (car (car a))
204                                )
205                          (cond ((null? (cdr (car a)))
206                                 ()
207                                 )
208                                (else
209                                 (car (cdr (car a)))
210                                 )
211                                )
212                          )
213                    (_b (cdr a) b)
214                    )
215                   )
216                  )
217            )
218
219                                         ; the parameters to the lambda is a list
220                                         ; of nils of the right length
221
222          (define (_c a)
223            (cond ((null? a) ())
224                  (else (cons () (_c (cdr a))))
225                  )
226            )
227                                         ; build the lambda.
228
229          (cons (cons lambda (cons (_a a) (_b a b))) (_c a))
230          )
231      )
232
233 (_?_ (letrec ((a 1) (b a)) (+ a b)) 2)
234
235                                         ; letrec is sufficient for let*
236
237 (define let* letrec)
238
239                                         ; use letrec for let in basic
240                                         ; syntax
241
242 (define let letrec)
243
244                                         ; Basic recursive
245                                         ; equality. Replaced with
246                                         ; vector-capable version in
247                                         ; advanced syntax
248
249 (define (equal? a b)
250   (cond ((eq? a b) #t)
251         ((pair? a)
252          (cond ((pair? b)
253                 (cond ((equal? (car a) (car b))
254                        (equal? (cdr a) (cdr b)))
255                       )
256                 )
257                )
258          )
259         )
260   )
261
262 (_?_ (equal? '(a b c) '(a b c)) #t)
263 (_?_ (equal? '(a b c) '(a b b)) #f)
264
265 (def (quote _??_) (lambda (a b) (cond ((equal? a b) a) (else (exit 1)))))
266
267                                         ; basic list accessors
268
269 (define (caar a) (car (car a)))
270
271 (define (cadr a) (car (cdr a)))
272
273 (define (cdar l) (cdr (car l)))
274
275 (_??_ (cdar '((1 2) (3 4))) '(2))
276
277 (define (cddr l) (cdr (cdr l)))
278
279 (_??_ (cddr '(1 2 3)) '(3))
280
281 (define (caddr l) (car (cdr (cdr l))))
282
283 (_??_ (caddr '(1 2 3 4)) 3)
284
285 (define (list-ref a b)
286   (car (list-tail a b))
287   )
288
289 (list-ref '(1 2 3) 2)
290
291 (define (member a b . t?)
292   (cond ((null? b)
293          #f
294          )
295         (else
296          (if (null? t?) (set! t? equal?) (set! t? (car t?)))
297          (if (t? a (car b))
298              b
299              (member a (cdr b) t?))
300          )
301         )
302   )
303
304 (_??_ (member '(2) '((1) (2) (3)))  '((2) (3)))
305 (_??_ (member '(4) '((1) (2) (3))) #f)
306
307 (define (memq a b) (member a b eq?))
308
309 (_??_ (memq 2 '(1 2 3)) '(2 3))
310 (_??_ (memq 4 '(1 2 3)) #f)
311 (_??_ (memq '(2) '((1) (2) (3))) #f)
312
313 (define (assoc a b . t?)
314   (if (null? t?)
315       (set! t? equal?)
316       (set! t? (car t?))
317       )
318   (if (null? b)
319       #f
320     (if (t? a (caar b))
321         (car b)
322       (assoc a (cdr b) t?)
323       )
324     )
325   )
326
327 (define (assq a b) (assoc a b eq?))
328 (define assv assq)
329
330 (_??_ (assq 'a '((a 1) (b 2) (c 3))) '(a 1))
331 (_??_ (assv 'b '((a 1) (b 2) (c 3))) '(b 2))
332 (_??_ (assoc '(c) '((a 1) (b 2) ((c) 3))) '((c) 3))
333
334 (define map
335   (lambda (proc . lists)
336          (define (_a lists)
337            (cond ((null? lists) ())
338                  (else
339                   (cons (caar lists) (_a (cdr lists)))
340                   )
341                  )
342            )
343          (define (_n lists)
344            (cond ((null? lists) ())
345                  (else
346                   (cons (cdr (car lists)) (_n (cdr lists)))
347                   )
348                  )
349            )
350          (define (_m lists)
351            (cond ((null? (car lists)) ())
352                  (else
353                   (cons (apply proc (_a lists)) (_m (_n lists)))
354                   )
355                  )
356            )
357          (_m lists)
358          )
359   )
360
361 (_??_ (map cadr '((a b) (d e) (g h))) '(b e h))
362
363                                         ; use map as for-each in basic
364                                         ; mode
365
366 (define for-each map)
367                                         ; simple math operators
368
369 (define zero? (macro (value) (list eq? value 0)))
370
371 (zero? 1)
372 (zero? 0)
373 (zero? "hello")
374
375 (define positive? (macro (value) (list > value 0)))
376
377 (positive? 12)
378 (positive? -12)
379
380 (define negative? (macro (value) (list < value 0)))
381
382 (negative? 12)
383 (negative? -12)
384
385 (define (abs a) (if (>= a 0) a (- a)))
386
387 (abs 12)
388 (abs -12)
389
390 (define max (lambda (a . b)
391                    (while (not (null? b))
392                      (cond ((< a (car b))
393                             (set! a (car b)))
394                            )
395                      (set! b (cdr b))
396                      )
397                    a)
398   )
399
400 (max 1 2 3)
401 (max 3 2 1)
402
403 (define min (lambda (a . b)
404                    (while (not (null? b))
405                      (cond ((> a (car b))
406                             (set! a (car b)))
407                            )
408                      (set! b (cdr b))
409                      )
410                    a)
411   )
412
413 (min 1 2 3)
414 (min 3 2 1)
415
416 (define (even? a) (zero? (% a 2)))
417
418 (even? 2)
419 (even? -2)
420 (even? 3)
421 (even? -1)
422
423 (define (odd? a) (not (even? a)))
424
425 (odd? 2)
426 (odd? -2)
427 (odd? 3)
428 (odd? -1)
429
430 (define (newline) (write-char #\newline))
431
432 (newline)
433
434 (define (eof-object? a)
435   (equal? a 'eof)
436   )
437