Pull up array expressions

This commit is contained in:
Adam Sampson 2007-04-12 16:55:26 +00:00
parent f28959c730
commit 00cec5cd5c
7 changed files with 76 additions and 34 deletions

View File

@ -17,9 +17,7 @@ module GenerateC where
-- FIXME: Should have a pass that converts functions to procs, and calls to a -- FIXME: Should have a pass that converts functions to procs, and calls to a
-- call outside the enclosing process (which can be found by a generic pass -- call outside the enclosing process (which can be found by a generic pass
-- over the tree). -- over the tree).
-- Array constants need pulling up at the same time (might as well avoid -- And array subscripts also.
-- walking the tree twice!).
-- And slices. Subscripts generally?
-- FIXME: The timer read mess can be cleaned up -- when you declare a timer, -- FIXME: The timer read mess can be cleaned up -- when you declare a timer,
-- that declares the temp variable... -- that declares the temp variable...
@ -69,7 +67,7 @@ withPS f
= do st <- get = do st <- get
return $ f st return $ f st
checkJust :: Maybe t -> CGen t checkJust :: Monad m => Maybe t -> m t
checkJust (Just v) = return v checkJust (Just v) = return v
checkJust Nothing = fail "checkJust failed" checkJust Nothing = fail "checkJust failed"
@ -483,7 +481,7 @@ CHAN OF INT c IS d: Channel *c = d;
for (...) { cs[i] = &tmp[i]; ChanInit(cs[i]); } for (...) { cs[i] = &tmp[i]; ChanInit(cs[i]); }
const int cs_sizes[] = { 10 }; const int cs_sizes[] = { 10 };
[]CHAN OF INT ds IS cs: Channel **ds = cs; []CHAN OF INT ds IS cs: Channel **ds = cs;
const int ds_sizes[] = cs_sizes; const int *ds_sizes = cs_sizes;
-} -}
introduceSpec :: A.Specification -> CGen () introduceSpec :: A.Specification -> CGen ()
introduceSpec (n, A.Declaration m t) introduceSpec (n, A.Declaration m t)
@ -545,9 +543,9 @@ introduceSpec (n, A.Is m am t v)
tell [";\n"] tell [";\n"]
case rhsSizes of case rhsSizes of
Just r -> Just r ->
do tell ["const int "] do tell ["const int *"]
genName n genName n
tell ["_sizes[] = "] tell ["_sizes = "]
r r
tell [";\n"] tell [";\n"]
Nothing -> return () Nothing -> return ()

View File

@ -67,7 +67,7 @@ main = do
if ParseOnly `elem` opts then if ParseOnly `elem` opts then
putStrLn $ show ast putStrLn $ show ast
else do else do
(ast', state') <- runPass (runPasses passes) ast state (ast', state') <- runPass (runPasses progress passes) ast state
progress "{{{ Generate C" progress "{{{ Generate C"
c <- generateC state' ast' c <- generateC state' ast'

View File

@ -59,3 +59,30 @@ applyPulled ast
let ast' = foldl (\p f -> f p) ast (psPulledItems ps) let ast' = foldl (\p f -> f p) ast (psPulledItems ps)
put $ ps { psPulledItems = [] } put $ ps { psPulledItems = [] }
return ast' return ast'
-- | Generate and define a nonce specification.
defineNonce :: MonadState ParseState m => Meta -> String -> A.SpecType -> A.NameType -> A.AbbrevMode -> m A.Specification
defineNonce m s st nt am
= do ns <- makeNonce s
let n = A.Name m A.ProcName ns
let nd = A.NameDef {
A.ndMeta = m,
A.ndName = ns,
A.ndOrigName = ns,
A.ndNameType = nt,
A.ndType = st,
A.ndAbbrevMode = am
}
modify $ psDefineName n nd
return (n, st)
-- | Generate and define a no-arg wrapper PROC around a process.
makeNonceProc :: MonadState ParseState m => Meta -> A.Process -> m A.Specification
makeNonceProc m p
= defineNonce m "wrapper_proc" (A.Proc m [] p) A.ProcName A.Abbrev
-- | Generate and define a VAL abbreviation.
makeNonceValIs :: MonadState ParseState m => Meta -> A.Type -> A.Expression -> m A.Specification
makeNonceValIs m t e
= defineNonce m "expr" (A.IsExpr m A.ValAbbrev t e) A.VariableName A.ValAbbrev

View File

