Lots more stuff implemented -- tagged and count protocols, CASE, rep PAR

This commit is contained in:
Adam Sampson 2007-04-13 01:35:09 +00:00
parent 5ac31f2e0f
commit 3f45d38f15
10 changed files with 423 additions and 115 deletions

View File

@ -16,7 +16,13 @@ data Name = Name {
nameType :: NameType, nameType :: NameType,
nameName :: String nameName :: String
} }
deriving (Show, Eq, Typeable, Data) deriving (Typeable, Data)
instance Show Name where
show n = show $ nameName n
instance Eq Name where
(==) a b = nameName a == nameName b
data NameDef = NameDef { data NameDef = NameDef {
ndMeta :: Meta, ndMeta :: Meta,
@ -56,7 +62,7 @@ data ConversionMode =
data Subscript = data Subscript =
Subscript Meta Expression Subscript Meta Expression
| SubscriptTag Meta Name | SubscriptField Meta Name
| SubscriptFromFor Meta Expression Expression | SubscriptFromFor Meta Expression Expression
| SubscriptFrom Meta Expression | SubscriptFrom Meta Expression
| SubscriptFor Meta Expression | SubscriptFor Meta Expression
@ -184,7 +190,7 @@ data SpecType =
-- FIXME Can these be multidimensional? -- FIXME Can these be multidimensional?
| IsChannelArray Meta Type [Variable] | IsChannelArray Meta Type [Variable]
| DataType Meta Type | DataType Meta Type
| DataTypeRecord Meta Bool [(Type, Name)] | DataTypeRecord Meta Bool [(Name, Type)]
| Protocol Meta [Type] | Protocol Meta [Type]
| ProtocolCase Meta [(Name, [Type])] | ProtocolCase Meta [(Name, [Type])]
| Proc Meta [Formal] Process | Proc Meta [Formal] Process

View File

@ -79,14 +79,14 @@ 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"
overArray :: A.Name -> A.Type -> (CGen () -> Maybe (CGen ())) -> CGen () overArray :: CGen () -> A.Type -> (CGen () -> Maybe (CGen ())) -> CGen ()
overArray n (A.Array ds _) func overArray name (A.Array ds _) func
= do indices <- mapM (\_ -> makeNonce "i") ds = do indices <- mapM (\_ -> makeNonce "i") ds
let arg = sequence_ [tell ["[", i, "]"] | i <- indices] let arg = sequence_ [tell ["[", i, "]"] | i <- indices]
case func arg of case func arg of
Just p -> Just p ->
do sequence_ [do tell ["for (int ", i, " = 0; ", i, " < "] do sequence_ [do tell ["for (int ", i, " = 0; ", i, " < "]
genName n name
tell ["_sizes[", show v, "]; ", i, "++) {\n"] tell ["_sizes[", show v, "]; ", i, "++) {\n"]
| (v, i) <- zip [0..] indices] | (v, i) <- zip [0..] indices]
p p
@ -117,11 +117,29 @@ genType (A.Array _ t)
= do genType t = do genType t
tell ["*"] tell ["*"]
genType (A.UserDataType n) = genName n genType (A.UserDataType n) = genName n
-- UserProtocol -- not used
genType (A.Chan t) = tell ["Channel *"] genType (A.Chan t) = tell ["Channel *"]
-- Counted -- not used
-- Any -- not used
--genType A.Timer =
--genType (A.Port t) =
genType t genType t
= case scalarType t of = case scalarType t of
Just s -> tell [s] Just s -> tell [s]
Nothing -> missing $ "genType " ++ show t Nothing -> missing $ "genType " ++ show t
genBytesInType :: A.Type -> CGen ()
genBytesInType (A.Array ds t) = genBytesInDims ds >> genBytesInType t
where
genBytesInDims [] = return ()
genBytesInDims ((A.Dimension e):ds)
= genBytesInDims ds >> genExpression e >> tell [" * "]
genBytesInDims _ = missing "genBytesInType with empty dimension"
--bytesInType (A.UserDataType n)
genBytesInType t
= case scalarType t of
Just s -> tell ["sizeof (", s, ")"]
Nothing -> missing $ "genBytesInType " ++ show t
--}}} --}}}
--{{{ declarations --{{{ declarations
@ -159,7 +177,7 @@ genSubscript (A.Subscript m e) p
tell ["["] tell ["["]
genExpression e genExpression e
tell ["]"] tell ["]"]
genSubscript (A.SubscriptTag m n) p genSubscript (A.SubscriptField m n) p
= do p = do p
tell ["."] tell ["."]
genName n genName n
@ -254,7 +272,6 @@ genExpression (A.Dyadic m op e f) = genDyadic op e f
genExpression (A.MostPos m t) = genTypeConstant "mostpos" t genExpression (A.MostPos m t) = genTypeConstant "mostpos" t
genExpression (A.MostNeg m t) = genTypeConstant "mostneg" t genExpression (A.MostNeg m t) = genTypeConstant "mostneg" t
--genExpression (A.SizeType m t) --genExpression (A.SizeType m t)
-- FIXME This needs to cope with subscripts
genExpression (A.SizeExpr m e) genExpression (A.SizeExpr m e)
= do genExpression e = do genExpression e
tell ["_sizes[0]"] tell ["_sizes[0]"]
@ -266,11 +283,7 @@ genExpression (A.False m) = tell ["false"]
--genExpression (A.FunctionCall m n es) --genExpression (A.FunctionCall m n es)
--genExpression (A.SubscriptedExpr m s e) --genExpression (A.SubscriptedExpr m s e)
--genExpression (A.BytesInExpr m e) --genExpression (A.BytesInExpr m e)
-- FIXME This needs to do special stuff with arrays. genExpression (A.BytesInType m t) = genBytesInType t
genExpression (A.BytesInType m t)
= do tell ["sizeof ("]
genType t
tell [")"]
--genExpression (A.OffsetOf m t n) --genExpression (A.OffsetOf m t n)
genExpression t = missing $ "genExpression " ++ show t genExpression t = missing $ "genExpression " ++ show t
@ -336,44 +349,80 @@ genDyadic A.After e f = genFuncDyadic "occam_after" e f
genInputItem :: A.Variable -> A.InputItem -> CGen () genInputItem :: A.Variable -> A.InputItem -> CGen ()
genInputItem c (A.InCounted m cv av) genInputItem c (A.InCounted m cv av)
= do genInputItem c (A.InVariable m cv) = do genInputItem c (A.InVariable m cv)
-- need to then input as much as appropriate ps <- get
missing "genInputItem counted" t <- checkJust $ typeOfVariable ps av
tell ["ChanIn ("]
genVariable c
tell [", "]
let (rhs, rhsS) = abbrevVariable A.Abbrev t av
rhs
tell [", "]
let subT = fromJust $ subscriptType ps (A.Subscript m $ makeConstant m 0) t
genVariable cv
tell [" * "]
genBytesInType subT
tell [");\n"]
genInputItem c (A.InVariable m v) genInputItem c (A.InVariable m v)
= do ps <- get = do ps <- get
t <- checkJust $ typeOfVariable ps v t <- checkJust $ typeOfVariable ps v
let (rhs, rhsS) = abbrevVariable A.Abbrev t v
case t of case t of
A.Int -> A.Int ->
do tell ["ChanInInt ("] do tell ["ChanInInt ("]
genVariable c genVariable c
tell [", &"] tell [", "]
genVariable v rhs
tell [");\n"] tell [");\n"]
_ -> _ ->
do tell ["ChanIn ("] do tell ["ChanIn ("]
genVariable c genVariable c
tell [", &"] tell [", "]
genVariable v rhs
tell [", sizeof ("] tell [", "]
genType t genBytesInType t
tell ["));\n"] tell [");\n"]
genOutputItem :: A.Variable -> A.OutputItem -> CGen () genOutputItem :: A.Variable -> A.OutputItem -> CGen ()
genOutputItem c (A.OutCounted m ce ae) genOutputItem c (A.OutCounted m ce ae)
= do genOutputItem c (A.OutExpression m ce) = do genOutputItem c (A.OutExpression m ce)
missing "genOutputItem counted"
genOutputItem c (A.OutExpression m e)
= do n <- makeNonce "output_item"
ps <- get ps <- get
t <- checkJust $ typeOfExpression ps ae
case ae of
A.ExprVariable m v ->
do tell ["ChanOut ("]
genVariable c
tell [", "]
let (rhs, rhsS) = abbrevVariable A.Abbrev t v
rhs
tell [", "]
let subT = fromJust $ subscriptType ps (A.Subscript m $ makeConstant m 0) t
genExpression ce
tell [" * "]
genBytesInType subT
tell [");\n"]
genOutputItem c (A.OutExpression m e)
= do ps <- get
t <- checkJust $ typeOfExpression ps e t <- checkJust $ typeOfExpression ps e
case t of case (t, e) of
A.Int -> (A.Int, _) ->
do tell ["ChanOutInt ("] do tell ["ChanOutInt ("]
genVariable c genVariable c
tell [", "] tell [", "]
genExpression e genExpression e
tell [");\n"] tell [");\n"]
(_, A.ExprVariable _ v) ->
do tell ["ChanOut ("]
genVariable c
tell [", "]
let (rhs, rhsS) = abbrevVariable A.Abbrev t v
rhs
tell [", "]
genBytesInType t
tell [");\n"]
-- FIXME It would be cleaner to do this with a pullup,
-- which would reduce it to the previous case.
_ -> _ ->
do tell ["{\n"] do n <- makeNonce "output_item"
tell ["const "] tell ["const "]
genType t genType t
tell [" ", n, " = "] tell [" ", n, " = "]
@ -381,10 +430,9 @@ genOutputItem c (A.OutExpression m e)
tell [";\n"] tell [";\n"]
tell ["ChanOut ("] tell ["ChanOut ("]
genVariable c genVariable c
tell [", &", n, ", sizeof ("] tell [", &", n, ", "]
genType t genBytesInType t
tell ["));\n"] tell [");\n"]
tell ["}\n"]
--}}} --}}}
--{{{ replicators --{{{ replicators
@ -410,6 +458,9 @@ genReplicatorLoop (A.For m n base count)
tell ["; ", counter, " > 0; ", counter, "--, "] tell ["; ", counter, " > 0; ", counter, "--, "]
genName n genName n
tell ["++"] tell ["++"]
genReplicatorSize :: A.Replicator -> CGen ()
genReplicatorSize (A.For m n base count) = genExpression count
--}}} --}}}
--{{{ choice/alternatives/options/variants --{{{ choice/alternatives/options/variants
@ -463,6 +514,43 @@ declareType :: A.Type -> CGen ()
declareType (A.Chan _) = tell ["Channel *"] declareType (A.Chan _) = tell ["Channel *"]
declareType t = genType t declareType t = genType t
genDimensions :: [A.Dimension] -> CGen ()
genDimensions ds
= sequence_ $ [case d of
A.Dimension e ->
do tell ["["]
genExpression e
tell ["]"]
A.UnknownDimension ->
missing "unknown dimension in declaration"
| d <- ds]
genDeclaration :: A.Type -> A.Name -> CGen ()
genDeclaration A.Timer n = return ()
genDeclaration (A.Chan _) n
= do tell ["Channel "]
genName n
tell [";\n"]
genDeclaration (A.Array ds t) n
= do declareType t
tell [" "]
genName n
genDimensions ds
tell [";\n"]
genDeclaration t n
= do declareType t
tell [" "]
genName n
tell [";\n"]
declareArraySizes :: [A.Dimension] -> CGen () -> CGen ()
declareArraySizes ds name
= do tell ["const int "]
name
tell ["_sizes[] = { "]
sequence_ $ intersperse genComma [genExpression e | (A.Dimension e) <- ds]
tell [" };\n"]
-- | Initialise an item being declared. -- | Initialise an item being declared.
declareInit :: A.Type -> CGen () -> CGen () -> Maybe (CGen ()) declareInit :: A.Type -> CGen () -> CGen () -> Maybe (CGen ())
declareInit (A.Chan _) name index declareInit (A.Chan _) name index
@ -470,6 +558,21 @@ declareInit (A.Chan _) name index
name name
index index
tell [");\n"] tell [");\n"]
declareInit t@(A.Array ds t') name _ -- index ignored because arrays can't nest
= Just $ do init <- case t' of
A.Chan _ ->
do store <- makeNonce "storage"
tell ["Channel ", store]
genDimensions ds
tell [";\n"]
return (\index -> Just $ do fromJust $ declareInit t' (tell [store]) index
name
index
tell [" = &", store]
index
tell [";\n"])
_ -> return $ declareInit t' name
overArray name t init
declareInit _ _ _ = Nothing declareInit _ _ _ = Nothing
-- | Free a declared item that's going out of scope. -- | Free a declared item that's going out of scope.
@ -493,53 +596,10 @@ CHAN OF INT c IS d: Channel *c = d;
-} -}
introduceSpec :: A.Specification -> CGen () introduceSpec :: A.Specification -> CGen ()
introduceSpec (n, A.Declaration m t) introduceSpec (n, A.Declaration m t)
= case t of = do genDeclaration t n
A.Timer -> return () case t of
A.Chan _ -> A.Array ds _ -> declareArraySizes ds (genName n)
do tell ["Channel "] _ -> return ()
genName n
tell [";\n"]
tell ["ChanInit (&"]
genName n
tell [");\n"]
A.Array ds t' ->
do declareType t'
tell [" "]
genName n
let dim = sequence_ $ [case d of
A.Dimension e ->
do tell ["["]
genExpression e
tell ["]"]
A.UnknownDimension ->
missing "unknown dimension in declaration"
| d <- ds]
dim
tell [";\n"]
init <- case t' of
A.Chan _ ->
do store <- makeNonce "storage"
tell ["Channel ", store]
dim
tell [";\n"]
return (\index -> Just $ do fromJust $ declareInit t' (tell [store]) index
genName n
index
tell [" = &", store]
index
tell [";\n"])
_ -> return $ declareInit t' (genName n)
tell ["const int "]
genName n
tell ["_sizes[] = { "]
sequence_ $ intersperse genComma [genExpression e | (A.Dimension e) <- ds]
tell [" };\n"]
overArray n t init
_ ->
do declareType t
tell [" "]
genName n
tell [";\n"]
case declareInit t (genName n) (return ()) of case declareInit t (genName n) (return ()) of
Just p -> p Just p -> p
Nothing -> return () Nothing -> return ()
@ -576,6 +636,28 @@ introduceSpec (n, A.IsChannelArray m t cs)
tell [" = {"] tell [" = {"]
sequence_ $ intersperse genComma (map genVariable cs) sequence_ $ intersperse genComma (map genVariable cs)
tell ["};\n"] tell ["};\n"]
--introduceSpec (n, A.DataType m t)
introduceSpec (n, A.DataTypeRecord _ b fs)
= do when b $ missing "packed record"
tell ["typedef struct {\n"]
sequence_ [case t of
_ ->
do declareType t
tell [" "]
genName n
tell [";"]
| (n, t) <- fs]
tell ["} "]
genName n
tell [";\n"]
introduceSpec (n, A.Protocol _ _) = return ()
introduceSpec (n, A.ProtocolCase _ ts)
= do tell ["typedef enum {\n"]
sequence_ $ intersperse genComma [genName tag | (tag, _) <- ts]
tell ["\n"]
tell ["} "]
genName n
tell [";\n"]
introduceSpec (n, A.Proc m fs p) introduceSpec (n, A.Proc m fs p)
= do tell ["void "] = do tell ["void "]
genName n genName n
@ -584,13 +666,15 @@ introduceSpec (n, A.Proc m fs p)
tell [") {\n"] tell [") {\n"]
genProcess p genProcess p
tell ["}\n"] tell ["}\n"]
-- CASE protocol should generate an enum for the tags introduceSpec (n, A.Function _ _ _ _) = missing "introduceSpec function"
--introduceSpec (n, A.Retypes m am t v)
--introduceSpec (n, A.RetypesExpr m am t e)
introduceSpec (n, t) = missing $ "introduceSpec " ++ show t introduceSpec (n, t) = missing $ "introduceSpec " ++ show t
removeSpec :: A.Specification -> CGen () removeSpec :: A.Specification -> CGen ()
removeSpec (n, A.Declaration m t) removeSpec (n, A.Declaration m t)
= case t of = case t of
A.Array _ t' -> overArray n t (declareFree t' (genName n)) A.Array _ t' -> overArray (genName n) t (declareFree t' (genName n))
_ -> _ ->
do case declareFree t (genName n) (return ()) of do case declareFree t (genName n) (return ()) of
Just p -> p Just p -> p
@ -654,17 +738,17 @@ genProcess p = case p of
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
--A.OutputCase m c t ois A.OutputCase m c t ois -> genOutputCase c t ois
A.Skip m -> tell ["/* skip */\n"] A.Skip m -> tell ["/* skip */\n"]
A.Stop m -> genStop A.Stop m -> genStop
A.Main m -> tell ["/* main */\n"] A.Main m -> tell ["/* main */\n"]
A.Seq m ps -> sequence_ $ map genProcess ps A.Seq m ps -> sequence_ $ map genProcess ps
A.SeqRep m r p -> genReplicator r (genProcess p) A.SeqRep m r p -> genReplicator r (genProcess p)
A.If m s -> genIf s A.If m s -> genIf s
--A.Case m e s A.Case m e s -> genCase 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 ps -> genPar pm ps
--A.ParRep m pm r p A.ParRep m pm r p -> genParRep pm r p
--A.Processor m e p --A.Processor m e p
--A.Alt m b s --A.Alt m b s
A.ProcCall m n as -> genProcCall n as A.ProcCall m n as -> genProcCall n as
@ -705,8 +789,43 @@ genInput c im
A.InputAfter m e -> genTimerWait e A.InputAfter m e -> genTimerWait e
_ -> case im of _ -> case im of
A.InputSimple m is -> sequence_ $ map (genInputItem c) is A.InputSimple m is -> sequence_ $ map (genInputItem c) is
A.InputCase m s -> genInputCase c s
_ -> missing $ "genInput " ++ show im _ -> missing $ "genInput " ++ show im
genInputCase :: A.Variable -> A.Structured -> CGen ()
genInputCase c s
= do ps <- get
t <- checkJust $ typeOfVariable ps c
let proto = case t of A.Chan (A.UserProtocol n) -> n
tag <- makeNonce "case_tag"
genName proto
tell [" ", tag, ";\n"]
tell ["ChanInInt ("]
genVariable c
tell [", &", tag, ");\n"]
tell ["switch (", tag, ") {\n"]
genInputCaseBody c (return ()) s
tell ["default:\n"]
genStop
tell ["}\n"]
-- This handles specs in a slightly odd way, because we can't insert specs into
-- the body of a switch.
genInputCaseBody :: A.Variable -> CGen () -> A.Structured -> CGen ()
genInputCaseBody c coll (A.Spec _ spec s)
= genInputCaseBody c (genSpec spec coll) s
genInputCaseBody c coll (A.OnlyV _ (A.Variant _ n iis p))
= do tell ["case "]
genName n
tell [": {\n"]
coll
sequence_ $ map (genInputItem c) iis
genProcess p
tell ["break;\n"]
tell ["}\n"]
genInputCaseBody c coll (A.Several _ ss)
= sequence_ $ map (genInputCaseBody c coll) ss
genTimerRead :: A.Variable -> CGen () genTimerRead :: A.Variable -> CGen ()
genTimerRead v genTimerRead v
= do n <- makeNonce "time" = do n <- makeNonce "time"
@ -726,11 +845,21 @@ genTimerWait e
genOutput :: A.Variable -> [A.OutputItem] -> CGen () genOutput :: A.Variable -> [A.OutputItem] -> CGen ()
genOutput c ois = sequence_ $ map (genOutputItem c) ois genOutput c ois = sequence_ $ map (genOutputItem c) ois
genOutputCase :: A.Variable -> A.Name -> [A.OutputItem] -> CGen ()
genOutputCase c t ois
= do tell ["ChanOutInt ("]
genVariable c
tell [", "]
genName t
tell [");\n"]
genOutput c ois
genStop :: CGen () genStop :: CGen ()
genStop = tell ["SetErr ();\n"] genStop = tell ["SetErr ();\n"]
-- FIXME: This could be special-cased to generate if ... else if ... for bits -- FIXME: This could be special-cased to generate if ... else if ... for bits
-- that aren't replicated and don't have specs. -- that aren't replicated and don't have specs.
-- FIXME: As with CASE, this could use a flag to detect whether to generate the STOP.
genIf :: A.Structured -> CGen () genIf :: A.Structured -> CGen ()
genIf s genIf s
= do label <- makeNonce "if_end" = do label <- makeNonce "if_end"
@ -738,7 +867,6 @@ genIf s
genStop genStop
tell [label, ":\n;\n"] tell [label, ":\n;\n"]
-- FIXME: This should be generic for any Structured type.
genIfBody :: String -> A.Structured -> CGen () genIfBody :: String -> A.Structured -> CGen ()
genIfBody label (A.Rep m rep s) = genReplicator rep (genIfBody label s) genIfBody label (A.Rep m rep s) = genReplicator rep (genIfBody label s)
genIfBody label (A.Spec m spec s) = genSpec spec (genIfBody label s) genIfBody label (A.Spec m spec s) = genSpec spec (genIfBody label s)
@ -751,6 +879,38 @@ genIfBody label (A.OnlyC m (A.Choice m' e p))
tell ["}\n"] tell ["}\n"]
genIfBody label (A.Several m ss) = sequence_ $ map (genIfBody label) ss genIfBody label (A.Several m ss) = sequence_ $ map (genIfBody label) ss
genCase :: A.Expression -> A.Structured -> CGen ()
genCase e s
= do tell ["switch ("]
genExpression e
tell [") {\n"]
seenDefault <- genCaseBody (return ()) s
when (not seenDefault) $ tell ["default:\n"] >> genStop
tell ["}\n"]
-- FIXME -- can this be made common with genInputCaseBody above?
genCaseBody :: CGen () -> A.Structured -> CGen Bool
genCaseBody coll (A.Spec _ spec s)
= genCaseBody (genSpec spec coll) s
genCaseBody coll (A.OnlyO _ (A.Option _ es p))
= do sequence_ [tell ["case "] >> genExpression e >> tell [":\n"] | e <- es]
tell ["{\n"]
coll
genProcess p
tell ["break;\n"]
tell ["}\n"]
return False
genCaseBody coll (A.OnlyO _ (A.Else _ p))
= do tell ["default:\n"]
tell ["{\n"]
coll
genProcess p
tell ["}\n"]
return True
genCaseBody coll (A.Several _ ss)
= do seens <- mapM (genCaseBody coll) ss
return $ or seens
genWhile :: A.Expression -> A.Process -> CGen () genWhile :: A.Expression -> A.Process -> CGen ()
genWhile e p genWhile e p
= do tell ["while ("] = do tell ["while ("]
@ -762,7 +922,10 @@ genWhile e p
genPar :: A.ParMode -> [A.Process] -> CGen () genPar :: A.ParMode -> [A.Process] -> CGen ()
genPar pm ps genPar pm ps
= do pids <- mapM (\_ -> makeNonce "pid") ps = do pids <- mapM (\_ -> makeNonce "pid") ps
sequence_ $ map genProcAlloc (zip pids ps) sequence_ $ [do tell ["Process *", pid, " = "]
genProcAlloc p
tell [";\n"]
| (pid, p) <- (zip pids ps)]
case pm of case pm of
A.PlainPar -> A.PlainPar ->
do tell ["ProcPar ("] do tell ["ProcPar ("]
@ -771,9 +934,29 @@ 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]
genProcAlloc :: (String, A.Process) -> CGen () -- FIXME -- This'll require a C99 dynamic array for a dynamic PAR count,
genProcAlloc (pid, A.ProcCall m n as) -- which may turn out to be a bad idea for very large counts (since I assume
= do tell ["Process *", pid, " = ProcAlloc ("] -- it'll allocate off the stack). We should probably do a malloc if it's
-- not determinable at compile time.
genParRep :: A.ParMode -> A.Replicator -> A.Process -> CGen ()
genParRep pm rep p
= do pids <- makeNonce "pids"
index <- makeNonce "i"
tell ["Process *", pids, "["]
genReplicatorSize rep
tell [" + 1];\n"]
tell ["int ", index, " = 0;\n"]
genReplicator rep $ do tell [pids, "[", index, "++] = "]
genProcAlloc p
tell [";\n"]
tell [pids, "[", index, "] = NULL;\n"]
tell ["ProcParList (", pids, ");\n"]
tell [index, " = 0;\n"]
genReplicator rep $ tell ["ProcAllocClean (", pids, "[", index, "++]);\n"]
genProcAlloc :: A.Process -> CGen ()
genProcAlloc (A.ProcCall m n as)
= do tell ["ProcAlloc ("]
genName n genName n
ps <- get ps <- get
let fs = case fromJust $ specTypeOfName ps n of A.Proc _ fs _ -> fs let fs = case fromJust $ specTypeOfName ps n of A.Proc _ fs _ -> fs
@ -781,7 +964,7 @@ genProcAlloc (pid, A.ProcCall m n as)
let stackSize = 4096 let stackSize = 4096
tell [", ", show stackSize, ", ", show $ numCArgs fs] tell [", ", show stackSize, ", ", show $ numCArgs fs]
genActuals (zip as fs) genActuals (zip as fs)
tell [");\n"] tell [")"]
genProcCall :: A.Name -> [A.Actual] -> CGen () genProcCall :: A.Name -> [A.Actual] -> CGen ()
genProcCall n as genProcCall n as

View File

@ -23,7 +23,8 @@ $(targets): $(sources)
CFLAGS = -g -std=gnu99 -Wall `kroc --cflags` `kroc --ccincpath` CFLAGS = -g -std=gnu99 -Wall `kroc --cflags` `kroc --ccincpath`
%.fco.c: %.occ fco %.fco.c: %.occ fco
./fco $< | indent -kr -pcs >$@ ./fco $< >$@ || ( rm -f $@; exit 1 )
indent -kr -pcs $@
%.fco: %.fco.o kroc-wrapper-c.o kroc-wrapper.occ %.fco: %.fco.o kroc-wrapper-c.o kroc-wrapper.occ
kroc -o $@ kroc-wrapper.occ $< kroc-wrapper-c.o -lcif kroc -o $@ kroc-wrapper.occ $< kroc-wrapper-c.o -lcif

View File

@ -244,10 +244,18 @@ maybeSubscripted :: String -> OccParser a -> (Meta -> A.Subscript -> a -> a) ->
maybeSubscripted prodName inner subscripter maybeSubscripted prodName inner subscripter
= do m <- md = do m <- md
v <- inner v <- inner
es <- many (do { m' <- md; sLeft; e <- expression; sRight; return (m', e) }) subs <- many postSubscript
return $ foldl (\e (m', s) -> subscripter m' (A.Subscript m' s) e) v es return $ foldl (\var sub -> subscripter m sub var) v subs
<?> prodName <?> prodName
postSubscript :: OccParser A.Subscript
postSubscript
= do m <- md
sLeft
--(do { f <- tryTrail fieldName sRight; return $ A.SubscriptField m f }
-- <|>
do { e <- expression; sRight; return $ A.Subscript m e } --)
maybeSliced :: OccParser a -> (Meta -> A.Subscript -> a -> a) -> OccParser a maybeSliced :: OccParser a -> (Meta -> A.Subscript -> a -> a) -> OccParser a
maybeSliced inner subscripter maybeSliced inner subscripter
= do m <- md = do m <- md
@ -326,10 +334,6 @@ pTypeOf f item
pTypeOfVariable = pTypeOf typeOfVariable pTypeOfVariable = pTypeOf typeOfVariable
pTypeOfExpression = pTypeOf typeOfExpression pTypeOfExpression = pTypeOf typeOfExpression
pSpecTypeOfName = pTypeOf specTypeOfName pSpecTypeOfName = pTypeOf specTypeOfName
-- | Generate a constant expression from an integer -- for array sizes and the like.
makeConstant :: Meta -> Int -> A.Expression
makeConstant m n = A.ExprLiteral m $ A.Literal m A.Int $ A.IntLiteral m (show n)
--}}} --}}}
--{{{ name scoping --{{{ name scoping
@ -887,9 +891,9 @@ recordKeyword
<|> do { sRECORD; return False } <|> do { sRECORD; return False }
<?> "recordKeyword" <?> "recordKeyword"
structuredTypeField :: OccParser [(A.Type, A.Name)] structuredTypeField :: OccParser [(A.Name, A.Type)]
structuredTypeField structuredTypeField
= do { t <- dataType; fs <- many1 newFieldName; sColon; eol; return [(t, f) | f <- fs] } = do { t <- dataType; fs <- many1 newFieldName; sColon; eol; return [(f, t) | f <- fs] }
<?> "structuredTypeField" <?> "structuredTypeField"
--}}} --}}}
--}}} --}}}

