7 import qualified CoreUtils
8 import qualified Control.Monad.State as State
10 -- | A datatype that maps each of the single values in a haskell structure to
11 -- a mapto. The map has the same structure as the haskell type mapped, ie
13 data HsValueMap mapto =
14 Tuple [HsValueMap mapto]
20 -- | Creates a HsValueMap with the same structure as the given type, using the
21 -- given function for mapping the single types.
23 Type.Type -- ^ The type to map to a HsValueMap
24 -> HsValueMap Type.Type -- ^ The resulting map and state
27 case Type.splitTyConApp_maybe ty of
29 if (TyCon.isTupleTyCon tycon)
31 Tuple (map mkHsValueMap args)
36 data FlatFunction = FlatFunction {
37 args :: [SignalDefMap],
39 --sigs :: [SignalDef],
44 type SignalUseMap = HsValueMap SignalUse
45 type SignalDefMap = HsValueMap SignalDef
48 data SignalUse = SignalUse {
52 data SignalDef = SignalDef {
57 appFunc :: HsFunction,
58 appArgs :: [SignalUseMap],
59 appRes :: SignalDefMap
62 data CondDef = CondDef {
69 -- | How is a given (single) value in a function's type (ie, argument or
70 -- return value) used?
72 Port -- ^ Use it as a port (input or output)
73 | State Int -- ^ Use it as state (input or output). The int is used to
74 -- match input state to output state.
75 | HighOrder { -- ^ Use it as a high order function input
76 hoName :: String, -- ^ Which function is passed in?
77 hoArgs :: [HsUseMap] -- ^ Which arguments are already applied? This
78 -- ^ map should only contain Port and other
83 type HsUseMap = HsValueMap HsValueUse
85 data HsFunction = HsFunction {
87 hsFuncArgs :: [HsUseMap],
92 CoreBndr, -- ^ The bind name
93 Either -- ^ The bind value which is either
94 SignalUseMap -- ^ a signal
96 HsValueUse, -- ^ or a HighOrder function
97 [SignalUse] -- ^ With these signals already applied to it
101 type FlattenState = State.State ([App], [CondDef], SignalId)
103 -- | Add an application to the current FlattenState
104 addApp :: App -> FlattenState ()
106 (apps, conds, n) <- State.get
107 State.put (a:apps, conds, n)
109 -- | Add a conditional definition to the current FlattenState
110 addCondDef :: CondDef -> FlattenState ()
112 (apps, conds, n) <- State.get
113 State.put (apps, c:conds, n)
115 -- | Generates a new signal id, which is unique within the current flattening.
116 genSignalId :: FlattenState SignalId
118 (apps, conds, n) <- State.get
119 State.put (apps, conds, n+1)
124 -> FlattenState SignalUseMap
126 genSignalUses ty = do
127 typeMapToUseMap tymap
129 -- First generate a map with the right structure containing the types
130 tymap = mkHsValueMap ty
134 -> FlattenState SignalUseMap
136 typeMapToUseMap (Single ty) = do
138 return $ Single (SignalUse id)
140 typeMapToUseMap (Tuple tymaps) = do
141 usemaps <- mapM typeMapToUseMap tymaps
142 return $ Tuple usemaps
144 -- | Flatten a haskell function
146 HsFunction -- ^ The function to flatten
147 -> CoreBind -- ^ The function value
148 -> FlatFunction -- ^ The resulting flat function
150 flattenFunction _ (Rec _) = error "Recursive binders not supported"
151 flattenFunction hsfunc bind@(NonRec var expr) =
152 FlatFunction args res apps conds
154 init_state = ([], [], 0)
155 (fres, end_state) = State.runState (flattenExpr [] expr) init_state
157 (apps, conds, _) = end_state
162 -> FlattenState ([SignalDefMap], SignalUseMap)
164 flattenExpr binds lam@(Lam b expr) = do
165 -- Find the type of the binder
166 let (arg_ty, _) = Type.splitFunTy (CoreUtils.exprType lam)
167 -- Create signal names for the binder
168 defs <- genSignalUses arg_ty
169 let binds' = (b, Left defs):binds
170 flattenExpr binds' expr
172 flattenExpr binds (Var id) =
174 Left sig_use -> return ([], sig_use)
175 Right _ -> error "Higher order functions not supported."
177 bind = Maybe.fromMaybe
178 (error $ "Argument " ++ Name.getOccString id ++ "is unknown")
182 return ([], Tuple [])
185 -- vim: set ts=8 sw=2 sts=2 expandtab: