{-# LANGUAGE GADTs, ExistentialQuantification, EmptyDataDecls #-}

module Interp2 where

-- No scoping errors for this interpreter
-- Typing errors still possible

import NList

-- Exp is indexed by 'n' the largest de Bruijn level
-- Note that this isn't a 'real' GADT
data Exp n =
    Var (LT n)     --- LT is the type of numbers less than n
  | Lit Int
  | Lam (Exp (S n)) 
  | App (Exp n) (Exp n) 

--
-- Can't derive Show anymore because of parameter to Exp
instance Show (Exp n) where
  show (Var lt)  = show lt
  show (Lit i)   = "(Lit " ++ show i ++ ")"
  show (Lam t)   = "(Lam " ++ show t ++ ")"
  show (App t u) = "(App " ++ show t ++ " " ++ show u ++ ")"

--- The environment is a list of n values

type Env n = List n Value 

data Value = 
    Const Int
    -- the environment captured in the closure must be the right
    -- length for the term 
  | forall n. Clos (Env n) (Exp (S n)) 

instance Show Value where
  show (Const i)  = show i
  show (Clos e t) = "Clos " ++ show e ++ " " ++ show t ++ ")" 


extend :: Value -> Env n -> Env (S n)
extend v e = (Cons v e)

interp :: Env n -> Exp n -> Value
interp e (Var x)   = sLookup x e
interp e (Lit i)   = Const i
interp e (Lam t) = Clos e t
interp e (App t1 t2) = 
  case interp e t1 of
    (Clos e' t) -> interp (extend (interp e t2) e') t
    _  -> error "Type error"


t0 = interp Nil (App (Lam (Var Z)) (Lit 2))

-- doesn't type check
-- t1 = interp nil (Var (s z))

t2 = interp Nil (App (Lit 2) (Lit 3))
