5 import qualified CoreUtils
6 import qualified Control.Monad.State as State
8 -- | A datatype that maps each of the single values in a haskell structure to
9 -- a mapto. The map has the same structure as the haskell type mapped, ie
11 data HsValueMap mapto =
12 Tuple [HsValueMap mapto]
18 -- | Creates a HsValueMap with the same structure as the given type, using the
19 -- given function for mapping the single types.
21 Type.Type -- ^ The type to map to a HsValueMap
22 -> HsValueMap Type.Type -- ^ The resulting map and state
25 case Type.splitTyConApp_maybe ty of
27 if (TyCon.isTupleTyCon tycon)
29 Tuple (map mkHsValueMap args)
34 data FlatFunction = FlatFunction {
35 args :: [SignalDefMap],
37 --sigs :: [SignalDef],
42 type SignalUseMap = HsValueMap SignalUse
43 type SignalDefMap = HsValueMap SignalDef
46 data SignalUse = SignalUse {
50 data SignalDef = SignalDef {
55 appFunc :: HsFunction,
56 appArgs :: [SignalUseMap],
57 appRes :: SignalDefMap
60 data CondDef = CondDef {
67 -- | How is a given (single) value in a function's type (ie, argument or
68 -- return value) used?
70 Port -- ^ Use it as a port (input or output)
71 | State Int -- ^ Use it as state (input or output). The int is used to
72 -- match input state to output state.
73 | HighOrder { -- ^ Use it as a high order function input
74 hoName :: String, -- ^ Which function is passed in?
75 hoArgs :: [HsUseMap] -- ^ Which arguments are already applied? This
76 -- ^ map should only contain Port and other
81 type HsUseMap = HsValueMap HsValueUse
83 data HsFunction = HsFunction {
85 hsFuncArgs :: [HsUseMap],
90 CoreBndr, -- ^ The bind name
91 Either -- ^ The bind value which is either
92 SignalUseMap -- ^ a signal
94 HsValueUse, -- ^ or a HighOrder function
95 [SignalUse] -- ^ With these signals already applied to it
99 type FlattenState = State.State ([App], [CondDef], SignalId)
101 -- | Add an application to the current FlattenState
102 addApp :: App -> FlattenState ()
104 (apps, conds, n) <- State.get
105 State.put (a:apps, conds, n)
107 -- | Add a conditional definition to the current FlattenState
108 addCondDef :: CondDef -> FlattenState ()
110 (apps, conds, n) <- State.get
111 State.put (apps, c:conds, n)
113 -- | Generates a new signal id, which is unique within the current flattening.
114 genSignalId :: FlattenState SignalId
116 (apps, conds, n) <- State.get
117 State.put (apps, conds, n+1)
122 -> FlattenState SignalUseMap
124 genSignalUses ty = do
125 typeMapToUseMap tymap
127 -- First generate a map with the right structure containing the types
128 tymap = mkHsValueMap ty
132 -> FlattenState SignalUseMap
134 typeMapToUseMap (Single ty) = do
136 return $ Single (SignalUse id)
138 typeMapToUseMap (Tuple tymaps) = do
139 usemaps <- mapM typeMapToUseMap tymaps
140 return $ Tuple usemaps
142 -- | Flatten a haskell function
144 HsFunction -- ^ The function to flatten
145 -> CoreBind -- ^ The function value
146 -> FlatFunction -- ^ The resulting flat function
148 flattenFunction _ (Rec _) = error "Recursive binders not supported"
149 flattenFunction hsfunc bind@(NonRec var expr) =
150 FlatFunction args res apps conds
152 init_state = ([], [], 0)
153 (fres, end_state) = State.runState (flattenExpr [] expr) init_state
155 (apps, conds, _) = end_state
160 -> FlattenState ([SignalDefMap], SignalUseMap)
162 flattenExpr binds lam@(Lam b expr) = do
163 -- Find the type of the binder
164 let (arg_ty, _) = Type.splitFunTy (CoreUtils.exprType lam)
165 -- Create signal names for the binder
166 defs <- genSignalUses arg_ty
167 let binds' = (b, Left defs):binds
168 flattenExpr binds' expr
171 return ([], Tuple [])
174 -- vim: set ts=8 sw=2 sts=2 expandtab: