/ src / Core.hs
Core.hs
  1  module Core where
  2  
  3  import Control.Exception (assert)
  4  import Control.Monad (unless)
  5  
  6  type Idx = Int
  7  
  8  type Lvl = Int
  9  
 10  type Stage = Int
 11  
 12  type Name = String
 13  
 14  data Raw
 15    = RVar Name
 16    | RLam Name Raw
 17    | RLet Stage Name Raw Raw Raw
 18    | RApp Raw Raw
 19    | RPi Name Raw Raw
 20    | RU Stage
 21    | RQuote Raw
 22    | RSplice Raw
 23    | RLift Raw
 24  
 25  data Term
 26    = Var Idx
 27    | Lam Term -- \idx. t
 28    | Let Stage Term Term Term -- let s idx: A = t in y
 29    | App Term Term
 30    | Pi Term Term -- (idx: A) -> B
 31    | U Stage
 32    | Quote Term
 33    | Splice Term
 34    | Lift Term
 35    deriving (Eq, Show)
 36  
 37  data Value
 38    = VRigid Lvl FrameStack
 39    | VLam Closure
 40    | VPi Value Closure
 41    | VU Stage
 42    | VQuote Value
 43    | VLift Value
 44    deriving Show
 45  
 46  data FrameStack
 47    = SNil
 48    | SApp FrameStack Value
 49    | SSplice FrameStack
 50    deriving Show
 51  
 52  type Env = [Value]
 53  data Closure = Closure Env Term deriving Show
 54  
 55  pattern VVar :: Lvl -> Value
 56  pattern VVar x = VRigid x SNil
 57  
 58  ($$) :: Closure -> Value -> Value
 59  (Closure env t) $$ b = eval (b : env) t
 60  
 61  -- Evaluation
 62  
 63  app :: Value -> Value -> Value
 64  app (VLam f) u = f $$ u
 65  app (VRigid l stack) u = VRigid l (SApp stack u)
 66  app _ _ = error "bad application"
 67  
 68  eval :: Env -> Term -> Value
 69  eval env (Var x) = env !! x
 70  eval env (Lam t) = VLam $ Closure env t
 71  eval env (Let _a_stage _a_ty a b) = eval (eval env a : env) b
 72  eval env (App t u) = app (eval env t) (eval env u)
 73  eval env (Pi a b) = VPi (eval env a) (Closure env b)
 74  eval _env (U s) = VU s
 75  eval env (Quote t) = case eval env t of
 76    VRigid x (SSplice stack) -> VRigid x stack
 77    t' -> VQuote t'
 78  eval env (Splice t) = case eval env t of
 79    VQuote t' -> t'
 80    VRigid x stack -> VRigid x (SSplice stack)
 81    _ -> error "bad splice"
 82  eval env (Lift t) = VLift (eval env t)
 83  
 84  -- | idx + lvl + 1 = lvl_max <==> lvl_max - lvl - 1 = idx
 85  lvl2idx :: Lvl -> Lvl -> Idx
 86  lvl2idx lvl_max lvl = lvl_max - lvl - 1
 87  
 88  reify :: Lvl -> Value -> Term
 89  reify lvl (VRigid l sp) = reify_stack (Var $ lvl2idx lvl l) sp
 90    where
 91      reify_stack :: Term -> FrameStack -> Term
 92      reify_stack t SNil = t
 93      reify_stack t (SApp stack u) = App (reify_stack t stack) (reify lvl u)
 94      reify_stack t (SSplice stack) = Splice (reify_stack t stack)
 95  reify lvl (VLam f) = Lam (reify (lvl + 1) (f $$ VVar lvl))
 96  reify lvl (VPi a b) = Pi (reify lvl a) (reify (lvl + 1) (b $$ VVar lvl))
 97  reify _lvl (VU s) = U s
 98  reify lvl (VLift t) = Lift (reify lvl t)
 99  reify lvl (VQuote t) = Quote (reify lvl t)
