diff --git a/compile.rkt b/compile.rkt index 96673f9..9d48495 100644 --- a/compile.rkt +++ b/compile.rkt @@ -60,8 +60,8 @@ (compile-application exp cenv target linkage)] [(Let1? exp) (compile-let1 exp cenv target linkage)] - #;[(Letrec? exp) - (compile-letrec exp cenv target linkage)])) + [(Let? exp) + (compile-let exp cenv target linkage)])) @@ -511,6 +511,50 @@ (make-instruction-sequence `(,(make-PopEnvironment 1 0))) after-let1)))) + + +(: compile-let (Let CompileTimeEnvironment Target Linkage -> InstructionSequence)) +(define (compile-let exp cenv target linkage) + (let*: ([n : Natural (length (Let-rhss exp))] + [rhs-codes : (Listof InstructionSequence) + (map (lambda: ([rhs : ExpressionCore] + [i : Natural]) + (compile rhs + (extend-lexical-environment/placeholders cenv n) + (make-EnvLexicalReference i) + 'next)) + (Let-rhss exp) + (build-list n + (lambda: ([i : Natural]) + i)))] + [after-let : Symbol (make-label 'afterLet)] + [after-body-code : Symbol (make-label 'afterLetBody)] + [extended-cenv : CompileTimeEnvironment + (extend-lexical-environment/names cenv (Let-names exp))] + [let-linkage : Linkage + (cond + [(eq? linkage 'next) + 'next] + [(eq? linkage 'return) + 'return] + [(symbol? linkage) + after-body-code])] + [body-target : Target (adjust-target-depth target n)] + [body-code : InstructionSequence + (compile (Let-body exp) extended-cenv body-target let-linkage)]) + (end-with-linkage + linkage + extended-cenv + (append-instruction-sequences (make-instruction-sequence `(,(make-PushEnvironment n))) + (apply append-instruction-sequences rhs-codes) + body-code + after-body-code + (make-instruction-sequence `(,(make-PopEnvironment n 0))) + after-let)))) + + + + (: adjust-target-depth (Target Natural -> Target)) (define (adjust-target-depth target n) (cond diff --git a/expression-structs.rkt b/expression-structs.rkt index 1e4cf72..ab550a7 100644 --- a/expression-structs.rkt +++ b/expression-structs.rkt @@ -6,7 +6,8 @@ ;; Expressions (define-type ExpressionCore (U Top Constant Var Branch Def Lam Seq App #;Letrec - Let1)) + Let1 + Let)) (define-struct: Top ([prefix : Prefix] [code : ExpressionCore]) #:transparent) @@ -27,6 +28,11 @@ [rhs : ExpressionCore ] [body : ExpressionCore]) #:transparent) +(define-struct: Let ([names : (Listof Symbol)] + [rhss : (Listof ExpressionCore)] + [body : ExpressionCore]) + #:transparent) + #;(define-struct: Letrec ([names : (Listof Symbol)] diff --git a/find-toplevel-variables.rkt b/find-toplevel-variables.rkt index f1ccdc1..f6f154d 100644 --- a/find-toplevel-variables.rkt +++ b/find-toplevel-variables.rkt @@ -46,6 +46,11 @@ (list-difference (loop (Let1-body exp)) (list (Let1-name exp))))] + [(Let? exp) + (append (apply append (map loop (Let-rhss exp))) + (list-difference (loop (Let-body exp)) + (Let-names exp)))] + #;[(Letrec? exp) (list-difference (append (apply append (map loop (Letrec-procs exp))) (loop (Letrec-body exp))) diff --git a/parse.rkt b/parse.rkt index c41fca0..4a50e54 100644 --- a/parse.rkt +++ b/parse.rkt @@ -158,7 +158,10 @@ (parse (car rhss)) (parse `(begin ,@body)))] [else - (error 'parse-let "not supported yet")]))) + (make-Let vars + (map parse rhss) + (parse `(begin ,@body)))]))) + (define (parse-let* exp) (parse @@ -172,11 +175,12 @@ `(let ([,(car vars) ,(car rhss)]) ,(loop (cdr vars) (cdr rhss)))]))))) - + ;; any -> boolean (define (let? exp) (tagged-list? exp 'let)) + ;; any -> boolean (define (let*? exp) (tagged-list? exp 'let*)) diff --git a/test-compiler.rkt b/test-compiler.rkt index 17721c2..c764ce4 100644 --- a/test-compiler.rkt +++ b/test-compiler.rkt @@ -598,6 +598,13 @@ 7) +(test (let ([x 3] + [y 4]) + (let ([x y] + [y x]) + (list x y))) + (list 4 3)) +