+(define wordsize 8)
+
+(define (codegen-let bindings body si env)
+ (let* ((stack-offsets (map (lambda (x) (- si (* x wordsize)))
+ (range 0 (length bindings))))
+ (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)
+ (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)))
+
+(define (codegen-var name si env)
+ (let ((offset (cdr (assoc name env))))
+ (emit "movq ~a(%rsp), %rax" offset)))
+
+(define (codegen-expr e si env)
+ (cond ((and (list? e) (eq? (car e) '+))
+ (codegen-add (cdr e)))
+ ((let? e) (codegen-let
+ (let-bindings e)
+ (let-body e)
+ si
+ env))
+ ((var? e) (codegen-var e si env))
+ (else (emit "movq $~a, %rax" e))))
+
+(define (codegen program)