Background
In this tutorial you will get more familiar with typechecking and (in particular) the unification based interpreter discussed in Lecture 14.
Step 0
Download the unification based TIFAE interpreter. You will modify this interpeter in the remaining steps of this tutorial.
Step 1
Add a With variant to the FAE type, and add dummy clauses (using
....) to the type-case statements in eval and typecheck. Extend the parser for with using e.g.
[(s-exp-match? `(with (SYMBOL ANY) ANY) sx)
(let* ([def (sx-ref sx 1)]
[id (s-exp->symbol (sx-ref def 0))]
[val (parse (sx-ref def 1))]
[expr (px 2)])
(With id val expr))]
Step 2
If needed, consult your notes for some of the previous interpreters
(e.g. the one discussed in Lecture 8)
to implement the eval functionality for With.
Add the following tests to your interpeter.
(test (run `{with {add3 {fun {x : ?} {+ x 3}}}
{with {add1 {fun {x : ?} {+ x 1}}}
{with {x 3}
{add1 {add3 x}}}}})
(NumV 7))
(test (run `{with {identity {fun {x : ?} x}}
{with {foo {fun {x : ?} {+ x 1}}}
{{identity foo}
123}}})
(NumV 124))
(test (run `{with {x 3}
{with {f {fun {y : ?} {+ x y}}}
{with {x 5}
{f 4}}}})
(NumV 7))
Step 3
Consider the following typechecking rule for with.
Γ ⊢ e₁ : τ₁, Γ[x←τ₁] ⊢ e₂ : τ₂
——————————————————————————————–
Γ ⊢ {with {x e₁} e₂} : τ₂
Impliment this rule in your typecheck function. It is possible to do
this without explicitly calling unify!. The skeleton of my solution is as follows:
[(With id bound-exp body)
(let* ([id-type ....]
[new-env ....])
(typecheck ....))]
Your completed interpreter should pass the following tests
(test/type
`{with {add3 {fun {x : ?} {+ x 3}}}
{with {add1 {fun {x : ?} {+ x 1}}}
{with {x 3}
{add1 {add3 x}}}}}
(NumT))
(test/type
`{with {identity {fun {x : ?} x}}
{with {foo {fun {x : ?} {+ x 1}}}
{{identity foo}
123}}}
(NumT))
(test/type
`{with {x 3}
{with {f {fun {y : ?} {+ x y}}}
{with {x 5}
{f 4}}}}
(NumT))
Notice the use of
test/typein the tests. Can you make equivalent tests without usingtest/typeorunify!?Why do we not need to specify a type annotation for
xin thewithform? Compare withfunin the same language.
Step 4 (Optional)
- If you have extra time, try implimenting
withusing the equivalence
{with {x e₁} e₂}
;; is equivalent to
{call {fun {x} e₂} e₁}
- Here you have to specify a type for
x,?or(GuessTE)should work.