Prototype, extremely bad code implementation of CCHM Cubical Type Theory
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
5.0 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. {-# LANGUAGE LambdaCase #-}
  2. module Main where
  3. import Control.Monad.IO.Class
  4. import Control.Monad.Catch
  5. import qualified Data.Map.Strict as Map
  6. import Data.List
  7. import Elab
  8. import Eval (eval, UnifyError (..))
  9. import Presyntax.Parser
  10. import Presyntax
  11. import Syntax
  12. import System.Console.Haskeline (runInputT, defaultSettings, getInputLine)
  13. import System.Exit
  14. import Systems (formulaOfFace, Face)
  15. import System.Environment
  16. showTypeError :: Maybe [String] -> Elab.TypeError -> String
  17. showTypeError lines (NotInScope l_c) = "Variable not in scope: " ++ l_c
  18. showTypeError lines (UnifyError (NotPiType vl)) = "Not a function type: " ++ show vl
  19. showTypeError lines (UnifyError (NotSigmaType vl)) = "Not a sigma type: " ++ show vl
  20. showTypeError lines (UnifyError (Mismatch a b)) =
  21. unlines [ "Types are not equal: "
  22. , " " ++ show (quote a)
  23. , " vs "
  24. , " " ++ show (quote b)
  25. ]
  26. showTypeError lines (WrongFaces _ faces) = unlines (map face faces) where
  27. face :: ([Value], Value, Elab.TypeError) -> String
  28. face (ixs, rhs, err) =
  29. "When checking face described by " ++ show ixs ++ ":\n" ++ showTypeError Nothing err
  30. showTypeError lines (InSpan start end err)
  31. | Just lines <- lines, fst start == fst end
  32. = makeRange (lines !! fst start) start end ++ '\n':showTypeError Nothing err
  33. | otherwise = showTypeError Nothing err
  34. showTypeError lines (IncompleteSystem formula extent) =
  35. unlines $
  36. [ "Incomplete system: "
  37. , "it is defined by " ++ show formula
  38. , "but the context mandates extent " ++ show extent ]
  39. showTypeError lines (IncompatibleFaces (fa, ta) (fb, tb) err) =
  40. unlines [ showTypeError lines err
  41. , "while checking that these overlapping faces are compatible:"
  42. , "* " ++ show fa ++ " -> " ++ show ta
  43. , "* " ++ show fb ++ " -> " ++ show tb
  44. ]
  45. showTypeError _ x = show x
  46. makeRange :: String -> (Int, Int) -> (Int, Int) -> String
  47. makeRange line (_, sc) (_, ec) = line ++ "\n" ++ replicate (sc + 1) ' ' ++ replicate (ec - sc) '~'
  48. main :: IO ()
  49. main = do
  50. t <- getArgs
  51. case t of
  52. [file] -> Main.check file
  53. _ -> repl
  54. check :: FilePath -> IO ()
  55. check file = do
  56. code <- readFile file
  57. let
  58. ste e = do
  59. putStrLn $ showTypeError (Just (lines code)) e
  60. exitFailure
  61. case parseString body code of
  62. Left e -> print e
  63. Right x -> do
  64. (tm, _) <- infer (Env mempty) x `catch` ste `catch` (ste . UnifyError)
  65. print (eval (Env mempty) tm)
  66. repl :: IO ()
  67. repl = runInputT defaultSettings (go (Env mempty)) where
  68. go env = getInputLine "> " >>= \case
  69. Just i | ":sq " `isPrefixOf` i -> do
  70. case parseString body (replicate 4 ' ' ++ drop 4 i) of
  71. Right exp ->
  72. (do
  73. (tm, ty) <- liftIO $ infer env exp
  74. liftIO $ drawExtent ty (eval env tm)
  75. `catch` \e -> liftIO $ putStrLn (showTypeError (Just [i]) e))
  76. `catch` \e -> liftIO $ print (e :: SomeException)
  77. Left e -> liftIO (print e)
  78. go env
  79. Just i ->
  80. case parseString statement i of
  81. Left e -> liftIO (print e) *> go env
  82. Right (Assume vs) ->
  83. let
  84. loop env ((v, t):vs) = do
  85. tm <- liftIO $ Elab.check env t VTypeω
  86. let ty = eval env tm
  87. loop env{ names = Map.insert v (ty, VVar v) (names env) } vs
  88. loop env [] = go env
  89. in (loop env vs
  90. `catch` \e -> (liftIO $ putStrLn (showTypeError (Just [i]) e)) *> go env)
  91. `catch` \e -> (liftIO $ print (e :: SomeException)) *> go env
  92. Right (Eval v) -> do
  93. liftIO $
  94. (do
  95. (tm, ty) <- infer env v
  96. let v_nf = eval env tm
  97. putStrLn $ show v_nf ++ " : " ++ show ty
  98. `catch` \e -> putStrLn (showTypeError (Just [i]) e))
  99. `catch` \e -> print (e :: SomeException)
  100. go env
  101. Right (Declare n t e) -> do
  102. (do
  103. t <- liftIO $ Elab.check env t VTypeω
  104. let t' = eval env t
  105. b <- liftIO $ Elab.check env e t'
  106. let b' = eval env b
  107. go env{ names = Map.insert n (t', b') (names env) })
  108. `catch` \e -> (liftIO $ putStrLn (showTypeError (Just [i]) e)) *> go env
  109. `catch` \e -> (liftIO $ print (e :: SomeException)) *> go env
  110. Nothing -> pure ()
  111. drawExtent :: Value -> Value -> IO ()
  112. drawExtent ty vl = nicely $ getDirections ty vl where
  113. getDirections :: Value -> Value -> [([(String, Bool)], Value, Value)]
  114. getDirections (VPi _ VI r) (VLam s VI k) =
  115. let trues = getDirections (r VI1) (k VI1)
  116. falses = getDirections (r VI0) (k VI0)
  117. in map (\(p, t, v) -> ((s, True):p, t, v)) trues
  118. ++ map (\(p, t, v) -> ((s, False):p, t, v)) falses
  119. getDirections ty t = [([], ty, t)]
  120. nicely :: [([(String, Bool)], Value, Value)] -> IO ()
  121. nicely [] = pure ()
  122. nicely ((bs, ty, el):fcs) = do
  123. putStr . unwords $ theFace bs
  124. putStrLn $ " => " ++ show el ++ " : " ++ show ty
  125. nicely fcs
  126. theFace = map (\(i, b) ->
  127. if b
  128. then "(" ++ i ++ "1)"
  129. else "(" ++ i ++ "0)")