Put getArchitecture inside the State monad.
[matthijs/master-project/cλash.git] / Translator.hs
index dea1fd7dfdf8730698316dac554f11c38b34a437..53e626903b26c68fb3dfdd91e75382a281590917 100644 (file)
@@ -8,6 +8,7 @@ import qualified TyCon
 import qualified DataCon
 import qualified Maybe
 import qualified Module
+import qualified Control.Monad.State as State
 import Name
 import Data.Generics
 import NameEnv ( lookupNameEnv )
@@ -42,13 +43,21 @@ main =
                                        liftIO $ printBinds (cm_binds core)
                                        let bind = findBind "half_adder" (cm_binds core)
                                        let NonRec var expr = bind
-                                       let sess = VHDLSession 0 builtin_funcs
-                                       let (sess', name, f) = mkHWFunction sess bind
-                                       let sess = addFunc sess' name f
+                                       -- Turn bind into VHDL
+                                       let vhdl = State.evalState (mkVHDL bind) (VHDLSession 0 builtin_funcs)
                                        liftIO $ putStr $ showSDoc $ ppr expr
                                        liftIO $ putStr "\n\n"
-                                       liftIO $ putStr $ render $ ForSyDe.Backend.Ppr.ppr $ getArchitecture sess bind
+                                       liftIO $ putStr $ render $ ForSyDe.Backend.Ppr.ppr $ vhdl
                                        return expr
+       where
+               -- Turns the given bind into VHDL
+               mkVHDL bind = do
+                       -- Get the function signature
+                       (name, f) <- mkHWFunction bind
+                       -- Add it to the session
+                       addFunc name f
+                       arch <- getArchitecture bind
+                       return arch
 
 printTarget (Target (TargetFile file (Just x)) obj Nothing) =
        print $ show file
@@ -192,14 +201,15 @@ mapOutputPorts (Tuple ports) (Tuple signals) =
        concat (zipWith mapOutputPorts ports signals)
 
 getArchitecture ::
-       VHDLSession
-       -> CoreBind               -- The binder to expand into an architecture
-       -> AST.ArchBody           -- The resulting architecture
+       CoreBind                  -- The binder to expand into an architecture
+       -> VHDLState AST.ArchBody -- The resulting architecture
         
-getArchitecture sess (Rec _) = error "Recursive binders not supported"
+getArchitecture (Rec _) = error "Recursive binders not supported"
 
-getArchitecture sess (NonRec var expr) =
-       AST.ArchBody
+getArchitecture (NonRec var expr) = do
+       HWFunction inports outport <- getHWFunc name
+       sess <- State.get
+       return $ AST.ArchBody
                (AST.unsafeVHDLBasicId "structural")
                -- Use unsafe for now, to prevent pulling in ForSyDe error handling
                (AST.NSimple (AST.unsafeVHDLBasicId name))
@@ -207,14 +217,11 @@ getArchitecture sess (NonRec var expr) =
                (getInstantiations sess inports outport [] expr)
        where
                name = (getOccString var)
-               hwfunc = Maybe.fromMaybe
-                       (error $ "Function " ++ name ++ "is unknown? This should not happen!")
-                       (lookup name (funcs sess))
-               HWFunction inports outport = hwfunc
 
 data PortNameMap =
        Tuple [PortNameMap]
        | Port  String
+  deriving (Show)
 
 -- Generate a port name map (or multiple for tuple types) in the given direction for
 -- each type given.
@@ -238,17 +245,16 @@ data HWFunction = HWFunction { -- A function that is available in hardware
        inPorts   :: [PortNameMap],
        outPort   :: PortNameMap
        --entity    :: AST.EntityDec
-}
+} deriving (Show)
 
 -- Turns a CoreExpr describing a function into a description of its input and
 -- output ports.
 mkHWFunction ::
-       VHDLSession
-       -> CoreBind                                -- The core binder to generate the interface for
-       -> (VHDLSession, String, HWFunction)       -- The name of the function and its interface
+       CoreBind                                   -- The core binder to generate the interface for
+       -> VHDLState (String, HWFunction)          -- The name of the function and its interface
 
-mkHWFunction sess (NonRec var expr) =
-       (sess, name, HWFunction inports outport)
+mkHWFunction (NonRec var expr) =
+               return (name, HWFunction inports outport)
        where
                name = (getOccString var)
                ty = CoreUtils.exprType expr
@@ -261,18 +267,30 @@ mkHWFunction sess (NonRec var expr) =
                        ps     -> getPortNameMapForTys "portin" 0 ps
                outport = getPortNameMapForTy "portout" res
 
-mkHWFunction sess (Rec _) =
+mkHWFunction (Rec _) =
        error "Recursive binders not supported"
 
 data VHDLSession = VHDLSession {
        nameCount :: Int,                      -- A counter that can be used to generate unique names
        funcs     :: [(String, HWFunction)]    -- All functions available, indexed by name
-}
+} deriving (Show)
+
+type VHDLState = State.State VHDLSession
 
 -- Add the function to the session
-addFunc :: VHDLSession -> String -> HWFunction -> VHDLSession
-addFunc sess name f =
-       sess {funcs = (name, f) : (funcs sess) }
+addFunc :: String -> HWFunction -> VHDLState ()
+addFunc name f = do
+       fs <- State.gets funcs -- Get the funcs element from the session
+       State.modify (\x -> x {funcs = (name, f) : fs }) -- Prepend name and f
+
+-- Lookup the function with the given name in the current session. Errors if
+-- it was not found.
+getHWFunc :: String -> VHDLState HWFunction
+getHWFunc name = do
+       fs <- State.gets funcs -- Get the funcs element from the session
+       return $ Maybe.fromMaybe
+               (error $ "Function " ++ name ++ "is unknown? This should not happen!")
+               (lookup name fs)
 
 builtin_funcs = 
        [