@@ -3,11 +3,9 @@
3{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE UndecidableInstances #-}
4{-# LANGUAGE UndecidableInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
7−module Language.Haskell.Generate.Monad
6+module Language.Haskell.Generate.Base
8− ( Generate(..), ExpG
7+ ( ExpM(..), ExpG, ExpType
9− , runGenerate, newName
8+ , runExpM, newName
11 , useValue, useCon, useVar
9 , useValue, useCon, useVar
13 , applyE, applyE2, applyE3, applyE4, applyE5, applyE6
11 , applyE, applyE2, applyE3, applyE4, applyE5, applyE6
@@ -21,7 +19,6 @@ module Language.Haskell.Generate.Monad
22 , runModuleM
20 , runModuleM
23 , generateModule
21 , generateModule
@@ -34,44 +31,32 @@ import qualified Data.Set as S
34import Language.Haskell.Exts.Pretty
31import Language.Haskell.Exts.Pretty
35import Language.Haskell.Exts.SrcLoc
32import Language.Haskell.Exts.SrcLoc
36import Language.Haskell.Exts.Syntax
33import Language.Haskell.Exts.Syntax
37−import Language.Haskell.Generate.Expression
41--------------------------------------------------------------------------------
35--------------------------------------------------------------------------------
42-- Generate expressions
36-- Generate expressions
44−-- | This monad keeps track of a counter for generating unique names and the set of modules
38+-- | A ExpM is a monad used to track the imports that are needed for a given expression. Usually, you don't have to use
45−-- that are needed for the expression.
39+-- this type directly, but use combinators to combine several ExpM into bigger expressions. The t type parameter tracks
40+-- the type of the expression, so you don't accidently build expression that don't type check.
46−newtype Generate a = Generate { unGenerate :: StateT Integer (Writer (S.Set ModuleName)) a } deriving (Functor, Applicative, Monad)
41+newtype ExpM t a = ExpM { unExpM :: StateT Integer (Writer (S.Set ModuleName)) a } deriving (Functor, Applicative, Monad)
48−-- | Extract the set of modules and the value from a Generate action.
49−runGenerate :: Generate a -> (a, S.Set ModuleName)
50−runGenerate (Generate a) = runWriter $ evalStateT a 0
52−-- | This is a type alias for a Generate action that returns an expression of type 't'.
43+-- | The ExpG type is a ExpM computation that returns an expression. Usually, this is the end result of a function generating
44+-- a haskell expression
53−type ExpG t = Generate (Expression t)
45+type ExpG t = ExpM t Exp
55−-- | Use a haskell-src-exts Exp as the result of a Generate action.
47+-- | Evaluate a ExpM action, returning the needed modules and the value.
56−returnE :: Exp -> ExpG t
48+runExpM :: ExpM t a -> (a, S.Set ModuleName)
57−returnE = return . Expression
49+runExpM (ExpM expt) = runWriter $ evalStateT expt 0
59−-- | Pretty print the expression generated by a given action.
51+unsafeCoerceE :: ExpM t a -> ExpM t' a
60−generateExp :: ExpG t -> String
52+unsafeCoerceE (ExpM x) = ExpM x
61−generateExp = prettyPrint . runExpression . fst . runGenerate
63-- | Generate a case expression.
54-- | Generate a case expression.
64caseE :: ExpG x -> [(Pat, ExpG t)] -> ExpG t
55caseE :: ExpG x -> [(Pat, ExpG t)] -> ExpG t
65caseE v alt = do
56caseE v alt = do
66− v' <- v
57+ v' <- unsafeCoerceE v
67−#if MIN_VERSION_haskell_src_exts(1,17,0)
68− alt' <- mapM (\(p,a) -> fmap (\a' -> Alt noLoc p (UnGuardedRhs $ runExpression a') Nothing) a) alt
69−#elif MIN_VERSION_haskell_src_exts(1,16,0)
70− alt' <- mapM (\(p,a) -> fmap (\a' -> Alt noLoc p (UnGuardedRhs $ runExpression a') (BDecls [])) a) alt
72− alt' <- mapM (\(p,a) -> fmap (\a' -> Alt noLoc p (UnGuardedAlt $ runExpression a') (BDecls [])) a) alt
58+ alt' <- mapM (\(p,a) -> fmap (\a' -> Alt noLoc p (UnGuardedAlt a') (BDecls [])) a) alt
74− return $ Expression $ Case (runExpression v') alt'
59+ return $ Case v' alt'
76-- | Import a function from a module. This function is polymorphic in the type of the resulting expression,
61-- | Import a function from a module. This function is polymorphic in the type of the resulting expression,
77-- you should probably only use this function to define type-restricted specializations.
62-- you should probably only use this function to define type-restricted specializations.
@@ -82,37 +67,32 @@ caseE v alt = do
82-- > addInt = useValue "Prelude" $ Symbol "+"
67-- > addInt = useValue "Prelude" $ Symbol "+"
84useValue :: String -> Name -> ExpG a
69useValue :: String -> Name -> ExpG a
85−useValue md name = Generate $ do
70+useValue md name = ExpM $ do
86 lift $ tell $ S.singleton $ ModuleName md
71 lift $ tell $ S.singleton $ ModuleName md
87− return $ Expression $ Var $ Qual (ModuleName md) name
72+ return $ Var $ Qual (ModuleName md) name
89-- | Import a value constructor from a module. Returns the qualified name of the constructor.
74-- | Import a value constructor from a module. Returns the qualified name of the constructor.
90−useCon :: String -> Name -> Generate QName
75+useCon :: String -> Name -> ExpM t QName
91−useCon md name = Generate $ do
76+useCon md name = ExpM $ do
92 lift $ tell $ S.singleton $ ModuleName md
77 lift $ tell $ S.singleton $ ModuleName md
93 return $ Qual (ModuleName md) name
78 return $ Qual (ModuleName md) name
95-- | Use the value of a variable with the given name.
80-- | Use the value of a variable with the given name.
96useVar :: Name -> ExpG t
81useVar :: Name -> ExpG t
97−useVar name = return $ Expression $ Var $ UnQual name
82+useVar name = return $ Var $ UnQual name
99-- | Generate a new unique variable name with the given prefix. Note that this new variable name
84-- | Generate a new unique variable name with the given prefix. Note that this new variable name
100-- is only unique relative to other variable names generated by this function.
85-- is only unique relative to other variable names generated by this function.
101−newName :: String -> Generate Name
86+newName :: String -> ExpM t Name
102−newName pref = Generate $ do
87+newName pref = ExpM $ do
103 i <- get <* modify succ
88 i <- get <* modify succ
104 return $ Ident $ pref ++ show i
89 return $ Ident $ pref ++ show i
106−-- | Generate a expression from a haskell value. This can for example be used to create lambdas:
91+-- | This type family can be used to get the type associated with some expression.
107−--
92+type family ExpType a :: *
108−-- >>> putStrLn $ generateExp $ expr (\x f -> f <>$ x)
93+type instance ExpType (ExpM t a) = t
109−-- \ pvar_0 -> \ pvar_1 -> pvar_1 pvar_0
94+
110−--
95+-- | Generate a expression from a haskell value.
111−-- Or string literals:
113−-- >>> putStrLn $ generateExp $ expr "I'm a string!"
114−-- ['I', '\'', 'm', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', '!']
116class GenExp t where
96class GenExp t where
117 type GenExpType t :: *
97 type GenExpType t :: *
@@ -123,41 +103,36 @@ instance GenExp (ExpG a) where
123 type GenExpType (ExpG a) = a
103 type GenExpType (ExpG a) = a
124 expr = id
104 expr = id
126−instance GenExp (Expression t) where
127− type GenExpType (Expression t) = t
130instance GenExp Char where
106instance GenExp Char where
131 type GenExpType Char = Char
107 type GenExpType Char = Char
132− expr = return . Expression . Lit . Char
108+ expr = return . Lit . Char
134instance GenExp Integer where
110instance GenExp Integer where
135 type GenExpType Integer = Integer
111 type GenExpType Integer = Integer
136− expr = return . Expression . Lit . Int
112+ expr = return . Lit . Int
138instance GenExp Rational where
114instance GenExp Rational where
139 type GenExpType Rational = Rational
115 type GenExpType Rational = Rational
140− expr = return . Expression . Lit . Frac
116+ expr = return . Lit . Frac
142instance GenExp a => GenExp [a] where
118instance GenExp a => GenExp [a] where
143 type GenExpType [a] = [GenExpType a]
119 type GenExpType [a] = [GenExpType a]
144− expr = Generate . fmap (Expression . List . map runExpression) . mapM (unGenerate . expr)
120+ expr = ExpM . fmap List . mapM (unExpM . expr)
146instance GenExp x => GenExp (ExpG a -> x) where
122instance GenExp x => GenExp (ExpG a -> x) where
147 type GenExpType (ExpG a -> x) = a -> GenExpType x
123 type GenExpType (ExpG a -> x) = a -> GenExpType x
148 expr f = do
124 expr f = do
149 pvarName <- newName "pvar_"
125 pvarName <- newName "pvar_"
150− body <- expr $ f $ return $ Expression $ Var $ UnQual pvarName
126+ body <- unsafeCoerceE $ expr $ f $ return $ Var $ UnQual pvarName
151− return $ Expression $ Lambda noLoc [PVar pvarName] $ runExpression body
127+ return $ Lambda noLoc [PVar pvarName] body
153--------------------------------------------------------------------------------
129--------------------------------------------------------------------------------
154-- Apply functions
130-- Apply functions
156-- | Apply a function in a haskell expression to a value.
132-- | Apply a function in a haskell expression to a value.
157applyE :: ExpG (a -> b) -> ExpG a -> ExpG b
133applyE :: ExpG (a -> b) -> ExpG a -> ExpG b
158−applyE a b = wrap $ liftM (foldl1 App) $ sequence [unwrap a, unwrap b]
134+applyE a b = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b]
159− where wrap = fmap Expression
135+ where ce = unsafeCoerceE
160− unwrap = fmap runExpression
162-- | Operator for 'applyE'.
137-- | Operator for 'applyE'.
163(<>$) :: ExpG (a -> b) -> ExpG a -> ExpG b
138(<>$) :: ExpG (a -> b) -> ExpG a -> ExpG b
@@ -167,33 +142,28 @@ infixl 1 <>$
168-- | ApplyE for 2 arguments
143-- | ApplyE for 2 arguments
169applyE2 :: ExpG (a -> b -> c) -> ExpG a -> ExpG b -> ExpG c
144applyE2 :: ExpG (a -> b -> c) -> ExpG a -> ExpG b -> ExpG c
170−applyE2 a b c = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c]
145+applyE2 a b c = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c]
171− where wrap = fmap Expression
146+ where ce = unsafeCoerceE
172− unwrap = fmap runExpression
174-- | Apply a function to 3 arguments
148-- | Apply a function to 3 arguments
175applyE3 :: ExpG (a -> b -> c -> d) -> ExpG a -> ExpG b -> ExpG c -> ExpG d
149applyE3 :: ExpG (a -> b -> c -> d) -> ExpG a -> ExpG b -> ExpG c -> ExpG d
176−applyE3 a b c d = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c,unwrap d]
150+applyE3 a b c d = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c,ce d]
177− where wrap = fmap Expression
151+ where ce = unsafeCoerceE
178− unwrap = fmap runExpression
180-- | Apply a function to 4 arguments
153-- | Apply a function to 4 arguments
181applyE4 :: ExpG (a -> b -> c -> d -> e) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e
154applyE4 :: ExpG (a -> b -> c -> d -> e) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e
182−applyE4 a b c d e = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c,unwrap d,unwrap e]
155+applyE4 a b c d e = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c,ce d,ce e]
183− where wrap = fmap Expression
156+ where ce = unsafeCoerceE
184− unwrap = fmap runExpression
186-- | Apply a function to 5 arguments
158-- | Apply a function to 5 arguments
187applyE5 :: ExpG (a -> b -> c -> d -> e -> f) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG f
159applyE5 :: ExpG (a -> b -> c -> d -> e -> f) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG f
188−applyE5 a b c d e f = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c,unwrap d,unwrap e,unwrap f]
160+applyE5 a b c d e f = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c,ce d,ce e,ce f]
189− where wrap = fmap Expression
161+ where ce = unsafeCoerceE
190− unwrap = fmap runExpression
192-- | Apply a function to 6 arguments
163-- | Apply a function to 6 arguments
193applyE6 :: ExpG (a -> b -> c -> d -> e -> f -> g) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG f -> ExpG g
164applyE6 :: ExpG (a -> b -> c -> d -> e -> f -> g) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG f -> ExpG g
194−applyE6 a b c d e f g = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c,unwrap d,unwrap e,unwrap f,unwrap g]
165+applyE6 a b c d e f g = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c,ce d,ce e,ce f,ce g]
195− where wrap = fmap Expression
166+ where ce = unsafeCoerceE
196− unwrap = fmap runExpression
198--------------------------------------------------------------------------------
168--------------------------------------------------------------------------------
199-- Generate modules
169-- Generate modules
@@ -210,35 +180,23 @@ data FunRef t = FunRef Name
211instance GenExp (FunRef t) where
181instance GenExp (FunRef t) where
212 type GenExpType (FunRef t) = t
182 type GenExpType (FunRef t) = t
213− expr (FunRef n) = return $ Expression $ Var $ UnQual n
183+ expr (FunRef n) = return $ Var $ UnQual n
215-- | Generate a ExportSpec for a given function item.
185-- | Generate a ExportSpec for a given function item.
216exportFun :: FunRef t -> ExportSpec
186exportFun :: FunRef t -> ExportSpec
217−#if MIN_VERSION_haskell_src_exts(1,16,0) && !MIN_VERSION_haskell_src_exts(1,17,0)
218−exportFun (FunRef name) = EVar NoNamespace (UnQual name)
220exportFun (FunRef name) = EVar (UnQual name)
187exportFun (FunRef name) = EVar (UnQual name)
223-- | Add a declaration to the module. Return a reference to it that can be used to either apply the function to some values or export it.
189-- | Add a declaration to the module. Return a reference to it that can be used to either apply the function to some values or export it.
224addDecl :: Name -> ExpG t -> ModuleM (FunRef t)
190addDecl :: Name -> ExpG t -> ModuleM (FunRef t)
225addDecl name e = ModuleM $ do
191addDecl name e = ModuleM $ do
226− let (body, mods) = runGenerate e
192+ let (body, mods) = runExpM e
227−#if MIN_VERSION_haskell_src_exts(1,17,0)
228− tell (mods, [FunBind [Match noLoc name [] Nothing (UnGuardedRhs $ runExpression body) Nothing]])
230− tell (mods, [FunBind [Match noLoc name [] Nothing (UnGuardedRhs $ runExpression body) $ BDecls []]])
193+ tell (mods, [FunBind [Match noLoc name [] Nothing (UnGuardedRhs body) $ BDecls []]])
232 return $ FunRef name
194 return $ FunRef name
234-- | Extract the Module from a module generator.
196-- | Extract the Module from a module generator.
235runModuleM :: ModuleG -> String -> Module
197runModuleM :: ModuleG -> String -> Module
236runModuleM (ModuleM act) name =
198runModuleM (ModuleM act) name =
237−#if MIN_VERSION_haskell_src_exts(1,16,0)
238− Module noLoc (ModuleName name) [] Nothing export (map (\md -> ImportDecl noLoc md True False False Nothing Nothing Nothing) $ S.toList imps) decls
240 Module noLoc (ModuleName name) [] Nothing export (map (\md -> ImportDecl noLoc md True False Nothing Nothing Nothing) $ S.toList imps) decls
199 Module noLoc (ModuleName name) [] Nothing export (map (\md -> ImportDecl noLoc md True False Nothing Nothing Nothing) $ S.toList imps) decls
242 where (export, (imps, decls)) = runWriter act
200 where (export, (imps, decls)) = runWriter act
244-- | Generate the source code for a module.
202-- | Generate the source code for a module.