@ -13,12 +13,12 @@ type Pass = A.Process -> PassM A.Process
runPass :: Pass -> A.Process -> ParseState -> IO (A.Process, ParseState) runPass :: Pass -> A.Process -> ParseState -> IO (A.Process, ParseState)
runPass pass ast st = runStateT (pass ast) st runPass pass ast st = runStateT (pass ast) st
runPasses :: [(String, Pass)] -> A.Process -> PassM A.Process runPasses :: (String -> IO ()) -> [(String, Pass)] -> A.Process -> PassM A.Process
runPasses [] ast = return ast runPasses _ [] ast = return ast
runPasses ((s, p):ps) ast runPasses progress ((s, p):ps) ast
= do liftIO $ putStrLn $ "{{{ " ++ s = do liftIO $ progress $ "{{{ " ++ s
ast' <- p ast ast' <- p ast
liftIO $ putStrLn $ "}}}" liftIO $ progress $ "}}}"
ast'' <- runPasses ps ast' ast'' <- runPasses progress ps ast'
return ast'' return ast''

View File

@ -3,6 +3,7 @@ module SimplifyExprs (simplifyExprs) where
import Control.Monad.State import Control.Monad.State
import Data.Generics import Data.Generics
import Data.Maybe
import qualified AST as A import qualified AST as A
import Metadata import Metadata
@ -13,15 +14,45 @@ import Pass
simplifyExprs :: A.Process -> PassM A.Process simplifyExprs :: A.Process -> PassM A.Process
simplifyExprs = pullUp simplifyExprs = pullUp
-- | Find things that need to be moved up to their enclosing process, and do
-- so.
pullUp :: Data t => t -> PassM t pullUp :: Data t => t -> PassM t
pullUp = doGeneric `extM` doProcess pullUp = doGeneric `extM` doProcess `extM` doExpression
where where
doGeneric :: Data t => t -> PassM t doGeneric :: Data t => t -> PassM t
doGeneric = gmapM pullUp doGeneric = gmapM pullUp
-- | When we encounter a process, create a new pulled items state,
-- recurse over it, then apply whatever pulled items we found to it.
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess p doProcess p
= do p' <- doGeneric p = do -- Save the pulled items
liftIO $ putStrLn $ "looking at process" origPS <- get
modify (\ps -> ps { psPulledItems = [] })
-- Recurse over the process, then apply the pulled items to it
p' <- doGeneric p >>= applyPulled
-- ... and restore the original pulled items
modify (\ps -> ps { psPulledItems = psPulledItems origPS })
return p' return p'
-- | Pull array expressions that aren't already variables.
doExpression :: A.Expression -> PassM A.Expression
doExpression e
= do e' <- doGeneric e
ps <- get
let t = fromJust $ typeOfExpression ps e'
case t of
A.Array _ _ ->
case e of
A.ExprVariable _ _ -> return e'
_ -> pull t e'
_ -> return e'
where
pull :: A.Type -> A.Expression -> PassM A.Expression
pull t e
= do -- FIXME Should get Meta from somewhere...
let m = []
spec@(n, _) <- makeNonceValIs m t e
addPulled $ A.ProcSpec m spec
return $ A.ExprVariable m (A.Variable m n)

View File

@ -3,6 +3,9 @@ module Types where
-- FIXME: This module is a mess -- sort it and document the functions. -- FIXME: This module is a mess -- sort it and document the functions.
-- FIXME: These functions should have state-monadic versions.
-- It'd be nice if we could provide an instance of StateMonad for the Parsec state...
import Control.Monad import Control.Monad
import qualified AST as A import qualified AST as A

View File

@ -15,23 +15,6 @@ import Pass
unnest :: A.Process -> PassM A.Process unnest :: A.Process -> PassM A.Process
unnest p = parsToProcs p >>= removeFreeNames >>= removeNesting unnest p = parsToProcs p >>= removeFreeNames >>= removeNesting
-- | Generate and define a no-arg wrapper PROC around a process.
makeNonceProc :: Meta -> A.Process -> PassM A.Specification
makeNonceProc m p
= do ns <- makeNonce "wrapper_proc"
let n = A.Name m A.ProcName ns
let st = A.Proc m [] p
let nd = A.NameDef {
A.ndMeta = m,
A.ndName = ns,
A.ndOrigName = ns,
A.ndNameType = A.ProcName,
A.ndType = st,
A.ndAbbrevMode = A.Abbrev
}
modify $ psDefineName n nd
return (n, st)
-- | Wrap the subprocesses of PARs in no-arg PROCs. -- | Wrap the subprocesses of PARs in no-arg PROCs.
parsToProcs :: Data t => t -> PassM t parsToProcs :: Data t => t -> PassM t
parsToProcs = doGeneric `extM` doProcess parsToProcs = doGeneric `extM` doProcess