Split out a chunk of CompState into a CompOpts type for things that can be set on the command-line

This commit is contained in:
Neil Brown 2009-04-17 21:10:14 +00:00
parent af3be945a4
commit 57ffc7bfa4
15 changed files with 106 additions and 76 deletions

47
Main.hs
View File

@ -58,7 +58,7 @@ import ShowCode
import Utils import Utils
-- Either gives back options, or an exact string to print out: -- Either gives back options, or an exact string to print out:
type OptFunc = CompState -> ErrorT String IO CompState type OptFunc = CompOpts -> ErrorT String IO CompOpts
printString :: String -> ErrorT String IO a printString :: String -> ErrorT String IO a
printString = throwError printString = throwError
@ -188,7 +188,7 @@ optPrintHelp _ = printString $ usageInfo "Usage: tock [OPTION...] SOURCEFILE" op
optPrintWarningHelp :: OptFunc optPrintWarningHelp :: OptFunc
optPrintWarningHelp _ = printString $ usageInfo "Usage: tock [OPTION...] SOURCEFILE" optionsWarnings optPrintWarningHelp _ = printString $ usageInfo "Usage: tock [OPTION...] SOURCEFILE" optionsWarnings
optOnOff :: (String, Bool -> CompState -> CompState) -> String -> OptFunc optOnOff :: (String, Bool -> CompOpts -> CompOpts) -> String -> OptFunc
optOnOff (n, f) s ps optOnOff (n, f) s ps
= do mode <- case s of = do mode <- case s of
"on" -> return True "on" -> return True
@ -240,7 +240,7 @@ main = do
Just $ take (length fn - length ".rain") fn) Just $ take (length fn - length ".rain") fn)
else (id, Nothing) else (id, Nothing)
res <- runErrorT $ foldl (>>=) (return $ frontendGuess emptyState) opts res <- runErrorT $ foldl (>>=) (return $ frontendGuess emptyOpts) opts
case res of case res of
Left str -> putStrLn str Left str -> putStrLn str
Right initState -> do Right initState -> do
@ -250,7 +250,7 @@ main = do
mode -> useOutputOptions (compile mode fn) mode -> useOutputOptions (compile mode fn)
-- Run the compiler. -- Run the compiler.
v <- runPassM initState operation v <- runPassM (emptyState { csOpts = initState}) operation
case v of case v of
(Left e, cs) -> showWarnings (csWarnings cs) >> dieIO e (Left e, cs) -> showWarnings (csWarnings cs) >> dieIO e
(Right r, cs) -> showWarnings (csWarnings cs) (Right r, cs) -> showWarnings (csWarnings cs)
@ -279,14 +279,14 @@ instance Die FilesPassM where
-- If removing the files fails, we don't want to die with that -- If removing the files fails, we don't want to die with that
-- error; we want the user to see the original error, so ignore -- error; we want the user to see the original error, so ignore
-- errors arising from removing the files: -- errors arising from removing the files:
optsPS <- getCompState optsPS <- getCompOpts
when (not $ csKeepTemporaries optsPS) $ when (not $ csKeepTemporaries optsPS) $
liftIO $ removeFiles files liftIO $ removeFiles files
FilesPassM $ dieReport err FilesPassM $ dieReport err
compileFull :: String -> Maybe String -> FilesPassM () compileFull :: String -> Maybe String -> FilesPassM ()
compileFull inputFile moutputFile compileFull inputFile moutputFile
= do optsPS <- getCompState = do optsPS <- getCompOpts
outputFile <- case (csOutputFile optsPS, moutputFile) of outputFile <- case (csOutputFile optsPS, moutputFile) of
-- If the user hasn't given an output file, we guess by -- If the user hasn't given an output file, we guess by
-- using a stem (input file minus known extension). -- using a stem (input file minus known extension).
@ -307,7 +307,7 @@ compileFull inputFile moutputFile
let cFile = outputFile ++ cExtension let cFile = outputFile ++ cExtension
hFile = outputFile ++ hExtension hFile = outputFile ++ hExtension
iFile = outputFile ++ ".tock.inc" iFile = outputFile ++ ".tock.inc"
modifyCompState $ \cs -> cs { csOutputIncFile = Just iFile } modifyCompOpts $ \cs -> cs { csOutputIncFile = Just iFile }
withOutputFile cFile $ \hb -> withOutputFile cFile $ \hb ->
withOutputFile hFile $ \hh -> withOutputFile hFile $ \hh ->
FilesPassM $ lift $ compile ModeCompile inputFile ((hb, hh), hFile) FilesPassM $ lift $ compile ModeCompile inputFile ((hb, hh), hFile)
@ -316,7 +316,7 @@ compileFull inputFile moutputFile
exec $ "indent " ++ cFile exec $ "indent " ++ cFile
cs <- getCompState cs <- getCompState
case csBackend cs of case csBackend (csOpts cs) of
BackendC -> BackendC ->
let sFile = outputFile ++ ".tock.s" let sFile = outputFile ++ ".tock.s"
oFile = outputFile ++ ".tock.o" oFile = outputFile ++ ".tock.o"
@ -325,52 +325,55 @@ compileFull inputFile moutputFile
postOFile = outputFile ++ ".tock_post.o" postOFile = outputFile ++ ".tock_post.o"
in in
do sequence_ $ map noteFile $ [sFile, postCFile, postOFile] do sequence_ $ map noteFile $ [sFile, postCFile, postOFile]
++ if csHasMain cs then [oFile] else [] ++ if csHasMain (csOpts cs) then [oFile] else []
-- The object file is a temporary to-be-removed -- The object file is a temporary to-be-removed
-- iff we are also linking the end product -- iff we are also linking the end product
-- Compile the C into assembly, and assembly into an object file -- Compile the C into assembly, and assembly into an object file
exec $ cAsmCommand cFile sFile (csCompilerFlags cs) exec $ cAsmCommand cFile sFile (csCompilerFlags $ csOpts cs)
exec $ cCommand sFile oFile (csCompilerFlags cs) exec $ cCommand sFile oFile (csCompilerFlags $ csOpts cs)
-- Analyse the assembly for stack sizes, and output a -- Analyse the assembly for stack sizes, and output a
-- "post" H file -- "post" H file
sizes <- withOutputFile sizesFile $ \h -> FilesPassM $ lift $ sizes <- withOutputFile sizesFile $ \h -> FilesPassM $ lift $
postCAnalyse sFile ((h,intErr),intErr) postCAnalyse sFile ((h,intErr),intErr)
when (csHasMain cs) $ do when (csHasMain $ csOpts cs) $ do
withOutputFile postCFile $ \h -> withOutputFile postCFile $ \h ->
computeFinalStackSizes searchReadFile (csUnknownStackSize cs) computeFinalStackSizes searchReadFile (csUnknownStackSize $ csOpts cs)
(Meta (Just sizesFile) 1 1) sizes >>= (liftIO . hPutStr h) (Meta (Just sizesFile) 1 1) sizes >>= (liftIO . hPutStr h)
-- Compile this new "post" C file into an object file -- Compile this new "post" C file into an object file
exec $ cCommand postCFile postOFile (csCompilerFlags cs) exec $ cCommand postCFile postOFile (csCompilerFlags $ csOpts cs)
let otherOFiles = [usedFile ++ ".tock.o" let otherOFiles = [usedFile ++ ".tock.o"
| usedFile <- Set.toList $ csUsedFiles cs] | usedFile <- Set.toList $ csUsedFiles cs]
-- Link the object files into a binary -- Link the object files into a binary
exec $ cLinkCommand (oFile : postOFile : otherOFiles) outputFile (csCompilerLinkFlags cs) exec $ cLinkCommand (oFile : postOFile : otherOFiles) outputFile
(csCompilerLinkFlags $ csOpts cs)
-- For C++, just compile the source file directly into a binary -- For C++, just compile the source file directly into a binary
BackendCPPCSP -> BackendCPPCSP ->
do cs <- getCompState do cs <- getCompState
if csHasMain cs if csHasMain $ csOpts cs
then let otherOFiles = [usedFile ++ ".tock.o" then let otherOFiles = [usedFile ++ ".tock.o"
| usedFile <- Set.toList $ csUsedFiles cs] | usedFile <- Set.toList $ csUsedFiles cs]
in exec $ cxxCommand cFile outputFile in exec $ cxxCommand cFile outputFile
(concat (intersperse " " otherOFiles) ++ " " ++ csCompilerFlags cs ++ " " ++ csCompilerLinkFlags cs) (concat (intersperse " " otherOFiles) ++ " "
++ csCompilerFlags (csOpts cs) ++ " "
++ csCompilerLinkFlags (csOpts cs))
else exec $ cxxCommand cFile (outputFile ++ ".tock.o") else exec $ cxxCommand cFile (outputFile ++ ".tock.o")
("-c " ++ csCompilerFlags cs) ("-c " ++ csCompilerFlags (csOpts cs))
BackendCHP -> BackendCHP ->
exec $ hCommand cFile outputFile exec $ hCommand cFile outputFile
_ -> dieReport (Nothing, "Cannot use specified backend: " _ -> dieReport (Nothing, "Cannot use specified backend: "
++ show (csBackend cs) ++ show (csBackend $ csOpts cs)
++ " with full-compile mode") ++ " with full-compile mode")
-- Finally, remove the temporary files: -- Finally, remove the temporary files:
tempFiles <- FilesPassM get tempFiles <- FilesPassM get
when (not $ csKeepTemporaries cs) $ when (not $ csKeepTemporaries $ csOpts cs) $
liftIO $ removeFiles tempFiles liftIO $ removeFiles tempFiles
where where
@ -404,7 +407,7 @@ compileFull inputFile moutputFile
-- | Picks out the handle from the options and passes it to the function: -- | Picks out the handle from the options and passes it to the function:
useOutputOptions :: (((Handle, Handle), String) -> PassM a) -> PassM a useOutputOptions :: (((Handle, Handle), String) -> PassM a) -> PassM a
useOutputOptions func useOutputOptions func
= do optsPS <- get = do optsPS <- getCompOpts
withHandleFor (csOutputFile optsPS) $ \hb -> withHandleFor (csOutputFile optsPS) $ \hb ->
withHandleFor (csOutputHeaderFile optsPS) $ \hh -> withHandleFor (csOutputHeaderFile optsPS) $ \hh ->
func ((hb, hh), csOutputHeaderFile optsPS) func ((hb, hh), csOutputHeaderFile optsPS)
@ -459,7 +462,7 @@ showTokens html ts = evalState (mapM showToken ts >>* spaceOut) 0
-- because then it's very easy to pass the state around. -- because then it's very easy to pass the state around.
compile :: CompMode -> String -> ((Handle, Handle), String) -> PassM () compile :: CompMode -> String -> ((Handle, Handle), String) -> PassM ()
compile mode fn (outHandles@(outHandle, _), headerName) compile mode fn (outHandles@(outHandle, _), headerName)
= do optsPS <- get = do optsPS <- getCompOpts
debug "{{{ Parse" debug "{{{ Parse"
progress "Parse" progress "Parse"

