Big AST rework: all spec/rep stuff is now done with Structured

This commit is contained in:
Adam Sampson 2007-04-27 21:49:34 +00:00
parent 5e32facc59
commit 2bcdd7cd66
9 changed files with 144 additions and 143 deletions

View File

@ -172,10 +172,13 @@ data Variant = Variant Meta Name [InputItem] Process
data Structured = data Structured =
Rep Meta Replicator Structured Rep Meta Replicator Structured
| Spec Meta Specification Structured | Spec Meta Specification Structured
| OnlyV Meta Variant | ProcThen Meta Process Structured
| OnlyC Meta Choice | OnlyV Meta Variant -- ^ Variant (CASE) input process
| OnlyO Meta Option | OnlyC Meta Choice -- ^ IF process
| OnlyA Meta Alternative | OnlyO Meta Option -- ^ CASE process
| OnlyA Meta Alternative -- ^ ALT process
| OnlyP Meta Process -- ^ SEQ, PAR
| OnlyEL Meta ExpressionList -- ^ VALOF
| Several Meta [Structured] | Several Meta [Structured]
deriving (Show, Eq, Typeable, Data) deriving (Show, Eq, Typeable, Data)
@ -193,7 +196,6 @@ data AbbrevMode =
data Specification = data Specification =
Specification Meta Name SpecType Specification Meta Name SpecType
| NoSpecification -- ^ A specification that's been removed by a pass.
deriving (Show, Eq, Typeable, Data) deriving (Show, Eq, Typeable, Data)
data SpecType = data SpecType =
@ -207,7 +209,7 @@ data SpecType =
| Protocol Meta [Type] | Protocol Meta [Type]
| ProtocolCase Meta [(Name, [Type])] | ProtocolCase Meta [(Name, [Type])]
| Proc Meta [Formal] Process | Proc Meta [Formal] Process
| Function Meta [Type] [Formal] ValueProcess | Function Meta [Type] [Formal] Structured
| Retypes Meta AbbrevMode Type Variable | Retypes Meta AbbrevMode Type Variable
| RetypesExpr Meta AbbrevMode Type Expression | RetypesExpr Meta AbbrevMode Type Expression
deriving (Show, Eq, Typeable, Data) deriving (Show, Eq, Typeable, Data)
@ -221,31 +223,23 @@ data Actual =
| ActualExpression Type Expression | ActualExpression Type Expression
deriving (Show, Eq, Typeable, Data) deriving (Show, Eq, Typeable, Data)
data ValueProcess =
ValOfSpec Meta Specification ValueProcess
| ValOf Meta Process ExpressionList
deriving (Show, Eq, Typeable, Data)
data ParMode = data ParMode =
PlainPar | PriPar | PlacedPar PlainPar | PriPar | PlacedPar
deriving (Show, Eq, Typeable, Data) deriving (Show, Eq, Typeable, Data)
data Process = data Process =
ProcSpec Meta Specification Process Assign Meta [Variable] ExpressionList
| Assign Meta [Variable] ExpressionList
| Input Meta Variable InputMode | Input Meta Variable InputMode
| Output Meta Variable [OutputItem] | Output Meta Variable [OutputItem]
| OutputCase Meta Variable Name [OutputItem] | OutputCase Meta Variable Name [OutputItem]
| Skip Meta | Skip Meta
| Stop Meta | Stop Meta
| Main Meta | Main Meta
| Seq Meta [Process] | Seq Meta Structured
| SeqRep Meta Replicator Process
| If Meta Structured | If Meta Structured
| Case Meta Expression Structured | Case Meta Expression Structured
| While Meta Expression Process | While Meta Expression Process
| Par Meta ParMode [Process] | Par Meta ParMode Structured
| ParRep Meta ParMode Replicator Process
| Processor Meta Expression Process | Processor Meta Expression Process
| Alt Meta Bool Structured | Alt Meta Bool Structured
| ProcCall Meta Name [Actual] | ProcCall Meta Name [Actual]

View File

