summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson@vistahigherlearning.com>2022-08-11 21:27:08 -0400
committerDavid Thompson <dthompson@vistahigherlearning.com>2022-09-22 16:24:07 -0400
commitcbed819a84f88d08e1f415ae5f006cdc44626eee (patch)
tree5006ac801a97bba4302fffe56b971d5bc8fc49b8
parent9614d2f60a1cc963a1a8cfc61494d0e5c7a3431f (diff)
Step 6: Conditional Expressions
-rw-r--r--compiler.scm52
1 files changed, 49 insertions, 3 deletions
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"))