View File

@ -203,7 +203,7 @@ cgenTopLevel headerName s
sequence_ [tell ["extern int "] >> genName n >> tell ["_stack_size;\n"] sequence_ [tell ["extern int "] >> genName n >> tell ["_stack_size;\n"]
| n <- nss] | n <- nss]
when (csHasMain cs) $ do when (csHasMain $ csOpts cs) $ do
(tlpName, tlpChans) <- tlpInterface (tlpName, tlpChans) <- tlpInterface
tell ["extern int "] tell ["extern int "]
genName tlpName genName tlpName
@ -215,7 +215,7 @@ cgenTopLevel headerName s
call genStructured TopLevel s (\m _ -> tell ["\n#error Invalid top-level item: ", show m]) call genStructured TopLevel s (\m _ -> tell ["\n#error Invalid top-level item: ", show m])
when (csHasMain cs) $ do when (csHasMain $ csOpts cs) $ do
(tlpName, tlpChans) <- tlpInterface (tlpName, tlpChans) <- tlpInterface
chans <- sequence [csmLift $ makeNonce emptyMeta "tlp_channel" | _ <- tlpChans] chans <- sequence [csmLift $ makeNonce emptyMeta "tlp_channel" | _ <- tlpChans]
killChans <- sequence [csmLift $ makeNonce emptyMeta "tlp_channel_kill" | _ <- tlpChans] killChans <- sequence [csmLift $ makeNonce emptyMeta "tlp_channel_kill" | _ <- tlpChans]

