-
Notifications
You must be signed in to change notification settings - Fork 0
/
Main.hs
106 lines (90 loc) · 3.04 KB
/
Main.hs
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
97
98
99
100
101
102
103
104
105
106
{-# LANGUAGE FlexibleInstances #-}
module Main where
import Lang
import Parse
import Elab hiding ( global )
import MonadTypeCheck
import TypeCheck
import Context
import Error
import Termination
import Reduce ( reduce, reduceType )
import Datatype
import Options.Applicative
( argument, fullDesc, idm, info, str, execParser )
import Control.Exception ( IOException, catch )
import System.IO ( stderr, hPutStrLn)
import Data.Char (isSpace)
import Text.Parsec ( ParseError )
import Control.Monad.Except
import Control.Monad.State
type RunTypeCheck = ExceptT TypeError (StateT Context IO)
instance MonadElab (ExceptT ElabError (State ElabContext))
instance MonadTypeCheck RunTypeCheck
-- NICETOHAVE cargar muchos archivos
main :: IO ()
main = execParser (info (argument str idm) fullDesc) >>= go
where
go :: FilePath -> IO ()
go f = do
mst <- loadFile f
case mst of
Nothing -> return ()
Just sp -> case runElab sp of
(Left e, ctx) -> case e of
ElabError e -> putStrLn e
DataError e -> putStrLn e
(Right p, _) -> case runTerminationCheck (onlyDecls p) of
TE e _ -> putStrLn $ "termination error: " ++ show e
TOK -> runProgram p
onlyDecls :: Program -> [Decl]
onlyDecls [] = []
onlyDecls (PDecl d : p) = d : onlyDecls p
onlyDecls (PData _ : p) = onlyDecls p
runElab :: SProgram -> (Either ElabError Program, ElabContext)
runElab p = runState (runExceptT (elabProgram p)) emptyElabContext
runTerminationCheck :: [Decl] -> TChecked
runTerminationCheck = foldMap (terminationCheck . declDef)
runProgram :: Program -> IO ()
runProgram p = do
r <- runStateT (runExceptT (mapM_ runDef p)) emptyContext
case r of
(Left e, ctx) -> print e -- TODO frees
(Right (), _) -> putStrLn "Todo OK"
where
runDef :: Definition Decl DataDef -> RunTypeCheck ()
runDef (PDecl d) = runDecl d
runDef (PData d) = runData d
runDecl :: Decl -> RunTypeCheck ()
runDecl d = do
ty <- infer (declDef d)
bindGlobal d ty
ctx <- get
-- MAYBE agrupar contexto global / local
put emptyContext
{ global = global ctx, datadefs = datadefs ctx }
when (declName d == "main") $ do
t <- reduce (declDef d)
liftIO $ do
putStrLn "main := "
print t
putStrLn ":"
print ty
runData :: DataDef -> RunTypeCheck ()
runData d = do
shouldBeType (dataType d)
addDataDef d
mapM_ (shouldBeType . conType) (dataCons d)
loadFile :: FilePath -> IO (Maybe SProgram)
loadFile f = do
let filename = reverse(dropWhile isSpace (reverse f))
x <- catch (readFile filename)
(\e -> do let err = show (e :: IOException)
hPutStrLn stderr ("No se pudo abrir el archivo " ++ filename ++ ": " ++ err)
return "")
-- setLastFile filename
case parseIO filename program x of
Left e -> print e >> return Nothing
Right a -> return (Just a)
parseIO :: String -> P a -> String -> Either ParseError a
parseIO filename p x = runP p x filename