{-# LANGUAGE PackageImports #-} module AbsSynToTerm where import Terms import qualified RawSyntax as A import RawSyntax (Identifier(..)) import "transformers" Control.Monad.Trans.State (runStateT, StateT) import "transformers" Control.Monad.Trans.Reader import "transformers" Control.Monad.Trans.Error hiding (throwError) import "monads-fd" Control.Monad.Error import "monads-fd" Control.Monad.State import Control.Applicative import Data.Functor.Identity import Data.List import Basics type LocalEnv = [String] type GlobalEnv = () type Resolver a = ReaderT LocalEnv (StateT GlobalEnv (ErrorT String Identity)) a runResolver :: Resolver a -> a runResolver x = case runIdentity $ runErrorT $ runStateT (runReaderT x []) () of Left err -> error err Right a -> fst a look :: Identifier -> Resolver Term look (ident@(Identifier (position,x))) = do e <- ask case elemIndex x e of Nothing -> throwError ("unknown identifier: " ++ show ident) Just x -> return $ Bound (Irr position) x insertVar :: Identifier -> LocalEnv -> LocalEnv insertVar (Identifier (_pos,x)) e = x:e dummyVar :: Identifier dummyVar = Identifier ((0,0),"_") manyDep binder a [] b = resolveTerm b manyDep binder a (x:xs) b = binder (Irr x) <$> resolveTerm a <*> local (insertVar x) (manyDep binder a xs b) manyLam :: [A.Bind] -> A.Exp -> Resolver Term manyLam [] b = resolveTerm b manyLam (A.NoBind (A.AIdent x):xs) b = Lam (Irr x) (Hole dummyPosition "") <$> local (insertVar x) (manyLam xs b) manyLam (A.Bind (A.AIdent x) t:xs) b = Lam (Irr x) <$> resolveTerm t <*> local (insertVar x) (manyLam xs b) extractVars :: A.Exp -> Resolver [Identifier] extractVars (A.EVar (A.AIdent i)) = return [i] extractVars (A.EApp (A.EVar (A.AIdent i)) rest) = (i:) <$> extractVars rest extractVars _ = throwError "list of variables expected" resolveTerm :: A.Exp -> Resolver Term resolveTerm (A.EHole (A.Hole (p,x))) = return $ Hole (Irr p) x resolveTerm (A.EParam x) = Param <$> resolveTerm x resolveTerm (A.EDestr x (A.Natural n)) = Destroy (Relevance $ read n) <$> resolveTerm x resolveTerm (A.EUp x) = Shift (Sort 1 0) <$> resolveTerm x resolveTerm (A.ELeft x) = Shift oneRel <$> resolveTerm x resolveTerm (A.EVar (A.AIdent x)) = look x resolveTerm (A.ESet (A.Sort (p,'*':s))) = return $ Star (Irr p) $ Sort lvl rel where (l,r) = break (== '@') s lvl = read ('0':l) rel = case r of ('@':xs) -> Relevance $ read ('0':xs) _ -> 0 resolveTerm (A.EProj x (A.AIdent (Identifier (_,field)))) = Proj <$> resolveTerm x <*> pure field resolveTerm (A.EExtr x (A.AIdent (Identifier (_,field)))) = Extr <$> resolveTerm x <*> pure field resolveTerm (A.EApp f x) = (:$:) <$> resolveTerm f <*> resolveTerm x resolveTerm (A.ESigma a b) = case a of (A.EAnn vars a') -> do vs <- extractVars vars manyDep Sigma a' vs b (A.EAbs _ _ _) -> throwError "cannot use lambda for type" _ -> Sigma (Irr dummyVar) <$> resolveTerm a <*> local (insertVar dummyVar) (resolveTerm b) resolveTerm (A.EPi a _arrow_ b) = case a of (A.EAnn vars a') -> do vs <- extractVars vars manyDep Pi a' vs b (A.EAbs _ _ _) -> throwError "cannot use lambda for type" _ -> Pi (Irr dummyVar) <$> resolveTerm a <*> local (insertVar dummyVar) (resolveTerm b) resolveTerm (A.EAbs ids _arrow_ b) = manyLam ids b resolveTerm (A.EPair (A.Decl (A.AIdent i) e) rest) = Pair (Irr i) <$> resolveTerm e <*> local (insertVar i) (resolveTerm rest) resolveTerm (A.EPair (A.PDecl (A.AIdent i) e t) rest) = Pair (Irr i) <$> (Ann <$> (OfParam (Irr i) <$> resolveTerm e) <*> resolveTerm t) <*> local (insertVar i) (resolveTerm rest) resolveTerm (A.EAnn e1 e2) = Ann <$> resolveTerm e1 <*> resolveTerm e2