Skip to content

Commit cc85367

Browse files
committed
Start of project write-ups.
1 parent e8efe92 commit cc85367

1 file changed

Lines changed: 131 additions & 2 deletions

File tree

www/project.scrbl

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,136 @@
11
#lang scribble/manual
22
@(require "defns.rkt")
3+
@(require "notes/ev.rkt")
4+
35
@title[#:style '(unnumbered)]{Project}
46

7+
The final assesment for this course consists of an individually
8+
completed project.
9+
10+
Final deliverables are due by the end of the time schedule for the
11+
class's final exam as set by the registrar.
12+
13+
Submissions should be made on Gradescope.
14+
15+
There are several projects to choose from, described below.
16+
17+
@section{Exceptions and Exception Handling}
18+
19+
Exceptions and exception handling mechanisms are widely used in modern
20+
programming languages. Implement Racket's @racket[raise] and
21+
@racket[with-handlers] forms to add exception handling.
22+
23+
You may choose to implement this feature for any language that is
24+
@seclink["Iniquity"]{Iniquity} or later for a maximum 95% of the
25+
possible points. For 100% you'll need to implement the feature for
26+
Perp and do the additional requirements below.
27+
28+
@subsection{Requirements}
29+
30+
Here are the key features that need to be added:
31+
32+
@itemlist[
33+
34+
@item{@racket[(raise _e)] will evaluate @racket[_e] and then ``raise''
35+
the value, side-stepping the usual flow of control and instead jump
36+
to the most recently installed exception handler.}
37+
38+
@item{@racket[(with-handlers ([_p1 _f1] ...) _e)] will install a new
39+
exception handler during the evaluation of @racket[_e]. If
40+
@racket[_e] raises an exception that is not caught, the predicates
41+
should be applied to the raised value until finding the first
42+
@racket[_pi] that returns true, at which point the corresponding
43+
function @racket[_fi] is called with the raised value and the result
44+
of that application is the result of the entire @racket[with-handlers]
45+
expression. If @racket[_e] does not raise an error, its value is the
46+
value of the @racket[with-handler] expression.}
47+
48+
]
49+
50+
Here are some examples to help illustrate:
51+
52+
@ex[
53+
54+
(with-handlers ([string? (λ (s) (cons "got" s))])
55+
(raise "a string!"))
56+
57+
(with-handlers ([string? (λ (s) (cons "got" s))]
58+
[number? (λ (n) (+ n n))])
59+
(raise 10))
60+
61+
(with-handlers ([string? (λ (s) (cons "got" s))]
62+
[number? (λ (n) (+ n n))])
63+
(+ (raise 10) 30))
64+
65+
(let ((f (λ (x) (raise 10))))
66+
(with-handlers ([string? (λ (s) (cons "got" s))]
67+
[number? (λ (n) (+ n n))])
68+
(+ (f 10) 30)))
69+
70+
(with-handlers ([string? (λ (s) (cons "got" s))]
71+
[number? (λ (n) (+ n n))])
72+
'nothing-bad-happens)
73+
74+
(with-handlers ([symbol? (λ (s) (cons 'reraised s))])
75+
(with-handlers ([string? (λ (s) (cons "got" s))]
76+
[number? (λ (n) (+ n n))])
77+
(raise 'not-handled-by-inner-handler)))
78+
79+
]
80+
81+
Notice that when a value is raised, the enclosing context is discard.
82+
In the third example, the surrounding @racket[(+ [] 30)] part is
83+
ignored and instead the raised value @racket[10] is given the
84+
exception handler predicates, selecting the appropriate handler.
85+
86+
Thinking about the implementation, what this means is that a portion
87+
of the stack needs to be discarded, namely the area between the
88+
current top of the stack and the stack that was in place when the
89+
@racket[with-handlers] expression was evaluated.
90+
91+
This suggestions that a @racket[with-handlers] expression should stash
92+
away the current value of @racket['rsp]. When a @racket[raise]
93+
happens, it grabs the stashed away value and installs it as the
94+
current value of @racket['rsp], effectively rolling back the stack to
95+
its state at the point the exception handler was installed. It should
96+
then jump to code that will carry out the applying of the predicates
97+
and right-hand-side functions.
98+
99+
Since @racket[with-handler]s can be nested, you will need to maintain
100+
an arbitrarily large collection of exception handlers, each of which
101+
has a pointer into the stack and a label for the code to handle the
102+
exception. This collection should operate like a stack: each
103+
@racket[with-handlers] expression adds a new handler to the handler
104+
stack. If the body expression returns normally, the top-most handler
105+
should be removed. When a raise happens, the top-most handler is
106+
popped and used.
107+
108+
@subsection{Additional requirements}
109+
110+
To receive full credit, you will to add the above features to Perp and
111+
do the following.
112+
113+
After you have a working implementation of @racket[raise] and
114+
@racket[with-handlers], add a structure definition to your standard
115+
library: @racket[(struct exn:fail (msg cm))]. Rework the compiler so
116+
that all run-time errors raise an instance of @racket[struct:fail].
117+
This enables user-programs to handle run-time errors like this:
118+
119+
@ex[
120+
121+
(with-handlers ([exn:fail? (λ (e) 'OK)])
122+
(add1 #f))
123+
124+
]
125+
126+
(The @racket[cm] field can be ignored; you can always populate it with
127+
@racket[#f] if you'd like. It's there just for consistency with
128+
Racket's @racket[exn:fail].)
129+
130+
131+
132+
133+
5134
There will be a final course project to be completed over the last
6135
several weeks of the course. The project will involve extending the
7136
design and implementation of the programming language and its compiler
@@ -48,13 +177,13 @@ semester:
48177

49178
@item{Typing Loot. We have discussed typing for @tt{Hustle} and its
50179
implications in the compiler (deleting a whole lot of assertions), as
51-
well as typing for a simple lambda calculus. This project would aim
180+
well as typing for a simple λ calculus. This project would aim
52181
to combine the two threads, implementing a type system on top of Loot.
53182
There are interesting design decisions here, so feel free to reach out
54183
to talk about them!}
55184

56185
@item{Loot Optimizations. Sky's the limit here. You can try
57-
high-level optimizations (e.g. inlining, lambda lifting, dead-code
186+
high-level optimizations (e.g. inlining, λ lifting, dead-code
58187
elimination, partial evaluation, etc.) or low-level ones (register
59188
allocation, register-based calling conventions etc.). Optimizations
60189
can be tricky to get right, so make sure you reuse all the unit

0 commit comments

Comments
 (0)