Properly load flag and symbol files
This commit is contained in:
parent
7446bcab45
commit
72e21d6ff2
4 changed files with 85 additions and 45 deletions
|
|
@ -33,7 +33,7 @@ main = doRun_ $ do
|
||||||
settings <- lift $ execParser opts
|
settings <- lift $ execParser opts
|
||||||
|
|
||||||
lift $ putStrLn $ "Loading assembly file at " ++ infile settings
|
lift $ putStrLn $ "Loading assembly file at " ++ infile settings
|
||||||
(state, _, _) <- loadFile readAssembly (infile settings)
|
(state, _, _) <- loadFile' readAssembly (infile settings)
|
||||||
lift $ putStrLn "Parsing successful"
|
lift $ putStrLn "Parsing successful"
|
||||||
|
|
||||||
lift $ putStrLn $ "Writing result to " ++ outfile settings
|
lift $ putStrLn $ "Writing result to " ++ outfile settings
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Monad.Trans.Class
|
import Control.Monad.Trans.Class
|
||||||
import Control.Monad.Trans.Except
|
import Data.Maybe
|
||||||
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.IO as T
|
import qualified Data.Text.IO as T
|
||||||
import Options.Applicative
|
import Options.Applicative
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
|
|
@ -14,6 +17,7 @@ import Mima.Label
|
||||||
import Mima.Load
|
import Mima.Load
|
||||||
import Mima.Options
|
import Mima.Options
|
||||||
import Mima.Parse.FlagFile
|
import Mima.Parse.FlagFile
|
||||||
|
import Mima.Parse.SymbolFile
|
||||||
import Mima.State
|
import Mima.State
|
||||||
import Mima.Util
|
import Mima.Util
|
||||||
import Mima.Word
|
import Mima.Word
|
||||||
|
|
@ -33,6 +37,26 @@ data Settings = Settings
|
||||||
, formatConf :: FormatConfig
|
, formatConf :: FormatConfig
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
|
getFlagFile :: Settings -> File
|
||||||
|
getFlagFile settings =
|
||||||
|
case flagFile settings of
|
||||||
|
Just path -> RequiredFile path
|
||||||
|
Nothing -> case discover settings of
|
||||||
|
False -> NoFile
|
||||||
|
True -> OptionalFile discoveredPath
|
||||||
|
where
|
||||||
|
discoveredPath = dropExtension (infile settings) ++ ".mima-flags"
|
||||||
|
|
||||||
|
getSymbolFile :: Settings -> File
|
||||||
|
getSymbolFile settings =
|
||||||
|
case symbolFile settings of
|
||||||
|
Just path -> RequiredFile path
|
||||||
|
Nothing -> case discover settings of
|
||||||
|
False -> NoFile
|
||||||
|
True -> OptionalFile discoveredPath
|
||||||
|
where
|
||||||
|
discoveredPath = dropExtension (infile settings) ++ ".mima-symbols"
|
||||||
|
|
||||||
{- Command-line parameters -}
|
{- Command-line parameters -}
|
||||||
|
|
||||||
settingsParser :: Parser Settings
|
settingsParser :: Parser Settings
|
||||||
|
|
@ -74,40 +98,30 @@ settingsParser = Settings
|
||||||
opts :: ParserInfo Settings
|
opts :: ParserInfo Settings
|
||||||
opts = info (helper <*> settingsParser) $ fullDesc <> failureCode 1 <> footer flagFooter
|
opts = info (helper <*> settingsParser) $ fullDesc <> failureCode 1 <> footer flagFooter
|
||||||
|
|
||||||
{- Loading the flag file -}
|
{- Loading supplemental files -}
|
||||||
|
|
||||||
-- If explicit file name:
|
printFile :: T.Text -> File -> Run ()
|
||||||
-- Try to load file
|
printFile name NoFile =
|
||||||
-- Fail if loading fails
|
lift $ T.putStrLn $ "Not loading " <> name <> ": No file specified and discovery turned off"
|
||||||
-- Elif discover:
|
printFile name (OptionalFile path) =
|
||||||
-- Try to load file
|
lift $ T.putStrLn $ "Attempting to load " <> name <> " from " <> T.pack path
|
||||||
-- Use defaults if loading fails
|
printFile name (RequiredFile path) =
|
||||||
-- Else:
|
lift $ T.putStrLn $ "Loading " <> name <> " from " <> T.pack path
|
||||||
-- Use defaults
|
|
||||||
|
|
||||||
loadFlagFile :: FilePath -> Run (Flags (MimaAddress -> Bool))
|
|
||||||
loadFlagFile filename = do
|
|
||||||
lift $ putStrLn $ "Loading flags from " ++ filename
|
|
||||||
(interpretFlagSpec . getFlagSpec) <$> loadFile readFlagFile filename
|
|
||||||
|
|
||||||
withDefaultFlags :: Run (Flags (MimaAddress -> Bool)) -> Run (Flags (MimaAddress -> Bool))
|
|
||||||
withDefaultFlags p = do
|
|
||||||
result <- tryRun p
|
|
||||||
case result of
|
|
||||||
Just flags -> pure flags
|
|
||||||
Nothing -> do
|
|
||||||
lift $ putStrLn "Using default flags"
|
|
||||||
pure noFlags
|
|
||||||
|
|
||||||
loadFlags :: Settings -> Run (Flags (MimaAddress -> Bool))
|
loadFlags :: Settings -> Run (Flags (MimaAddress -> Bool))
|
||||||
loadFlags settings =
|
loadFlags settings = do
|
||||||
case flagFile settings of
|
let file = getFlagFile settings
|
||||||
Just filename -> loadFlagFile filename
|
printFile "flags" file
|
||||||
Nothing -> withDefaultFlags $ if discover settings
|
mRawFlags <- loadFile readFlagFile file
|
||||||
then loadFlagFile discovered
|
pure $ case mRawFlags of
|
||||||
else throwE "File not specified and discovery turned off"
|
Nothing -> noFlags
|
||||||
where
|
Just flagSpec -> interpretFlagSpec $ getFlagSpec flagSpec
|
||||||
discovered = dropExtension (infile settings) ++ ".mima-flags"
|
|
||||||
|
loadSymbols :: Settings -> Run LabelSpec
|
||||||
|
loadSymbols settings = do
|
||||||
|
let file = getSymbolFile settings
|
||||||
|
printFile "symbols" file
|
||||||
|
fromMaybe noLabels <$> loadFile readSymbolFile file
|
||||||
|
|
||||||
{- Other functions -}
|
{- Other functions -}
|
||||||
|
|
||||||
|
|
@ -150,7 +164,7 @@ main = doRun_ $ do
|
||||||
ms <- loadStateFromFile (infile settings)
|
ms <- loadStateFromFile (infile settings)
|
||||||
|
|
||||||
flags <- loadFlags settings
|
flags <- loadFlags settings
|
||||||
labels <- pure noLabels -- loadSymbolFile settings
|
labels <- loadSymbols settings
|
||||||
|
|
||||||
ms' <- if norun settings
|
ms' <- if norun settings
|
||||||
then pure ms
|
then pure ms
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
{-# LANGUAGE MultiWayIf #-}
|
{-# LANGUAGE MultiWayIf #-}
|
||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
|
|
||||||
module Mima.IO
|
module Mima.IO
|
||||||
( Run
|
( Run
|
||||||
, doRun
|
, doRun
|
||||||
, doRun_
|
, doRun_
|
||||||
, tryRun
|
, tryRun
|
||||||
|
, File(..)
|
||||||
, readTextFile
|
, readTextFile
|
||||||
, loadFile
|
, loadFile
|
||||||
|
, loadFile'
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.Trans.Class
|
import Control.Monad.Trans.Class
|
||||||
|
|
@ -39,6 +42,12 @@ tryRun r = do
|
||||||
lift $ putStrLn e
|
lift $ putStrLn e
|
||||||
pure Nothing
|
pure Nothing
|
||||||
|
|
||||||
|
data File
|
||||||
|
= NoFile
|
||||||
|
| OptionalFile FilePath
|
||||||
|
| RequiredFile FilePath
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
readTextFile :: FilePath -> Run T.Text
|
readTextFile :: FilePath -> Run T.Text
|
||||||
readTextFile filepath = do
|
readTextFile filepath = do
|
||||||
eitherContent <- lift $ catchIOError (Right <$> T.readFile filepath) handleError
|
eitherContent <- lift $ catchIOError (Right <$> T.readFile filepath) handleError
|
||||||
|
|
@ -49,9 +58,27 @@ readTextFile filepath = do
|
||||||
then pure $ Left $ "Can't load file " ++ filepath ++ ": " ++ ioeGetErrorString e
|
then pure $ Left $ "Can't load file " ++ filepath ++ ": " ++ ioeGetErrorString e
|
||||||
else ioError e -- This error does not concern us
|
else ioError e -- This error does not concern us
|
||||||
|
|
||||||
loadFile :: (FilePath -> T.Text -> Either WeedErrorBundle a) -> FilePath -> Run a
|
loadTextFile :: File -> Run (Maybe (FilePath, T.Text))
|
||||||
loadFile f filepath = do
|
loadTextFile NoFile = pure Nothing
|
||||||
content <- readTextFile filepath
|
loadTextFile (OptionalFile path) = do
|
||||||
case f filepath content of
|
mContent <- tryRun $ readTextFile path
|
||||||
|
pure $ (path,) <$> mContent
|
||||||
|
loadTextFile (RequiredFile path) = do
|
||||||
|
content <- readTextFile path
|
||||||
|
pure $ Just (path, content)
|
||||||
|
|
||||||
|
loadFile :: (FilePath -> T.Text -> Either WeedErrorBundle a) -> File -> Run (Maybe a)
|
||||||
|
loadFile f file = do
|
||||||
|
mContent <- loadTextFile file
|
||||||
|
case mContent of
|
||||||
|
Nothing -> pure Nothing
|
||||||
|
Just (path, content) -> case f path content of
|
||||||
Left errorBundle -> throwE $ errorBundlePretty errorBundle
|
Left errorBundle -> throwE $ errorBundlePretty errorBundle
|
||||||
Right a -> pure a
|
Right result -> pure $ Just result
|
||||||
|
|
||||||
|
loadFile' :: (FilePath -> T.Text -> Either WeedErrorBundle a) -> FilePath -> Run a
|
||||||
|
loadFile' f path = do
|
||||||
|
content <- readTextFile path
|
||||||
|
case f path content of
|
||||||
|
Left errorBundle -> throwE $ errorBundlePretty errorBundle
|
||||||
|
Right result -> pure result
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,12 @@ parseSymbolFile = space *> many lNewline *> (combineLines <$> many lLine) <* eof
|
||||||
|
|
||||||
{- Weeding -}
|
{- Weeding -}
|
||||||
|
|
||||||
wBuildMap :: [(WithOffset LabelName, MimaAddress)]
|
wBuildMap :: [(WithOffset LabelName, MimaAddress)] -> Weed WeedError LabelSpec
|
||||||
-> Weed WeedError (Map.Map LabelName MimaAddress)
|
|
||||||
wBuildMap = foldM helper Map.empty
|
wBuildMap = foldM helper Map.empty
|
||||||
where
|
where
|
||||||
helper :: Map.Map LabelName MimaAddress
|
helper :: Map.Map LabelName MimaAddress
|
||||||
-> (WithOffset LabelName, MimaAddress)
|
-> (WithOffset LabelName, MimaAddress)
|
||||||
-> Weed WeedError (Map.Map LabelName MimaAddress)
|
-> Weed WeedError LabelSpec
|
||||||
helper m (l, addr)
|
helper m (l, addr)
|
||||||
| name `Map.member` m = do
|
| name `Map.member` m = do
|
||||||
harmless $ errorAt l "label was specified more than once"
|
harmless $ errorAt l "label was specified more than once"
|
||||||
|
|
@ -62,12 +61,12 @@ wBuildMap = foldM helper Map.empty
|
||||||
where name = woValue l
|
where name = woValue l
|
||||||
|
|
||||||
weedSymbolFile :: Map.Map MimaAddress [WithOffset LabelName]
|
weedSymbolFile :: Map.Map MimaAddress [WithOffset LabelName]
|
||||||
-> Weed WeedError (Map.Map LabelName MimaAddress)
|
-> Weed WeedError LabelSpec
|
||||||
weedSymbolFile m =
|
weedSymbolFile m =
|
||||||
let pairs = [(l, a) | (a, ls) <- Map.assocs m, l <- ls]
|
let pairs = [(l, a) | (a, ls) <- Map.assocs m, l <- ls]
|
||||||
in wBuildMap pairs
|
in wBuildMap pairs
|
||||||
|
|
||||||
readSymbolFile :: FilePath -> T.Text -> Either WeedErrorBundle (Map.Map LabelName MimaAddress)
|
readSymbolFile :: FilePath -> T.Text -> Either WeedErrorBundle LabelSpec
|
||||||
readSymbolFile filename input = do
|
readSymbolFile filename input = do
|
||||||
unweeded <- parse parseSymbolFile filename input
|
unweeded <- parse parseSymbolFile filename input
|
||||||
runWeedBundle filename input $ weedSymbolFile unweeded
|
runWeedBundle filename input $ weedSymbolFile unweeded
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue