Sockeye: Add stub for net builder
[barrelfish] / tools / sockeye / Main.hs
1 {-
2   SockeyeMain.hs: Sockeye
3
4   Copyright (c) 2017, ETH Zurich.
5
6   All rights reserved.
7
8   This file is distributed under the terms in the attached LICENSE file.
9   If you do not find this file, copies can be found by writing to:
10   ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich,
11   Attn: Systems Group.
12 -}
13
14 module Main where
15
16 import Control.Monad
17
18 import Data.List
19
20 import System.Console.GetOpt
21 import System.Exit
22 import System.Environment
23 import System.IO
24
25 import SockeyeASTFrontend as ASTF
26 import SockeyeASTIntermediate as ASTI
27 import SockeyeASTBackend as ASTB
28
29 import SockeyeParser
30 import SockeyeChecker
31 import SockeyeNetBuilder
32
33 import qualified SockeyeBackendPrintAST as PrintAST
34 import qualified SockeyeBackendProlog as Prolog
35
36 import Text.Groom(groom)
37
38 {- Exit codes -}
39 usageError :: ExitCode
40 usageError = ExitFailure 1
41
42 parseError :: ExitCode
43 parseError = ExitFailure 2
44
45 checkError :: ExitCode
46 checkError = ExitFailure 3
47
48 buildError :: ExitCode
49 buildError = ExitFailure 4
50
51 {- Compilation targets -}
52 data Target = None | PrintAST | Prolog
53
54 {- Possible options for the Sockeye Compiler -}
55 data Options = Options { optInputFile  :: FilePath
56                        , optTarget     :: Target
57                        , optOutputFile :: Maybe FilePath
58                        }
59
60 {- Default options -}
61 defaultOptions :: Options
62 defaultOptions = Options { optInputFile  = ""
63                          , optTarget     = Prolog
64                          , optOutputFile = Nothing
65                          }
66
67 {- Set the input file name -}
68 optSetInputFileName :: FilePath -> Options -> Options
69 optSetInputFileName f o = o { optInputFile = f }
70
71 {- Set the target -}
72 optSetTarget :: Target -> Options -> Options
73 optSetTarget t o = o { optTarget = t }
74
75 {- Set the outpue file name -}
76 optSetOutputFile :: Maybe String -> Options -> Options
77 optSetOutputFile f o = o { optOutputFile = f }
78
79 {- Prints usage information possibly with usage errors -}
80 usage :: [String] -> IO ()
81 usage errors = do
82     prg <- getProgName
83     let usageString = "Usage: " ++ prg ++ " [options] file\nOptions:"
84     hPutStrLn stderr $ usageInfo (concat errors ++ usageString) options
85     hPutStrLn stderr "The backend (capital letter options) specified last takes precedence."
86
87
88 {- Setup option parser -}
89 options :: [OptDescr (Options -> IO Options)]
90 options = 
91     [ Option "P" ["Prolog"]
92         (NoArg (\opts -> return $ optSetTarget Prolog opts))
93         "Generate a prolog file that can be loaded into the SKB (default)."
94     , Option "A" ["AST"]
95         (NoArg (\opts -> return $ optSetTarget PrintAST opts))
96         "Print the AST."
97     , Option "C" ["Check"]
98         (NoArg (\opts -> return $ optSetTarget None opts))
99         "Just check the file, do not compile."
100     , Option "o" ["output-file"]
101         (ReqArg (\f opts -> return $ optSetOutputFile (Just f) opts) "FILE")
102         "If no output file is specified the compilation result is written to stdout."
103     , Option "h" ["help"]
104         (NoArg (\_ -> do
105                     usage []
106                     exitWith ExitSuccess))
107         "Show help."
108     ]
109
110 {- evaluates the compiler options -}
111 compilerOpts :: [String] -> IO (Options)
112 compilerOpts argv =
113     case getOpt Permute options argv of
114         (actions, fs, []) -> do
115             opts <- foldl (>>=) (return defaultOptions) actions
116             case fs of
117                 []  -> do
118                     usage ["No input file\n"]
119                     exitWith usageError
120                 [f] -> return $ optSetInputFileName f opts
121                 _   -> do
122                     usage ["Multiple input files not supported\n"]
123                     exitWith usageError
124
125         (_, _, errors) -> do
126             usage errors
127             exitWith $ usageError
128
129 {- Runs the parser -}
130 parseFile :: FilePath -> IO (ASTF.SockeyeSpec)
131 parseFile file = do
132     src <- readFile file
133     case parseSockeye file src of
134         Left err -> do
135             hPutStrLn stderr $ "Parse error at " ++ show err
136             exitWith parseError
137         Right ast -> return ast
138
139 {- Runs the checker -}
140 checkAST :: ASTF.SockeyeSpec -> IO ASTI.SockeyeSpec
141 checkAST parsedAst = do
142     case checkSockeye parsedAst of 
143         Left fail -> do
144             hPutStr stderr $ show fail
145             exitWith checkError
146         Right intermAst -> return intermAst
147
148 {- Builds the decoding net from the Sockeye AST -}
149 buildNet :: ASTI.SockeyeSpec -> IO ASTB.NetSpec
150 buildNet ast = do
151     case sockeyeBuildNet ast of 
152         Left fail -> do
153             hPutStr stderr $ show fail
154             exitWith buildError
155         Right netAst -> return netAst
156
157 {- Compiles the AST with the appropriate backend -}
158 compile :: Target -> ASTB.NetSpec -> IO String
159 compile None     _   = return ""
160 compile PrintAST ast = return $ PrintAST.compile ast
161 compile Prolog   ast = return $ Prolog.compile ast
162
163 {- Outputs the compilation result -}
164 output :: Maybe FilePath -> String -> IO ()
165 output outFile out = do
166     case outFile of
167         Nothing -> putStr out
168         Just f  -> writeFile f out
169
170 main = do
171     args <- getArgs
172     opts <- compilerOpts args
173     let inFile = optInputFile opts
174     parsedAst <- parseFile inFile
175     ast <- checkAST parsedAst
176     netAst <- buildNet ast
177     putStrLn $ groom netAst
178     -- out <- compile (optTarget opts) ast
179     -- output (optOutputFile opts) out
180