pisigma-0.1.0.2: src/PiSigma/Syntax.hs
{-# LANGUAGE TypeSynonymInstances #-}
module PiSigma.Syntax where
import Prelude hiding (pi)
-- * Abstract syntax
data Phrase = Prog Prog | Term Term
deriving (Show,Eq)
type Name = String
type Label = String
data Entry = Decl Name Type | Defn Name Term
deriving (Show,Eq)
type Prog = [Entry]
{-
Maybe better
data Prog = Decl Type (Bind Prog) | Defn Name Term Prog
-}
type Type = Term
-- | The use of Bind indicates the scope of the
-- bound identifier.
type Bind a = (Name,a)
-- | For treating quantifiers in a uniform way.
data PiSigma = Pi | Sigma
deriving (Show,Eq)
data Term =
Var String
| Let Prog Term
| Type
| Q PiSigma (Type,Bind Type)
| Lam (Bind Term)
| Term :. Term
| Pair (Term,Term)
| Split Term (Bind (Bind Term)) -- split t with (x,y) -> u
| Enum [Label]
| Label Label
| Case Term [(Label,Term)] -- case t of { L -> u }
| Lift Term
| Box Term
| Force Term
deriving (Show,Eq)
-- * Smart constructors
-- | Smart constructor for lambda abstractions.
lam :: [Name] -> Term -> Term
lam [] t = t
lam (x:xs) t = Lam (x,lam xs t)
-- | Smart constructor for split.
split :: Term -> Name -> Name -> Term -> Term
split t1 x y t2 = Split t1 (x,(y,t2))
-- | Smart constructor for quantifiers.
q :: PiSigma -> [(Name,Type)] -> Type -> Type
q ps [] b = b
q ps ((x,a):xas) b = Q ps (a,(x,q ps xas b))
-- | Smart constructor for multiple Pi applications.
pis' :: [(Name,Type)] -> Type -> Type
pis' = q Pi
-- | Smart constructor for multiple Pi applications.
pis :: [Name] -> Type -> Type -> Type
pis ns t = pis' (map (\ n -> (n,t)) ns)
-- | Smart constructor for Pi.
pi :: Name -> Type -> Type -> Type
pi n t = pis' [(n,t)]
-- | Smart constructor for multiple Sigma applications.
sigmas' :: [(Name,Type)] -> Type -> Type
sigmas' = q Sigma
-- | Smart constructor for multiple Sigma applications.
sigmas :: [Name] -> Type -> Type -> Type
sigmas ns t = sigmas' (map (\ n -> (n,t)) ns)
-- | Smart constructor for Sigma.
sigma :: Name -> Type -> Type -> Type
sigma n t = sigmas' [(n,t)]
-- | Smart constructor for function space.
(->-) :: Type -> Type -> Type
(->-) = pi ""
-- | Smart constructor for product.
(-*-) :: Type -> Type -> Type
(-*-) = sigma ""
-- * Values (well-scoped WHNFs) and environments
-- ** Identifiers
type Id = Int -- index in (potentially multiple) environments
-- ** Scopes
data Scope = Scope [(Name,(Id,Maybe (Clos Type)))]
deriving (Show,Eq)
{-
TODO:
Perhaps return to the following types for scopes:
data Sc a = Scope [(Name,(Id, a))]
type Scope = Sc ()
type Ctx = Sc (Clos Type)
We then need a forgetful mapping:
fog :: Ctx -> Scope
fog c = map (\ (x,(i,a)) -> (x,(i,()))) c
Alternatively, we can try to make Scopes
existential, essentially:
type Scope = exists a. Sc a
-}
emptyScope :: Scope
emptyScope = Scope []
extendScope :: Scope -> Name -> (Id,Maybe (Clos Type)) -> Scope
extendScope (Scope s) x (i,a) = Scope ((x,(i,a)) : s)
lookupScope :: Scope -> Name -> Maybe Id
lookupScope (Scope s) x = do (i,_) <- lookup x s
return i
lookupCon :: Scope -> Name -> Maybe (Clos Type)
lookupCon (Scope s) x = do (_,Just a) <- lookup x s
return a
-- ** Closures
type Clos a = (a,Scope)
--type C a = (Con,a)
--c2clos :: C a -> Clos a
--c2clos (g,a) = (a,fog g)
-- fix order, name of C...
class Closure a where
getScope :: a -> Scope
putScope :: a -> Scope -> a
instance Closure (Clos a) where
getScope (_,s) = s
putScope (a,_) s = (a,s)
instance Closure a => Closure (Bind a) where
getScope (_,a) = getScope a
putScope (x,a) s = (x,putScope a s)
instance Closure Boxed where
getScope (Boxed c) = getScope c
putScope (Boxed c) s = Boxed (putScope c s)
{- could be used to refactor the code using bindings. -}
ty :: Clos Type
ty = (Type,emptyScope)
label :: String -> Clos Term
label s = (Label s,emptyScope)
type VType = Val
newtype Boxed = Boxed (Clos Term) deriving (Show,Eq)
-- ** Values
data Val =
Ne Ne
| VType
| VQ PiSigma (Clos (Type,Bind Type))
| VLift (Clos Type)
| VLam (Bind (Clos Term))
| VPair (Clos (Term, Term))
| VEnum [Label]
| VLabel Label
| VBox Boxed
deriving (Show,Eq)
-- | Neutral terms.
data Ne =
NVar Id
| Ne :.. (Clos Term)
| NSplit Ne (Bind (Bind (Clos Term)))
| NCase Ne (Clos [(Label,Term)])
| NForce Ne
deriving (Show,Eq)
-- ** Environments
data EnvEntry = Id Id | Closure (Clos Term) deriving Show
data PrtInfo = PrtInfo {name :: Name, expand :: Bool}
class Env e where
emptyE :: e
extE :: e -> PrtInfo -> (Id,e)
setE :: e -> Id -> EnvEntry -> e
getE :: e -> Id -> EnvEntry
prtE :: e -> Id -> PrtInfo
set :: [a] -> Int -> a -> [a]
set (a:as) 0 b = b:as
set (a:as) i b = a:set as (i-1) b
type EnvEntries = [(EnvEntry,PrtInfo)]
instance Env EnvEntries where
emptyE = []
extE e x = let i = length e in (i,e++[(Id i,x)])
setE e i v = let (_,x) = e!!i in set e i (v,x)
getE e i = let (v,_) = e!!i in v
prtE e i = let (_,x) = e!!i in x