MainIntel.hs 2.14 KB

module Main where

import Control.Monad

import Data.List -- find, isSuffixOf
import qualified Data.Map as Map

import System.Environment
import System.Exit
import System.IO
import System.Console.GetOpt

import Text.PrettyPrint

import Frame
import FrameIntel
import LexIntel
import ParseIntel
import StateIntel hiding (print)
import Util -- Pretty
import Wellformed

data Flag
  = Verbose
  | Help
    deriving (Eq, Show)

optDescrs :: [OptDescr Flag]
optDescrs =
  [ Option ['?'] ["help"]      (NoArg Help)    "show usage information"
  , Option ['v'] ["verbose"]   (NoArg Verbose) "be verbose"
  ]

usage :: IO a
usage = do
  putStr $ usageInfo "Usage: risc386 [options] <file>" optDescrs
  exitFailure

-- | Extract the input file name from command line.
--   Display usage info for malformed command lines.
parseCmdLine :: [String] -> IO String
parseCmdLine argv = do
  let (os, ns, _) = getOpt Permute optDescrs argv
  unless (length ns == 1)
    usage
  let prgFile = head ns
  when (Verbose `elem` os) $
    hPutStrLn stderr $ "Reading program from file: " ++ prgFile
  when (Help `elem` os) $
    ioError (userError "No execution with --help")
  return prgFile

exitOnError :: Either String b -> IO b
exitOnError = either crash return where crash a = putStrLn a >> exitFailure

{- main:
  * parse IntelFrame list
  * search "*main" function
  * split frames into blocks IBlockFrame
  * convert frame list into a map
  * execute main function
 -}
main :: IO ()
main = do
  cmdLine <- getArgs
  prgFile <- parseCmdLine cmdLine
  input   <- readFile prgFile
  let frames = parse (alexScanTokens input)

  -- anyting that ends in "main" is considered the main function
  lmain <- do
    exitOnError $
      maybe (Left "no main function found") Right $
        find (== "Lmain") $
          map frameName frames

  hPutStrLn stderr ("## Input:\n" ++ (render $ ppr frames))
  -- check instructions for well-formedness
  exitOnError $ wellformed frames

  let bfs = map iBlocksFrame frames
  hPutStrLn stderr ("## Blocks:\n" ++ (render $ ppr bfs))

  let framemap =  Map.fromList $ map (\ f@(IBlockFrame l _) -> (l,f)) $ bfs
  result <- run framemap lmain
  exitOnError result
  exitSuccess