+ ('string-literal (emit "movq ~a, %rax" label))
+ ('bool-literal (emit "movq $~a, %rax" (if e 1 0)))
+ ('int-literal (emit "movq $~a, %rax" e))
+
+ (else (error #f "don't know how to codegen this"))))
+
+
+(define (fold-map f x) (fold-left append '() (map f x)))
+
+(define (free-vars prog)
+ (define bound '())
+ (define (collect e)
+ (case (ast-type e)
+ ('builtin '()) ; do nothing
+ ('var (if (memq e bound) '() (list e)))
+ ('lambda
+ (set! bound (append (lambda-args e) bound))
+ (collect (lambda-body e)))
+
+ ('app (fold-map collect e))
+ ('let
+ (let ((bind-fvs (fold-map (lambda (a)
+ ((set! bound (cons (car a) bound))
+ (collect (cdr a))))
+ (let-bindings cadr)))
+ (body-fvs (fold-map collect (let-body e))))
+ (append bind-fvs body-fvs)))
+ (else '())))
+ (collect prog))
+
+ ; ((lambda (x) (+ x 1)) 42) => {lambda0: (x) (+ x 1)}, (@lambda0 42)
+(define (extract-lambdas program)
+ (define lambdas '())
+ (define (add-lambda e)
+ (let* ((label (fresh-lambda))
+ (args (lambda-args e))
+ (captured (free-vars e))
+ (body (extract (lambda-body e)))
+ (new-lambda (list label args captured body)))
+ (set! lambdas (cons new-lambda lambdas))
+ `(closure ,label ,captured))) ; todo: should we string->symbol?
+ (define (extract e)
+ (case (ast-type e)
+ ('lambda (add-lambda e))
+ ('let `(let
+ ,(map extract (let-bindings e))
+ ,@(map extract (let-body e))))
+ ('app (append (list (extract (car e)))
+ (map extract (cdr e))))
+ (else e)))
+ (let ((transformed (extract program)))
+ (cons lambdas transformed)))
+
+;(define (extract-strings program))
+
+(define (amd64-abi f)
+ ; preserve registers