Skip to content

Commit f04467e

Browse files
authored
Merge pull request #15 from dvanhorn/next
Next
2 parents ff8bddd + 7f04605 commit f04467e

5 files changed

Lines changed: 78 additions & 15 deletions

File tree

www/notes/abscond.scrbl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838

3939
@emph{Let's Make a Programming Language!}
4040

41+
@table-of-contents[]
42+
43+
@section{Overview}
44+
4145
A compiler is just one (optional!) component of a @emph{programming
4246
language}. So if you want to make a compiler, you must first settle
4347
on a programming language to compile.

www/notes/blackmail.scrbl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
@emph{Let's Do It Again!}
3737

38+
@table-of-contents[]
39+
40+
@section{Refinement, take one}
41+
3842
We've seen all the essential peices (a grammar, an AST data type
3943
definition, an operational semantics, an interpreter, a compiler,
4044
etc.) for implementing a programming language, albeit for an amazingly

www/notes/con.scrbl

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,26 @@
1515

1616
@(define codeblock-include (make-codeblock-include #'h))
1717

18+
19+
@(ev '(require rackunit))
1820
@(for-each (λ (f) (ev `(require (file ,(path->string (build-path notes "con" f))))))
19-
'("interp.rkt" "compile.rkt" "asm/interp.rkt" "asm/printer.rkt"))
21+
'("interp.rkt" "compile.rkt" "asm/interp.rkt" "asm/printer.rkt" "random.rkt"))
2022

2123

2224
@title[#:tag "Con"]{Con: branching with conditionals}
2325

26+
@emph{When you come to a fork in the road, take it.}
27+
28+
@table-of-contents[]
29+
30+
@section{Conditional execution}
31+
2432
Let's now consider add a notion of @bold{conditionals} to our target
2533
language.
2634

2735
We'll call it @bold{Con}.
2836

29-
We will use the following syntax...
37+
We will use the following syntax: @racket[(if (zero? _e0) _e1 _e2)].
3038

3139
Together this leads to the following grammar for Con:
3240

@@ -46,9 +54,9 @@ the new form is an if-expression.
4654

4755
@itemlist[
4856

49-
@item{the meaning of a if expression @tt{(if (zero? e0) e1 e2)} is the
50-
meaning of @math{e1} if the meaning of @tt{e1} if the meaning of
51-
@tt{e0} is 0 and is the meaning of @math{e2} otherwise.}
57+
@item{the meaning of a if expression @racket[(if (zero? _e0) _e1 _e2)] is the
58+
meaning of @racket[_e1] if the meaning of @racket[_e1] if the meaning of
59+
@racket[_e0] is 0 and is the meaning of @racket[_e2] otherwise.}
5260

5361
]
5462

@@ -204,6 +212,9 @@ In total, the code for this example would look like:
204212
if-else-end)
205213
]
206214

215+
216+
@section{A Compiler for Con}
217+
207218
Notice that the @racket['(mov rax 8)], @racket['(mov rax 3)] and
208219
@racket['(mov rax 2)] parts are just the instructions generated by
209220
compiling @racket[8], @racket[2] and @racket[3]. Generalizing from
@@ -213,9 +224,9 @@ this, we arrive at the following code for the compiler:
213224
(let ((c0 (compile-e e0))
214225
(c1 (compile-e e1))
215226
(c2 (compile-e e2))
216-
(l0 (gensym "if-else-begin"))
217-
(l1 (gensym "if-else-end")))
218-
'(,@c0
227+
(l0 (gensym "if"))
228+
(l1 (gensym "if")))
229+
`(,@c0
219230
(cmp rax 0)
220231
(jne ,l0)
221232
,@c1
@@ -226,22 +237,65 @@ this, we arrive at the following code for the compiler:
226237
]
227238

228239

229-
@ex[
230-
(asm-display (compile '(if (zero? 8) 2 3)))
231-
]
232-
240+
This will require extending our representation of x86 instructions; in
241+
particular, we add @racket['jmp], @racket['jne], and @racket['cmp]
242+
instructions:
233243

234244
@codeblock-include["con/asm/ast.rkt"]
235245

236246
We omit the printer code, which is mundane. See
237247
@link["con/asm/printer.rkt"]{@tt{asm/printer.rkt}} for details.
238248

249+
The complete compiler code is:
250+
239251
@codeblock-include["con/compile.rkt"]
240252

253+
Let's take a look at a few examples:
254+
@ex[
255+
(asm-display (compile '(if (zero? 8) 2 3)))
256+
(asm-display (compile '(if (zero? 0) 1 2)))
257+
(asm-display (compile '(if (zero? 0) (if (zero? 0) 8 9) 2)))
258+
(asm-display (compile '(if (zero? (if (zero? 2) 1 0)) 4 5)))
259+
]
241260

261+
And confirm they are running as expected:
242262
@ex[
263+
(asm-interp (compile '(if (zero? 8) 2 3)))
243264
(asm-interp (compile '(if (zero? 0) 1 2)))
244-
(asm-interp (compile '(if (zero? 3) 1 2)))
245265
(asm-interp (compile '(if (zero? 0) (if (zero? 0) 8 9) 2)))
246266
(asm-interp (compile '(if (zero? (if (zero? 2) 1 0)) 4 5)))
247267
]
268+
269+
270+
@section[#:tag-prefix "con"]{Correctness and random testing}
271+
272+
The statement of correctness follows the same outline as before:
273+
274+
@bold{Compiler Correctness}: @emph{For all expressions @racket[e] and
275+
integers @racket[i], if (@racket[e],@racket[i]) in @render-term[C 𝑪],
276+
then @racket[(asm-interp (compile e))] equals @racket[i].}
277+
278+
Again, we formulate correctness as a property that can be tested:
279+
280+
@ex[
281+
(define (check-compiler e)
282+
(check-equal? (asm-interp (compile e))
283+
(interp e)
284+
e))]
285+
286+
Generating random Con programs is essentially the same as Blackmail
287+
programs, and are provided in a @link["con/random.rkt"]{random.rkt}
288+
module.
289+
290+
@ex[
291+
(eval:alts (require "random.rkt") (void))
292+
(random-expr)
293+
(random-expr)
294+
(random-expr)
295+
(random-expr)
296+
(for ([i (in-range 10)])
297+
(check-compiler (random-expr)))
298+
]
299+
300+
301+

www/notes/con/compile-file.rkt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
(define (main fn)
99
(with-input-from-file fn
1010
(λ ()
11-
(let ((p (read)))
11+
(let ((_ (read-line))
12+
(p (read)))
1213
(unless (expr? p) (error "syntax error" p))
1314
(asm-display (compile p))))))

www/schedule.scrbl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
@secref["Dupe"])
3030

3131
(list @wk{9/17}
32-
"A3" @;seclink["Assignment 3"]{A3}
32+
@seclink["Assignment 3"]{A3}
3333
@secref["Extort"]
3434
@secref["Fraud"])
3535

0 commit comments

Comments
 (0)