100  
101  data Ctx = Ctx
102    { env :: [Value]
103    , tyenv :: [(Value, Stage)]
104    }
105  
106  nf :: Env -> Term -> Term
107  nf env = reify (length env) . eval env
108  
109  conv :: Lvl -> Value -> Value -> Bool
110  conv lvl t u = reify lvl t == reify lvl u
111  
112  -- Typechecking
113  
114  check :: Ctx -> Term -> Value -> Stage -> Either String ()
115  check ctx (Lam t) (VPi a b) stage = do
116    let ctx' = ctx{tyenv = (a, stage) : ctx.tyenv, env = VVar (length ctx.env) : ctx.env}
117    check ctx' t (b $$ VVar (length ctx.env)) stage
118  check ctx (Lift ty) (VU 1) _stage = check ctx ty (VU 0) 0
119  check ctx (Quote t) (VLift ty) _stage = check ctx t ty 0
120  check ctx (Let a_stage a_ty a b) ty stage = do
121    check ctx a_ty (VU a_stage) stage
122    let a_ty' = eval ctx.env a_ty
123    check ctx a a_ty' a_stage
124    let ctx' = ctx{env = eval ctx.env a : ctx.env, tyenv = (a_ty', a_stage) : ctx.tyenv}
125    check ctx' b ty stage
126  check ctx t ty stage = do
127    (ty', stage') <- infer ctx t
128    let lvl = length ctx.env
129    unless (conv lvl ty ty' && stage == stage') $
130      Left "Inferred type different from expected type"
131  
132  infer :: Ctx -> Term -> Either String (Value, Stage)
133  infer ctx (Var x) = pure $ ctx.tyenv !! x
134  infer ctx (App t u) = do
135    (t_ty, stage) <- infer ctx t
136    case t_ty of
137      VPi a b -> do
138        check ctx u a stage -- check function input
139        pure (b $$ eval ctx.env u, stage)
140      _ -> Left "Expected function type in application head"
141  infer _ctx (U s) = pure (VU s, s)
142  infer ctx (Pi a b) = do
143    (a_ty, stage) <- infer ctx a
144    let ctx' = ctx{tyenv = (a_ty, stage) : ctx.tyenv, env = eval ctx.env a : ctx.env}
145    check ctx' b (VU stage) stage
146    pure (VU stage, stage)
147  infer ctx (Lift t) = do check ctx t (VU 0) 0; pure (VU 1, 1)
148  infer ctx (Splice t) = do
149    (t_ty, stage) <- infer ctx t
150    unless (stage == 1) $ Left "Not meta language term in splice."
151    case t_ty of
152      VLift t_ty' -> pure (t_ty', 0)
153      _ -> Left "Bad Splice"
154  infer ctx (Quote t) = do
155    (t_ty, stage) <- infer ctx t
156    unless (stage == 0) $ Left "Not object language term in quote "
157    pure (VLift t_ty, 1)
158  infer ctx (Let a_stage a_ty a b) = do
159    check ctx a_ty (VU a_stage) a_stage
160    let a_ty' = eval ctx.env a_ty
161    check ctx a a_ty' a_stage
162    let ctx' = ctx{env = eval ctx.env a : ctx.env, tyenv = (a_ty', a_stage) : ctx.tyenv}
163    infer ctx' b
164  infer _ _ = Left "Couldn't infer type"
165  
166  -- Staging
167  
168  stage_term :: Term -> Term
169  stage_term = reify0 0 . eval0 []
170  
171  type StagingEnv = [Either Value0 Value1]
172  
173  data Value0
174    = VVar0 Idx
175    | VLam0 (Value0 -> Value0)
176    | VPi0 Value0 (Value0 -> Value0)
177    | VU0
178    | VApp0 Value0 Value0
179    | VLet0 Value0 Value0 (Value0 -> Value0)
180  
181  data Value1
182    = VLam1 (Value1 -> Value1)
183    | VQuote1 Value0
184    | -- vvv these apparently can be ignored
185      VPi1 Value1 (Value1 -> Value1)
186    | VU1
187    | VLift1 Value0
188  
189  eval1 :: StagingEnv -> Term -> Value1
190  eval1 env (Var x) = case env !! x of
191    Left _ -> error "Value0 in Value1 context"
192    Right v -> v
193  eval1 env (Lam t) = VLam1 (\u -> eval1 (Right u : env) t)
194  eval1 env (App t u) = case eval1 env t of
195    VLam1 t' -> t' $ eval1 env u
196    _ -> error "bad application during staging"
197  eval1 env (Pi a b) = VPi1 (eval1 env a) (\a' -> eval1 (Right a' : env) b)
198  eval1 _env (U s)
199    | s == 1 = VU1
200    | s == 0 = error "U 0 in Value1 context"
201    | otherwise = error "unreachable"
202  eval1 env (Quote t) = VQuote1 $ eval0 env t
203  eval1 env (Let a_stage _a_ty a b) = assert (a_stage == 1) $ eval1 (Right (eval1 env a) : env) b
204  eval1 _env (Splice _t) = error "splice in Value1 context"
205  eval1 env (Lift t) = VLift1 $ eval0 env t
206  
207  eval0 :: StagingEnv -> Term -> Value0
208  -- why does this actually do a lookup instead of constructing a VVar0?
209  eval0 env (Var x) = case env !! x of
210    Left v -> v
211    Right _ -> error "Value1 in Value0 context"
212  eval0 env (Lam t) = VLam0 $ \u -> eval0 (Left u : env) t
213  eval0 env (App t u) = VApp0 (eval0 env t) (eval0 env u)
214  eval0 env (Pi a b) = VPi0 (eval0 env a) (\a' -> eval0 (Left a' : env) b)
215  eval0 _env (U s)
216    | s == 1 = error "U 1 in Value0 context"
217    | s == 0 = VU0
218    | otherwise = error "unreachable"
219  eval0 _env (Quote _) = error "Quote in Value0 context"
220  eval0 env (Let a_stage a_ty a b) =
221    assert (a_stage == 0) $
222      VLet0 (eval0 env a_ty) (eval0 env a) (\a' -> eval0 (Left a' : env) b)
223  eval0 env (Splice t) = case eval1 env t of
224    VQuote1 v -> v
225    _ -> error "Splice didn't return quote"
226  eval0 _env (Lift _) = error "Lifted type in Value0 context"
227  
228  reify0 :: Lvl -> Value0 -> Term
229  reify0 lvl (VVar0 x) = Var $ lvl2idx lvl x
230  reify0 lvl (VLam0 t) = Lam $ reify0 (lvl + 1) (t $ VVar0 lvl)
231  reify0 lvl (VPi0 a b) = Pi (reify0 lvl a) $ reify0 (lvl + 1) (b $ VVar0 lvl)
232  reify0 _lvl VU0 = U 0
233  reify0 lvl (VApp0 t u) = App (reify0 lvl t) (reify0 lvl u)
234  reify0 lvl (VLet0 a_ty a b) = Let 0 (reify0 lvl a_ty) (reify0 lvl a) (reify0 (lvl + 1) (b $ VVar0 lvl))