@ -89,6 +89,7 @@ overArray var func
genStructured :: A.Structured -> (A.Structured -> CGen ()) -> CGen () genStructured :: A.Structured -> (A.Structured -> CGen ()) -> CGen ()
genStructured (A.Rep _ rep s) def = genReplicator rep (genStructured s def) genStructured (A.Rep _ rep s) def = genReplicator rep (genStructured s def)
genStructured (A.Spec _ spec s) def = genSpec spec (genStructured s def) genStructured (A.Spec _ spec s) def = genSpec spec (genStructured s def)
genStructured (A.ProcThen _ p s) def = genProcess p >> genStructured s def
genStructured (A.Several _ ss) def = sequence_ [genStructured s def | s <- ss] genStructured (A.Several _ ss) def = sequence_ [genStructured s def | s <- ss]
genStructured s def = def s genStructured s def = def s
@ -591,12 +592,6 @@ genReplicatorSize :: A.Replicator -> CGen ()
genReplicatorSize (A.For m n base count) = genExpression count genReplicatorSize (A.For m n base count) = genExpression count
--}}} --}}}
--{{{ choice/alternatives/options/variants
--}}}
--{{{ structured
--}}}
--{{{ abbreviations --{{{ abbreviations
-- FIXME: This code is horrible, and I can't easily convince myself that it's correct. -- FIXME: This code is horrible, and I can't easily convince myself that it's correct.
@ -964,13 +959,9 @@ genFormal (A.Formal am t n)
_ -> genDecl am t n _ -> genDecl am t n
--}}} --}}}
--{{{ par modes
--}}}
--{{{ processes --{{{ processes
genProcess :: A.Process -> CGen () genProcess :: A.Process -> CGen ()
genProcess p = case p of genProcess p = case p of
A.ProcSpec m s p -> genSpec s (genProcess p)
A.Assign m vs es -> genAssign vs es A.Assign m vs es -> genAssign vs es
A.Input m c im -> genInput c im A.Input m c im -> genInput c im
A.Output m c ois -> genOutput c ois A.Output m c ois -> genOutput c ois
@ -978,14 +969,13 @@ genProcess p = case p of
A.Skip m -> tell ["/* skip */\n"] A.Skip m -> tell ["/* skip */\n"]
A.Stop m -> genStop m "STOP process" A.Stop m -> genStop m "STOP process"
A.Main m -> tell ["/* main */\n"] A.Main m -> tell ["/* main */\n"]
A.Seq m ps -> sequence_ $ map genProcess ps A.Seq _ s -> genSeqBody s
A.SeqRep m r p -> genReplicator r (genProcess p)
A.If m s -> genIf m s A.If m s -> genIf m s
A.Case m e s -> genCase m e s A.Case m e s -> genCase m e s
A.While m e p -> genWhile e p A.While m e p -> genWhile e p
A.Par m pm ps -> genPar pm ps A.Par m pm s -> genParBody pm s
A.ParRep m pm r p -> genParRep pm r p -- PROCESSOR does nothing special.
A.Processor m e p -> missing "PROCESSOR not supported" A.Processor m e p -> genProcess p
A.Alt m b s -> genAlt b s A.Alt m b s -> genAlt b s
A.ProcCall m n as -> genProcCall n as A.ProcCall m n as -> genProcCall n as
@ -1098,6 +1088,12 @@ genStop m s
genMeta m genMeta m
tell [", \"", s, "\");\n"] tell [", \"", s, "\");\n"]
--}}} --}}}
--{{{ seq
genSeqBody :: A.Structured -> CGen ()
genSeqBody s = genStructured s doP
where
doP (A.OnlyP _ p) = genProcess p
--}}}
--{{{ if --{{{ if
genIf :: Meta -> A.Structured -> CGen () genIf :: Meta -> A.Structured -> CGen ()
genIf m s genIf m s
@ -1162,13 +1158,28 @@ genWhile e p
tell ["}\n"] tell ["}\n"]
--}}} --}}}
--{{{ par --{{{ par
genPar :: A.ParMode -> [A.Process] -> CGen () -- FIXME: This is a bit odd because it'll only generate the two forms of the
genPar pm ps -- AST resulting from regular and replicated PARs. It'd probably be better to
= do pids <- mapM (\_ -> makeNonce "pid") ps -- make it deal with a general Structured PAR.
sequence_ $ [do tell ["Process *", pid, " = "]
genProcAlloc p genParBody :: A.ParMode -> A.Structured -> CGen ()
tell [";\n"] genParBody pm (A.Spec _ spec s) = genSpec spec (genParBody pm s)
| (pid, p) <- (zip pids ps)] genParBody pm (A.ProcThen _ p s) = genProcess p >> genParBody pm s
genParBody pm (A.Several _ ss) = genPar pm ss
genParBody pm (A.Rep _ rep s) = genParRep pm rep s
genParProc :: (A.Process -> CGen()) -> A.Structured -> CGen ()
genParProc gen (A.Spec _ spec s) = genSpec spec (genParProc gen s)
genParProc gen (A.ProcThen _ p s) = genProcess p >> genParProc gen s
genParProc gen (A.OnlyP _ p) = gen p
genPar :: A.ParMode -> [A.Structured] -> CGen ()
genPar pm ss
= do pids <- sequence [makeNonce "pid" | _ <- ss]
sequence_ $ [genParProc (\p -> do tell ["Process *", pid, " = "]
genProcAlloc p
tell [";\n"]) s
| (pid, s) <- (zip pids ss)]
case pm of case pm of
A.PlainPar -> A.PlainPar ->
do tell ["ProcPar ("] do tell ["ProcPar ("]
@ -1177,17 +1188,17 @@ genPar pm ps
_ -> missing $ "genPar " ++ show pm _ -> missing $ "genPar " ++ show pm
sequence_ $ [tell ["ProcAllocClean (", pid, ");\n"] | pid <- pids] sequence_ $ [tell ["ProcAllocClean (", pid, ");\n"] | pid <- pids]
genParRep :: A.ParMode -> A.Replicator -> A.Process -> CGen () genParRep :: A.ParMode -> A.Replicator -> A.Structured -> CGen ()
genParRep pm rep p genParRep pm rep s
= do pids <- makeNonce "pids" = do pids <- makeNonce "pids"
index <- makeNonce "i" index <- makeNonce "i"
tell ["Process *", pids, "["] tell ["Process *", pids, "["]
genReplicatorSize rep genReplicatorSize rep
tell [" + 1];\n"] tell [" + 1];\n"]
tell ["int ", index, " = 0;\n"] tell ["int ", index, " = 0;\n"]
genReplicator rep $ do tell [pids, "[", index, "++] = "] genReplicator rep $ genParProc (\p -> do tell [pids, "[", index, "++] = "]
genProcAlloc p genProcAlloc p
tell [";\n"] tell [";\n"]) s
tell [pids, "[", index, "] = NULL;\n"] tell [pids, "[", index, "] = NULL;\n"]
tell ["ProcParList (", pids, ");\n"] tell ["ProcParList (", pids, ");\n"]
tell [index, " = 0;\n"] tell [index, " = 0;\n"]
@ -1202,6 +1213,7 @@ genProcAlloc (A.ProcCall m n as)
tell [", ", show stackSize, ", ", show $ numCArgs as] tell [", ", show stackSize, ", ", show $ numCArgs as]
genActuals as genActuals as
tell [")"] tell [")"]
genProcAlloc p = missing $ "genProcAlloc " ++ show p
--}}} --}}}
--{{{ alt --{{{ alt
genAlt :: Bool -> A.Structured -> CGen () genAlt :: Bool -> A.Structured -> CGen ()

View File

@ -1194,7 +1194,7 @@ definition
rs <- tryVX (sepBy1 dataType sComma) sFUNCTION rs <- tryVX (sepBy1 dataType sComma) sFUNCTION
n <- newFunctionName n <- newFunctionName
fs <- formalList fs <- formalList
do { sIS; fs' <- scopeInFormals fs; el <- expressionList rs; scopeOutFormals fs'; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' (A.ValOf m (A.Skip m) el) } do { sIS; fs' <- scopeInFormals fs; el <- expressionList rs; scopeOutFormals fs'; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' (A.OnlyEL m el) }
<|> do { eol; indent; fs' <- scopeInFormals fs; vp <- valueProcess rs; scopeOutFormals fs'; outdent; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' vp } <|> do { eol; indent; fs' <- scopeInFormals fs; vp <- valueProcess rs; scopeOutFormals fs'; outdent; sColon; eol; return $ A.Specification m n $ A.Function m rs fs' vp }
<|> retypesAbbrev <|> retypesAbbrev
<?> "definition" <?> "definition"
@ -1277,7 +1277,7 @@ formalVariableType
return (A.Abbrev, s) return (A.Abbrev, s)
<?> "formal variable type" <?> "formal variable type"
valueProcess :: [A.Type] -> OccParser A.ValueProcess valueProcess :: [A.Type] -> OccParser A.Structured
valueProcess rs valueProcess rs
= do m <- md = do m <- md
sVALOF sVALOF
@ -1288,8 +1288,8 @@ valueProcess rs
el <- expressionList rs el <- expressionList rs
eol eol
outdent outdent
return $ A.ValOf m p el return $ A.ProcThen m p (A.OnlyEL m el)
<|> handleSpecs specification (valueProcess rs) A.ValOfSpec <|> handleSpecs specification (valueProcess rs) A.Spec
<?> "value process" <?> "value process"
--}}} --}}}
--{{{ RECORDs --{{{ RECORDs
@ -1336,7 +1336,8 @@ process
<|> altProcess <|> altProcess
<|> procInstance <|> procInstance
<|> mainProcess <|> mainProcess
<|> handleSpecs (allocation <|> specification) process A.ProcSpec <|> handleSpecs (allocation <|> specification) process
(\m s p -> A.Seq m (A.Spec m s (A.OnlyP m p)))
<|> preprocessorDirective <|> preprocessorDirective
<?> "process" <?> "process"
@ -1510,8 +1511,8 @@ seqProcess :: OccParser A.Process
seqProcess seqProcess
= do m <- md = do m <- md
sSEQ sSEQ
do { eol; ps <- maybeIndentedList m "empty SEQ" process; return $ A.Seq m ps } do { eol; ps <- maybeIndentedList m "empty SEQ" process; return $ A.Seq m (A.Several m (map (A.OnlyP m) ps)) }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.SeqRep m r' p } <|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.Seq m (A.Rep m r' (A.OnlyP m p)) }
<?> "SEQ process" <?> "SEQ process"
--}}} --}}}
--{{{ IF --{{{ IF
@ -1598,24 +1599,21 @@ parallel :: OccParser A.Process
parallel parallel
= do m <- md = do m <- md
isPri <- parKeyword isPri <- parKeyword
do { eol; ps <- maybeIndentedList m "empty PAR" process; return $ A.Par m isPri ps } do { eol; ps <- maybeIndentedList m "empty PAR" process; return $ A.Par m isPri (A.Several m (map (A.OnlyP m) ps)) }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.ParRep m isPri r' p } <|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- process; scopeOutRep r'; outdent; return $ A.Par m isPri (A.Rep m r' (A.OnlyP m p)) }
<|> placedpar <|> processor
<?> "PAR process" <?> "PAR process"
parKeyword :: OccParser A.ParMode parKeyword :: OccParser A.ParMode
parKeyword parKeyword
= do { sPAR; return A.PlainPar } = do { sPAR; return A.PlainPar }
<|> do { tryXX sPRI sPAR; return A.PriPar } <|> do { tryXX sPRI sPAR; return A.PriPar }
<|> do { tryXX sPLACED sPAR; return A.PlacedPar }
-- XXX PROCESSOR as a process isn't really legal, surely? -- XXX PROCESSOR as a process isn't really legal, surely?
placedpar :: OccParser A.Process processor :: OccParser A.Process
placedpar processor
= do m <- md = do m <- md
tryXX sPLACED sPAR
do { eol; ps <- maybeIndentedList m "empty PLACED PAR" placedpar; return $ A.Par m A.PlacedPar ps }
<|> do { r <- replicator; eol; indent; r' <- scopeInRep r; p <- placedpar; scopeOutRep r'; outdent; return $ A.ParRep m A.PlacedPar r' p }
<|> do m <- md
sPROCESSOR sPROCESSOR
e <- intExpr e <- intExpr
eol eol
@ -1851,7 +1849,8 @@ parseFile file ps
Right (p, ps'') -> return (replaceMain p, ps'') Right (p, ps'') -> return (replaceMain p, ps'')
where where
replaceMain :: A.Process -> A.Process -> A.Process replaceMain :: A.Process -> A.Process -> A.Process
replaceMain (A.ProcSpec m s p) np = A.ProcSpec m s (replaceMain p np) replaceMain (A.Seq m (A.Spec m' s (A.OnlyP m'' p))) np
= A.Seq m (A.Spec m' s (A.OnlyP m'' (replaceMain p np)))
replaceMain (A.Main _) np = np replaceMain (A.Main _) np = np
-- | Parse the top level source file in a program. -- | Parse the top level source file in a program.

View File

@ -32,13 +32,13 @@ data ParseState = ParseState {
-- Set by passes -- Set by passes
psNonceCounter :: Int, psNonceCounter :: Int,
psFunctionReturns :: [(String, [A.Type])], psFunctionReturns :: [(String, [A.Type])],
psPulledItems :: [A.Process -> A.Process], psPulledItems :: [A.Structured -> A.Structured],
psAdditionalArgs :: [(String, [A.Actual])] psAdditionalArgs :: [(String, [A.Actual])]
} }
deriving (Show, Data, Typeable) deriving (Show, Data, Typeable)
instance Show (A.Process -> A.Process) where instance Show (A.Structured -> A.Structured) where
show p = "(function on A.Process)" show p = "(function on Structured)"
emptyState :: ParseState emptyState :: ParseState
emptyState = ParseState { emptyState = ParseState {
@ -95,11 +95,11 @@ makeNonce s
return $ s ++ "_n" ++ show i return $ s ++ "_n" ++ show i
-- | Add a pulled item to the collection. -- | Add a pulled item to the collection.
addPulled :: PSM m => (A.Process -> A.Process) -> m () addPulled :: PSM m => (A.Structured -> A.Structured) -> m ()
addPulled item = modify (\ps -> ps { psPulledItems = item : psPulledItems ps }) addPulled item = modify (\ps -> ps { psPulledItems = item : psPulledItems ps })
-- | Apply pulled items to a Process. -- | Apply pulled items to a Structured.
applyPulled :: PSM m => A.Process -> m A.Process applyPulled :: PSM m => A.Structured -> m A.Structured
applyPulled ast applyPulled ast
= do ps <- get = do ps <- get
let ast' = foldl (\p f -> f p) ast (psPulledItems ps) let ast' = foldl (\p f -> f p) ast (psPulledItems ps)

View File

@ -35,7 +35,7 @@ functionsToProcs = doGeneric `extM` doSpecification
-- Note the return types so we can fix calls later. -- Note the return types so we can fix calls later.
modify $ (\ps -> ps { psFunctionReturns = (A.nameName n, rts) : psFunctionReturns ps }) modify $ (\ps -> ps { psFunctionReturns = (A.nameName n, rts) : psFunctionReturns ps })
-- Turn the value process into an assignment process. -- Turn the value process into an assignment process.
let p = vpToProc vp [A.Variable mf n | n <- names] let p = A.Seq mf $ vpToSeq vp [A.Variable mf n | n <- names]
let st = A.Proc mf (fs ++ [A.Formal A.Abbrev t n | (t, n) <- zip rts names]) p let st = A.Proc mf (fs ++ [A.Formal A.Abbrev t n | (t, n) <- zip rts names]) p
-- Build a new specification and redefine the function. -- Build a new specification and redefine the function.
let spec = A.Specification m n st let spec = A.Specification m n st
@ -51,9 +51,10 @@ functionsToProcs = doGeneric `extM` doSpecification
doGeneric spec doGeneric spec
doSpecification s = doGeneric s doSpecification s = doGeneric s
vpToProc :: A.ValueProcess -> [A.Variable] -> A.Process vpToSeq :: A.Structured -> [A.Variable] -> A.Structured
vpToProc (A.ValOfSpec m s vp) vs = A.ProcSpec m s (vpToProc vp vs) vpToSeq (A.Spec m spec s) vs = A.Spec m spec (vpToSeq s vs)
vpToProc (A.ValOf m p el) vs = A.Seq m [p, A.Assign m vs el] vpToSeq (A.ProcThen m p s) vs = A.ProcThen m p (vpToSeq s vs)
vpToSeq (A.OnlyEL m el) vs = A.OnlyP m $ A.Assign m vs el
-- | Convert AFTER expressions to the equivalent using MINUS (which is how the -- | Convert AFTER expressions to the equivalent using MINUS (which is how the
-- occam 3 manual defines AFTER). -- occam 3 manual defines AFTER).
@ -72,26 +73,28 @@ removeAfter = doGeneric `extM` doExpression
return $ A.Dyadic m A.More (A.Dyadic m A.Minus a' b') zero return $ A.Dyadic m A.More (A.Dyadic m A.Minus a' b') zero
doExpression e = doGeneric e doExpression e = doGeneric e
-- | Find things that need to be moved up to their enclosing process, and do -- | Find things that need to be moved up to their enclosing Structured, and do
-- so. -- so.
-- FIXME We probably need to force there to be Structureds in some places -- or
-- construct them if we get to a Process without finding one.
pullUp :: Data t => t -> PassM t pullUp :: Data t => t -> PassM t
pullUp = doGeneric `extM` doProcess `extM` doSpecification `extM` doExpression `extM` doVariable `extM` doExpressionList pullUp = doGeneric `extM` doStructured `extM` doSpecification `extM` doExpression `extM` doVariable `extM` doExpressionList
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, -- | When we encounter a process, create a new pulled items state,
-- recurse over it, then apply whatever pulled items we found to it. -- recurse over it, then apply whatever pulled items we found to it.
doProcess :: A.Process -> PassM A.Process doStructured :: A.Structured -> PassM A.Structured
doProcess p doStructured s
= do -- Save the pulled items = do -- Save the pulled items
origPS <- get origPulled <- liftM psPulledItems get
modify (\ps -> ps { psPulledItems = [] }) modify (\ps -> ps { psPulledItems = [] })
-- Recurse over the process, then apply the pulled items to it -- Recurse over the body, then apply the pulled items to it
p' <- doGeneric p >>= applyPulled s' <- doGeneric s >>= applyPulled
-- ... and restore the original pulled items -- ... and restore the original pulled items
modify (\ps -> ps { psPulledItems = psPulledItems origPS }) modify (\ps -> ps { psPulledItems = origPulled })
return p' return s'
-- | *Don't* pull anything that's already an abbreviation. -- | *Don't* pull anything that's already an abbreviation.
doSpecification :: A.Specification -> PassM A.Specification doSpecification :: A.Specification -> PassM A.Specification
@ -119,7 +122,7 @@ pullUp = doGeneric `extM` doProcess `extM` doSpecification `extM` doExpression `
pull t e pull t e
= do let m = metaOfExpression e = do let m = metaOfExpression e
spec@(A.Specification _ n _) <- makeNonceIsExpr "array_expr" m t e spec@(A.Specification _ n _) <- makeNonceIsExpr "array_expr" m t e
addPulled $ A.ProcSpec m spec addPulled $ A.Spec m spec
return $ A.ExprVariable m (A.Variable m n) return $ A.ExprVariable m (A.Variable m n)
-- | Pull any variable subscript that results in an array. -- | Pull any variable subscript that results in an array.
@ -132,7 +135,7 @@ pullUp = doGeneric `extM` doProcess `extM` doSpecification `extM` doExpression `
do origAM <- abbrevModeOfVariable v' do origAM <- abbrevModeOfVariable v'
let am = makeAbbrevAM origAM let am = makeAbbrevAM origAM
spec@(A.Specification _ n _) <- makeNonceIs "array_slice" m t am v' spec@(A.Specification _ n _) <- makeNonceIs "array_slice" m t am v'
addPulled $ A.ProcSpec m spec addPulled $ A.Spec m spec
return $ A.Variable m n return $ A.Variable m n
_ -> return v' _ -> return v'
doVariable v = doGeneric v doVariable v = doGeneric v
@ -146,12 +149,12 @@ pullUp = doGeneric `extM` doProcess `extM` doSpecification `extM` doExpression `
ps <- get ps <- get
let rts = fromJust $ lookup (A.nameName n) (psFunctionReturns ps) let rts = fromJust $ lookup (A.nameName n) (psFunctionReturns ps)
specs <- sequence [makeNonceVariable "return_actual" m t A.VariableName A.Original | t <- rts] specs <- sequence [makeNonceVariable "return_actual" m t A.VariableName A.Original | t <- rts]
sequence_ [addPulled $ A.ProcSpec m spec | spec <- specs] sequence_ [addPulled $ A.Spec m spec | spec <- specs]
let names = [n | A.Specification _ n _ <- specs] let names = [n | A.Specification _ n _ <- specs]
let vars = [A.Variable m n | n <- names] let vars = [A.Variable m n | n <- names]
let call = A.ProcCall m n ([A.ActualExpression t e | (t, e) <- zip ets es'] ++ [A.ActualVariable A.Abbrev t v | (t, v) <- zip rts vars]) let call = A.ProcCall m n ([A.ActualExpression t e | (t, e) <- zip ets es'] ++ [A.ActualVariable A.Abbrev t v | (t, v) <- zip rts vars])
addPulled (\p -> A.Seq m [call, p]) addPulled $ A.ProcThen m call
return vars return vars

View File

@ -28,20 +28,33 @@ parsToProcs = doGeneric `extM` doProcess
doGeneric = gmapM parsToProcs doGeneric = gmapM parsToProcs
doProcess :: A.Process -> PassM A.Process doProcess :: A.Process -> PassM A.Process
doProcess (A.Par m pm ps) doProcess (A.Par m pm s)
= do ps' <- mapM parsToProcs ps = do s' <- doStructured s
procs <- mapM (makeNonceProc m) ps' return $ A.Par m pm s'
let calls = [A.ProcSpec m s (A.ProcCall m n []) | s@(A.Specification m n _) <- procs]
return $ A.Par m pm calls
doProcess (A.ParRep m pm rep p)
= do p' <- parsToProcs p
rep' <- parsToProcs rep
s@(A.Specification _ n _) <- makeNonceProc m p'
let call = A.ProcSpec m s (A.ProcCall m n [])
return $ A.ParRep m pm rep' call
doProcess p = doGeneric p doProcess p = doGeneric p
-- | Turn parallel assignment into multiple single assignments. -- FIXME This should be generic and in Pass.
doStructured :: A.Structured -> PassM A.Structured
doStructured (A.Rep m r s)
= do r' <- parsToProcs r
s' <- doStructured s
return $ A.Rep m r' s'
doStructured (A.Spec m spec s)
= do spec' <- parsToProcs spec
s' <- doStructured s
return $ A.Spec m spec' s'
doStructured (A.ProcThen m p s)
= do p' <- parsToProcs p
s' <- doStructured s
return $ A.ProcThen m p' s'
doStructured (A.OnlyP m p)
= do p' <- parsToProcs p
s@(A.Specification _ n _) <- makeNonceProc m p'
return $ A.Spec m s (A.OnlyP m (A.ProcCall m n []))
doStructured (A.Several m ss)
= liftM (A.Several m) $ mapM doStructured ss
-- | Turn parallel assignment into multiple single assignments through temporaries.
removeParAssign :: Data t => t -> PassM t removeParAssign :: Data t => t -> PassM t
removeParAssign = doGeneric `extM` doProcess removeParAssign = doGeneric `extM` doProcess
where where
@ -55,6 +68,6 @@ removeParAssign = doGeneric `extM` doProcess
let temps = [A.Variable m n | A.Specification _ n _ <- specs] let temps = [A.Variable m n | A.Specification _ n _ <- specs]
let first = [A.Assign m [v] (A.ExpressionList m [e]) | (v, e) <- zip temps es] let first = [A.Assign m [v] (A.ExpressionList m [e]) | (v, e) <- zip temps es]
let second = [A.Assign m [v] (A.ExpressionList m [A.ExprVariable m v']) | (v, v') <- zip vs temps] let second = [A.Assign m [v] (A.ExpressionList m [A.ExprVariable m v']) | (v, v') <- zip vs temps]
return $ foldl (\p s -> A.ProcSpec m s p) (A.Seq m $ first ++ second) specs return $ A.Seq m $ foldl (\s spec -> A.Spec m spec s) (A.Several m (map (A.OnlyP m) (first ++ second))) specs
doProcess p = doGeneric p doProcess p = doGeneric p

View File

@ -38,15 +38,6 @@ Output item expressions should be pulled up to variables.
RETYPES of expressions should be converted to RETYPES of variables. RETYPES of expressions should be converted to RETYPES of variables.
Pulling up won't work correctly for things like:
IF i = 0 FOR 5
some.func (i)
...
This will require some thought (and probably some AST changes to insert an
artifical place to pull up to -- perhaps just a more flexible Specification
type).
How about having a slot for "process, then" in Structured?
Before code generation, have a pass that resolves all the DATA TYPE .. IS Before code generation, have a pass that resolves all the DATA TYPE .. IS
directives to their real types. directives to their real types.

View File

@ -19,14 +19,13 @@ unnest = runPasses passes
passes = passes =
[ ("Convert free names to arguments", removeFreeNames) [ ("Convert free names to arguments", removeFreeNames)
, ("Pull nested definitions to top level", removeNesting) , ("Pull nested definitions to top level", removeNesting)
, ("Clean up removed specifications", removeNoSpecs)
] ]
type NameMap = Map.Map String A.Name type NameMap = Map.Map String A.Name
-- | Get the set of free names within a block of code. -- | Get the set of free names within a block of code.
freeNamesIn :: Data t => t -> NameMap freeNamesIn :: Data t => t -> NameMap
freeNamesIn = doGeneric `extQ` doName `extQ` doProcess `extQ` doStructured `extQ` doValueProcess `extQ` doSpecType freeNamesIn = doGeneric `extQ` doName `extQ` doStructured `extQ` doSpecType
where where
doGeneric :: Data t => t -> NameMap doGeneric :: Data t => t -> NameMap
doGeneric n = Map.unions $ gmapQ freeNamesIn n doGeneric n = Map.unions $ gmapQ freeNamesIn n
@ -34,21 +33,11 @@ freeNamesIn = doGeneric `extQ` doName `extQ` doProcess `extQ` doStructured `extQ
doName :: A.Name -> NameMap doName :: A.Name -> NameMap
doName n = Map.singleton (A.nameName n) n doName n = Map.singleton (A.nameName n) n
doProcess :: A.Process -> NameMap
doProcess (A.ProcSpec _ spec p) = doSpec spec p
doProcess (A.SeqRep _ rep p) = doRep rep p
doProcess (A.ParRep _ _ rep p) = doRep rep p
doProcess p = doGeneric p
doStructured :: A.Structured -> NameMap doStructured :: A.Structured -> NameMap
doStructured (A.Rep _ rep s) = doRep rep s doStructured (A.Rep _ rep s) = doRep rep s
doStructured (A.Spec _ spec s) = doSpec spec s doStructured (A.Spec _ spec s) = doSpec spec s
doStructured s = doGeneric s doStructured s = doGeneric s
doValueProcess :: A.ValueProcess -> NameMap
doValueProcess (A.ValOfSpec _ spec vp) = doSpec spec vp
doValueProcess vp = doGeneric vp
doSpec :: Data t => A.Specification -> t -> NameMap doSpec :: Data t => A.Specification -> t -> NameMap
doSpec (A.Specification _ n st) child doSpec (A.Specification _ n st) child
= Map.union fns $ Map.delete (A.nameName n) $ freeNamesIn child = Map.union fns $ Map.delete (A.nameName n) $ freeNamesIn child
@ -156,22 +145,24 @@ removeFreeNames = doGeneric `extM` doSpecification `extM` doProcess
removeNesting :: A.Process -> PassM A.Process removeNesting :: A.Process -> PassM A.Process
removeNesting p removeNesting p
= do p' <- pullSpecs p = do p' <- pullSpecs p
applyPulled p' s <- applyPulled $ A.OnlyP emptyMeta p'
return $ A.Seq emptyMeta s
where where
pullSpecs :: Data t => t -> PassM t pullSpecs :: Data t => t -> PassM t
pullSpecs = doGeneric `extM` doSpecification pullSpecs = doGeneric `extM` doStructured
doGeneric :: Data t => t -> PassM t doGeneric :: Data t => t -> PassM t
doGeneric = gmapM pullSpecs doGeneric = gmapM pullSpecs
doSpecification :: A.Specification -> PassM A.Specification doStructured :: A.Structured -> PassM A.Structured
doSpecification spec@(A.Specification m n st) doStructured s@(A.Spec m spec@(A.Specification _ n st) subS)
= do isConst <- isConstantName n = do isConst <- isConstantName n
if isConst || canPull st then if isConst || canPull st then
do spec' <- doGeneric spec do spec' <- doGeneric spec
addPulled $ A.ProcSpec m spec' addPulled $ A.Spec m spec'
return A.NoSpecification return subS
else doGeneric spec else doGeneric s
doStructured s = doGeneric s
canPull :: A.SpecType -> Bool canPull :: A.SpecType -> Bool
canPull (A.Proc _ _ _) = True canPull (A.Proc _ _ _) = True
@ -181,21 +172,3 @@ removeNesting p
canPull (A.ProtocolCase _ _) = True canPull (A.ProtocolCase _ _) = True
canPull _ = False canPull _ = False
-- | Remove specifications that have been turned into NoSpecifications.
removeNoSpecs :: Data t => t -> PassM t
removeNoSpecs = doGeneric `extM` doProcess `extM` doStructured `extM` doValueProcess
where
doGeneric :: Data t => t -> PassM t
doGeneric n = gmapM removeNoSpecs n
doProcess :: A.Process -> PassM A.Process
doProcess (A.ProcSpec _ A.NoSpecification p) = removeNoSpecs p
doProcess p = doGeneric p
doStructured :: A.Structured -> PassM A.Structured
doStructured (A.Spec _ A.NoSpecification s) = removeNoSpecs s
doStructured s = doGeneric s
doValueProcess :: A.ValueProcess -> PassM A.ValueProcess
doValueProcess (A.ValOfSpec _ A.NoSpecification vp) = removeNoSpecs vp
doValueProcess vp = doGeneric vp

View File

@ -0,0 +1,16 @@
-- From cgtest00.
PROC S19 ()
INT X:
SEQ
X := 42
[4]INT V:
[3]CHAN OF INT c:
PAR
PAR i = 0 FOR 3
c[i] ! (i + 5)
X := X
PAR i = 0 FOR 3
c[i] ? V[i]
: