summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2020-11-08 04:22:35 +0000
committerAkshay <[email protected]>2020-11-08 04:22:35 +0000
commiteb6da7644bcf0656602fdf6e43f293759c853f66 (patch)
tree058f3f2c35889a26ebbcba5babc43748ea3816ca
parentd217ffbca7a50c434cb0db1541dfbc667e2b8a48 (diff)
add named let and simultaneous define semantics
-rw-r--r--environment.scm2
-rw-r--r--main.scm48
-rw-r--r--prelude/primitives.scm10
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
diff --git a/main.scm b/main.scm
index dd60662..1781255 100644
--- a/main.scm
+++ b/main.scm
@@ -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))