(inner-si (- si (* (length bindings) wordsize)))
(names (map car bindings))
(exprs (map cadr bindings))
- (inner-env (append (map cons names stack-offsets) env)))
- (for-each (lambda (expr offset)
+
+ ; recursive let bindings: build environment as we go
+ (inner-env (fold-left
+ (lambda (env name expr offset)
(codegen-expr expr inner-si env)
- (emit "movq %rax, ~a(%rsp)" offset))
- exprs stack-offsets)
- (for-each (lambda (form) (codegen-expr form inner-si inner-env)) body)))
+ (emit "movq %rax, ~a(%rsp)" offset)
+ (cons (cons name offset) env))
+ env names exprs stack-offsets)))
+ (for-each (lambda (form)
+ (codegen-expr form inner-si inner-env))
+ body)))
(define (codegen-var name si env)
+ (when (not (assoc name env))
+ (error #f (format "Variable ~a is not bound" name)))
(let ((offset (cdr (assoc name env))))
(emit "movq ~a(%rsp), %rax" offset)))
(amd64-abi
(lambda () (codegen-expr xform-prog 0 '())))))
-(define (compile-to-binary program)
+(define (compile-to-binary program output)
(when (not (eq? (typecheck program) 'int)) (error #f "not an int"))
(let ([tmp-path "/tmp/a.s"])
(when (file-exists? tmp-path) (delete-file tmp-path))
(with-output-to-file tmp-path
(lambda () (codegen program)))
- (system "clang -fomit-frame-pointer /tmp/a.s rts.c")))
+ (system (format "clang -fomit-frame-pointer /tmp/a.s rts.c -o ~a" output))))