@@ -3,9 +3,10 @@
3{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE UndecidableInstances #-}
4{-# LANGUAGE UndecidableInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
6−module Language.Haskell.Generate.Base
6+module Language.Haskell.Generate.Monad
7− ( ExpM(..), ExpG, ExpType
7+ ( Generate(..), ExpG
8− , runExpM, newName
8+ , runGenerate, newName
9 , useValue, useCon, useVar
10 , useValue, useCon, useVar
11 , applyE, applyE2, applyE3, applyE4, applyE5, applyE6
12 , applyE, applyE2, applyE3, applyE4, applyE5, applyE6
@@ -19,6 +20,7 @@ module Language.Haskell.Generate.Base
20 , runModuleM
21 , runModuleM
21 , generateModule
22 , generateModule
@@ -31,32 +33,30 @@ import qualified Data.Set as S
31import Language.Haskell.Exts.Pretty
33import Language.Haskell.Exts.Pretty
32import Language.Haskell.Exts.SrcLoc
34import Language.Haskell.Exts.SrcLoc
33import Language.Haskell.Exts.Syntax
35import Language.Haskell.Exts.Syntax
36+import Language.Haskell.Generate.Expression
35--------------------------------------------------------------------------------
38--------------------------------------------------------------------------------
36-- Generate expressions
39-- Generate expressions
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
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.
41−newtype ExpM t a = ExpM { unExpM :: StateT Integer (Writer (S.Set ModuleName)) a } deriving (Functor, Applicative, Monad)
41+newtype Generate a = Generate { unGenerate :: StateT Integer (Writer (S.Set ModuleName)) a } deriving (Functor, Applicative, Monad)
43−-- | The ExpG type is a ExpM computation that returns an expression. Usually, this is the end result of a function generating
43+runGenerate :: Generate a -> (a, S.Set ModuleName)
44−-- a haskell expression
44+runGenerate (Generate a) = runWriter $ evalStateT a 0
45−type ExpG t = ExpM t Exp
47−-- | Evaluate a ExpM action, returning the needed modules and the value.
46+type ExpG t = Generate (Expression t)
48−runExpM :: ExpM t a -> (a, S.Set ModuleName)
49−runExpM (ExpM expt) = runWriter $ evalStateT expt 0
51−unsafeCoerceE :: ExpM t a -> ExpM t' a
48+returnE :: Exp -> ExpG t
52−unsafeCoerceE (ExpM x) = ExpM x
49+returnE = return . Expression
51+generateExp :: ExpG t -> String
52+generateExp = prettyPrint . runExpression . fst . runGenerate
54-- | Generate a case expression.
54-- | Generate a case expression.
55caseE :: ExpG x -> [(Pat, ExpG t)] -> ExpG t
55caseE :: ExpG x -> [(Pat, ExpG t)] -> ExpG t
56caseE v alt = do
56caseE v alt = do
57− v' <- unsafeCoerceE v
57+ v' <- v
58− alt' <- mapM (\(p,a) -> fmap (\a' -> Alt noLoc p (UnGuardedAlt a') (BDecls [])) a) alt
58+ alt' <- mapM (\(p,a) -> fmap (\a' -> Alt noLoc p (UnGuardedAlt $ runExpression a') (BDecls [])) a) alt
59− return $ Case v' alt'
59+ return $ Expression $ Case (runExpression v') alt'
61-- | 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,
62-- 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.
@@ -67,31 +67,27 @@ caseE v alt = do
67-- > addInt = useValue "Prelude" $ Symbol "+"
67-- > addInt = useValue "Prelude" $ Symbol "+"
69useValue :: String -> Name -> ExpG a
69useValue :: String -> Name -> ExpG a
70−useValue md name = ExpM $ do
70+useValue md name = Generate $ do
71 lift $ tell $ S.singleton $ ModuleName md
71 lift $ tell $ S.singleton $ ModuleName md
72− return $ Var $ Qual (ModuleName md) name
72+ return $ Expression $ Var $ Qual (ModuleName md) name
74-- | 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.
75−useCon :: String -> Name -> ExpM t QName
75+useCon :: String -> Name -> Generate QName
76−useCon md name = ExpM $ do
76+useCon md name = Generate $ do
77 lift $ tell $ S.singleton $ ModuleName md
77 lift $ tell $ S.singleton $ ModuleName md
78 return $ Qual (ModuleName md) name
78 return $ Qual (ModuleName md) name
80-- | Use the value of a variable with the given name.
80-- | Use the value of a variable with the given name.
81useVar :: Name -> ExpG t
81useVar :: Name -> ExpG t
82−useVar name = return $ Var $ UnQual name
82+useVar name = return $ Expression $ Var $ UnQual name
84-- | 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
85-- 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.
86−newName :: String -> ExpM t Name
86+newName :: String -> Generate Name
87−newName pref = ExpM $ do
87+newName pref = Generate $ do
88 i <- get <* modify succ
88 i <- get <* modify succ
89 return $ Ident $ pref ++ show i
89 return $ Ident $ pref ++ show i
91−-- | This type family can be used to get the type associated with some expression.
92−type family ExpType a :: *
93−type instance ExpType (ExpM t a) = t
95-- | Generate a expression from a haskell value.
91-- | Generate a expression from a haskell value.
96class GenExp t where
92class GenExp t where
97 type GenExpType t :: *
93 type GenExpType t :: *
@@ -103,36 +99,43 @@ instance GenExp (ExpG a) where
103 type GenExpType (ExpG a) = a
99 type GenExpType (ExpG a) = a
104 expr = id
100 expr = id
102+instance GenExp (Expression t) where
103+ type GenExpType (Expression t) = t
106instance GenExp Char where
106instance GenExp Char where
107 type GenExpType Char = Char
107 type GenExpType Char = Char
108− expr = return . Lit . Char
108+ expr = return . Expression . Lit . Char
110instance GenExp Integer where
110instance GenExp Integer where
111 type GenExpType Integer = Integer
111 type GenExpType Integer = Integer
112− expr = return . Lit . Int
112+ expr = return . Expression . Lit . Int
114instance GenExp Rational where
114instance GenExp Rational where
115 type GenExpType Rational = Rational
115 type GenExpType Rational = Rational
116− expr = return . Lit . Frac
116+ expr = return . Expression . Lit . Frac
118instance GenExp a => GenExp [a] where
118instance GenExp a => GenExp [a] where
119 type GenExpType [a] = [GenExpType a]
119 type GenExpType [a] = [GenExpType a]
120− expr = ExpM . fmap List . mapM (unExpM . expr)
120+ expr = Generate . fmap (Expression . List . map runExpression) . mapM (unGenerate . expr)
122instance GenExp x => GenExp (ExpG a -> x) where
122instance GenExp x => GenExp (ExpG a -> x) where
123 type GenExpType (ExpG a -> x) = a -> GenExpType x
123 type GenExpType (ExpG a -> x) = a -> GenExpType x
124 expr f = do
124 expr f = do
125 pvarName <- newName "pvar_"
125 pvarName <- newName "pvar_"
126− body <- unsafeCoerceE $ expr $ f $ return $ Var $ UnQual pvarName
126+ body <- expr $ f $ return $ Expression $ Var $ UnQual pvarName
127− return $ Lambda noLoc [PVar pvarName] body
127+ return $ Expression $ Lambda noLoc [PVar pvarName] $ runExpression body
129--------------------------------------------------------------------------------
129--------------------------------------------------------------------------------
130-- Apply functions
130-- Apply functions
132-- | Apply a function in a haskell expression to a value.
133-- | Apply a function in a haskell expression to a value.
133applyE :: ExpG (a -> b) -> ExpG a -> ExpG b
134applyE :: ExpG (a -> b) -> ExpG a -> ExpG b
134−applyE a b = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b]
135+applyE a b = wrap $ liftM (foldl1 App) $ sequence [unwrap a, unwrap b]
135− where ce = unsafeCoerceE
136+ where wrap = fmap Expression
137+ unwrap = fmap runExpression
137-- | Operator for 'applyE'.
140-- | Operator for 'applyE'.
138(<>$) :: ExpG (a -> b) -> ExpG a -> ExpG b
141(<>$) :: ExpG (a -> b) -> ExpG a -> ExpG b
@@ -142,28 +145,33 @@ infixl 1 <>$
143-- | ApplyE for 2 arguments
146-- | ApplyE for 2 arguments
144applyE2 :: ExpG (a -> b -> c) -> ExpG a -> ExpG b -> ExpG c
147applyE2 :: ExpG (a -> b -> c) -> ExpG a -> ExpG b -> ExpG c
145−applyE2 a b c = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c]
148+applyE2 a b c = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c]
146− where ce = unsafeCoerceE
149+ where wrap = fmap Expression
150+ unwrap = fmap runExpression
148-- | Apply a function to 3 arguments
152-- | Apply a function to 3 arguments
149applyE3 :: ExpG (a -> b -> c -> d) -> ExpG a -> ExpG b -> ExpG c -> ExpG d
153applyE3 :: ExpG (a -> b -> c -> d) -> ExpG a -> ExpG b -> ExpG c -> ExpG d
150−applyE3 a b c d = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c,ce d]
154+applyE3 a b c d = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c,unwrap d]
151− where ce = unsafeCoerceE
155+ where wrap = fmap Expression
156+ unwrap = fmap runExpression
153-- | Apply a function to 4 arguments
158-- | Apply a function to 4 arguments
154applyE4 :: ExpG (a -> b -> c -> d -> e) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e
159applyE4 :: ExpG (a -> b -> c -> d -> e) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e
155−applyE4 a b c d e = unsafeCoerceE $ liftM (foldl1 App) $ sequence [ce a,ce b,ce c,ce d,ce e]
160+applyE4 a b c d e = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c,unwrap d,unwrap e]
156− where ce = unsafeCoerceE
161+ where wrap = fmap Expression
162+ unwrap = fmap runExpression
158-- | Apply a function to 5 arguments
164-- | Apply a function to 5 arguments
159applyE5 :: ExpG (a -> b -> c -> d -> e -> f) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG f
165applyE5 :: ExpG (a -> b -> c -> d -> e -> f) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG 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]
166+applyE5 a b c d e f = wrap $ liftM (foldl1 App) $ sequence [unwrap a,unwrap b,unwrap c,unwrap d,unwrap e,unwrap f]
161− where ce = unsafeCoerceE
167+ where wrap = fmap Expression
168+ unwrap = fmap runExpression
163-- | Apply a function to 6 arguments
170-- | Apply a function to 6 arguments
164applyE6 :: ExpG (a -> b -> c -> d -> e -> f -> g) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG f -> ExpG g
171applyE6 :: ExpG (a -> b -> c -> d -> e -> f -> g) -> ExpG a -> ExpG b -> ExpG c -> ExpG d -> ExpG e -> ExpG f -> ExpG 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]
172+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]
166− where ce = unsafeCoerceE
173+ where wrap = fmap Expression
174+ unwrap = fmap runExpression
168--------------------------------------------------------------------------------
176--------------------------------------------------------------------------------
169-- Generate modules
177-- Generate modules
@@ -180,7 +188,7 @@ data FunRef t = FunRef Name
181instance GenExp (FunRef t) where
189instance GenExp (FunRef t) where
182 type GenExpType (FunRef t) = t
190 type GenExpType (FunRef t) = t
183− expr (FunRef n) = return $ Var $ UnQual n
191+ expr (FunRef n) = return $ Expression $ Var $ UnQual n
185-- | Generate a ExportSpec for a given function item.
193-- | Generate a ExportSpec for a given function item.
186exportFun :: FunRef t -> ExportSpec
194exportFun :: FunRef t -> ExportSpec
@@ -189,8 +197,8 @@ exportFun (FunRef name) = EVar (UnQual name)
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.
197-- | 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.
190addDecl :: Name -> ExpG t -> ModuleM (FunRef t)
198addDecl :: Name -> ExpG t -> ModuleM (FunRef t)
191addDecl name e = ModuleM $ do
199addDecl name e = ModuleM $ do
192− let (body, mods) = runExpM e
200+ let (body, mods) = runGenerate e
193− tell (mods, [FunBind [Match noLoc name [] Nothing (UnGuardedRhs body) $ BDecls []]])
201+ tell (mods, [FunBind [Match noLoc name [] Nothing (UnGuardedRhs $ runExpression body) $ BDecls []]])
194 return $ FunRef name
202 return $ FunRef name
196-- | Extract the Module from a module generator.
204-- | Extract the Module from a module generator.