Implemented recursive procs

This works fine in the C++ backend, not tested with the C backend yet
This commit is contained in:
Neil Brown 2009-01-29 00:43:24 +00:00
parent 10e6b4ce02
commit 8a28d765e7
8 changed files with 16 additions and 11 deletions

View File

@ -1420,7 +1420,7 @@ realFormals (A.Formal am t n)
-- This will use ProcGetParam if the Proc is in csParProcs, or the normal C
-- calling convention otherwise.
genProcSpec :: A.Name -> A.SpecType -> Bool -> CGen ()
genProcSpec n (A.Proc _ sm fs p) forwardDecl
genProcSpec n (A.Proc _ (sm, _) fs p) forwardDecl
= do cs <- getCompState
let (header, params) = if n `Set.member` csParProcs cs
then (genParHeader, genParParams)

View File

@ -537,7 +537,7 @@ cppgenFormal :: (A.Name -> A.Name) -> A.Formal -> CGen ()
cppgenFormal nameFunc (A.Formal am t n) = call genDecl am t (nameFunc n)
cppgenForwardDeclaration :: A.Specification -> CGen()
cppgenForwardDeclaration (A.Specification _ n (A.Proc _ sm fs _))
cppgenForwardDeclaration (A.Specification _ n (A.Proc _ (sm, _) fs _))
= do --Generate the "process" as a C++ function:
call genSpecMode sm
tell ["void "]
@ -592,7 +592,7 @@ cppgenForwardDeclaration _ = return ()
cppintroduceSpec :: A.Specification -> CGen ()
--I generate process wrappers for all functions by default:
cppintroduceSpec (A.Specification _ n (A.Proc _ sm fs p))
cppintroduceSpec (A.Specification _ n (A.Proc _ (sm, _) fs p))
= do --Generate the "process" as a C++ function:
call genSpecMode sm
tell ["void "]

View File

@ -499,7 +499,7 @@ data SpecType =
-- The list pairs tag names with item types.
| ProtocolCase Meta [(Name, [Type])]
-- | Declare a @PROC@.
| Proc Meta SpecMode [Formal] Process
| Proc Meta (SpecMode, RecMode) [Formal] Process
-- | Declare a @FUNCTION@.
| Function Meta (SpecMode, RecMode) [Type] [Formal]
(Either (Structured ExpressionList) Process)

View File

@ -349,7 +349,7 @@ defineNonce m s st am
-- | Generate and define a no-arg wrapper PROC around a process.
makeNonceProc :: CSM m => Meta -> A.Process -> m A.Specification
makeNonceProc m p
= defineNonce m "wrapper_proc" (A.Proc m A.PlainSpec [] p) A.Abbrev
= defineNonce m "wrapper_proc" (A.Proc m (A.PlainSpec, A.PlainRec) [] p) A.Abbrev
-- | Generate and define a counter for a replicator.
makeNonceCounter :: CSM m => String -> Meta -> m A.Name

View File

@ -409,6 +409,7 @@ scopeInSpec (spec@(A.Specification m n st), nt)
return $ A.Specification m n' st
where
isRecursive (A.Function _ (_, A.Recursive) _ _ _) = True
isRecursive (A.Proc _ (_, A.Recursive) _ _) = True
isRecursive _ = False
scopeOutSpec :: A.Specification -> OccParser ()
@ -1087,18 +1088,22 @@ definition
do { sIS; p <- sequentialProtocol; sColon; eol; return (A.Specification m n $ A.Protocol m p, ProtocolName) }
<|> do { eol; indent; sCASE; eol; ps <- maybeIndentedList m "empty CASE protocol" taggedProtocol; outdent; sColon; eol; return (A.Specification m n $ A.ProtocolCase m ps, ProtocolName) }
<|> do m <- md
(sm, _) <- specMode sPROC
(sm, (rm, _)) <- specMode $ recMode sPROC
n <- newProcName
fs <- formalList
eol
indent
n' <- if rm == A.Recursive
then scopeIn n ProcName
(A.Proc m (sm, rm) (map fst fs) (A.Skip m)) A.Original
else return n
fs' <- scopeInFormals fs
p <- process
scopeOutFormals fs'
outdent
sColon
eol
return (A.Specification m n $ A.Proc m sm fs' p, ProcName)
return (A.Specification m n' $ A.Proc m (sm, rm) fs' p, ProcName)
<|> do m <- md
(rs, (sm, (rm, _))) <- tryVV (sepBy1 dataType sComma) (specMode $ recMode sFUNCTION)
n <- newFunctionName

View File

@ -494,7 +494,7 @@ terminator = A.Several emptyMeta []
processDecl :: RainParser A.AST
processDecl = do {m <- sProcess ; procName <- name ; params <- tupleDef ; body <- block ;
return $ A.Spec m
(A.Specification m procName (A.Proc m A.PlainSpec (formaliseTuple params) body))
(A.Specification m procName (A.Proc m (A.PlainSpec, A.Recursive) (formaliseTuple params) body))
terminator}
functionDecl :: RainParser A.AST

View File

@ -53,7 +53,7 @@ functionsToProcs = pass "Convert FUNCTIONs to PROCs"
(applyDepthM doSpecification)
where
doSpecification :: A.Specification -> PassM A.Specification
doSpecification (A.Specification m n (A.Function mf (sm, _) rts fs evp))
doSpecification (A.Specification m n (A.Function mf smrm rts fs evp))
= do -- Create new names for the return values.
specs <- sequence [makeNonceVariable "return_formal" mf t A.Abbrev | t <- rts]
let names = [n | A.Specification mf n _ <- specs]
@ -61,7 +61,7 @@ functionsToProcs = pass "Convert FUNCTIONs to PROCs"
modify $ (\ps -> ps { csFunctionReturns = Map.insert (A.nameName n) rts (csFunctionReturns ps) })
-- Turn the value process into an assignment process.
let p = vpToSeq m n evp [A.Variable mf n | n <- names]
let st = A.Proc mf sm (fs ++ [A.Formal A.Abbrev t n | (t, n) <- zip rts names]) p
let st = A.Proc mf smrm (fs ++ [A.Formal A.Abbrev t n | (t, n) <- zip rts names]) p
-- Build a new specification and redefine the function.
let spec = A.Specification m n st
let nd = A.NameDef {

View File

@ -158,4 +158,4 @@ flattenAssign = pass "Flatten assignment"
let code = A.Seq m $ A.Several m $ map (A.Only m) assigns
return (A.Spec m (A.Specification m (n {A.nameName = "copy_" ++ A.nameName n})
(A.Proc m A.InlineSpec [A.Formal A.Abbrev t nonceLHS, A.Formal A.ValAbbrev t nonceRHS] code)))
(A.Proc m (A.InlineSpec, A.PlainRec) [A.Formal A.Abbrev t nonceLHS, A.Formal A.ValAbbrev t nonceRHS] code)))