Skip to content

Commit 06911bc

Browse files
committed
Rework Extort notes.
1 parent 314aac0 commit 06911bc

4 files changed

Lines changed: 80 additions & 69 deletions

File tree

www/notes/dupe.scrbl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121

2222
@title[#:tag "Dupe"]{Dupe: a duplicity of types}
2323

24+
@emph{There are 10 types of values...}
25+
26+
@table-of-contents[]
27+
28+
@section{Integers and Booleans}
2429

2530
Up until now we have worked to maintain a single type of values:
2631
integers. This led to some awkwardness in the design of conditionals.

www/notes/extort.scrbl

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,6 @@ programs: values and errors. We will say that evaluation produces an
3737

3838
@section{Meaning of Extort programs}
3939

40-
The meaning of Extort programs...
41-
42-
@itemlist[
43-
44-
@item{...}
45-
46-
]
47-
48-
Let's consider some examples:
49-
50-
@itemlist[
51-
52-
@item{...}
53-
54-
]
55-
5640
Languages adopt several approaches to type mismatches:
5741

5842
@itemlist[
@@ -68,7 +52,18 @@ We've previously seen the last approach. Now let's do what Racket
6852
does and signal an error.
6953

7054

55+
The meaning of Extort programs that have type errors will now be
56+
defined as @racket['err]:
57+
58+
@itemlist[
59+
60+
@item{@racket[(add1 #f)]: means @racket['err].}
61+
62+
@item{@racket[(zero? #t)]: means @racket['err].}
7163

64+
@item{@racket[(if (zero? #f) 1 2)]: means @racket['err].}
65+
66+
]
7267

7368
@(define ((rewrite s) lws)
7469
(define lhs (list-ref lws 2))
@@ -99,40 +94,42 @@ And there are four rules for propagating errors from subexpressions:
9994

10095

10196

102-
Now what does the semantics say about @racket['(add1 #f)]? What about
103-
@racket['(if 7 #t -2)]?
97+
Now what does the semantics say about @racket[(add1 #f)]? What about
98+
@racket[(if 7 #t -2)]?
10499

105100

106-
The interpreter ...
101+
The signature of the interpreter is extended to produce answers. Each
102+
use of a Racket primitive is guarded by checking the type of the
103+
arguments and an error is produced if the check fails. Errors are
104+
also propagated when a subexpression produces an error:
107105

108106
@codeblock-include["extort/interp.rkt"]
109107

110108
We can confirm the interpreter computes the right result for the
111109
examples given earlier:
112110

113111
@ex[
114-
'...
112+
(interp '(add1 #f))
113+
(interp '(zero? #t))
114+
(interp '(if (zero? #f) 1 2))
115115
]
116116

117-
Correctness...
118-
119-
@section{An Example of Extort compilation}
120-
121-
Suppose we want to compile ...
117+
The statement of correctness stays the same, but now observe that
118+
there is no way to crash the interpreter with any @tt{Expr} value.
122119

123-
What needs to happen? ...
124120

125-
@;codeblock-include["extort/asm/ast.rkt"]
121+
@section{An Example of Extort compilation}
126122

127-
We omit the printer code, which is mundane. See
128-
@link["extort/asm/printer.rkt"]{@tt{asm/printer.rkt}} for details.
123+
Suppose we want to compile @racket[(add1 #f)], what needs to happen?
124+
Just as in the interpreter, we need to check the integerness of the
125+
argument's value before doing the addition operation.
129126

130-
We must extend the run-time system with a C function called @tt{error}
127+
We extend the run-time system with a C function called @tt{error}
131128
that prints "err" and exits:
132129

133130
@filebox-include[fancy-c "extort/main.c"]
134131

135-
Compiler...
132+
The compiler now emits code to check the type of arguments:
136133

137134
@codeblock-include["extort/compile.rkt"]
138135

@@ -156,4 +153,19 @@ Here are some examples running the compiler:
156153
(asm-interp (compile '(if (zero? #t) 1 2)))
157154
]
158155

156+
Since the interpreter and compiler have well defined specifications
157+
for what should happen when type errors occur, we can test in the
158+
usual way again:
159+
160+
@ex[
161+
(define (check-correctness e)
162+
(check-equal? (asm-interp (compile e))
163+
(interp e)
164+
e))
165+
166+
(check-correctness '(add1 7))
167+
(check-correctness '(add1 #f))
168+
]
169+
170+
159171

www/notes/extort/compile.rkt

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,60 @@
11
#lang racket
22
(provide (all-defined-out))
3-
(require "compile/help.rkt")
43

54
;; Expr -> Asm
65
(define (compile e)
76
`(entry
87
,@(compile-e e)
98
ret
109
err
11-
(push rbp) ; doesn't seem to matter what we push
10+
(push rbp) ; push before calling
1211
(call error)))
1312

1413
;; Expr -> Asm
1514
(define (compile-e e)
1615
(match e
1716
[(? integer? i)
18-
`((mov rax ,(arithmetic-shift i fixnum-shift)))]
17+
`((mov rax ,(* i 2)))]
1918
[(? boolean? b)
20-
`((mov rax ,(if b true-rep false-rep)))]
19+
`((mov rax ,(if b #b11 #b01)))]
2120
[`(add1 ,e0)
2221
(let ((c0 (compile-e e0)))
2322
`(,@c0
2423
,@assert-integer
25-
(add rax ,(arithmetic-shift 1 fixnum-shift))))]
24+
(add rax 2)))]
2625
[`(sub1 ,e0)
2726
(let ((c0 (compile-e e0)))
2827
`(,@c0
2928
,@assert-integer
30-
(sub rax ,(arithmetic-shift 1 fixnum-shift))))]
29+
(sub rax 2)))]
3130
[`(zero? ,e0)
32-
(let ((c0 (compile-e e0)))
31+
(let ((c0 (compile-e e0))
32+
(l0 (gensym))
33+
(l1 (gensym)))
3334
`(,@c0
3435
,@assert-integer
3536
(cmp rax 0)
36-
(sete al)
37-
(movzx rax al)
38-
(sal rax ,bool-shift)
39-
(or eax ,false-rep)))]
37+
(mov rax #b01) ; #f
38+
(jne ,l0)
39+
(mov rax #b11) ; #t
40+
,l0))]
4041
[`(if ,e0 ,e1 ,e2)
4142
(let ((c0 (compile-e e0))
4243
(c1 (compile-e e1))
43-
(c2 (compile-e e2)))
44-
(match (gen-if-labels)
45-
[(list if-f if-x)
46-
`(,@c0
47-
(cmp rax ,false-rep)
48-
(je ,if-f)
49-
,@c1
50-
(jmp ,if-x)
51-
,if-f
52-
,@c2
53-
,if-x)]))]))
54-
55-
(define true-rep #b10011111)
56-
(define false-rep #b00011111)
57-
(define fixnum-mask #b11)
58-
(define fixnum-shift 2)
59-
(define bool-shift 8)
44+
(c2 (compile-e e2))
45+
(l0 (gensym))
46+
(l1 (gensym)))
47+
`(,@c0
48+
(cmp rax #b01) ; compare to #f
49+
(je ,l0) ; jump to c2 if #f
50+
,@c1
51+
(jmp ,l1) ; jump past c2
52+
,l0
53+
,@c2
54+
,l1))]))
6055

6156
(define assert-integer
6257
`((mov rbx rax)
63-
(and rbx ,fixnum-mask)
58+
(and rbx 1)
6459
(cmp rbx 0)
6560
(jne err)))

www/notes/extort/main.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,29 @@
11
#include <stdio.h>
2-
#include <stdlib.h>
32
#include <inttypes.h>
3+
#include <stdlib.h>
44

5-
#define fixnum_mask 3
5+
#define fixnum_mask 1
66
#define fixnum_tag 0
7-
#define fixnum_shift 2
7+
#define fixnum_shift 1
88

9-
#define boolean_tag 31
10-
#define boolean_mask 127
11-
#define boolean_shift 7
9+
#define boolean_mask 1
10+
#define boolean_tag 1
11+
#define boolean_shift 1
1212

1313
int64_t entry();
1414

1515
int main(int argc, char** argv) {
1616
int64_t result = entry();
1717
if ((result & fixnum_mask) == fixnum_tag) {
18-
printf("%" PRId64 "\n", result >> fixnum_shift);
18+
printf("%" PRId64 "\n", result >> fixnum_shift);
1919
} else if ((result & boolean_mask) == boolean_tag) {
2020
if (result >> boolean_shift) {
2121
printf("#t\n");
2222
} else {
2323
printf("#f\n");
2424
}
25-
} else {
26-
printf("unknown value\n");
2725
}
26+
2827
return 0;
2928
}
3029

0 commit comments

Comments
 (0)