View File

@ -10,13 +10,11 @@ import Control.Monad
import qualified AST as A import qualified AST as A
import ParseState import ParseState
import Metadata
perhaps :: Maybe a -> (a -> b) -> Maybe b perhaps :: Maybe a -> (a -> b) -> Maybe b
perhaps m f = m >>= (Just . f) perhaps m f = m >>= (Just . f)
sameName :: A.Name -> A.Name -> Bool
sameName a b = A.nameName a == A.nameName b
specTypeOfName :: ParseState -> A.Name -> Maybe A.SpecType specTypeOfName :: ParseState -> A.Name -> Maybe A.SpecType
specTypeOfName ps n specTypeOfName ps n
= (psLookupName ps n) `perhaps` A.ndType = (psLookupName ps n) `perhaps` A.ndType
@ -36,16 +34,27 @@ typeOfName ps n
Just (A.RetypesExpr m am t e) -> Just t Just (A.RetypesExpr m am t e) -> Just t
_ -> Nothing _ -> Nothing
-- FIXME: This should fail if the subscript is invalid... typeOfRecordField :: ParseState -> A.Type -> A.Name -> Maybe A.Type
subscriptType :: A.Type -> Maybe A.Type typeOfRecordField ps (A.UserDataType rec) field
subscriptType (A.Array [_] t) = Just t = do st <- specTypeOfName ps rec
subscriptType (A.Array (_:ds) t) = Just $ A.Array ds t case st of
subscriptType _ = Nothing A.DataTypeRecord _ _ fs -> lookup field fs
_ -> Nothing
typeOfRecordField _ _ _ = Nothing
subscriptType :: ParseState -> A.Subscript -> A.Type -> Maybe A.Type
subscriptType _ (A.SubscriptFromFor _ _ _) t = Just t
subscriptType _ (A.SubscriptFrom _ _) t = Just t
subscriptType _ (A.SubscriptFor _ _) t = Just t
subscriptType ps (A.SubscriptField _ tag) t = typeOfRecordField ps t tag
subscriptType _ (A.Subscript _ _) (A.Array [_] t) = Just t
subscriptType _ (A.Subscript _ _) (A.Array (_:ds) t) = Just $ A.Array ds t
subscriptType _ _ _ = Nothing
typeOfVariable :: ParseState -> A.Variable -> Maybe A.Type typeOfVariable :: ParseState -> A.Variable -> Maybe A.Type
typeOfVariable ps (A.Variable m n) = typeOfName ps n typeOfVariable ps (A.Variable m n) = typeOfName ps n
typeOfVariable ps (A.SubscriptedVariable m s v) typeOfVariable ps (A.SubscriptedVariable m s v)
= typeOfVariable ps v >>= subscriptType = typeOfVariable ps v >>= subscriptType ps s
abbrevModeOfVariable :: ParseState -> A.Variable -> Maybe A.AbbrevMode abbrevModeOfVariable :: ParseState -> A.Variable -> Maybe A.AbbrevMode
abbrevModeOfVariable ps (A.Variable _ n) = abbrevModeOfName ps n abbrevModeOfVariable ps (A.Variable _ n) = abbrevModeOfName ps n
@ -81,7 +90,7 @@ typeOfExpression ps e
Just [t] -> Just t Just [t] -> Just t
_ -> Nothing _ -> Nothing
A.SubscriptedExpr m s e -> A.SubscriptedExpr m s e ->
typeOfExpression ps e >>= subscriptType typeOfExpression ps e >>= subscriptType ps s
A.BytesInExpr m e -> Just A.Int A.BytesInExpr m e -> Just A.Int
A.BytesInType m t -> Just A.Int A.BytesInType m t -> Just A.Int
A.OffsetOf m t n -> Just A.Int A.OffsetOf m t n -> Just A.Int
@ -89,7 +98,7 @@ typeOfExpression ps e
typeOfLiteral :: ParseState -> A.Literal -> Maybe A.Type typeOfLiteral :: ParseState -> A.Literal -> Maybe A.Type
typeOfLiteral ps (A.Literal m t lr) = Just t typeOfLiteral ps (A.Literal m t lr) = Just t
typeOfLiteral ps (A.SubscriptedLiteral m s l) typeOfLiteral ps (A.SubscriptedLiteral m s l)
= typeOfLiteral ps l >>= subscriptType = typeOfLiteral ps l >>= subscriptType ps s
returnTypesOfFunction :: ParseState -> A.Name -> Maybe [A.Type] returnTypesOfFunction :: ParseState -> A.Name -> Maybe [A.Type]
returnTypesOfFunction ps n returnTypesOfFunction ps n
@ -129,3 +138,6 @@ stripArrayType :: A.Type -> A.Type
stripArrayType (A.Array _ t) = stripArrayType t stripArrayType (A.Array _ t) = stripArrayType t
stripArrayType t = t stripArrayType t = t
-- | Generate a constant expression from an integer -- for array sizes and the like.
makeConstant :: Meta -> Int -> A.Expression
makeConstant m n = A.ExprLiteral m $ A.Literal m A.Int $ A.IntLiteral m (show n)

