summaryrefslogtreecommitdiff
path: root/src/Main.idr
blob: 6f3fafeca000d412bdb8bc8182bdabd104ae7625 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
module Main

import CC.Name
import CC.Term
import CC.Term.Elaborate
import CC.Term.Eval
import CC.Term.Parse
import CC.Term.Pretty
import CC.Term.Raw

import Data.String

import System
import System.File.ReadWrite
import System.File.Virtual

import Text.Parser
import Text.PrettyPrint.Prettyprinter
import Text.PrettyPrint.Prettyprinter.Render.Terminal

--- Error Reporting ------------------------------------------------------------

putErrLn : HasIO io => String -> io ()
putErrLn str = do
  Right () <- fPutStrLn stderr str
    | Left e => pure ()
  pure ()

putBoundErrLn : HasIO io => Maybe Bounds -> String -> io ()
putBoundErrLn Nothing str = putErrLn str
putBoundErrLn (Just bounds) str =
  let startLine = padLeft 3 '0' $ show (1 + bounds.startLine) in
  let startCol = padLeft 2 '0' $ show bounds.startCol in
  let endLine = padLeft 3 '0' $ show (1 + bounds.endLine) in
  let endCol = padLeft 2 '0' $ show bounds.endCol in
  putErrLn "\{startLine}:\{startCol}--\{endLine}:\{endCol}: \{str}"

-- Parsing ---------------------------------------------------------------------

parse : String -> IO RawTerm
parse str =
  case parseString str of
    Left errs => for_ errs putErr >> exitFailure
    Right v => pure v
  where
  putErr : ParsingError CCToken -> IO ()
  putErr (Error str bounds) = putBoundErrLn bounds ("parse error: \{str}" )

partial
parseStdin : IO RawTerm
parseStdin = do
  Right str <- fRead stdin
    | Left err => putErrLn "failed to read input: \{show err}" >> exitFailure
  parse str

-- Main Function ---------------------------------------------------------------

helpMsg : String
helpMsg = unlines [
  "usage: cc-check [--help|nf|type]",
  "  --help : display this message",
  "  nf     : read & typecheck expression from stdin, print its normal form and type",
  "  type   : read & typecheck expression from stdin, print its type"
  ]



mainWith : IO (List String) -> IO RawTerm -> IO ()
mainWith getOpt getTerm = do
  opts <- getOpt
  case opts of
    [_, "--help"] => putStrLn helpMsg
    [_, "nf"] => do
      rawTerm <- getTerm
      let Right (t, ty) = runElabError $ inferTerm rawTerm
        | Left errs => for_ errs putErr >> exitFailure
      let nf : Term [<] = normalise [<] t
      let ty = quote ty
      putDoc (group $ pretty nf <++> colon <+> line <+> pretty ty)
    [_, "type"] => do
      rawTerm <- getTerm
      let Right (t, ty) = runElabError $ inferTerm rawTerm
        | Left errs => for_ errs putErr >> exitFailure
      putDoc (group $ pretty $ quote ty)
    _ => putErrLn helpMsg >> exitFailure
  where
  putErr : Either Name (String, Maybe Bounds) -> IO ()
  putErr (Left n) = putBoundErrLn (bounds n) "undefined name: \{n}"
  putErr (Right (s, bounds)) = putBoundErrLn bounds s

partial
main : IO ()
main = mainWith getArgs parseStdin

main' : String -> String -> IO ()
main' mode src = mainWith (pure [mode]) (parse src)