Pull up array expressions
This commit is contained in:
parent
f28959c730
commit
00cec5cd5c
|
@ -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 ()
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
12
fco2/Pass.hs
12
fco2/Pass.hs
|
@ -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''
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user