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.

133 lines
4.8 KiB

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