View File

@ -100,7 +100,7 @@ chansToAny :: PassOn A.Type
chansToAny = cppOnlyPass "Transform channels to ANY" chansToAny = cppOnlyPass "Transform channels to ANY"
[Prop.processTypesChecked] [Prop.processTypesChecked]
[Prop.allChansToAnyOrProtocol] [Prop.allChansToAnyOrProtocol]
$ \x -> do st <- get $ \x -> do st <- getCompOpts
case csFrontend st of case csFrontend st of
FrontendOccam -> FrontendOccam ->
do chansToAnyInCompState do chansToAnyInCompState
@ -118,7 +118,7 @@ chansToAny = cppOnlyPass "Transform channels to ANY"
chansToAnyM = applyBottomUpM chansToAny' chansToAnyM = applyBottomUpM chansToAny'
chansToAnyInCompState :: PassM () chansToAnyInCompState :: PassM ()
chansToAnyInCompState = do st <- get chansToAnyInCompState = do st <- getCompState
csn <- chansToAnyM (csNames st) csn <- chansToAnyM (csNames st)
put $ st {csNames = csn} put $ st {csNames = csn}
return () return ()
@ -160,12 +160,12 @@ cppgenTopLevel headerName s
call genStructured TopLevel s (\m _ -> tell ["\n#error Invalid top-level item: ",show m]) call genStructured TopLevel s (\m _ -> tell ["\n#error Invalid top-level item: ",show m])
when (csHasMain cs) $ do when (csHasMain $ csOpts cs) $ do
(name, chans) <- tlpInterface (name, chans) <- tlpInterface
tell ["int main (int argc, char** argv) { csp::Start_CPPCSP();"] tell ["int main (int argc, char** argv) { csp::Start_CPPCSP();"]
(chanTypeRead, chanTypeWrite, writer, reader) <- (chanTypeRead, chanTypeWrite, writer, reader) <-
do st <- getCompState do st <- getCompState
case csFrontend st of case csFrontend $ csOpts st of
FrontendOccam -> return ("tockSendableArrayOfBytes", FrontendOccam -> return ("tockSendableArrayOfBytes",
"tockSendableArrayOfBytes", "tockSendableArrayOfBytes",
"StreamWriterByteArray", "StreamWriterByteArray",

View File

@ -396,7 +396,7 @@ testOccamPassWarn str check code pass
(put $ inpS {csWarnings = []}) -- Blank the warnings for the new pass (put $ inpS {csWarnings = []}) -- Blank the warnings for the new pass
(assertEqual str (csNames expS) . csNames) (assertEqual str (csNames expS) . csNames)
where where
emptyStateWithWarnings = emptyState { csEnabledWarnings = Set.fromList [minBound..maxBound] } emptyStateWithWarnings = emptyState { csOpts = emptyOpts {csEnabledWarnings = Set.fromList [minBound..maxBound]} }
-- | Like testOccamPass, but applies a transformation to the patterns (such as -- | Like testOccamPass, but applies a transformation to the patterns (such as
-- using stopCaringPattern) before pattern-matching -- using stopCaringPattern) before pattern-matching

View File

@ -179,7 +179,7 @@ instance ShowRain () where
showCode :: (CSMR m, ShowOccam a, ShowRain a) => a -> m String showCode :: (CSMR m, ShowOccam a, ShowRain a) => a -> m String
showCode o showCode o
= do st <- getCompState = do st <- getCompState
case csFrontend st of case csFrontend $ csOpts st of
FrontendOccam -> return $ concat $ snd $ runWriter $ evalStateT (showOccamM o) FrontendOccam -> return $ concat $ snd $ runWriter $ evalStateT (showOccamM o)
(initialShowCodeState $ transformNames $ csNames st) (initialShowCodeState $ transformNames $ csNames st)
FrontendRain -> return $ concat $ snd $ runWriter $ evalStateT (showRainM o) FrontendRain -> return $ concat $ snd $ runWriter $ evalStateT (showRainM o)

View File

@ -70,8 +70,11 @@ data AutoTest = AutoTest
automaticTest :: CompFrontend -> Int -> FilePath -> IO Test automaticTest :: CompFrontend -> Int -> FilePath -> IO Test
automaticTest fr verb fileName = readFile fileName >>* performTest fr verb fileName automaticTest fr verb fileName = readFile fileName >>* performTest fr verb fileName
defaultOpts :: CompFrontend -> Int -> CompOpts
defaultOpts fr v = emptyOpts {csVerboseLevel = v, csFrontend = fr}
defaultState :: CompFrontend -> Int -> CompState defaultState :: CompFrontend -> Int -> CompState
defaultState fr v = emptyState {csVerboseLevel = v, csFrontend = fr} defaultState fr v = emptyState { csOpts = defaultOpts fr v }
-- | Tests if compiling the given source gives any errors. -- | Tests if compiling the given source gives any errors.
-- If there are errors, they are returned. Upon success, Nothing is returned -- If there are errors, they are returned. Upon success, Nothing is returned
@ -83,7 +86,7 @@ testOccam v source = do (result,_) <- runPassM (defaultState FrontendOccam v) co
where where
compilation = preprocessOccamSource source compilation = preprocessOccamSource source
>>= parseOccamProgram >>= parseOccamProgram
>>= runPasses (getPassList $ defaultState FrontendOccam v) >>= runPasses (getPassList $ defaultOpts FrontendOccam v)
testRain :: Int -> String -> IO (Maybe (Maybe Meta, String)) testRain :: Int -> String -> IO (Maybe (Maybe Meta, String))
testRain v source = do (result,_) <- runPassM (defaultState FrontendRain v) compilation testRain v source = do (result,_) <- runPassM (defaultState FrontendRain v) compilation
@ -92,7 +95,7 @@ testRain v source = do (result,_) <- runPassM (defaultState FrontendRain v) comp
Right _ -> Nothing Right _ -> Nothing
where where
compilation = parseRainProgram "<test>" source compilation = parseRainProgram "<test>" source
>>= runPasses (getPassList $ defaultState FrontendRain v) >>= runPasses (getPassList $ defaultOpts FrontendRain v)
-- | Substitutes each substitution into the prologue -- | Substitutes each substitution into the prologue
substitute :: AutoTest -> Either String [(Bool, String, String)] substitute :: AutoTest -> Either String [(Bool, String, String)]

View File

@ -630,7 +630,7 @@ testPassShouldFail' testName actualPass startStateTrans =
--{{{ miscellaneous utilities --{{{ miscellaneous utilities
markRainTest :: State CompState () markRainTest :: State CompState ()
markRainTest = modify (\cs -> cs { csFrontend = FrontendRain }) markRainTest = modifyCompOpts (\cs -> cs { csFrontend = FrontendRain })
castOrFail :: (Typeable b) => String -> String -> Items -> IO b castOrFail :: (Typeable b) => String -> String -> Items -> IO b
castOrFail testName key items = castOrFail testName key items =

View File

@ -330,7 +330,7 @@ returnTypesOfFunction n
returnTypesOfIntrinsic :: (CSMR m, Die m) => Meta -> String -> m [A.Type] returnTypesOfIntrinsic :: (CSMR m, Die m) => Meta -> String -> m [A.Type]
returnTypesOfIntrinsic m s returnTypesOfIntrinsic m s
= do frontend <- getCompState >>* csFrontend = do frontend <- getCompOpts >>* csFrontend
let intrinsicList = case frontend of let intrinsicList = case frontend of
FrontendOccam -> intrinsicFunctions FrontendOccam -> intrinsicFunctions
FrontendRain -> rainIntrinsicFunctions FrontendRain -> rainIntrinsicFunctions
@ -623,7 +623,7 @@ justSize n = return $ BIJust $ makeConstant emptyMeta n
-- backend. If the backend is not recognised, the C sizes are used. -- backend. If the backend is not recognised, the C sizes are used.
justSizeBackends :: CSMR m => Int -> Int -> m BytesInResult justSizeBackends :: CSMR m => Int -> Int -> m BytesInResult
justSizeBackends c cxx justSizeBackends c cxx
= do backend <- getCompState >>* csBackend = do backend <- getCompOpts >>* csBackend
case backend of case backend of
BackendCPPCSP -> justSize c BackendCPPCSP -> justSize c
_ -> justSize cxx _ -> justSize cxx

View File

@ -97,14 +97,13 @@ data NameAttr = NameShared | NameAliasesPermitted deriving (Typeable, Data, Eq,
data ExternalType = ExternalOldStyle | ExternalOccam data ExternalType = ExternalOldStyle | ExternalOccam
deriving (Typeable, Data, Eq, Show, Ord) deriving (Typeable, Data, Eq, Show, Ord)
-- | State necessary for compilation. -- | Options for the compiler.
data CompState = CompState { --
-- This structure needs to be printable with pshow. -- CompOpts should contain things are adjustable from the command-line. They may
-- There are explicit rules for the Maps and Sets used here -- also change during compilation; for example, the preprocessor definitions will
-- in PrettyShow.hs; if you add any new ones here then remember -- be affected by the preprocessor, and other options may be affected by pragmas
-- to add matching rules there. -- in future.
data CompOpts = CompOpts {
-- Set by Main (from command-line options)
csMode :: CompMode, csMode :: CompMode,
csBackend :: CompBackend, csBackend :: CompBackend,
csFrontend :: CompFrontend, csFrontend :: CompFrontend,
@ -124,6 +123,21 @@ data CompState = CompState {
csUnknownStackSize :: Integer, csUnknownStackSize :: Integer,
csSearchPath :: [String], csSearchPath :: [String],
csImplicitModules :: [String], csImplicitModules :: [String],
csDefinitions :: Map String PreprocDef
}
deriving (Data, Typeable, Show)
-- | State necessary for compilation.
data CompState = CompState {
-- This structure needs to be printable with pshow.
-- There are explicit rules for the Maps and Sets used here
-- in PrettyShow.hs; if you add any new ones here then remember
-- to add matching rules there.
-- Set by Main (from command-line options)
csOpts :: CompOpts,
-- Extra sizes files to look up. These are stored without the tock suffix -- Extra sizes files to look up. These are stored without the tock suffix
csExtraSizes :: [String], csExtraSizes :: [String],
-- Extra include files, stored without the .tock.h suffix. -- Extra include files, stored without the .tock.h suffix.
@ -133,7 +147,6 @@ data CompState = CompState {
csCurrentFile :: String, -- Also used by some later passes! csCurrentFile :: String, -- Also used by some later passes!
-- #USEd files. These are stored with any (known) extensions removed: -- #USEd files. These are stored with any (known) extensions removed:
csUsedFiles :: Set String, csUsedFiles :: Set String,
csDefinitions :: Map String PreprocDef,
-- Set by Parse -- Set by Parse
csMainLocals :: [(String, (A.Name, NameType))], csMainLocals :: [(String, (A.Name, NameType))],
@ -159,8 +172,8 @@ data CompState = CompState {
} }
deriving (Data, Typeable, Show) deriving (Data, Typeable, Show)
emptyState :: CompState emptyOpts :: CompOpts
emptyState = CompState { emptyOpts = CompOpts {
csMode = ModeFull, csMode = ModeFull,
csBackend = BackendC, csBackend = BackendC,
csFrontend = FrontendOccam, csFrontend = FrontendOccam,
@ -185,16 +198,22 @@ emptyState = CompState {
csUnknownStackSize = 512, csUnknownStackSize = 512,
csSearchPath = [".", tockIncludeDir], csSearchPath = [".", tockIncludeDir],
csImplicitModules = [], csImplicitModules = [],
csDefinitions = Map.fromList [("COMPILER.TOCK", PreprocNothing)
,("TARGET.BITS.PER.WORD", PreprocInt $ show $ cIntSize * 8)
,("TARGET.BYTES.PER.WORD", PreprocInt $ show cIntSize)
-- ,("TARGET.HAS.FPU", PreprocNothing)
]
}
emptyState :: CompState
emptyState = CompState {
csOpts = emptyOpts,
csExtraSizes = [], csExtraSizes = [],
csExtraIncludes = [], csExtraIncludes = [],
csCurrentFile = "none", csCurrentFile = "none",
csUsedFiles = Set.empty, csUsedFiles = Set.empty,
csDefinitions = Map.fromList [("COMPILER.TOCK", PreprocNothing)
,("TARGET.BITS.PER.WORD", PreprocInt $ show $ cIntSize * 8)
,("TARGET.BYTES.PER.WORD", PreprocInt $ show cIntSize)
-- ,("TARGET.HAS.FPU", PreprocNothing)
],
csMainLocals = [], csMainLocals = [],
csNames = Map.empty, csNames = Map.empty,
@ -229,6 +248,9 @@ class (Monad m, CSMR m) => CSM m where
modifyCompState :: (CompState -> CompState) -> m () modifyCompState :: (CompState -> CompState) -> m ()
modifyCompState f = (getCompState >>* f) >>= putCompState modifyCompState f = (getCompState >>* f) >>= putCompState
modifyCompOpts :: CSM m => (CompOpts -> CompOpts) -> m ()
modifyCompOpts f = modifyCompState $ \cs -> cs { csOpts = f (csOpts cs) }
-- If it's State CompState, I doubt they will want any other instance than this -- If it's State CompState, I doubt they will want any other instance than this
-- one: -- one:
instance CSM (State CompState) where instance CSM (State CompState) where
@ -268,6 +290,8 @@ instance (CSMR m, Error e) => CSMR (ErrorT e m) where
instance (CSMR m, Monoid w) => CSMR (WriterT w m) where instance (CSMR m, Monoid w) => CSMR (WriterT w m) where
getCompState = lift getCompState getCompState = lift getCompState
getCompOpts :: CSMR m => m CompOpts
getCompOpts = getCompState >>* csOpts
--instance (MonadWriter [WarningReport] m) => Warn m where --instance (MonadWriter [WarningReport] m) => Warn m where
-- warnReport r = tell [r] -- warnReport r = tell [r]
@ -475,7 +499,7 @@ searchFile m filename
= do cs <- getCompState = do cs <- getCompState
let currentFile = csCurrentFile cs let currentFile = csCurrentFile cs
let possibilities = joinPath currentFile filename let possibilities = joinPath currentFile filename
: [dir ++ "/" ++ filename | dir <- csSearchPath cs] : [dir ++ "/" ++ filename | dir <- (csSearchPath . csOpts) cs]
openOneOf possibilities possibilities openOneOf possibilities possibilities
where where
openOneOf :: [String] -> [String] -> m (Handle, String) openOneOf :: [String] -> [String] -> m (Handle, String)

View File

@ -61,7 +61,7 @@ occamPasses =
writeIncFile :: Pass A.AST writeIncFile :: Pass A.AST
writeIncFile = occamOnlyPass "Write .inc file" [] [] writeIncFile = occamOnlyPass "Write .inc file" [] []
(passOnlyOnAST "writeIncFile" (\t -> (passOnlyOnAST "writeIncFile" (\t ->
do out <- getCompState >>* csOutputIncFile do out <- getCompOpts >>* csOutputIncFile
case out of case out of
Just fn -> do f <- liftIO $ openFile fn WriteMode Just fn -> do f <- liftIO $ openFile fn WriteMode
contents <- emitProcsAsExternal t >>* (unlines . F.toList) contents <- emitProcsAsExternal t >>* (unlines . F.toList)

View File

@ -65,7 +65,7 @@ addLocalName n = do st <- getState
instance Warn (GenParser tok OccParserState) where instance Warn (GenParser tok OccParserState) where
warnReport w@(_,t,_) = modifyCompState $ warnReport w@(_,t,_) = modifyCompState $
\cs -> cs { csWarnings = \cs -> cs { csWarnings =
if t `Set.member` csEnabledWarnings cs if t `Set.member` csEnabledWarnings (csOpts cs)
then csWarnings cs ++ [w] then csWarnings cs ++ [w]
else csWarnings cs } else csWarnings cs }
@ -1536,7 +1536,7 @@ pragma = do m <- getPosition >>* sourcePosToMeta
modifyCompState $ \cs -> cs { csExtraIncludes = (f' ++ pragStr) : csExtraIncludes cs } modifyCompState $ \cs -> cs { csExtraIncludes = (f' ++ pragStr) : csExtraIncludes cs }
return Nothing return Nothing
handleNativeLink m [pragStr] handleNativeLink m [pragStr]
= do modifyCompState $ \cs -> cs { csCompilerLinkFlags = csCompilerLinkFlags cs ++ " " ++ pragStr} = do modifyCompOpts $ \cs -> cs { csCompilerLinkFlags = csCompilerLinkFlags cs ++ " " ++ pragStr}
return Nothing return Nothing
handleExternal isCExternal m handleExternal isCExternal m

View File

@ -51,11 +51,11 @@ preprocessFile m implicitMods filename
then Set.insert (dropTockInc realFilename) then Set.insert (dropTockInc realFilename)
. Set.delete (dropTockInc filename) . Set.delete (dropTockInc filename)
else id else id
modify (\cs -> cs { csCurrentFile = realFilename modifyCompState (\cs -> cs { csCurrentFile = realFilename
, csUsedFiles = modFunc $ csUsedFiles cs }) , csUsedFiles = modFunc $ csUsedFiles cs })
s <- liftIO $ hGetContents handle s <- liftIO $ hGetContents handle
toks <- preprocessSource m implicitMods realFilename s toks <- preprocessSource m implicitMods realFilename s
modify (\cs -> cs { csCurrentFile = csCurrentFile origCS }) modifyCompState (\cs -> cs { csCurrentFile = csCurrentFile origCS })
return toks return toks
where where
-- drops ".tock.inc" from the end if it's there: -- drops ".tock.inc" from the end if it's there:
@ -146,7 +146,7 @@ preprocessOccam (Token m (TokPreprocessor s) : ts)
stripPrefix _ = error "bad TokPreprocessor prefix" stripPrefix _ = error "bad TokPreprocessor prefix"
preprocessOccam (Token _ (TokReserved "##") : Token m (TokIdentifier var) : ts) preprocessOccam (Token _ (TokReserved "##") : Token m (TokIdentifier var) : ts)
= do st <- get = do st <- get
case Map.lookup var (csDefinitions st) of case Map.lookup var (csDefinitions $ csOpts st) of
Just (PreprocInt num) -> toToken $ TokIntLiteral num Just (PreprocInt num) -> toToken $ TokIntLiteral num
Just (PreprocString str) -> toToken $ TokStringLiteral str Just (PreprocString str) -> toToken $ TokStringLiteral str
Just (PreprocNothing) -> dieP m $ var ++ " is defined, but has no value" Just (PreprocNothing) -> dieP m $ var ++ " is defined, but has no value"
@ -243,16 +243,16 @@ handleUse m (modName:_)
handleDefine :: DirectiveFunc handleDefine :: DirectiveFunc
handleDefine m [definition] handleDefine m [definition]
= do (var, value) <- runPreprocParser m defineDirective definition = do (var, value) <- runPreprocParser m defineDirective definition
st <- get st <- getCompState >>* csOpts
when (Map.member var $ csDefinitions st) $ when (Map.member var $ csDefinitions st) $
dieP m $ "Preprocessor symbol is already defined: " ++ var dieP m $ "Preprocessor symbol is already defined: " ++ var
put $ st { csDefinitions = Map.insert var value $ csDefinitions st } modifyCompOpts $ \st -> st { csDefinitions = Map.insert var value $ csDefinitions st }
return return return return
-- | Handle the @#UNDEF@ directive. -- | Handle the @#UNDEF@ directive.
handleUndef :: DirectiveFunc handleUndef :: DirectiveFunc
handleUndef m [var] handleUndef m [var]
= do modify $ \st -> st { csDefinitions = Map.delete var $ csDefinitions st } = do modifyCompOpts $ \st -> st { csDefinitions = Map.delete var $ csDefinitions st }
return return return return
-- | Handle the @#IF@ directive. -- | Handle the @#IF@ directive.
@ -408,7 +408,7 @@ expression
-- | Match a 'PreprocParser' production. -- | Match a 'PreprocParser' production.
runPreprocParser :: Meta -> PreprocParser a -> String -> PassM a runPreprocParser :: Meta -> PreprocParser a -> String -> PassM a
runPreprocParser m prod s runPreprocParser m prod s
= do st <- get = do st <- getCompState >>* csOpts
case runParser wrappedProd (csDefinitions st) (show m) s of case runParser wrappedProd (csDefinitions st) (show m) s of
Left err -> dieP m $ "Error parsing preprocessor instruction: " ++ show err Left err -> dieP m $ "Error parsing preprocessor instruction: " ++ show err
Right b -> return b Right b -> return b
@ -423,10 +423,10 @@ runPreprocParser m prod s
-- | Load and preprocess an occam program. -- | Load and preprocess an occam program.
preprocessOccamProgram :: String -> PassM [Token] preprocessOccamProgram :: String -> PassM [Token]
preprocessOccamProgram filename preprocessOccamProgram filename
= do mods <- getCompState >>* csImplicitModules = do mods <- getCompState >>* (csImplicitModules . csOpts)
toks <- preprocessFile emptyMeta mods filename toks <- preprocessFile emptyMeta mods filename
-- Leave the main file name in the csCurrentFile slot: -- Leave the main file name in the csCurrentFile slot:
modify $ \cs -> cs { csCurrentFile = filename } modifyCompState $ \cs -> cs { csCurrentFile = filename }
veryDebug $ "{{{ tokenised source" veryDebug $ "{{{ tokenised source"
veryDebug $ pshow toks veryDebug $ pshow toks
veryDebug $ "}}}" veryDebug $ "}}}"

View File

@ -46,7 +46,7 @@ instance Die PassM where
instance Warn PassM where instance Warn PassM where
warnReport w@(_,t,_) = lift $ modify $ warnReport w@(_,t,_) = lift $ modify $
\cs -> cs { csWarnings = \cs -> cs { csWarnings =
if t `Set.member` csEnabledWarnings cs if t `Set.member` csEnabledWarnings (csOpts cs)
then csWarnings cs ++ [w] then csWarnings cs ++ [w]
else csWarnings cs } else csWarnings cs }
@ -102,7 +102,7 @@ data Pass t = Pass {
, passName :: String , passName :: String
, passPre :: Set.Set Property , passPre :: Set.Set Property
, passPost :: Set.Set Property , passPost :: Set.Set Property
, passEnabled :: CompState -> Bool , passEnabled :: CompOpts -> Bool
} }
instance Eq (Pass t) where instance Eq (Pass t) where
@ -130,7 +130,7 @@ runPassM :: CompState -> PassM a -> IO (Either ErrorReport a, CompState)
runPassM cs pass runPassM cs pass
= flip runStateT cs $ runErrorT pass = flip runStateT cs $ runErrorT pass
enablePassesWhen :: (CompState -> Bool) -> [Pass A.AST] -> [Pass A.AST] enablePassesWhen :: (CompOpts -> Bool) -> [Pass A.AST] -> [Pass A.AST]
enablePassesWhen f enablePassesWhen f
= map (\p -> p { passEnabled = \c -> f c && (passEnabled p c) }) = map (\p -> p { passEnabled = \c -> f c && (passEnabled p c) })
@ -140,7 +140,7 @@ passOnlyOnAST name = id
type PassMaker t = String -> [Property] -> [Property] -> PassType t -> Pass t type PassMaker t = String -> [Property] -> [Property] -> PassType t -> Pass t
passMakerHelper :: (CompState -> Bool) -> PassMaker t passMakerHelper :: (CompOpts -> Bool) -> PassMaker t
passMakerHelper f name pre post code passMakerHelper f name pre post code
= Pass { passCode = code = Pass { passCode = code
, passName = name , passName = name
@ -186,7 +186,7 @@ runPasses (p:ps) ast
verboseMessage :: (CSMR m, MonadIO m) => Int -> String -> m () verboseMessage :: (CSMR m, MonadIO m) => Int -> String -> m ()
verboseMessage n s verboseMessage n s
= do ps <- getCompState = do ps <- getCompState
when (csVerboseLevel ps >= n) $ when (csVerboseLevel (csOpts ps) >= n) $
liftIO $ hPutStrLn stderr s liftIO $ hPutStrLn stderr s
-- | Print a progress message. -- | Print a progress message.

View File

@ -47,7 +47,7 @@ import SimplifyTypes
import Unnest import Unnest
import Utils import Utils
commonPasses :: CompState -> [Pass A.AST] commonPasses :: CompOpts -> [Pass A.AST]
commonPasses opts = concat $ commonPasses opts = concat $
-- Rain does simplifyTypes separately: -- Rain does simplifyTypes separately:
[ enablePassesWhen ((== FrontendOccam) . csFrontend) simplifyTypes [ enablePassesWhen ((== FrontendOccam) . csFrontend) simplifyTypes
@ -72,7 +72,7 @@ commonPasses opts = concat $
-- (passOnlyOnAST "checkUnusedVar" (runChecks checkUnusedVar))] -- (passOnlyOnAST "checkUnusedVar" (runChecks checkUnusedVar))]
] ]
filterPasses :: CompState -> [Pass t] -> [Pass t] filterPasses :: CompOpts -> [Pass t] -> [Pass t]
filterPasses opts = filter (\p -> passEnabled p opts) filterPasses opts = filter (\p -> passEnabled p opts)
-- This pass is so small that we may as well just give it here: -- This pass is so small that we may as well just give it here:
@ -94,7 +94,7 @@ nullStateBodies = Pass
nullProcFuncDefs x = x nullProcFuncDefs x = x
getPassList :: CompState -> [Pass A.AST] getPassList :: CompOpts -> [Pass A.AST]
getPassList optsPS = checkList $ filterPasses optsPS $ concat getPassList optsPS = checkList $ filterPasses optsPS $ concat
[ [nullStateBodies] [ [nullStateBodies]
, enablePassesWhen ((== FrontendOccam) . csFrontend) , enablePassesWhen ((== FrontendOccam) . csFrontend)
@ -108,7 +108,7 @@ getPassList optsPS = checkList $ filterPasses optsPS $ concat
calculatePassList :: CSMR m => m [Pass A.AST] calculatePassList :: CSMR m => m [Pass A.AST]
calculatePassList calculatePassList
= do optsPS <- getCompState = do optsPS <- getCompOpts
let passes = getPassList optsPS let passes = getPassList optsPS
return $ if csSanityCheck optsPS return $ if csSanityCheck optsPS
then addChecks passes then addChecks passes

View File

@ -82,7 +82,7 @@ addForkNames = occamOnlyPass "Add FORK labels" [] []
return $ A.Spec m spec scope' return $ A.Spec m spec scope'
doStructured (A.Spec m (A.Specification m' n spec@(A.Proc m'' smrm fs mbody)) scope) doStructured (A.Spec m (A.Specification m' n spec@(A.Proc m'' smrm fs mbody)) scope)
= do cs <- lift getCompState = do cs <- lift getCompState
if csHasMain cs && Just n == listToMaybe (map (fst . snd) (csMainLocals cs)) if csHasMain (csOpts cs) && Just n == listToMaybe (map (fst . snd) (csMainLocals cs))
then do scope' <- recurse scope then do scope' <- recurse scope
mbody' <- case mbody of mbody' <- case mbody of
Nothing -> return Nothing Nothing -> return Nothing