module Quox.Syntax.Term.Base import public Quox.Syntax.Var import public Quox.Syntax.Shift import public Quox.Syntax.Subst import public Quox.Syntax.Universe import public Quox.Syntax.Qty import public Quox.Syntax.Dim import public Quox.Name -- import public Quox.OPE import Quox.Pretty import public Data.DPair import Data.List import Data.Maybe import Data.Nat import public Data.So import Data.String import Data.Vect %default total infixl 8 :# infixl 9 :@ mutual public export TSubst : Nat -> Nat -> Nat -> Type TSubst d = Subst (\n => Elim d n) ||| first argument `d` is dimension scope size, second `n` is term scope size public export data Term : (d, n : Nat) -> Type where ||| type of types TYPE : (l : Universe) -> Term d n ||| function type Pi : (qty : Qty) -> (x : Name) -> (arg : Term d n) -> (res : ScopeTerm d n) -> Term d n ||| function term Lam : (x : Name) -> (body : ScopeTerm d n) -> Term d n ||| elimination E : (e : Elim d n) -> Term d n ||| term closure/suspended substitution CloT : (tm : Term d from) -> (th : Lazy (TSubst d from to)) -> Term d to ||| dimension closure/suspended substitution DCloT : (tm : Term dfrom n) -> (th : Lazy (DSubst dfrom dto)) -> Term dto n ||| first argument `d` is dimension scope size, second `n` is term scope size public export data Elim : (d, n : Nat) -> Type where ||| free variable F : (x : Name) -> Elim d n ||| bound variable B : (i : Var n) -> Elim d n ||| term application (:@) : (fun : Elim d n) -> (arg : Term d n) -> Elim d n ||| type-annotated term (:#) : (tm, ty : Term d n) -> Elim d n ||| term closure/suspended substitution CloE : (el : Elim d from) -> (th : Lazy (TSubst d from to)) -> Elim d to ||| dimension closure/suspended substitution DCloE : (el : Elim dfrom n) -> (th : Lazy (DSubst dfrom dto)) -> Elim dto n ||| a scope with one more bound variable public export data ScopeTerm : (d, n : Nat) -> Type where ||| variable is used TUsed : (body : Term d (S n)) -> ScopeTerm d n ||| variable is unused TUnused : (body : Term d n) -> ScopeTerm d n ||| a scope with one more bound dimension variable public export data DScopeTerm : (d, n : Nat) -> Type where ||| variable is used DUsed : (body : Term (S d) n) -> DScopeTerm d n ||| variable is unused DUnused : (body : Term d n) -> DScopeTerm d n %name Term s, t, r %name Elim e, f %name ScopeTerm body %name DScopeTerm body public export %inline Arr : (qty : Qty) -> (arg, res : Term d n) -> Term d n Arr {qty, arg, res} = Pi {qty, x = "_", arg, res = TUnused res} ||| same as `F` but as a term public export %inline FT : Name -> Term d n FT = E . F ||| abbreviation for a bound variable like `BV 4` instead of ||| `B (VS (VS (VS (VS VZ))))` public export %inline BV : (i : Nat) -> (0 _ : LT i n) => Elim d n BV i = B $ V i ||| same as `BV` but as a term public export %inline BVT : (i : Nat) -> (0 _ : LT i n) => Term d n BVT i = E $ BV i