|
| 1 | +{-# LANGUAGE ExistentialQuantification #-} |
| 2 | + |
| 3 | +-- | This is a duplicate version of @Copilot.Compile.Bluespec.External@ that is |
| 4 | +-- specific to the test suite. Ideally, we would move this into a common library |
| 5 | +-- that is shared between both @copilot-bluespec@ and @copilot-c99@ so that we |
| 6 | +-- can avoid this duplication. See |
| 7 | +-- https://github.com/Copilot-Language/copilot-bluespec/issues/3. |
| 8 | +-- |
| 9 | +-- Represent information about externs needed in the generation of Bluespec |
| 10 | +-- code for stream declarations and triggers. |
| 11 | +module Test.Copilot.Compile.Bluespec.External |
| 12 | + ( External(..) |
| 13 | + , gatherExts |
| 14 | + ) where |
| 15 | + |
| 16 | +-- External imports |
| 17 | +import Data.List (unionBy) |
| 18 | + |
| 19 | +-- External imports: Copilot |
| 20 | +import Copilot.Core ( Expr (..), Stream (..), Trigger (..), Type, UExpr (..) ) |
| 21 | + |
| 22 | +-- | Representation of external variables. |
| 23 | +data External = forall a. External |
| 24 | + { extName :: String |
| 25 | + , extType :: Type a |
| 26 | + } |
| 27 | + |
| 28 | +-- | Collect all external variables from the streams and triggers. |
| 29 | +-- |
| 30 | +-- Although Copilot specifications can contain also properties and theorems, |
| 31 | +-- the Bluespec backend currently only generates code for streams and triggers. |
| 32 | +gatherExts :: [Stream] -> [Trigger] -> [External] |
| 33 | +gatherExts streams triggers = streamsExts `extUnion` triggersExts |
| 34 | + where |
| 35 | + streamsExts = foldr (extUnion . streamExts) mempty streams |
| 36 | + triggersExts = foldr (extUnion . triggerExts) mempty triggers |
| 37 | + |
| 38 | + streamExts :: Stream -> [External] |
| 39 | + streamExts (Stream _ _ expr _) = exprExts expr |
| 40 | + |
| 41 | + triggerExts :: Trigger -> [External] |
| 42 | + triggerExts (Trigger _ guard args) = guardExts `extUnion` argExts |
| 43 | + where |
| 44 | + guardExts = exprExts guard |
| 45 | + argExts = concatMap uExprExts args |
| 46 | + |
| 47 | + uExprExts :: UExpr -> [External] |
| 48 | + uExprExts (UExpr _ expr) = exprExts expr |
| 49 | + |
| 50 | + exprExts :: Expr a -> [External] |
| 51 | + exprExts (Local _ _ _ e1 e2) = exprExts e1 `extUnion` exprExts e2 |
| 52 | + exprExts (ExternVar ty name _) = [External name ty] |
| 53 | + exprExts (Op1 _ e) = exprExts e |
| 54 | + exprExts (Op2 _ e1 e2) = exprExts e1 `extUnion` exprExts e2 |
| 55 | + exprExts (Op3 _ e1 e2 e3) = exprExts e1 `extUnion` exprExts e2 |
| 56 | + `extUnion` exprExts e3 |
| 57 | + exprExts (Label _ _ e) = exprExts e |
| 58 | + exprExts _ = [] |
| 59 | + |
| 60 | + -- | Union over lists of External, we solely base the equality on the |
| 61 | + -- extName's. |
| 62 | + extUnion :: [External] -> [External] -> [External] |
| 63 | + extUnion = unionBy (\a b -> extName a == extName b) |
0 commit comments