diff --git a/backends/GenerateC.hs b/backends/GenerateC.hs index fcd99f8..5845ec2 100644 --- a/backends/GenerateC.hs +++ b/backends/GenerateC.hs @@ -105,6 +105,7 @@ data GenOps = GenOps { genFlatArraySize :: GenOps -> [A.Dimension] -> CGen (), genFormal :: GenOps -> A.Formal -> CGen (), genFormals :: GenOps -> [A.Formal] -> CGen (), + genForwardDeclaration :: GenOps -> A.Specification -> CGen(), genFuncDyadic :: GenOps -> Meta -> String -> A.Expression -> A.Expression -> CGen (), genFuncMonadic :: GenOps -> Meta -> String -> A.Expression -> CGen (), genIf :: GenOps -> Meta -> A.Structured -> CGen (), @@ -191,6 +192,7 @@ cgenOps = GenOps { genFlatArraySize = cgenFlatArraySize, genFormal = cgenFormal, genFormals = cgenFormals, + genForwardDeclaration = cgenForwardDeclaration, genFuncDyadic = cgenFuncDyadic, genFuncMonadic = cgenFuncMonadic, genIf = cgenIf, @@ -262,6 +264,7 @@ cgenTopLevel ops p cs <- get tell ["extern int " ++ nameString n ++ "_stack_size;\n" | n <- Set.toList $ csParProcs cs] + sequence_ $ map (call genForwardDeclaration ops) (listify (const True :: A.Specification -> Bool) p) call genProcess ops p (name, chans) <- tlpInterface tell ["void tock_main (Process *me, Channel *in, Channel *out, Channel *err) {\n"] @@ -1388,6 +1391,16 @@ cintroduceSpec ops (A.Specification _ n (A.Retypes m am t v)) --cintroduceSpec ops (A.Specification _ n (A.RetypesExpr _ am t e)) cintroduceSpec ops n = call genMissing ops $ "introduceSpec " ++ show n +cgenForwardDeclaration :: GenOps -> A.Specification -> CGen () +cgenForwardDeclaration ops (A.Specification _ n (A.Proc _ sm fs _)) + = do call genSpecMode ops sm + tell ["void "] + genName n + tell [" (Process *me"] + call genFormals ops fs + tell [");"] +cgenForwardDeclaration _ _ = return () + cremoveSpec :: GenOps -> A.Specification -> CGen () cremoveSpec ops (A.Specification m n (A.Declaration _ t)) = case t of diff --git a/backends/GenerateCPPCSP.hs b/backends/GenerateCPPCSP.hs index 6455c85..d9d7d34 100644 --- a/backends/GenerateCPPCSP.hs +++ b/backends/GenerateCPPCSP.hs @@ -73,6 +73,7 @@ module GenerateCPPCSP (generateCPPCSP) where import Data.Char import Data.List import Data.Maybe +import Data.Generics import Control.Monad.Writer import Control.Monad.Error import Control.Monad.State @@ -107,6 +108,7 @@ cppgenOps = cgenOps { genDeclType = cppgenDeclType, genDeclaration = cppgenDeclaration, genFlatArraySize = cppgenFlatArraySize, + genForwardDeclaration = cppgenForwardDeclaration, genIf = cppgenIf, genInput = cppgenInput, genInputCase = cppgenInputCase, @@ -141,6 +143,8 @@ generateCPPCSP = generate cppgenOps cppgenTopLevel :: GenOps -> A.Process -> CGen () cppgenTopLevel ops p = do tell ["#include \n"] + --In future, these declarations could be moved to a header file: + sequence_ $ map (call genForwardDeclaration ops) (listify (const True :: A.Specification -> Bool) p) call genProcess ops p (name, chans) <- tlpInterface tell ["int main (int argc, char** argv) { csp::Start_CPPCSP();"] @@ -791,6 +795,67 @@ cppgenFlatArraySize ops dims = sequence_ $ intersperse (tell ["*"]) $ map genDim genDim (A.Dimension n) = tell [show n] genDim dim = call genMissing ops ("No support for dimension: " ++ show dim) +--Changed from GenerateC to add a name function (to allow us to use the same function for doing function parameters as constructor parameters) +--and also changed to use infixComma. +--Therefore these functions are not part of GenOps. They are called directly by cppgenForwardDeclaration and cppintroduceSpec. +--To use for a constructor list, pass prefixUnderscore as the function, otherwise pass the identity function +cppgenFormals :: GenOps -> (A.Name -> A.Name) -> [A.Formal] -> CGen () +cppgenFormals ops nameFunc list = infixComma (map (cppgenFormal ops nameFunc) list) + +--Changed as genFormals +cppgenFormal :: GenOps -> (A.Name -> A.Name) -> A.Formal -> CGen () +cppgenFormal ops nameFunc (A.Formal am t n) = call genDecl ops am t (nameFunc n) + +cppgenForwardDeclaration :: GenOps -> A.Specification -> CGen() +cppgenForwardDeclaration ops (A.Specification _ n (A.Proc _ sm fs _)) + = do --Generate the "process" as a C++ function: + call genSpecMode ops sm + tell ["void "] + name + tell [" ("] + cppgenFormals ops (\x -> x) fs + tell [");"] + + --And generate its CSProcess wrapper: + tell ["class proc_"] + name + tell [" : public csp::CSProcess {private:"] + genClassVars fs + tell ["public:inline proc_"] + name + tell ["("] + cppgenFormals ops prefixUnderscore fs + tell [") : csp::CSProcess(262144)"] + genConstructorList fs + tell ["{} protected: virtual void run(); };"] + where + name = genName n + + --A simple function for generating declarations of class variables + genClassVar :: A.Formal -> CGen() + genClassVar (A.Formal am t n) + = do call genDecl ops am t n + tell[";"] + + --Generates the given list of class variables + genClassVars :: [A.Formal] -> CGen () + genClassVars fs = cgmap genClassVar fs + + --A helper function for generating the initialiser list in a process wrapper constructor + genConsItem :: A.Formal -> CGen() + genConsItem (A.Formal am t n) + = do tell[","] + genName n + tell["(_"] + genName n + tell[")"] + + --A function for generating the initialiser list in a process wrapper constructor + genConstructorList :: [A.Formal] -> CGen () + genConstructorList fs = cgmap genConsItem fs + +cppgenForwardDeclaration _ _ = return () + cppintroduceSpec :: GenOps -> A.Specification -> CGen () --I generate process wrappers for all functions by default: cppintroduceSpec ops (A.Specification _ n (A.Proc _ sm fs p)) @@ -805,57 +870,16 @@ cppintroduceSpec ops (A.Specification _ n (A.Proc _ sm fs p)) tell ["}\n"] --And generate its CSProcess wrapper: - tell ["class proc_"] + tell ["void proc_"] name - tell [" : public csp::CSProcess {private:"] - genClassVars fs - tell ["public:inline proc_"] - name - tell ["("] - cppgenFormals ops prefixUnderscore fs - tell [") : csp::CSProcess(262144)"] - genConstructorList fs - tell ["{} protected: virtual void run() { try {"] + tell ["::run() { try {"] name tell [" ( "] genParamList fs - tell [" ); } catch (StopException e) {std::cerr << \"Stopped because: \" << e.reason << std::endl; } } };"] + tell [" ); } catch (StopException e) {std::cerr << \"Stopped because: \" << e.reason << std::endl; } }"] where name = genName n - --A simple function for generating declarations of class variables - genClassVar :: A.Formal -> CGen() - genClassVar (A.Formal am t n) - = do call genDecl ops am t n - tell[";"] - - --Generates the given list of class variables - genClassVars :: [A.Formal] -> CGen () - genClassVars fs = cgmap genClassVar fs - - --Changed from GenerateC to add a name function (to allow us to use the same function for doing function parameters as constructor parameters) - --and also changed to use infixComma - --To use for a constructor list, pass prefixUnderscore as the function, otherwise pass the identity function - cppgenFormals :: GenOps -> (A.Name -> A.Name) -> [A.Formal] -> CGen () - cppgenFormals ops nameFunc list = infixComma (map (cppgenFormal ops nameFunc) list) - - --Changed as genFormals - cppgenFormal :: GenOps -> (A.Name -> A.Name) -> A.Formal -> CGen () - cppgenFormal ops nameFunc (A.Formal am t n) = call genDecl ops am t (nameFunc n) - - --A helper function for generating the initialiser list in a process wrapper constructor - genConsItem :: A.Formal -> CGen() - genConsItem (A.Formal am t n) - = do tell[","] - genName n - tell["(_"] - genName n - tell[")"] - - --A function for generating the initialiser list in a process wrapper constructor - genConstructorList :: [A.Formal] -> CGen () - genConstructorList fs = cgmap genConsItem fs - --A helper function for calling the wrapped functions: genParam :: A.Formal -> CGen() genParam (A.Formal _ _ n) = genName n