diff options
-rw-r--r-- | environment.scm | 2 | ||||
-rw-r--r-- | main.scm | 48 | ||||
-rw-r--r-- | prelude/primitives.scm | 10 |
3 files changed, 54 insertions, 6 deletions
diff --git a/environment.scm b/environment.scm index 4917a40..37f9fa4 100644 --- a/environment.scm +++ b/environment.scm | |||
@@ -29,6 +29,7 @@ | |||
29 | (error "Too few or too many arguments supplied" vars vals))) | 29 | (error "Too few or too many arguments supplied" vars vals))) |
30 | 30 | ||
31 | ;;; variable lookup | 31 | ;;; variable lookup |
32 | (define (is-unassigned? u) (eq? u '*unassigned*)) | ||
32 | (define (lookup-variable-value var env) | 33 | (define (lookup-variable-value var env) |
33 | (cond | 34 | (cond |
34 | [(empty-env? env) (error "Unbound variable" var)] | 35 | [(empty-env? env) (error "Unbound variable" var)] |
@@ -76,5 +77,6 @@ | |||
76 | the-empty-env)]) | 77 | the-empty-env)]) |
77 | (define-variable! 'true #t initial-env) | 78 | (define-variable! 'true #t initial-env) |
78 | (define-variable! 'false #f initial-env) | 79 | (define-variable! 'false #f initial-env) |
80 | (define-variable! '*unassigned* #f initial-env) | ||
79 | initial-env)) | 81 | initial-env)) |
80 | 82 | ||
@@ -76,7 +76,9 @@ | |||
76 | (define (lambda-form? expr) (tagged? expr 'lambda)) | 76 | (define (lambda-form? expr) (tagged? expr 'lambda)) |
77 | (define (lambda-params expr) (cadr expr)) | 77 | (define (lambda-params expr) (cadr expr)) |
78 | (define (lambda-body expr) (cddr expr)) | 78 | (define (lambda-body expr) (cddr expr)) |
79 | (define (make-lambda params body) (cons 'lambda (cons params body))) | 79 | (define (make-lambda params body) |
80 | (cons 'lambda | ||
81 | (cons params (scan-out-defines body)))) | ||
80 | 82 | ||
81 | ;;; begin | 83 | ;;; begin |
82 | (define (begin-form? expr) (tagged? expr 'begin)) | 84 | (define (begin-form? expr) (tagged? expr 'begin)) |
@@ -92,6 +94,11 @@ | |||
92 | ;;; let | 94 | ;;; let |
93 | (define (let-form? expr) (tagged? expr 'let)) | 95 | (define (let-form? expr) (tagged? expr 'let)) |
94 | (define (let*-form? expr) (tagged? expr 'let*)) | 96 | (define (let*-form? expr) (tagged? expr 'let*)) |
97 | (define (named-let-variable expr) (cadr expr)) | ||
98 | (define (named-let-form? expr) (and (tagged? expr 'let) | ||
99 | (variable? (named-let-variable expr)))) | ||
100 | (define (named-let-bindings expr) (caddr expr)) | ||
101 | (define (named-let-body expr) (cdddr expr)) | ||
95 | (define (let-bindings expr) (cadr expr)) | 102 | (define (let-bindings expr) (cadr expr)) |
96 | (define (last-binding? bindings) (null? (cdr bindings))) | 103 | (define (last-binding? bindings) (null? (cdr bindings))) |
97 | (define (let-body expr) (cddr expr)) | 104 | (define (let-body expr) (cddr expr)) |
@@ -110,22 +117,50 @@ | |||
110 | [(last-binding? bindings) (make-let bindings body)] | 117 | [(last-binding? bindings) (make-let bindings body)] |
111 | [else (make-let (list (car bindings)) | 118 | [else (make-let (list (car bindings)) |
112 | (let*->let (make-let* (cdr bindings) body)))]))) | 119 | (let*->let (make-let* (cdr bindings) body)))]))) |
120 | (define (named-let->let expr) | ||
121 | (let ([name (named-let-variable expr)] | ||
122 | [body (sequence->expr (named-let-body expr))] | ||
123 | [bindings (named-let-bindings expr)]) | ||
124 | (let ([new-binding (make-lambda (let-binding-variables bindings) | ||
125 | body)]) | ||
126 | (make-let (cons (list name new-binding) | ||
127 | bindings) | ||
128 | body)))) | ||
129 | |||
130 | ;;; handle internal definitions | ||
131 | (define (define->set statements) | ||
132 | (map (lambda (d) | ||
133 | (cons 'set! (cdr d))) | ||
134 | statements)) | ||
135 | (define (make-unassigned-bindings internal-defines) | ||
136 | (map (lambda (d) | ||
137 | (list (definition-name d) '*unassigned*)) internal-defines)) | ||
138 | (define (scan-out-defines body) | ||
139 | (let ([internal-defines (filter definition? body)] | ||
140 | [rest (filter (lambda (n) (not (definition? n))) body)]) | ||
141 | (cond | ||
142 | [(null? internal-defines) body] | ||
143 | [else | ||
144 | (let ([variables (make-unassigned-bindings internal-defines)]) | ||
145 | (let ([new-bindings (define->set internal-defines)]) | ||
146 | (list (cons 'let (cons variables (append new-bindings rest))))))]))) | ||
113 | 147 | ||
114 | 148 | ||
115 | (define (eval-expr expr env) | 149 | (define (eval-expr expr env) |
116 | (cond | 150 | (cond |
117 | [(self-evaluating? expr) expr] | 151 | [(self-evaluating? expr) expr] |
118 | [(variable? expr) (lookup-variable-value expr env)] | 152 | [(variable? expr) (lookup-variable-value expr env)] |
153 | [(assignment? expr) (eval-assignment expr env)] | ||
154 | [(definition? expr) (eval-definition expr env)] | ||
155 | [(quote-form? expr) (quotation-text expr)] | ||
119 | [(if-else? expr) (eval-if expr env)] | 156 | [(if-else? expr) (eval-if expr env)] |
120 | [(begin-form? expr) (eval-sequence (begin-actions expr) env)] | 157 | [(begin-form? expr) (eval-sequence (begin-actions expr) env)] |
121 | [(lambda-form? expr) (make-lambda (lambda-params expr) | 158 | [(lambda-form? expr) (make-lambda (lambda-params expr) |
122 | (lambda-body expr))] | 159 | (lambda-body expr))] |
160 | [(named-let-form? expr) 'false] | ||
123 | [(let-form? expr) (eval-let expr env)] | 161 | [(let-form? expr) (eval-let expr env)] |
124 | [(let*-form? expr) (eval-let* expr env)] | 162 | [(let*-form? expr) (eval-let* expr env)] |
125 | [(assignment? expr) (eval-assignment expr env)] | ||
126 | [(definition? expr) (eval-definition expr env)] | ||
127 | [(cond-form? expr) (eval-cond expr env)] | 163 | [(cond-form? expr) (eval-cond expr env)] |
128 | [(quote-form? expr) (quotation-text expr)] | ||
129 | [(function-application? expr) (eval-function-application expr env)])) | 164 | [(function-application? expr) (eval-function-application expr env)])) |
130 | 165 | ||
131 | (define (eval-if expr env) | 166 | (define (eval-if expr env) |
@@ -143,6 +178,9 @@ | |||
143 | (eval-expr (car exprs) env) | 178 | (eval-expr (car exprs) env) |
144 | (eval-sequence (cdr exprs) env))])) | 179 | (eval-sequence (cdr exprs) env))])) |
145 | 180 | ||
181 | (define (eval-named-let expr env) | ||
182 | (eval-let (named-let->let expr) env)) | ||
183 | |||
146 | (define (eval-let expr env) | 184 | (define (eval-let expr env) |
147 | (eval-function-application | 185 | (eval-function-application |
148 | (cons (let->lambda expr) | 186 | (cons (let->lambda expr) |
@@ -153,7 +191,7 @@ | |||
153 | (eval-expr (let*->let expr) env)) | 191 | (eval-expr (let*->let expr) env)) |
154 | 192 | ||
155 | (define (eval-assignment expr env) | 193 | (define (eval-assignment expr env) |
156 | (set-variable-value! | 194 | (set-variable-value! |
157 | (assignment-name expr) | 195 | (assignment-name expr) |
158 | (eval-expr (assignment-value expr) env) | 196 | (eval-expr (assignment-value expr) env) |
159 | env)) | 197 | env)) |
diff --git a/prelude/primitives.scm b/prelude/primitives.scm index cd7f1bf..ad1584d 100644 --- a/prelude/primitives.scm +++ b/prelude/primitives.scm | |||
@@ -45,12 +45,20 @@ | |||
45 | (> . ,(lift-bool >)) | 45 | (> . ,(lift-bool >)) |
46 | (<= . ,(lift-bool <=)) | 46 | (<= . ,(lift-bool <=)) |
47 | (>= . ,(lift-bool >=)) | 47 | (>= . ,(lift-bool >=)) |
48 | (= . ,(lift-bool =)) | ||
48 | (eq? . ,(lift-bool eq?)) | 49 | (eq? . ,(lift-bool eq?)) |
49 | (&& . ,and-special) | 50 | (&& . ,and-special) |
50 | (|| . ,or-special) | 51 | (|| . ,or-special) |
51 | (/= . ,not-fn) | 52 | (/= . ,not-fn) |
52 | (first . ,car) | 53 | (first . ,car) |
53 | (rest . ,cdr))) | 54 | (second . ,cadr) |
55 | (third . ,caddr) | ||
56 | (fourth . ,cadddr) | ||
57 | (rest . ,cdr) | ||
58 | (cons . ,cons) | ||
59 | (list . ,list) | ||
60 | (map . ,map) | ||
61 | (null? . ,(lift-bool null?)))) | ||
54 | 62 | ||
55 | (define (primitive-names) (map car primitives)) | 63 | (define (primitive-names) (map car primitives)) |
56 | (define (primitive-objs) (map cdr primitives)) | 64 | (define (primitive-objs) (map cdr primitives)) |