systemqfw

system Q F omega elaborator
git clone git://git.rr3.xyz/systemqfw
Log | Files | Refs | Submodules | LICENSE

commit d9f8021abfe73b38a5de9e93cc2bf5152baf5098
parent 28f3bc9cd70267578af66975c8216ca595fcc2e3
Author: Robert Russell <robert@rr3.xyz>
Date:   Thu, 29 Aug 2024 00:10:11 -0700

Add means to declare types

Diffstat:
MMain.hs | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
MParser.hs | 10++++++++--
2 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/Main.hs b/Main.hs @@ -3,10 +3,13 @@ import Control.Monad import Control.Monad.Except import Control.Monad.Reader import Data.ByteString (ByteString) +import Data.Foldable (foldlM) import qualified Data.ByteString as ByteString import Sparsec +import System.Exit import Algebra +import Qul (Qul) import Ledger (Ledger) import qualified Ledger as L import Common @@ -252,20 +255,66 @@ checkTerm t q a = case (t, a) of -------------------------------------------------------------------------------- -input :: ByteString +type Q = Qul +pQ :: Parse P.Err Q +pQ = P.pQul + +data Decl = Decl ByteString ByteString ByteString + +data Prog = Prog { + decls :: [Decl], + body :: ByteString +} + +parseKind :: ByteString -> IO Kind +parseKind k = + case P.runP P.pTopKind pQ k of + Ok k _ _ -> pure k + result -> print result *> exitFailure + +parseType :: ByteString -> IO (S.Type Q) +parseType a = + case P.runP P.pTopType pQ a of + Ok a _ _ -> pure a + result -> print result *> exitFailure + +parseTerm :: ByteString -> IO (S.Term Q) +parseTerm t = + case P.runP P.pTopTerm pQ t of + Ok t _ _ -> pure t + result -> print result *> exitFailure + +declare :: TypeCtx Q -> Decl -> IO (TypeCtx Q) +declare typeCtx (Decl x k a) = do + let x' = S.TypeName x + k' <- parseKind k + a' <- parseType a + a'' <- case checkType a' k' `runElab` BothCtx typeCtx Ctx.empty of + Left e -> print e *> exitFailure + Right a -> pure a + let a''' = V.evalType typeCtx.env a'' + let (lvl, typeCtx') = Ctx.bindAndAssign x' k' typeCtx + pure $ Ctx.define lvl a''' typeCtx' + +input :: Prog input = - ByteString.intercalate "\n" [ - "let zero : @M:* -> M -> (M -> M) -> M = \\[M] z s => z;", - "\\[M] z s => z : @M:* -> M -> (M -> M) -> M" + Prog [ + Decl "Nat" "*" "@M:* -> M -> (M -> M) -> M" + ] $ ByteString.intercalate "\n" [ + "let zero : Nat = \\[M] z s => z;", + "let succ : Nat -> Nat = \\n => \\[M] z s => s (n [M] z s);", + "succ (succ zero)" ] main :: IO () -main = - case P.runP P.pSrc P.pQul input of - Ok t _ _ -> - case inferTerm t one `runElab` bothCtxEmpty of - Left e -> print e - Right (t, a, _) -> do - print t - print $ V.quoteType Env.empty a - result -> print result +main = do + typeCtx <- foldlM declare Ctx.empty input.decls + t <- parseTerm input.body + case inferTerm t one `runElab` BothCtx typeCtx Ctx.empty of + Left e -> print e + Right (t, a, _) -> do + putStrLn "term:" + print t + putStrLn "----------------------------" + putStrLn "type:" + print $ V.quoteType Env.empty a diff --git a/Parser.hs b/Parser.hs @@ -98,6 +98,9 @@ pKind = \case <|> pDelim "(" (pKind 0) ")" _ -> error "pKind: invalid precedence" +pTopKind :: P q Kind +pTopKind = pWs *> pKind 0 <* eof + pTypeAnnot :: Type q -> P q (Type q) pTypeAnnot a = pSym ":" *> (TypeAnnot a <$> pKind 0) `cut` Err @@ -144,6 +147,9 @@ pType = \case <|> pDelim "(" (pType 0) ")" _ -> error "pType: invalid precedence" +pTopType :: P q (Type q) +pTopType = pWs *> pType 0 <* eof + pTermAnnot :: Term q -> P q (Term q) pTermAnnot t = pSym ":" *> (TermAnnot t <$> pType 0) `cut` Err @@ -180,5 +186,5 @@ pTerm = \case <|> pDelim "(" (pTerm 0) ")" _ -> error "pTerm: invalid precedence" -pSrc :: P q (Term q) -pSrc = pWs *> pTerm 0 <* eof +pTopTerm :: P q (Term q) +pTopTerm = pWs *> pTerm 0 <* eof