UNB/ CS/ David Bremner/ teaching/ cs4613/ lectures/ lecture7/ snippet-014.rkt
#lang plait
(define-type FLANG
  [Num  (val : Number)]
  [Add  (l : FLANG) (r : FLANG)]
  [Sub  (l : FLANG) (r : FLANG)]
  [Mul  (l : FLANG) (r : FLANG)]
  [Div  (l : FLANG) (r : FLANG)]
  [Id   (name : Symbol)]
  [Let1 (id : Symbol) (named-expr : FLANG) (bound-body : FLANG)]
  [Lam  (param : Symbol) (body : FLANG)]
  [Call (fun : FLANG) (val : FLANG)]) ; first type!
(define-type ENV
  [EmptyEnv]
  [Extend (name : Symbol) (val : VAL) (rest : ENV)])

(define-type VAL
  [NumV (n : Number)]
  [FunV (arg : Symbol) (body : FLANG) (env : ENV)])
(module+ test
  (test/exn (lookup 'x (EmptyEnv)) "no binding")
  (test/exn (lookup 'y (Extend 'x (NumV 1) (EmptyEnv))) "no binding")
  (test (lookup 'y (Extend 'y (NumV 1) (EmptyEnv))) (NumV 1)))

(define (lookup name env)
  (type-case ENV env
    [(EmptyEnv)  (error 'lookup "no binding")]
    [(Extend id val rest-env)
     (if (eq? id name) 
         val 
         (lookup name rest-env))]))