Added support for extended rendezvous throughout the compiler
This commit is contained in:
parent
41cf599ebe
commit
3a5565471f
|
@ -1044,11 +1044,24 @@ genDest f v = call genVariable' v A.Original (f . Pointer . stripPointers)
|
||||||
genChan :: A.Variable -> CGen ()
|
genChan :: A.Variable -> CGen ()
|
||||||
genChan c = call genVariable' c A.Original (const $ Pointer $ Plain "Channel")
|
genChan c = call genVariable' c A.Original (const $ Pointer $ Plain "Channel")
|
||||||
|
|
||||||
cgenInputItem :: A.Variable -> A.InputItem -> CGen ()
|
cgenInputItem :: A.Variable -> A.InputItem -> Maybe A.Process -> CGen ()
|
||||||
cgenInputItem c (A.InCounted m cv av)
|
cgenInputItem c (A.InCounted m cv av) mp
|
||||||
= do call genInputItem c (A.InVariable m cv)
|
= do call genInputItem c (A.InVariable m cv) Nothing
|
||||||
t <- astTypeOf av
|
case mp of
|
||||||
tell ["ChanIn(wptr,"]
|
Nothing -> cgenInputItem' ""
|
||||||
|
Just p ->
|
||||||
|
do tell ["ChanXAble(wptr,"]
|
||||||
|
genChan c
|
||||||
|
tell [");"]
|
||||||
|
cgenInputItem' "X"
|
||||||
|
call genProcess p
|
||||||
|
tell ["ChanXEnd(wptr,"]
|
||||||
|
genChan c
|
||||||
|
tell [");"]
|
||||||
|
where
|
||||||
|
cgenInputItem' x
|
||||||
|
= do t <- astTypeOf av
|
||||||
|
tell ["Chan", x, "In(wptr,"]
|
||||||
genChan c
|
genChan c
|
||||||
tell [","]
|
tell [","]
|
||||||
genDest id av
|
genDest id av
|
||||||
|
@ -1058,7 +1071,19 @@ cgenInputItem c (A.InCounted m cv av)
|
||||||
tell ["*"]
|
tell ["*"]
|
||||||
call genBytesIn m subT (Right av)
|
call genBytesIn m subT (Right av)
|
||||||
tell [");"]
|
tell [");"]
|
||||||
cgenInputItem c (A.InVariable m v)
|
cgenInputItem c (A.InVariable m v) mp
|
||||||
|
= case mp of
|
||||||
|
Nothing -> cgenInputItem' ""
|
||||||
|
Just p -> do tell ["ChanXAble(wptr,"]
|
||||||
|
genChan c
|
||||||
|
tell [");"]
|
||||||
|
cgenInputItem' "X"
|
||||||
|
call genProcess p
|
||||||
|
tell ["ChanXEnd(wptr,"]
|
||||||
|
genChan c
|
||||||
|
tell [");"]
|
||||||
|
where
|
||||||
|
cgenInputItem' x
|
||||||
= do case v of
|
= do case v of
|
||||||
-- If we are reading into a dereferenced mobile, we must make sure
|
-- If we are reading into a dereferenced mobile, we must make sure
|
||||||
-- that something is in that mobile first:
|
-- that something is in that mobile first:
|
||||||
|
@ -1075,22 +1100,16 @@ cgenInputItem c (A.InVariable m v)
|
||||||
t <- astTypeOf v
|
t <- astTypeOf v
|
||||||
isMobile <- isMobileType t
|
isMobile <- isMobileType t
|
||||||
let rhs = genDest (if isMobile then Pointer else id) v
|
let rhs = genDest (if isMobile then Pointer else id) v
|
||||||
case (t, isMobile) of
|
if isMobile
|
||||||
(A.Int, _) ->
|
then
|
||||||
do tell ["ChanInInt(wptr,"]
|
|
||||||
genChan c
|
|
||||||
tell [","]
|
|
||||||
rhs
|
|
||||||
tell [");"]
|
|
||||||
(_, True) ->
|
|
||||||
do call genClearMobile m v -- TODO insert this via a pass
|
do call genClearMobile m v -- TODO insert this via a pass
|
||||||
tell ["MTChanIn(wptr,"]
|
tell ["MTChan", x, "In(wptr,"]
|
||||||
genChan c
|
genChan c
|
||||||
tell [",(void**)"]
|
tell [",(void**)"]
|
||||||
rhs
|
rhs
|
||||||
tell [");"]
|
tell [");"]
|
||||||
_ ->
|
else
|
||||||
do tell ["ChanIn(wptr,"]
|
do tell ["Chan", x, "In(wptr,"]
|
||||||
genChan c
|
genChan c
|
||||||
tell [","]
|
tell [","]
|
||||||
rhs
|
rhs
|
||||||
|
@ -1815,7 +1834,7 @@ cgenInput c im
|
||||||
= do case im of
|
= do case im of
|
||||||
A.InputTimerRead m (A.InVariable m' v) -> call genTimerRead c v
|
A.InputTimerRead m (A.InVariable m' v) -> call genTimerRead c v
|
||||||
A.InputTimerAfter m e -> call genTimerWait e
|
A.InputTimerAfter m e -> call genTimerWait e
|
||||||
A.InputSimple m is -> sequence_ $ map (call genInputItem c) is
|
A.InputSimple m [ii] mp -> call genInputItem c ii mp
|
||||||
_ -> call genMissing $ "genInput " ++ show im
|
_ -> call genMissing $ "genInput " ++ show im
|
||||||
|
|
||||||
cgenTimerRead :: A.Variable -> A.Variable -> CGen ()
|
cgenTimerRead :: A.Variable -> A.Variable -> CGen ()
|
||||||
|
|
|
@ -166,7 +166,7 @@ data GenOps = GenOps {
|
||||||
-- | Generates an IF statement (which can have replicators, specifications and such things inside it).
|
-- | Generates an IF statement (which can have replicators, specifications and such things inside it).
|
||||||
genIf :: Meta -> A.Structured A.Choice -> CGen (),
|
genIf :: Meta -> A.Structured A.Choice -> CGen (),
|
||||||
genInput :: A.Variable -> A.InputMode -> CGen (),
|
genInput :: A.Variable -> A.InputMode -> CGen (),
|
||||||
genInputItem :: A.Variable -> A.InputItem -> CGen (),
|
genInputItem :: A.Variable -> A.InputItem -> Maybe A.Process -> CGen (),
|
||||||
genIntrinsicFunction :: Meta -> String -> [A.Expression] -> CGen (),
|
genIntrinsicFunction :: Meta -> String -> [A.Expression] -> CGen (),
|
||||||
genIntrinsicProc :: Meta -> String -> [A.Actual] -> CGen (),
|
genIntrinsicProc :: Meta -> String -> [A.Actual] -> CGen (),
|
||||||
genListAssign :: A.Variable -> A.Expression -> CGen (),
|
genListAssign :: A.Variable -> A.Expression -> CGen (),
|
||||||
|
|
|
@ -329,11 +329,11 @@ cppgenTimerWait e
|
||||||
time <- genCPPCSPTime e
|
time <- genCPPCSPTime e
|
||||||
tell ["csp::SleepUntil(",time,");"]
|
tell ["csp::SleepUntil(",time,");"]
|
||||||
|
|
||||||
cppgenInputItem :: A.Variable -> A.InputItem -> CGen ()
|
cppgenInputItem :: A.Variable -> A.InputItem -> Maybe A.Process -> CGen ()
|
||||||
cppgenInputItem c dest
|
cppgenInputItem c dest Nothing
|
||||||
= case dest of
|
= case dest of
|
||||||
(A.InCounted m cv av) ->
|
(A.InCounted m cv av) ->
|
||||||
do call genInputItem c (A.InVariable m cv)
|
do call genInputItem c (A.InVariable m cv) Nothing
|
||||||
recvBytes av (
|
recvBytes av (
|
||||||
do call genVariable cv A.Original
|
do call genVariable cv A.Original
|
||||||
tell ["*"]
|
tell ["*"]
|
||||||
|
|
|
@ -163,7 +163,7 @@ getVarProc (A.Output _ chanVar outItems)
|
||||||
getVarOutputItem :: A.OutputItem -> Vars
|
getVarOutputItem :: A.OutputItem -> Vars
|
||||||
getVarOutputItem (A.OutExpression _ e) = getVarExp e
|
getVarOutputItem (A.OutExpression _ e) = getVarExp e
|
||||||
getVarOutputItem (A.OutCounted _ ce ae) = (getVarExp ce) `unionVars` (getVarExp ae)
|
getVarOutputItem (A.OutCounted _ ce ae) = (getVarExp ce) `unionVars` (getVarExp ae)
|
||||||
getVarProc (A.Input _ chanVar (A.InputSimple _ iis))
|
getVarProc (A.Input _ chanVar (A.InputSimple _ iis _))
|
||||||
= return $ (processVarUsed chanVar)
|
= return $ (processVarUsed chanVar)
|
||||||
`unionVars` (mapUnionVars getVarInputItem iis)
|
`unionVars` (mapUnionVars getVarInputItem iis)
|
||||||
where
|
where
|
||||||
|
|
|
@ -557,9 +557,9 @@ showProtocolItem (n,ts) = sequence_ $ intersperse (tell [" ; "]) $
|
||||||
showName n : (map showOccamM ts)
|
showName n : (map showOccamM ts)
|
||||||
|
|
||||||
instance ShowOccam A.Variant where
|
instance ShowOccam A.Variant where
|
||||||
showOccamM (A.Variant _ n iis p)
|
showOccamM (A.Variant _ n iis p mp)
|
||||||
= (showOccamLine (sequence_ $ intersperse (tell [" ; "]) $ [showName n] ++ (map showOccamM iis)))
|
= (showOccamLine (sequence_ $ intersperse (tell [" ; "]) $ [showName n] ++ (map showOccamM iis)))
|
||||||
>> occamIndent >> showOccamM p >> occamOutdent
|
>> occamIndent >> showOccamM p >> doMaybe (fmap showOccamM mp) >> occamOutdent
|
||||||
|
|
||||||
instance ShowOccam A.Actual where
|
instance ShowOccam A.Actual where
|
||||||
showOccamM (A.ActualVariable v) = showOccamM v
|
showOccamM (A.ActualVariable v) = showOccamM v
|
||||||
|
@ -579,10 +579,19 @@ instance ShowOccam A.InputItem where
|
||||||
showOccamM (A.InCounted _ cv av) = showOccamM cv >> tell [" :: "] >> showOccamM av
|
showOccamM (A.InCounted _ cv av) = showOccamM cv >> tell [" :: "] >> showOccamM av
|
||||||
|
|
||||||
instance ShowOccam A.InputMode where
|
instance ShowOccam A.InputMode where
|
||||||
showOccamM (A.InputSimple _ iis)
|
showOccamM (A.InputSimple _ iis Nothing)
|
||||||
= showOccamLine $ getTempItem >> tell [" ? "] >> (showWithSemis iis)
|
= showOccamLine $ getTempItem >> tell [" ? "] >> (showWithSemis iis)
|
||||||
showOccamM (A.InputCase _ str)
|
showOccamM (A.InputSimple _ iis (Just p))
|
||||||
= (showOccamLine $ getTempItem >> tell [" ? CASE"]) >> occamIndent >> showOccamM str >> occamOutdent
|
= do showOccamLine $ getTempItem >> tell [" ?? "] >> (showWithSemis iis)
|
||||||
|
occamIndent
|
||||||
|
showOccamM p
|
||||||
|
occamOutdent
|
||||||
|
showOccamM (A.InputCase _ ty str)
|
||||||
|
= (showOccamLine $ getTempItem >> tell [op, "CASE"]) >> occamIndent >> showOccamM str >> occamOutdent
|
||||||
|
where
|
||||||
|
op = case ty of
|
||||||
|
A.InputCaseNormal -> " ? "
|
||||||
|
A.InputCaseExtended -> " ?? "
|
||||||
showOccamM (A.InputTimerRead _ ii)
|
showOccamM (A.InputTimerRead _ ii)
|
||||||
= showOccamLine $ getTempItem >> tell [" ? "] >> showOccamM ii
|
= showOccamLine $ getTempItem >> tell [" ? "] >> showOccamM ii
|
||||||
showOccamM (A.InputTimerAfter _ e)
|
showOccamM (A.InputTimerAfter _ e)
|
||||||
|
|
17
data/AST.hs
17
data/AST.hs
|
@ -360,7 +360,12 @@ data Option =
|
||||||
-- | An option in a @? CASE@ process.
|
-- | An option in a @? CASE@ process.
|
||||||
-- The name is the protocol tag, followed by zero or more input items, followed
|
-- The name is the protocol tag, followed by zero or more input items, followed
|
||||||
-- by the process to be executed if that option is matched.
|
-- by the process to be executed if that option is matched.
|
||||||
data Variant = Variant Meta Name [InputItem] Process
|
--
|
||||||
|
-- If this is part of a normal input, the first process is the process to execute,
|
||||||
|
-- and the Maybe item is ignored. If it is an extended input, the first process
|
||||||
|
-- is the one to execute during the extended rendezvous and the Maybe item is the
|
||||||
|
-- optional process to execute afterwards
|
||||||
|
data Variant = Variant Meta Name [InputItem] Process (Maybe Process)
|
||||||
deriving (Show, Eq, Typeable, Data)
|
deriving (Show, Eq, Typeable, Data)
|
||||||
|
|
||||||
-- | This represents something that can contain local replicators and
|
-- | This represents something that can contain local replicators and
|
||||||
|
@ -410,12 +415,16 @@ instance Data a => Data (Structured a) where
|
||||||
dataTypeOf _ = _struct_DataType
|
dataTypeOf _ = _struct_DataType
|
||||||
dataCast1 f = gcast1 f
|
dataCast1 f = gcast1 f
|
||||||
|
|
||||||
|
data InputCaseType
|
||||||
|
= InputCaseNormal | InputCaseExtended
|
||||||
|
deriving (Eq, Show, Typeable, Data)
|
||||||
|
|
||||||
-- | The mode in which an input operates.
|
-- | The mode in which an input operates.
|
||||||
data InputMode =
|
data InputMode =
|
||||||
-- | A plain input from a channel.
|
-- | A plain input from a channel, with a possible extended action.
|
||||||
InputSimple Meta [InputItem]
|
InputSimple Meta [InputItem] (Maybe Process)
|
||||||
-- | A variant input from a channel.
|
-- | A variant input from a channel.
|
||||||
| InputCase Meta (Structured Variant)
|
| InputCase Meta InputCaseType (Structured Variant)
|
||||||
-- | Read the value of a timer.
|
-- | Read the value of a timer.
|
||||||
| InputTimerRead Meta InputItem
|
| InputTimerRead Meta InputItem
|
||||||
-- | Wait for a particular time to go past on a timer.
|
-- | Wait for a particular time to go past on a timer.
|
||||||
|
|
|
@ -336,15 +336,15 @@ checkProcesses x = checkDepthM doProcess x >> return x
|
||||||
doChoice (A.Choice _ e _) = checkExpressionBool e
|
doChoice (A.Choice _ e _) = checkExpressionBool e
|
||||||
|
|
||||||
doInput :: A.Variable -> A.InputMode -> PassM ()
|
doInput :: A.Variable -> A.InputMode -> PassM ()
|
||||||
doInput c (A.InputSimple m iis)
|
doInput c (A.InputSimple m iis _)
|
||||||
= do t <- checkChannel A.DirInput c
|
= do t <- checkChannel A.DirInput c
|
||||||
checkProtocol m t Nothing iis doInputItem
|
checkProtocol m t Nothing iis doInputItem
|
||||||
doInput c (A.InputCase _ s)
|
doInput c (A.InputCase _ _ s)
|
||||||
= do t <- checkChannel A.DirInput c
|
= do t <- checkChannel A.DirInput c
|
||||||
checkStructured (doVariant t) s
|
checkStructured (doVariant t) s
|
||||||
where
|
where
|
||||||
doVariant :: A.Type -> A.Variant -> PassM ()
|
doVariant :: A.Type -> A.Variant -> PassM ()
|
||||||
doVariant t (A.Variant m tag iis _)
|
doVariant t (A.Variant m tag iis _ _)
|
||||||
= checkProtocol m t (Just tag) iis doInputItem
|
= checkProtocol m t (Just tag) iis doInputItem
|
||||||
doInput c (A.InputTimerRead m ii)
|
doInput c (A.InputTimerRead m ii)
|
||||||
= do t <- checkTimer c
|
= do t <- checkTimer c
|
||||||
|
|
|
@ -416,14 +416,15 @@ inferTypes = occamOnlyPass "Infer types"
|
||||||
return $ A.AlternativeSkip m pre' p'
|
return $ A.AlternativeSkip m pre' p'
|
||||||
|
|
||||||
doInputMode :: A.Variable -> Infer A.InputMode
|
doInputMode :: A.Variable -> Infer A.InputMode
|
||||||
doInputMode v (A.InputSimple m iis)
|
doInputMode v (A.InputSimple m iis mp)
|
||||||
= do ts <- protocolItems m v >>* either id (const [])
|
= do ts <- protocolItems m v >>* either id (const [])
|
||||||
iis' <- sequence [doInputItem t ii
|
iis' <- sequence [doInputItem t ii
|
||||||
| (t, ii) <- zip ts iis]
|
| (t, ii) <- zip ts iis]
|
||||||
return $ A.InputSimple m iis'
|
mp' <- recurse mp
|
||||||
doInputMode v (A.InputCase m sv)
|
return $ A.InputSimple m iis' mp'
|
||||||
|
doInputMode v (A.InputCase m ty sv)
|
||||||
= do ct <- astTypeOf v
|
= do ct <- astTypeOf v
|
||||||
inTypeContext (Just ct) (recurse sv) >>* A.InputCase m
|
inTypeContext (Just ct) (recurse sv) >>* A.InputCase m ty
|
||||||
doInputMode _ (A.InputTimerRead m ii)
|
doInputMode _ (A.InputTimerRead m ii)
|
||||||
= doInputItem A.Int ii >>* A.InputTimerRead m
|
= doInputItem A.Int ii >>* A.InputTimerRead m
|
||||||
doInputMode _ im = inTypeContext (Just A.Int) $ descend im
|
doInputMode _ im = inTypeContext (Just A.Int) $ descend im
|
||||||
|
@ -441,7 +442,7 @@ inferTypes = occamOnlyPass "Infer types"
|
||||||
return $ A.InCounted m cv' av'
|
return $ A.InCounted m cv' av'
|
||||||
|
|
||||||
doVariant :: Infer A.Variant
|
doVariant :: Infer A.Variant
|
||||||
doVariant (A.Variant m n iis p)
|
doVariant (A.Variant m n iis p mp)
|
||||||
= do ctx <- getTypeContext
|
= do ctx <- getTypeContext
|
||||||
ets <- case ctx of
|
ets <- case ctx of
|
||||||
Just x -> protocolItems m x
|
Just x -> protocolItems m x
|
||||||
|
@ -454,7 +455,8 @@ inferTypes = occamOnlyPass "Infer types"
|
||||||
Just ts -> do iis' <- sequence [doInputItem t ii
|
Just ts -> do iis' <- sequence [doInputItem t ii
|
||||||
| (t, ii) <- zip ts iis]
|
| (t, ii) <- zip ts iis]
|
||||||
p' <- recurse p
|
p' <- recurse p
|
||||||
return $ A.Variant m n iis' p'
|
mp' <- recurse mp
|
||||||
|
return $ A.Variant m n iis' p' mp'
|
||||||
|
|
||||||
doStructured :: ( PolyplateM (A.Structured t) InferTypeOps () InferTypeM
|
doStructured :: ( PolyplateM (A.Structured t) InferTypeOps () InferTypeM
|
||||||
, PolyplateM (A.Structured t) () InferTypeOps InferTypeM
|
, PolyplateM (A.Structured t) () InferTypeOps InferTypeM
|
||||||
|
|
|
@ -19,7 +19,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-- | Parse occam code into an AST.
|
-- | Parse occam code into an AST.
|
||||||
module ParseOccam (parseOccamProgram) where
|
module ParseOccam (parseOccamProgram) where
|
||||||
|
|
||||||
import Control.Monad (join, liftM)
|
import Control.Monad (join, liftM, when)
|
||||||
import Control.Monad.State (MonadState, modify, get, put)
|
import Control.Monad.State (MonadState, modify, get, put)
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import Data.List
|
import Data.List
|
||||||
|
@ -125,7 +125,7 @@ plainToken t = genToken test
|
||||||
test (Token _ t') = if t == t' then Just () else Nothing
|
test (Token _ t') = if t == t' then Just () else Nothing
|
||||||
--}}}
|
--}}}
|
||||||
--{{{ symbols
|
--{{{ symbols
|
||||||
sAmp, sAssign, sBang, sBar, sColon, sColons, sComma, sEq, sLeft, sLeftR,
|
sAmp, sAssign, sBang, sBar, sColon, sColons, sComma, sDoubleQuest, sEq, sLeft, sLeftR,
|
||||||
sQuest, sRight, sRightR, sSemi
|
sQuest, sRight, sRightR, sSemi
|
||||||
:: OccParser ()
|
:: OccParser ()
|
||||||
|
|
||||||
|
@ -136,6 +136,7 @@ sBar = reserved "|"
|
||||||
sColon = reserved ":"
|
sColon = reserved ":"
|
||||||
sColons = reserved "::"
|
sColons = reserved "::"
|
||||||
sComma = reserved ","
|
sComma = reserved ","
|
||||||
|
sDoubleQuest = reserved "??"
|
||||||
sEq = reserved "="
|
sEq = reserved "="
|
||||||
sLeft = reserved "["
|
sLeft = reserved "["
|
||||||
sLeftR = reserved "("
|
sLeftR = reserved "("
|
||||||
|
@ -1106,7 +1107,7 @@ specification
|
||||||
= do m <- md
|
= do m <- md
|
||||||
(ns, d, nt) <- declaration
|
(ns, d, nt) <- declaration
|
||||||
return ([(A.Specification m n d, nt, normalName) | n <- ns], return ())
|
return ([(A.Specification m n d, nt, normalName) | n <- ns], return ())
|
||||||
<|> do { a <- abbreviation; return ([a], return ()) }
|
<|> do { a <- abbreviation; return (a, return ()) }
|
||||||
<|> do { d <- definition; return ([d], return ()) }
|
<|> do { d <- definition; return ([d], return ()) }
|
||||||
<|> do { n <- pragma ; return (maybeToList n, return ()) }
|
<|> do { n <- pragma ; return (maybeToList n, return ()) }
|
||||||
<?> "specification"
|
<?> "specification"
|
||||||
|
@ -1668,37 +1669,60 @@ assignment
|
||||||
inputProcess :: OccParser A.Process
|
inputProcess :: OccParser A.Process
|
||||||
inputProcess
|
inputProcess
|
||||||
= do m <- md
|
= do m <- md
|
||||||
(c, i) <- input
|
(c, i, mp) <- input False
|
||||||
return $ A.Input m c i
|
return $ case mp of
|
||||||
|
Nothing -> A.Input m c i
|
||||||
|
Just p -> A.Seq m $ A.Several m $ map (A.Only m) [A.Input m c i, p]
|
||||||
<?> "input process"
|
<?> "input process"
|
||||||
|
|
||||||
input :: OccParser (A.Variable, A.InputMode)
|
-- True for in-ALT, False for normal
|
||||||
input
|
input :: Bool ->OccParser (A.Variable, A.InputMode, Maybe A.Process)
|
||||||
= channelInput
|
input inAlt
|
||||||
<|> timerInput
|
= channelInput inAlt
|
||||||
|
<|> (timerInput >>* (\(a, b) -> (a, b, Nothing)))
|
||||||
<|> do m <- md
|
<|> do m <- md
|
||||||
p <- tryVX port sQuest
|
p <- tryVX port sQuest
|
||||||
v <- variable
|
v <- variable
|
||||||
eol
|
eol
|
||||||
return (p, A.InputSimple m [A.InVariable m v])
|
return (p, A.InputSimple m [A.InVariable m v] Nothing, Nothing)
|
||||||
<?> "input"
|
<?> "input"
|
||||||
|
|
||||||
channelInput :: OccParser (A.Variable, A.InputMode)
|
channelInput :: Bool -> OccParser (A.Variable, A.InputMode, Maybe A.Process)
|
||||||
channelInput
|
channelInput inAlt
|
||||||
= do m <- md
|
= do m <- md
|
||||||
c <- tryVX channel sQuest
|
( do c <- tryVX channel sQuest
|
||||||
caseInput m c <|> plainInput m c
|
caseInput m c <|> plainInput m c
|
||||||
|
<|> do c <- tryVX channel sDoubleQuest
|
||||||
|
extCaseInput m c <|> extInput m c
|
||||||
|
)
|
||||||
<?> "channel input"
|
<?> "channel input"
|
||||||
where
|
where
|
||||||
caseInput m c
|
caseInput m c
|
||||||
= do sCASE
|
= do sCASE
|
||||||
tl <- taggedList
|
tl <- taggedList
|
||||||
eol
|
eol
|
||||||
return (c, A.InputCase m (A.Only m (tl (A.Skip m))))
|
return (c, A.InputCase m A.InputCaseNormal (A.Only m (tl (A.Skip m) Nothing)), Nothing)
|
||||||
plainInput m c
|
plainInput m c
|
||||||
= do is <- sepBy1 inputItem sSemi
|
= do is <- sepBy1 inputItem sSemi
|
||||||
eol
|
eol
|
||||||
return (c, A.InputSimple m is)
|
return (c, A.InputSimple m is Nothing, Nothing)
|
||||||
|
|
||||||
|
extInput m c
|
||||||
|
= do is <- sepBy1 inputItem sSemi
|
||||||
|
eol
|
||||||
|
indent
|
||||||
|
p <- process
|
||||||
|
mp <- if inAlt then return Nothing else (tryVX process outdent >>* Just) <|> (outdent >> return Nothing)
|
||||||
|
return (c, A.InputSimple m is (Just p), mp)
|
||||||
|
|
||||||
|
extCaseInput m c
|
||||||
|
= do sCASE
|
||||||
|
tl <- taggedList
|
||||||
|
eol
|
||||||
|
indent
|
||||||
|
p <- process
|
||||||
|
mp <- if inAlt then return Nothing else (tryVX process outdent >>* Just) <|> (outdent >> return Nothing)
|
||||||
|
return (c, A.InputCase m A.InputCaseExtended (A.Only m (tl p mp)), Nothing)
|
||||||
|
|
||||||
timerInput :: OccParser (A.Variable, A.InputMode)
|
timerInput :: OccParser (A.Variable, A.InputMode)
|
||||||
timerInput
|
timerInput
|
||||||
|
@ -1708,7 +1732,7 @@ timerInput
|
||||||
<|> do { sAFTER; e <- expression; eol; return (c, A.InputTimerAfter m e) }
|
<|> do { sAFTER; e <- expression; eol; return (c, A.InputTimerAfter m e) }
|
||||||
<?> "timer input"
|
<?> "timer input"
|
||||||
|
|
||||||
taggedList :: OccParser (A.Process -> A.Variant)
|
taggedList :: OccParser (A.Process -> Maybe A.Process -> A.Variant)
|
||||||
taggedList
|
taggedList
|
||||||
= do m <- md
|
= do m <- md
|
||||||
tag <- tagName
|
tag <- tagName
|
||||||
|
@ -1732,19 +1756,28 @@ caseInput :: OccParser A.Process
|
||||||
caseInput
|
caseInput
|
||||||
= do m <- md
|
= do m <- md
|
||||||
c <- tryVX channel (sQuest >> sCASE >> eol)
|
c <- tryVX channel (sQuest >> sCASE >> eol)
|
||||||
vs <- maybeIndentedList m "empty ? CASE" variant
|
vs <- maybeIndentedList m "empty ? CASE" (variant A.InputCaseNormal)
|
||||||
return $ A.Input m c (A.InputCase m (A.Several m vs))
|
return $ A.Input m c (A.InputCase m A.InputCaseNormal (A.Several m vs))
|
||||||
|
<|> do m <- md
|
||||||
|
c <- tryVX channel (sDoubleQuest >> sCASE >> eol)
|
||||||
|
vs <- maybeIndentedList m "empty ? CASE" (variant A.InputCaseExtended)
|
||||||
|
return $ A.Input m c (A.InputCase m A.InputCaseExtended (A.Several m vs))
|
||||||
<?> "case input"
|
<?> "case input"
|
||||||
|
|
||||||
variant :: OccParser (A.Structured A.Variant)
|
variant :: A.InputCaseType -> OccParser (A.Structured A.Variant)
|
||||||
variant
|
variant ty
|
||||||
= do m <- md
|
= do m <- md
|
||||||
tl <- tryVX taggedList eol
|
tl <- tryVX taggedList eol
|
||||||
indent
|
indent
|
||||||
p <- process
|
p <- process
|
||||||
outdent
|
case ty of
|
||||||
return $ A.Only m (tl p)
|
A.InputCaseNormal -> do outdent
|
||||||
<|> handleSpecs specification variant A.Spec
|
return $ A.Only m (tl p Nothing)
|
||||||
|
A.InputCaseExtended ->
|
||||||
|
do mp <- (tryVX process outdent >>* Just)
|
||||||
|
<|> (outdent >> return Nothing)
|
||||||
|
return $ A.Only m (tl p mp)
|
||||||
|
<|> handleSpecs specification (variant ty) A.Spec
|
||||||
<?> "variant"
|
<?> "variant"
|
||||||
--}}}
|
--}}}
|
||||||
--{{{ output (!)
|
--{{{ output (!)
|
||||||
|
@ -1943,39 +1976,48 @@ alternative
|
||||||
-- guards are below.
|
-- guards are below.
|
||||||
<|> do m <- md
|
<|> do m <- md
|
||||||
(b, c) <- tryVXVX expression sAmp channel (sQuest >> sCASE >> eol)
|
(b, c) <- tryVXVX expression sAmp channel (sQuest >> sCASE >> eol)
|
||||||
vs <- maybeIndentedList m "empty ? CASE" variant
|
guardCaseBody m b c A.InputCaseNormal
|
||||||
return $ A.Only m (A.Alternative m b c (A.InputCase m $ A.Several m vs) (A.Skip m))
|
|
||||||
<|> do m <- md
|
<|> do m <- md
|
||||||
c <- tryVXX channel sQuest (sCASE >> eol)
|
c <- tryVXX channel sQuest (sCASE >> eol)
|
||||||
vs <- maybeIndentedList m "empty ? CASE" variant
|
guardCaseBody m (A.True m) c A.InputCaseNormal
|
||||||
return $ A.Only m (A.Alternative m (A.True m) c (A.InputCase m $ A.Several m vs) (A.Skip m))
|
<|> do m <- md
|
||||||
|
(b, c) <- tryVXVX expression sAmp channel (sDoubleQuest >> sCASE >> eol)
|
||||||
|
guardCaseBody m b c A.InputCaseExtended
|
||||||
|
<|> do m <- md
|
||||||
|
c <- tryVXX channel sDoubleQuest (sCASE >> eol)
|
||||||
|
guardCaseBody m (A.True m) c A.InputCaseExtended
|
||||||
<|> guardedAlternative
|
<|> guardedAlternative
|
||||||
<|> handleSpecs specification alternative A.Spec
|
<|> handleSpecs specification alternative A.Spec
|
||||||
<?> "alternative"
|
<?> "alternative"
|
||||||
|
where
|
||||||
|
guardCaseBody :: Meta -> A.Expression -> A.Variable -> A.InputCaseType -> OccParser (A.Structured A.Alternative)
|
||||||
|
guardCaseBody m b c ty
|
||||||
|
= do vs <- maybeIndentedList m "empty ? CASE" (variant ty)
|
||||||
|
return $ A.Only m (A.Alternative m b c (A.InputCase m ty $ A.Several m vs) (A.Skip m))
|
||||||
|
|
||||||
guardedAlternative :: OccParser (A.Structured A.Alternative)
|
guardedAlternative :: OccParser (A.Structured A.Alternative)
|
||||||
guardedAlternative
|
guardedAlternative
|
||||||
= do m <- md
|
= do m <- md
|
||||||
makeAlt <- guard
|
(makeAlt, alreadyIndented) <- guard
|
||||||
indent
|
when (not alreadyIndented) $ indent
|
||||||
p <- process
|
p <- process
|
||||||
outdent
|
outdent
|
||||||
return $ A.Only m (makeAlt p)
|
return $ A.Only m (makeAlt p)
|
||||||
<?> "guarded alternative"
|
<?> "guarded alternative"
|
||||||
|
|
||||||
guard :: OccParser (A.Process -> A.Alternative)
|
guard :: OccParser (A.Process -> A.Alternative, Bool)
|
||||||
guard
|
guard
|
||||||
= do m <- md
|
= do m <- md
|
||||||
(c, im) <- input
|
(c, im, _) <- input True
|
||||||
return $ A.Alternative m (A.True m) c im
|
return (A.Alternative m (A.True m) c im, True)
|
||||||
<|> do m <- md
|
<|> do m <- md
|
||||||
sSKIP
|
sSKIP
|
||||||
eol
|
eol
|
||||||
return $ A.AlternativeSkip m (A.True m)
|
return (A.AlternativeSkip m (A.True m), False)
|
||||||
<|> do m <- md
|
<|> do m <- md
|
||||||
b <- tryVX expression sAmp
|
b <- tryVX expression sAmp
|
||||||
do { (c, im) <- input; return $ A.Alternative m b c im }
|
do { (c, im, _) <- input True; return (A.Alternative m b c im, True) }
|
||||||
<|> do { sSKIP; eol; return $ A.AlternativeSkip m b }
|
<|> do { sSKIP; eol; return (A.AlternativeSkip m b, False) }
|
||||||
<?> "guard"
|
<?> "guard"
|
||||||
--}}}
|
--}}}
|
||||||
--{{{ PROC calls
|
--{{{ PROC calls
|
||||||
|
|
|
@ -391,7 +391,7 @@ comm isAlt
|
||||||
(if isAlt
|
(if isAlt
|
||||||
then pzero
|
then pzero
|
||||||
else do {sOut ; exp <- expression ; possSemiColon ; return $ A.Output (findMeta lv) lv [A.OutExpression (findMeta exp) exp] })
|
else do {sOut ; exp <- expression ; possSemiColon ; return $ A.Output (findMeta lv) lv [A.OutExpression (findMeta exp) exp] })
|
||||||
<|> do {sIn ; rv <- lvalue ; possSemiColon ; return $ A.Input (findMeta lv) lv $ A.InputSimple (findMeta rv) [A.InVariable (findMeta rv) rv] }
|
<|> do {sIn ; rv <- lvalue ; possSemiColon ; return $ A.Input (findMeta lv) lv $ A.InputSimple (findMeta rv) [A.InVariable (findMeta rv) rv] Nothing }
|
||||||
<?> (if isAlt then "input statement" else "input or output statement")
|
<?> (if isAlt then "input statement" else "input or output statement")
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
|
|
|
@ -309,7 +309,7 @@ markCommTypes = checkDepthM2 checkInputOutput checkAltInput
|
||||||
checkWait _ = return ()
|
checkWait _ = return ()
|
||||||
|
|
||||||
checkInputOutput :: RainTypeCheck A.Process
|
checkInputOutput :: RainTypeCheck A.Process
|
||||||
checkInputOutput p@(A.Input m chanVar (A.InputSimple _ [A.InVariable _ destVar]))
|
checkInputOutput p@(A.Input m chanVar (A.InputSimple _ [A.InVariable _ destVar] _))
|
||||||
= checkInput chanVar destVar m p
|
= checkInput chanVar destVar m p
|
||||||
checkInputOutput (A.Input _ _ im@(A.InputTimerFor {})) = checkWait im
|
checkInputOutput (A.Input _ _ im@(A.InputTimerFor {})) = checkWait im
|
||||||
checkInputOutput (A.Input _ _ im@(A.InputTimerAfter {})) = checkWait im
|
checkInputOutput (A.Input _ _ im@(A.InputTimerAfter {})) = checkWait im
|
||||||
|
@ -319,7 +319,7 @@ markCommTypes = checkDepthM2 checkInputOutput checkAltInput
|
||||||
checkInputOutput _ = return ()
|
checkInputOutput _ = return ()
|
||||||
|
|
||||||
checkAltInput :: RainTypeCheck A.Alternative
|
checkAltInput :: RainTypeCheck A.Alternative
|
||||||
checkAltInput a@(A.Alternative m _ chanVar (A.InputSimple _ [A.InVariable _ destVar]) body)
|
checkAltInput a@(A.Alternative m _ chanVar (A.InputSimple _ [A.InVariable _ destVar] _) body)
|
||||||
= checkInput chanVar destVar m a
|
= checkInput chanVar destVar m a
|
||||||
checkAltInput (A.Alternative m _ _ im@(A.InputTimerFor {}) _) = checkWait im
|
checkAltInput (A.Alternative m _ _ im@(A.InputTimerFor {}) _) = checkWait im
|
||||||
checkAltInput (A.Alternative m _ _ im@(A.InputTimerAfter {}) _) = checkWait im
|
checkAltInput (A.Alternative m _ _ im@(A.InputTimerAfter {}) _) = checkWait im
|
||||||
|
|
|
@ -391,7 +391,7 @@ seqInputsFlattened :: Property
|
||||||
seqInputsFlattened = Property "seqInputsFlattened" $ checkNull "seqInputsFlattened" . listify findMultipleInputs
|
seqInputsFlattened = Property "seqInputsFlattened" $ checkNull "seqInputsFlattened" . listify findMultipleInputs
|
||||||
where
|
where
|
||||||
findMultipleInputs :: A.InputMode -> Bool
|
findMultipleInputs :: A.InputMode -> Bool
|
||||||
findMultipleInputs (A.InputSimple _ (_:_:_)) = True
|
findMultipleInputs (A.InputSimple _ (_:_:_) _) = True
|
||||||
findMultipleInputs _ = False
|
findMultipleInputs _ = False
|
||||||
|
|
||||||
arraySizesDeclared :: Property
|
arraySizesDeclared :: Property
|
||||||
|
|
|
@ -21,6 +21,7 @@ module SimplifyComms where
|
||||||
|
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Data.List
|
import Data.List
|
||||||
|
import Data.Maybe
|
||||||
|
|
||||||
import qualified AST as A
|
import qualified AST as A
|
||||||
import CompState
|
import CompState
|
||||||
|
@ -142,30 +143,60 @@ transformInputCase = pass "Transform ? CASE statements/guards into plain CASE"
|
||||||
(applyBottomUpM doProcess)
|
(applyBottomUpM doProcess)
|
||||||
where
|
where
|
||||||
doProcess :: A.Process -> PassM A.Process
|
doProcess :: A.Process -> PassM A.Process
|
||||||
doProcess (A.Input m v (A.InputCase m' s))
|
doProcess (A.Input m v (A.InputCase m' ty s))
|
||||||
= do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int) A.Original
|
= do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int) A.Original
|
||||||
s' <- doStructuredV v s
|
case ty of
|
||||||
return $ A.Seq m $ A.Spec m' spec $ A.Several m'
|
A.InputCaseNormal -> do
|
||||||
[A.Only m $ A.Input m v (A.InputSimple m [A.InVariable m (A.Variable m n)])
|
s' <- doStructuredV Nothing v s
|
||||||
,A.Only m' $ A.Case m' (A.ExprVariable m $ A.Variable m n) s']
|
return $ A.Seq m $ A.Spec m' spec $ A.Several m'
|
||||||
|
[A.Only m $ A.Input m v (A.InputSimple m [A.InVariable m (A.Variable m n)] Nothing)
|
||||||
|
,A.Only m' $ A.Case m' (A.ExprVariable m $ A.Variable m n) s']
|
||||||
|
A.InputCaseExtended -> do
|
||||||
|
sA <- doStructuredV (Just A.InputCaseExtended) v s
|
||||||
|
sB <- doStructuredV (Just A.InputCaseNormal) v s
|
||||||
|
return $ A.Seq m $ A.Spec m' spec $ A.Several m' $ map (A.Only m')
|
||||||
|
[A.Input m v (A.InputSimple m [A.InVariable m (A.Variable m n)]
|
||||||
|
$ Just (A.Case m' (A.ExprVariable m $ A.Variable m n) sA))
|
||||||
|
,A.Case m' (A.ExprVariable m $ A.Variable m n) sB
|
||||||
|
]
|
||||||
|
|
||||||
doProcess (A.Alt m pri s)
|
doProcess (A.Alt m pri s)
|
||||||
= do s' <- doStructuredA s
|
= do s' <- doStructuredA s
|
||||||
return (A.Alt m pri s')
|
return (A.Alt m pri s')
|
||||||
doProcess p = return p
|
doProcess p = return p
|
||||||
|
|
||||||
-- Convert Structured Variant into the equivalent Structured Option.
|
-- Convert Structured Variant into the equivalent Structured Option.
|
||||||
doStructuredV :: A.Variable -> A.Structured A.Variant -> PassM (A.Structured A.Option)
|
--
|
||||||
doStructuredV chanVar = transformOnly transform
|
-- For extended inputs, if there are no extra inputs after the tag, we must
|
||||||
|
-- perform the extended action during the extended input on the tag. This
|
||||||
|
-- is when (Just A.InputCaseExtended) is passed. If there are extra inputs
|
||||||
|
-- after the tag, we perform SKIP for the extended action, and then do our
|
||||||
|
-- real extended action on the further inputs
|
||||||
|
doStructuredV :: (Maybe A.InputCaseType) -> A.Variable -> A.Structured A.Variant -> PassM (A.Structured A.Option)
|
||||||
|
doStructuredV mty chanVar = transformOnly transform
|
||||||
where
|
where
|
||||||
transform m (A.Variant m' n iis p)
|
transform m (A.Variant m' n iis p mp)
|
||||||
= do (Right items) <- protocolItems m' chanVar
|
= do (Right items) <- protocolItems m' chanVar
|
||||||
let (Just idx) = elemIndex n (fst $ unzip items)
|
let (Just idx) = elemIndex n (fst $ unzip items)
|
||||||
return $ A.Only m $ A.Option m' [makeConstant m' idx] $
|
return $ A.Only m $ A.Option m' [makeConstant m' idx] $
|
||||||
if length iis == 0
|
case (mty, null iis) of
|
||||||
then p
|
-- Normal input, no extra inputs:
|
||||||
else A.Seq m' $ A.Several m'
|
(Nothing, True) -> p
|
||||||
[A.Only m' $ A.Input m' chanVar (A.InputSimple m' iis),
|
-- Extended phase, no extra inputs, so do extended process now:
|
||||||
|
(Just A.InputCaseExtended, True) -> p
|
||||||
|
-- After extended, no extra inputs, do after process:
|
||||||
|
(Just A.InputCaseNormal, True) -> fromMaybe (A.Skip m) mp
|
||||||
|
-- Normal input, extra inputs to do:
|
||||||
|
(Nothing, False) -> A.Seq m' $ A.Several m'
|
||||||
|
[A.Only m' $ A.Input m' chanVar (A.InputSimple m' iis Nothing),
|
||||||
A.Only (findMeta p) p]
|
A.Only (findMeta p) p]
|
||||||
|
-- Extended phase, extra inputs to do:
|
||||||
|
(Just A.InputCaseExtended, False) -> A.Skip m
|
||||||
|
-- After extended, extra inputs to do:
|
||||||
|
(Just A.InputCaseNormal, False) -> A.Seq m' $ A.Several m'
|
||||||
|
$ map (A.Only m') $
|
||||||
|
[A.Input m' chanVar (A.InputSimple m' iis $ Just p)
|
||||||
|
] ++ maybeToList mp
|
||||||
|
|
||||||
-- Transform alt guards.
|
-- Transform alt guards.
|
||||||
doStructuredA :: A.Structured A.Alternative -> PassM (A.Structured A.Alternative)
|
doStructuredA :: A.Structured A.Alternative -> PassM (A.Structured A.Alternative)
|
||||||
|
@ -173,12 +204,21 @@ transformInputCase = pass "Transform ? CASE statements/guards into plain CASE"
|
||||||
where
|
where
|
||||||
-- The processes that are the body of input-case guards are always
|
-- The processes that are the body of input-case guards are always
|
||||||
-- skip, so we can discard them.
|
-- skip, so we can discard them.
|
||||||
doAlternative m (A.Alternative m' e v (A.InputCase m'' s) _)
|
doAlternative m (A.Alternative m' e v (A.InputCase m'' ty s) _)
|
||||||
= do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int) A.Original
|
= do spec@(A.Specification _ n _) <- defineNonce m "input_tag" (A.Declaration m' A.Int) A.Original
|
||||||
s' <- doStructuredV v s
|
case ty of
|
||||||
return $ A.Spec m' spec $ A.Only m $
|
A.InputCaseNormal -> do
|
||||||
A.Alternative m' e v (A.InputSimple m [A.InVariable m (A.Variable m n)]) $
|
s' <- doStructuredV Nothing v s
|
||||||
A.Case m'' (A.ExprVariable m'' $ A.Variable m n) s'
|
return $ A.Spec m' spec $ A.Only m $
|
||||||
|
A.Alternative m' e v (A.InputSimple m [A.InVariable m (A.Variable m n)] Nothing) $
|
||||||
|
A.Case m'' (A.ExprVariable m'' $ A.Variable m n) s'
|
||||||
|
A.InputCaseExtended -> do
|
||||||
|
sA <- doStructuredV (Just A.InputCaseExtended) v s
|
||||||
|
sB <- doStructuredV (Just A.InputCaseNormal) v s
|
||||||
|
return $ A.Spec m' spec $ A.Only m $
|
||||||
|
A.Alternative m' e v (A.InputSimple m [A.InVariable m (A.Variable m n)] $
|
||||||
|
Just $ A.Case m'' (A.ExprVariable m'' $ A.Variable m n) sA)
|
||||||
|
(A.Case m'' (A.ExprVariable m'' $ A.Variable m n) sB)
|
||||||
-- Leave other guards untouched.
|
-- Leave other guards untouched.
|
||||||
doAlternative m a = return $ A.Only m a
|
doAlternative m a = return $ A.Only m a
|
||||||
|
|
||||||
|
@ -189,14 +229,18 @@ transformProtocolInput = pass "Flatten sequential protocol inputs into multiple
|
||||||
(applyBottomUpM2 doProcess doAlternative)
|
(applyBottomUpM2 doProcess doAlternative)
|
||||||
where
|
where
|
||||||
doProcess :: A.Process -> PassM A.Process
|
doProcess :: A.Process -> PassM A.Process
|
||||||
doProcess (A.Input m v (A.InputSimple m' iis@(_:_:_)))
|
doProcess (A.Input m v (A.InputSimple m' iis@(_:_:_) mp))
|
||||||
= return $ A.Seq m $ A.Several m $
|
= return $ A.Seq m $ A.Several m $ map (A.Only m . A.Input m v) $ flatten m' iis mp
|
||||||
map (A.Only m . A.Input m v . A.InputSimple m' . singleton) iis
|
|
||||||
doProcess p = return p
|
doProcess p = return p
|
||||||
|
|
||||||
|
-- We put the extended input on the final input:
|
||||||
|
flatten :: Meta -> [A.InputItem] -> Maybe A.Process -> [A.InputMode]
|
||||||
|
flatten m [ii] mp = [A.InputSimple m [ii] mp]
|
||||||
|
flatten m (ii:iis) mp = A.InputSimple m [ii] Nothing : flatten m iis mp
|
||||||
|
|
||||||
doAlternative :: A.Alternative -> PassM A.Alternative
|
doAlternative :: A.Alternative -> PassM A.Alternative
|
||||||
doAlternative (A.Alternative m cond v (A.InputSimple m' (firstII:(otherIIS@(_:_)))) body)
|
doAlternative (A.Alternative m cond v (A.InputSimple m' (firstII:(otherIIS@(_:_))) mp) body)
|
||||||
= return $ A.Alternative m cond v (A.InputSimple m' [firstII]) $ A.Seq m' $ A.Several m' $
|
= return $ A.Alternative m cond v (A.InputSimple m' [firstII] Nothing) $ A.Seq m' $ A.Several m' $
|
||||||
map (A.Only m' . A.Input m' v . A.InputSimple m' . singleton) otherIIS
|
(map (A.Only m' . A.Input m' v) $ flatten m' otherIIS mp)
|
||||||
++ [A.Only m' body]
|
++ [A.Only m' body]
|
||||||
doAlternative s = return s
|
doAlternative s = return s
|
||||||
|
|
Loading…
Reference in New Issue
Block a user