@@ -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-
5640Languages 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
6852does 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
110108We can confirm the interpreter computes the right result for the
111109examples 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}
131128that 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
0 commit comments