From cbed819a84f88d08e1f415ae5f006cdc44626eee Mon Sep 17 00:00:00 2001 From: David Thompson Date: Thu, 11 Aug 2022 21:27:08 -0400 Subject: Step 6: Conditional Expressions --- compiler.scm | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'compiler.scm') diff --git a/compiler.scm b/compiler.scm index b373ecc..4305f2c 100644 --- a/compiler.scm +++ b/compiler.scm @@ -56,6 +56,10 @@ = < <= > >= eq? char=?)))) +(define (if? x) + (and (pair? x) + (eq? (first x) 'if))) + (define (primcall-op x) (first x)) @@ -78,6 +82,22 @@ (define (body x) (third x)) +(define (test x) + (second x)) + +(define (consequent x) + (third x)) + +(define (alternate x) + (fourth x)) + +(define unique-counter (make-parameter 0)) + +(define (unique-label) + (let ((n (unique-counter))) + (unique-counter (+ n 1)) + (format #f "L~a" n))) + (define (register name) (format #f "%~a" name)) @@ -138,6 +158,15 @@ (define (emit-sete dest) (emit "sete ~a" dest)) +(define (emit-je label) + (emit "je ~a" label)) + +(define (emit-jmp label) + (emit "jmp ~a" label)) + +(define (emit-label label) + (format #t "~a:\n" label)) + (define (emit-tag-check x mask tag si env) (emit-expr x si env) (emit-and (immediate mask) rax) @@ -246,6 +275,18 @@ (extend-env (lhs b) si new-env) (- si wordsize)))))) +(define (emit-if test conseq altern si env) + (let ((L0 (unique-label)) + (L1 (unique-label))) + (emit-expr test si env) + (emit-cmp (immediate (immediate-rep #f)) rax) + (emit-je L0) + (emit-expr conseq si env) + (emit-jmp L1) + (emit-label L0) + (emit-expr altern si env) + (emit-label L1))) + (define (emit-expr x si env) (cond ((immediate? x) @@ -256,12 +297,15 @@ (emit-let (bindings x) (body x) si env)) ((primcall? x) (emit-primitive-call x si env)) + ((if? x) + (emit-if (test x) (consequent x) (alternate x) si env)) (else (error "unknown expression" x)))) (define (compile-program x) - (emit-expr x (- wordsize) '()) - (emit "ret")) + (parameterize ((unique-counter 0)) + (emit-expr x (- wordsize) '()) + (emit "ret"))) (define (compile-and-run x) (with-output-to-file "scheme_entry.S" @@ -337,4 +381,6 @@ scheme_entry: (test-case '(char=? #\a #\b) "#f") (test-case '(char=? #\b #\b) "#t") (test-case '(let ((x 1)) x) "1") - (test-case '(let ((x 1) (y 2)) (+ x y)) "3")) + (test-case '(let ((x 1) (y 2)) (+ x y)) "3") + (test-case '(if #t 1 2) "1") + (test-case '(if #f 1 2) "2")) -- cgit v1.2.3