View File

@ -124,7 +124,7 @@ removeFreeNames = doGeneric `extM` doProcess `extM` doStructured `extM` doValueP
where where
atcProc :: A.Process -> A.Process atcProc :: A.Process -> A.Process
atcProc p@(A.ProcCall m n as) atcProc p@(A.ProcCall m n as)
= if sameName n matchN then A.ProcCall m n (as ++ newAs) else p = if n == matchN then A.ProcCall m n (as ++ newAs) else p
atcProc p = p atcProc p = p
doSpec :: Data t => Meta -> A.Specification -> t -> PassM (A.Specification, t) doSpec :: Data t => Meta -> A.Specification -> t -> PassM (A.Specification, t)

View File

@ -12,7 +12,7 @@ PROC out.int (VAL INT n, w, CHAN OF BYTE out)
STOP STOP
: :
INT, INT FUNCTION random (VAL INT range, seed) IS 0, 0: INT, INT FUNCTION random (VAL INT range, seed) IS 0, 0:
PROC copy.string ([]BYTE dest, VAL []BYTE src) PROC copy.string (VAL []BYTE src, []BYTE dest)
STOP STOP
: :
PROC make.string ([]BYTE dest, VAL INT len) PROC make.string ([]BYTE dest, VAL INT len)

18
fco2/testcases/case.occ Normal file
View File

