diff --git a/backends/GenerateC.hs b/backends/GenerateC.hs index 907f15a..9119c7f 100644 --- a/backends/GenerateC.hs +++ b/backends/GenerateC.hs @@ -182,6 +182,10 @@ cgenTopLevel s genName tlpName tell ["_stack_size;\n"] + -- Forward declarations of externals: + sequence_ [tell ["extern void ", mungeExternalName n, "(int*);"] + | (n, fs) <- csExternals cs] + call genStructured s (\m _ -> tell ["\n#error Invalid top-level item: ", show m]) tell ["void tock_main (Workspace wptr) {\n"] @@ -227,6 +231,8 @@ cgenTopLevel s \ return 0;\n\ \}\n"] where + mungeExternalName (_:cs) = [if c == '.' then '_' else c | c <- cs] + -- | Allocate a TLP channel handler process, and return the function that -- implements it. genTLPHandler :: (Maybe A.Direction, TLPChannel) -> String -> String -> String -> CGen String @@ -2026,13 +2032,22 @@ withIf cond body cgenProcCall :: A.Name -> [A.Actual] -> CGen () cgenProcCall n as = do A.Proc _ (_, rm) _ _ <- specTypeOfName n - case rm of + externalProcs <- getCompState >>* csExternals + let ext = lookup (A.nameName n) externalProcs + case (rm, ext) of -- This is rather inefficient, because if a recursive PROC is called -- anywhere (from other processes as well as from itself), it will -- be done in a PAR. - A.Recursive -> + (A.Recursive, _) -> let m = A.nameMeta n in call genPar A.PlainPar $ A.Only m $ A.ProcCall m n as + (_, Just fs) -> + do tell ["{int args_plus_blank[] = {0"] + call genActuals fs as + tell ["};"] + let (_:cs) = A.nameName n + tell [[if c == '.' then '_' else c | c <- cs]] + tell ["(args_plus_blank + 1);}"] _ -> do genName n tell [" (wptr"] (A.Proc _ _ fs _) <- specTypeOfName n diff --git a/data/CompState.hs b/data/CompState.hs index eaf9314..85892c9 100644 --- a/data/CompState.hs +++ b/data/CompState.hs @@ -121,6 +121,7 @@ data CompState = CompState { csUnscopedNames :: Map String String, csNameCounter :: Int, csNameAttr :: Map String (Set.Set NameAttr), + csExternals :: [(String, [A.Formal])], -- Set by passes csTypeContext :: [Maybe A.Type], @@ -165,6 +166,7 @@ emptyState = CompState { csUnscopedNames = Map.empty, csNameCounter = 0, csNameAttr = Map.empty, + csExternals = [], csTypeContext = [], csNonceCounter = 0, diff --git a/frontends/ParseOccam.hs b/frontends/ParseOccam.hs index 0d54dab..3f1bb54 100644 --- a/frontends/ParseOccam.hs +++ b/frontends/ParseOccam.hs @@ -1383,6 +1383,7 @@ pragma = do Pragma p <- genToken isPragma modify $ \st -> st { csNames = Map.insert on nd (csNames st) , csLocalNames = (on, (n, ProcName)) : csLocalNames st + , csExternals = (on, fs) : csExternals st } _ -> warnP m WarnUnknownPreprocessorDirective $ "Unknown PRAGMA: " ++ p