diff --git a/assemble.rkt b/assemble.rkt index 78b67bb..9261131 100644 --- a/assemble.rkt +++ b/assemble.rkt @@ -257,8 +257,11 @@ EOF "MACHINE.control.pop();"] [(PushEnvironment? stmt) (format "MACHINE.env.push(~a);" (string-join - (build-list (PushEnvironment-n stmt) (lambda: ([i : Natural]) - "undefined")) + (build-list (PushEnvironment-n stmt) + (lambda: ([i : Natural]) + (if (PushEnvironment-unbox? stmt) + "[]" + "undefined"))) ", "))] [(PopEnvironment? stmt) (format "MACHINE.env.splice(MACHINE.env.length-(~a),~a);" @@ -321,13 +324,17 @@ EOF (EnvWholePrefixReference-depth a-prefix-ref))) -(: assemble-env-reference (EnvReference -> String)) -(define (assemble-env-reference ref) +(: assemble-env-reference/closure-capture (EnvReference -> String)) +;; When we're capturing the values for a closure, we need to not unbox +;; lexical references: they must remain boxes. +(define (assemble-env-reference/closure-capture ref) (cond [(EnvLexicalReference? ref) - (assemble-lexical-reference ref)] + (format "MACHINE.env[MACHINE.env.length - 1 - ~a]" + (EnvLexicalReference-depth ref))] [(EnvWholePrefixReference? ref) - (assemble-whole-prefix-reference ref)])) + (format "MACHINE.env[MACHINE.env.length - 1 - ~a]" + (EnvWholePrefixReference-depth ref))])) (: assemble-op-expression (PrimitiveOperator -> String)) @@ -340,7 +347,7 @@ EOF (format "new Closure(~a, ~a, [~a], ~s)" (MakeCompiledProcedure-label op) (MakeCompiledProcedure-arity op) - (string-join (map assemble-env-reference + (string-join (map assemble-env-reference/closure-capture ;; The closure values are in reverse order ;; to make it easier to push, in bulk, into ;; the environment (which is also in reversed order) diff --git a/test-browser-evaluate.rkt b/test-browser-evaluate.rkt index 4743c53..9880329 100644 --- a/test-browser-evaluate.rkt +++ b/test-browser-evaluate.rkt @@ -125,3 +125,19 @@ y)))))))) (displayln (ctak 18 12 6))) "7\n") + +(test '(letrec ([f (lambda (x) + (if (= x 0) + 1 + (* x (f (sub1 x)))))]) + (display (f 10))) + "3628800") + +(test '(letrec ([tak (lambda (x y z) + (if (>= y x) + z + (tak (tak (- x 1) y z) + (tak (- y 1) z x) + (tak (- z 1) x y))))]) + (displayln (tak 18 12 6))) + "7\n") \ No newline at end of file