0854a1dea6d776ba0f2f8fd890228d8d10436f64
[mes.git] / module / mes / mes-0.mes
1 ;;; -*-scheme-*-
2
3 ;;; Mes --- Maxwell Equations of Software
4 ;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
5 ;;;
6 ;;; mes-0.mes: This file is part of Mes.
7 ;;;
8 ;;; Mes is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
12 ;;;
13 ;;; Mes is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;;; GNU General Public License for more details.
17 ;;;
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with Mes.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Commentary:
22
23 ;;; mes-0.mes - bootstrap into Scheme, re
24
25 ;;; When compiling mes.c with -DBOOT=1, eval/apply et al. are lacking
26 ;;; features wrt the fat-c variant, e.g., define and define-macro are
27 ;;; not available; instead label is supplied.  Before loading
28 ;;; boot-0.mes, loop-0.mes is loaded to provide a richer eval/apply.
29
30 ;;; This might enable moving more functionality from C to Scheme,
31 ;;; making the entirely-from-source bootstrap process more feasible.
32 ;;; However, currently performance is 400x worse.  Also several tests
33 ;;; in the test suite fail and the REPL does not work yet.
34
35 ;;; Code:
36
37 (define-macro (cond . clauses)
38   (list 'if (null? clauses) *unspecified*
39         (if (null? (cdr clauses))
40             (list 'if (car (car clauses))
41                   (list (cons 'lambda (cons '() (cons (car (car clauses)) (cdr (car clauses))))))
42                   *unspecified*)
43             (if (eq? (car (cadr clauses)) 'else)
44                 (list 'if (car (car clauses))
45                       (list (cons 'lambda (cons '() (car clauses))))
46                       (list (cons 'lambda (cons '() (cons *unspecified* (cdr (cadr clauses)))))))
47                 (list 'if (car (car clauses))
48                       (list (cons 'lambda (cons '() (car clauses))))
49                       (cons 'cond (cdr clauses)))))))
50
51 (define (map f l . r)
52   (if (null? l) '()
53       (if (null? r) (cons (f (car l)) (map f (cdr l)))
54           (if (null? (cdr r))
55               (cons (f (car l) (caar r)) (map f (cdr l) (cdar r)))))))
56
57 (define-macro (simple-let bindings . rest)
58   (cons (cons 'lambda (cons (map car bindings) rest))
59         (map cadr bindings)))
60
61 (define-macro (let bindings . rest)
62   (cons 'simple-let (cons bindings rest)))
63
64 (define-macro (or . x)
65   (if (null? x) #f
66       (if (null? (cdr x)) (car x)
67           (list 'if (car x) (car x)
68                 (cons 'or (cdr x))))))
69
70 (define-macro (and . x)
71   (if (null? x) #t
72       (if (null? (cdr x)) (car x)
73           (list 'if (car x) (cons 'and (cdr x))
74                 #f))))
75
76 (define (not x)
77   (if x #f #t))
78
79 (define (evlis-env m a)
80   (cond
81    ((null? m) '())
82    ((not (pair? m)) (eval-env m a))
83    (#t (cons (eval-env (car m) a) (evlis-env (cdr m) a)))))
84
85 (define (apply-env fn x a) 
86   (cond
87    ((atom? fn)
88     (cond
89      ((builtin? fn) (call fn x))
90      ((eq? fn 'call-with-values) (call call-with-values-env (append x (cons a '()))))
91      ((eq? fn 'current-module) a)
92      (#t (apply-env (eval-env fn a) x a))))
93    ((eq? (car fn) 'lambda)
94     (let ((p (pairlis (cadr fn) x a)))
95       (cache-invalidate-range p (cdr a))
96       (let ((r (eval-begin-env (cddr fn) (cons (cons '*closure* p) p))))
97         (cache-invalidate-range p (cdr a))
98         r)))
99    ((eq? (car fn) '*closure*)
100     (let ((args (caddr fn))
101           (body (cdddr fn))
102           (a (cddr (cadr fn))))
103       (let ((p (pairlis args x a)))
104         (cache-invalidate-range p (cdr a))
105         (let ((r (eval-begin-env body (cons (cons '*closure* p) p))))
106           (cache-invalidate-range p (cdr a))
107           r))))
108    ;;((eq? (car fn) 'label) (apply-env (caddr fn) x (cons (cons (cadr fn) (caddr fn)) a)))
109    (#t (apply-env (eval-env fn a) x a))))
110
111 (define (eval-expand e a)
112   (cond
113    ((symbol? e) (assq-ref-cache e a))
114    ((atom? e) e)
115    ((atom? (car e))
116     (cond
117      ((eq? (car e) 'quote) (cadr e))
118      ((eq? (car e) 'syntax) (cadr e))
119      ((eq? (car e) 'begin) (eval-begin-env e a))
120      ((eq? (car e) 'lambda) (make-closure (cadr e) (cddr e) (assq '*closure* a)))
121      ((eq? (car e) '*closure*) e)
122      ((eq? (car e) 'if) (eval-if-env (cdr e) a))
123      ((eq? (car e) 'define) (env:define (cons (sexp:define e a) '()) a))
124      ((eq? (car e) 'define-macro) (env:define (env:macro (sexp:define e a)) a))
125      ((eq? (car e) 'set!) (set-env! (cadr e) (eval-env (caddr e) a) a))
126      ((eq? (car e) 'apply-env) (apply-env (eval-env (cadr e) a) (evlis-env (caddr e) a) a))
127      ((eq? (car e) 'unquote) (eval-env (cadr e) a))
128      ((eq? (car e) 'quasiquote) (eval-quasiquote (cadr e) (add-unquoters a)))
129      (#t (apply-env (car e) (evlis-env (cdr e) a) a))))
130    (#t (apply-env (car e) (evlis-env (cdr e) a) a))))
131
132 (define (unquote x) (cons 'unquote x))
133 (define (unquote-splicing x) (cons 'quasiquote x))
134
135 (define %the-unquoters
136   (cons
137    (cons 'unquote unquote)
138    (cons (cons 'unquote-splicing unquote-splicing) '())))
139
140 (define (add-unquoters a)
141   (cons %the-unquoters a))
142
143 (define (eval-env e a)
144   (eval-expand (expand-macro-env e a) a))
145
146 (define (expand-macro-env e a)
147   (if (pair? e) ((lambda (macro)
148                    (if macro (expand-macro-env (apply-env macro (cdr e) a) a)
149                        e))
150                  (lookup-macro (car e) a))
151       e))
152
153 (define (eval-begin-env e a)
154   (if (null? e) *unspecified*
155       (if (null? (cdr e)) (eval-env (car e) a)
156           (begin
157             (eval-env (car e) a)
158             (eval-begin-env (cdr e) a)))))
159
160 (define (eval-if-env e a)
161   (if (eval-env (car e) a) (eval-env (cadr e) a)
162       (if (pair? (cddr e)) (eval-env (caddr e) a))))
163
164 (define (eval-quasiquote e a)
165   (cond ((null? e) e)
166         ((atom? e) e)
167         ((eq? (car e) 'unquote) (eval-env (cadr e) a))
168         ((and (pair? (car e))
169               (eq? (caar e) 'unquote-splicing))
170          (append2 (eval-env (cadar e) a) (eval-quasiquote (cdr e) a)))
171         (#t (cons (eval-quasiquote (car e) a) (eval-quasiquote (cdr e) a)))))
172
173 (define (sexp:define e a)
174   (if (atom? (cadr e)) (cons (cadr e) (eval-env (caddr e) a))
175       (cons (caadr e) (eval-env (cons 'lambda (cons (cdadr e) (cddr e))) a))))
176
177 (define (env:define a+ a)
178   (set-cdr! a+ (cdr a))
179   (set-cdr! a a+)
180   (set-cdr! (assq '*closure* a) a))
181
182 (define (env:macro name+entry)
183   (cons
184    (cons (car name+entry)
185          (make-macro (car name+entry)
186                      (cdr name+entry)))
187    '()))
188
189 ;; boot into loop-0
190 (cache-invalidate-range (current-module) '())
191 ()