@ -0,0 +1,18 @@
PROC P ()
INT n:
SEQ
CASE n -- with ELSE
1, 2
SKIP
3
SKIP
4, 5, 6, 7, 8
SKIP
ELSE
SKIP
CASE n -- without ELSE
1
SKIP
2
SKIP
:

View File

@ -0,0 +1,45 @@
PROTOCOL SIMPLE IS INT; BOOL; BYTE:
PROTOCOL COMPLEX
CASE
three.args; INT; BOOL; BYTE
one.arg; INT
no.args
:
PROTOCOL ARRAY IS [10]BYTE:
PROTOCOL COUNTED IS INT::[]BYTE:
PROC P ()
CHAN OF SIMPLE simple:
CHAN OF COMPLEX complex:
CHAN OF ARRAY array:
CHAN OF COUNTED counted:
INT i:
BOOL b:
BYTE y:
[10]BYTE is:
PAR
SEQ
simple ! 42; TRUE; 42
complex ! three.args; 42; TRUE; 42
complex ! one.arg; 42
complex ! no.args
complex ! one.arg; 24
array ! "abcdefghij"
counted ! 5::"abcde"
SEQ
simple ? i; b; y
complex ? CASE three.args; i; b; y
complex ? CASE one.arg; i
complex ? CASE no.args
complex ? CASE
INT ii:
BOOL bb:
three.args; ii; bb; y
STOP
INT ii:
one.arg; ii
SKIP
no.args
STOP
array ? is
counted ? i::is
:

View File

@ -0,0 +1,39 @@
DATA TYPE PLAIN.REC
RECORD
INT i:
BOOL b:
:
DATA TYPE PACKED.REC
PACKED RECORD
INT i:
BOOL b:
:
PROC Q (INT i, BOOL b)
SKIP
:
PROC R (VAL INT i, VAL BOOL b)
SKIP
:
PROC S (PLAIN.REC rec)
SEQ
Q (rec[i], rec[b])
R (rec[i], rec[b])
:
PROC T (VAL PLAIN.REC rec)
R (rec[i], rec[b])
:
PROC P ()
PLAIN.REC plain:
PACKED.REC packed:
SEQ
plain[i] := 42
plain[b] := FALSE
Q (plain[i], plain[b])
R (plain[i], plain[b])
packed[i] := 42
packed[b] := FALSE
Q (packed[i], packed[b])
R (packed[i], packed[b])
S (plain)
T (plain)
: