Skip to content

Commit 2c6d7ec

Browse files
authored
Merge pull request #18 from dvanhorn/next
Next
2 parents c66175b + a8fe3ff commit 2c6d7ec

9 files changed

Lines changed: 85 additions & 78 deletions

File tree

www/notes/blackmail/asm/interp.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#:exists 'truncate
1414
(λ ()
1515
(asm-display a)))
16-
(system (format "(cd ~a && make -s ~a)" dir t.run))
16+
(system (format "(cd ~a && make -s ~a) 2>&1 >/dev/null" dir t.run))
1717
(delete-file t.s)
1818
(with-input-from-string
1919
(with-output-to-string

www/notes/con/asm/interp.rkt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
#:exists 'truncate
1414
(λ ()
1515
(asm-display a)))
16-
(with-output-to-string ; ignore make output
17-
(λ ()
18-
(system (format "(cd ~a && make -s ~a)" dir t.run))))
16+
(system (format "(cd ~a && make -s ~a) 2>&1 >/dev/null" dir t.run))
1917
(delete-file t.s)
2018
(with-input-from-string
2119
(with-output-to-string

www/notes/con/syntax.rkt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
;; Is x a well-formed expression?
66
(define (expr? x)
77
(match x
8-
[(? symbol?) #t]
98
[(? integer? i) #t]
109
[`(add1 ,x) (expr? x)]
1110
[`(sub1 ,x) (expr? x)]

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/dupe/asm/interp.rkt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
#:exists 'truncate
1414
(λ ()
1515
(asm-display a)))
16-
(with-output-to-string ; ignore make output
17-
(λ ()
18-
(system (format "(cd ~a && make -s ~a)" dir t.run))))
16+
(system (format "(cd ~a && make -s ~a) 2>&1 >/dev/null" dir t.run))
1917
(delete-file t.s)
2018
(with-input-from-string
2119
(with-output-to-string

www/notes/extort.scrbl

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

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

17+
@(ev '(require rackunit))
1718
@(for-each (λ (f) (ev `(require (file ,(path->string (build-path notes "extort" f))))))
1819
'("interp.rkt" "compile.rkt" "asm/interp.rkt" "asm/printer.rkt"))
1920

@@ -37,22 +38,6 @@ programs: values and errors. We will say that evaluation produces an
3738

3839
@section{Meaning of Extort programs}
3940

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-
5641
Languages adopt several approaches to type mismatches:
5742

5843
@itemlist[
@@ -68,7 +53,18 @@ We've previously seen the last approach. Now let's do what Racket
6853
does and signal an error.
6954

7055

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

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

7369
@(define ((rewrite s) lws)
7470
(define lhs (list-ref lws 2))
@@ -99,40 +95,42 @@ And there are four rules for propagating errors from subexpressions:
9995

10096

10197

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

105101

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

108107
@codeblock-include["extort/interp.rkt"]
109108

110109
We can confirm the interpreter computes the right result for the
111110
examples given earlier:
112111

113112
@ex[
114-
'...
113+
(interp '(add1 #f))
114+
(interp '(zero? #t))
115+
(interp '(if (zero? #f) 1 2))
115116
]
116117

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

123-
What needs to happen? ...
124121

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

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

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

133131
@filebox-include[fancy-c "extort/main.c"]
134132

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

137135
@codeblock-include["extort/compile.rkt"]
138136

@@ -156,4 +154,19 @@ Here are some examples running the compiler:
156154
(asm-interp (compile '(if (zero? #t) 1 2)))
157155
]
158156

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

www/notes/extort/asm/interp.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#:exists 'truncate
1414
(λ ()
1515
(asm-display a)))
16-
(system (format "(cd ~a && make -s ~a)" dir t.run))
16+
(system (format "(cd ~a && make -s ~a) 2>&1 >/dev/null" dir t.run))
1717
(delete-file t.s)
1818
(with-input-from-string
1919
(with-output-to-string

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)