{-# LANGUAGE ExistentialQuantification #-} -- | Represent information about externs needed in the generation of C99 code -- for stream declarations and triggers. module Copilot.Compile.C99.External where import Data.List (unionBy) import Copilot.Core import Copilot.Compile.C99.Util -- | Representation of external variables. data External = forall a. External { extname :: String , extcpyname :: String , exttype :: Type a } -- | Union over lists of External, we solely base the equality on the -- extname's. extunion :: [External] -> [External] -> [External] extunion = unionBy (\a b -> extname a == extname b) -- | Collect all external variables from the streams and triggers. -- -- Although Copilot specifications can contain also properties and theorems, -- the C99 backend currently only generates code for streams and triggers. gatherexts :: [Stream] -> [Trigger] -> [External] gatherexts streams triggers = streamsexts `extunion` triggersexts where streamsexts = foldr extunion mempty $ map streamexts streams triggersexts = foldr extunion mempty $ map triggerexts triggers streamexts :: Stream -> [External] streamexts (Stream _ _ expr _) = exprexts expr triggerexts :: Trigger -> [External] triggerexts (Trigger _ guard args) = guardexts `extunion` argexts where guardexts = exprexts guard argexts = concat $ map uexprexts args uexprexts :: UExpr -> [External] uexprexts (UExpr _ expr) = exprexts expr exprexts :: Expr a -> [External] exprexts expr = let rec = exprexts in case expr of Local _ _ _ e1 e2 -> rec e1 `extunion` rec e2 ExternVar ty name _ -> [External name (excpyname name) ty] Op1 _ e -> rec e Op2 _ e1 e2 -> rec e1 `extunion` rec e2 Op3 _ e1 e2 e3 -> rec e1 `extunion` rec e2 `extunion` rec e3 Label _ _ e -> rec e _ -> []