--

data ObjType:: *1 where
 ArrT:: ObjType ~> ObjType ~> ObjType
 IntT:: ObjType
 ProdT::  ObjType ~> ObjType ~> ObjType

data Rel:: ObjType ~> *0 ~> *0 where
 IntR:: Rel IntT Int
 IntTo:: Rel b s -> Rel (ArrT IntT b) (Int -> s)
   -- First order functions only as constants

data Mode:: *1 where
 Exp:: Mode
 Val:: Mode

data E:: Mode ~> Row Tag ObjType ~> ObjType ~> *0  where
  Const:: Rel a b -> b -> E Val env a
  Var  :: Label s -> E Val (RCons s t env) t
  Shift:: E m env t -> E m (RCons s q env) t
  Lam  :: Label a -> E m (RCons a s env) t -> E Val env (ArrT s t)
  App  :: E m1 env (ArrT s t) -> E m2 env s -> E Exp env t
  Pair :: E m1 env t -> E m2 env s -> E Exp env (ProdT t s)


exp1 = Lam `f (Lam `y (App (Shift(Var `f)) (Var `y)))
int n = Const IntR n
oper x = Const (IntTo (IntTo IntR)) x

t3 = Shift (Lam `x (Pair (Var `x) (Shift (Var `y))))

one = int 1
plus = oper (+)

data Shifter:: Row Tag ObjType ~> Row Tag ObjType ~> *0 where
   Zs :: Shifter env env
   Sz :: Shifter (RCons a b e1) e2 -> Shifter e1 e2
   Bind:: Shifter e g -> Shifter (RCons s b e) (RCons s b g)
 deriving syntax(s) Nat(Zs,Sz)

-- (Shifter _e _g -> Shifter {_s=_b; _e}r {_s=v; w}r)

down:: Shifter e1 e2 -> E m e1 t -> E m e2 t
down d (App x y) = App (down d x) (down d y)
down d (Pair x y) = Pair (down d x) (down d y)
down d (t@(Shift x)) = down (Sz d) x
down d (Var c) = push d (Var c)
down d (Const p x) = Const p x
down d (t@(Lam c body)) = Lam c (down (Bind d) body)


push:: Shifter e1 e2 -> E Val e1 t -> E Val e2 t
push (d@Zs) (t@(Var c)) = Var c
push (d@Zs) (t@(Shift c)) = Shift c
push (Sz d) x = push d (Shift x)
push (d@(Bind n)) (t@(Var c)) = Var c
push (d@(Bind n)) (t@(Shift c)) = Shift(push n c)

bump x = down Zs x

--