Instructions:
(define-type LType
[UnitT]
[ProdT (t1 : LType) (t2 : LType)]
[SumT (t1 : LType) (t2 : LType)]
[FunT (arg : LType) (body : LType)]
[MuT (var : Symbol) (body : LType)]
[VarT (id : Symbol)])
(define-type LExp
[foldE (e : LExp)]
[unfoldE (e : LExp)]
[fixE (x : Symbol) (e : LExp)]
[varE (s : Symbol)]
[unitE]
[pairE (e1 : LExp) (e2 : LExp)]
[pi1E (e : LExp)]
[pi2E (e : LExp)]
[tag1E (e : LExp)]
[tag2E (e : LExp)]
[caseE (s : LExp)
(x : Symbol) (b1 : LExp)
(y : Symbol) (b2 : LExp)]
[lamE (id : Symbol) (body : LExp)]
[appE (fun : LExp) (arg : LExp)]
[annoE (e : LExp) (t : LType)])
We have provided you an interpreter for the LExp language (syntax given above) in the
starter code; you should not change this interpreter. We have also provided a
type checker and type synthesizer with some (but not all) cases already implemented.
An LType and LExp can be represented by the following CFG:
t ::= Unit | t x t | t + t | t -> t | mu a.t | a
e ::= fold(e) | unfold(e) | fix(x.e) | x | () | (e1, e2)
| pi1(e) | pi2(e) | tag1E(e) | tag2E(e)
| case(e, x.e1, y.e2) | λx.e | e1 e2 | (e : t)
Your task is to implement the missing cases in type-check and type-synth.
annoE).tag1E, tag2E, caseE).foldE and unfoldE)fixE)As usual, please include unit tests to make sure your implementation is working as expected for all the new cases.
Given the following encoding of natural numbers:
(define-type Nat
[Zero]
[Succ (n : Nat)])
(encode-nat : (Nat -> LExp))
(define (encode-nat n)
(type-case Nat n
[(Zero) zeroE]
[(Succ n) (foldE (tag2E (encode-nat n)))]))
;; Examples:
(define oneE (encode-nat (Succ (Zero))))
(define twoE (encode-nat (Succ (Succ (Zero)))))
Your task is to:
addE as a LExp (STLC+) expression.addE as a LType.