Skip to content

Commit e987dc1

Browse files
committed
Refactor Fraud.
1 parent b67c5c2 commit e987dc1

3 files changed

Lines changed: 136 additions & 0 deletions

File tree

www/notes.scrbl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@include-section{notes/dupe.scrbl}
1212
@include-section{notes/extort.scrbl}
1313
@include-section{notes/fraud.scrbl}
14+
@include-section{notes/interlude1.scrbl}
1415
@include-section{notes/grift.scrbl}
1516
@include-section{notes/hustle.scrbl}
1617
@;{
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#lang racket
2+
(provide (all-defined-out))
3+
4+
;; type CEnv = [Listof Variable]
5+
6+
;; Expr -> Asm
7+
(define (compile e)
8+
`(entry
9+
,@(compile-e e '())
10+
ret
11+
err
12+
(push rbp)
13+
(call error)
14+
ret))
15+
16+
;; Expr CEnv -> Asm
17+
(define (compile-e e c)
18+
(match e
19+
[(? integer? i) (compile-integer i)]
20+
[(? boolean? b) (compile-boolean b)]
21+
[`(add1 ,e0) (compile-add1 e0 c)]
22+
[`(sub1 ,e0) (compile-sub1 e0 c)]
23+
[`(zero? ,e0) (compile-zero? e0 c)]
24+
[`(if ,e0 ,e1 ,e2) (compile-if e0 e1 e2 c)]
25+
[(? symbol? x) (compile-variable x c)]
26+
[`(let ((,x ,e0)) ,e1) (compile-let x e0 e1 c)]))
27+
28+
;; Integer -> Asm
29+
(define (compile-integer i)
30+
`((mov rax ,(* i 2))))
31+
32+
;; Boolean -> Asm
33+
(define (compile-boolean b)
34+
`((mov rax ,(if b #b11 #b01))))
35+
36+
;; Expr CEnv -> Asm
37+
(define (compile-add1 e0 c)
38+
(let ((c0 (compile-e e0 c)))
39+
`(,@c0
40+
,@assert-integer
41+
(add rax 2))))
42+
43+
;; Expr CEnv -> Asm
44+
(define (compile-sub1 e0 c)
45+
(let ((c0 (compile-e e0 c)))
46+
`(,@c0
47+
,@assert-integer
48+
(sub rax 2))))
49+
50+
;; Expr CEnv -> Asm
51+
(define (compile-zero? e0 c)
52+
(let ((c0 (compile-e e0 c))
53+
(l0 (gensym))
54+
(l1 (gensym)))
55+
`(,@c0
56+
,@assert-integer
57+
(cmp rax 0)
58+
(mov rax #b01) ; #f
59+
(jne ,l0)
60+
(mov rax #b11) ; #t
61+
,l0)))
62+
63+
;; Expr Expr Expr CEnv -> Asm
64+
(define (compile-if e0 e1 e2 c)
65+
(let ((c0 (compile-e e0 c))
66+
(c1 (compile-e e1 c))
67+
(c2 (compile-e e2 c))
68+
(l0 (gensym))
69+
(l1 (gensym)))
70+
`(,@c0
71+
(cmp rax #b01) ; compare to #f
72+
(je ,l0) ; jump to c2 if #f
73+
,@c1
74+
(jmp ,l1) ; jump past c2
75+
,l0
76+
,@c2
77+
,l1)))
78+
79+
;; Variable CEnv -> Asm
80+
(define (compile-variable x c)
81+
(let ((i (lookup x c)))
82+
`((mov rax (offset rsp ,(- (add1 i)))))))
83+
84+
;; Variable Expr Expr CEnv -> Asm
85+
(define (compile-let x e0 e1 c)
86+
(let ((c0 (compile-e e0 c))
87+
(c1 (compile-e e1 (cons x c))))
88+
`(,@c0
89+
(mov (offset rsp ,(- (add1 (length c)))) rax)
90+
,@c1)))
91+
92+
;; Variable CEnv -> Natural
93+
(define (lookup x cenv)
94+
(match cenv
95+
['() (error "undefined variable:" x)]
96+
[(cons y cenv)
97+
(match (symbol=? x y)
98+
[#t (length cenv)]
99+
[#f (lookup x cenv)])]))
100+
101+
(define assert-integer
102+
`((mov rbx rax)
103+
(and rbx 1)
104+
(cmp rbx 0)
105+
(jne err)))

www/notes/interlude1.scrbl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#lang scribble/manual
2+
3+
@(require "utils.rkt"
4+
"../utils.rkt")
5+
6+
7+
@(define codeblock-include (make-codeblock-include #'h))
8+
9+
@title[#:tag "Interlude"]{Refactoring the Compiler}
10+
11+
We've now written half-a-dozen compilers, each of which has centered
12+
around a structurally recursive function over the syntax of
13+
@tt{Expr}s.
14+
15+
In each case of this function, we emit the appropriate code for that
16+
kind of expression.
17+
18+
This works fine while our language is small and the concepts are
19+
simple enough that just a few instructions need to be produced.
20+
21+
But this leads to a monolithic and unwieldy function as the language
22+
and the complexity of its constructs grow.
23+
24+
Moving forward we will refactor this main compiler function to call
25+
out to a separate helper function for each kind of expression.
26+
27+
For example, here is the Fraud compiler written in the new style:
28+
29+
30+
@codeblock-include["fraud/compile-refactor.rkt"]

0 commit comments

Comments
 (0)