git.iko.soy/haskell-generate
on 14fa497 help sign in
.travis.yml+3−5
since splitsnapshots
unifiedsplit
@@ -1,9 +1,7 @@
1env:
1env:
2 - GHCVER=7.4.2 CABALVER=1.16
2 - GHCVER=7.4.2 CABALVER=1.16
3 - GHCVER=7.6.3 CABALVER=1.18
3 - GHCVER=7.6.3 CABALVER=1.18
4− - GHCVER=7.8.3 CABALVER=1.20
5− - GHCVER=7.10.2 CABALVER=1.22
6− - GHCVER=head CABALVER=1.22
4+ - GHCVER=head CABALVER=1.18
7
5
8before_install:
6before_install:
9 - sudo add-apt-repository -y ppa:hvr/ghc
7 - sudo add-apt-repository -y ppa:hvr/ghc
@@ -22,5 +20,5 @@ script:
22
20
23matrix:
21matrix:
24 allow_failures:
22 allow_failures:
25− - env: GHCVER=head CABALVER=1.22
23+ - env: GHCVER=head CABALVER=1.18
26− fast_finish: true
24+ fast_finish: true
LICENSE+1−1
@@ -1,4 +1,4 @@
1−Copyright 2013-2015 Benno Fünfstück
1+Copyright 2013 Benno Fünfstück
2
2
3All rights reserved.
3All rights reserved.
4
4
README.md+1−99
@@ -1,104 +1,6 @@
1haskell-generate
1haskell-generate
2−================
2+====================
3
3
4[![Build Status](https://secure.travis-ci.org/bennofs/haskell-generate.png?branch=master)](http://travis-ci.org/bennofs/haskell-generate)
4[![Build Status](https://secure.travis-ci.org/bennofs/haskell-generate.png?branch=master)](http://travis-ci.org/bennofs/haskell-generate)
5
5
6−## Introduction
7
6
8−If you want to generate haskell source code, you could build up haskell-src-exts AST and then pretty print it. But that's easy to screw up, because haskell-src-exts doesn't include tag it's AST with a type. This library aims to fill the gap, adding type information to haskell-src-exts expressions and also managing imports for you.
9−
10−## Getting started
11−
12−First, you need to import this library:
13−
14−```haskell
15−import Language.Haskell.Generate
16−```
17−
18−This module reexports `Language.Haskell.Exts.Syntax`, because haskell-generate builds on top of that.
19−
20−There are two main types in haskell-generate. The first is the monad `Generate` and the type alias `ExpG`. The `Generate` monad is used to track required imports. It also allows to generate unique names. `ExpG t` is just an action in the `Generate` monad that returns an expression of type `t`.
21−
22−How do you build expressions? There is a number of predefined expressions for the functions in the
23−Prelude. This allows you to just use these and combine them to new expressions. For example, let's define a expression that reads a file called "names":
24−
25−```haskell
26−readNamesFile' :: ExpG (IO String)
27−readNamesFile' = readFile' <>$ expr "names"
28−```
29−
30−Here we use `(<>$)` to apply the `readFile'` expression to the string `names`. `readFile'` is one of the expressions already provided by haskell-generate. All expressions that are provided by haskell-generate end with an apostrophe. You can find more of them in the module `Language.Haskell.Generate.PreludeDef`. The `expr` function is used to lift the string `names` into an expression of type `ExpG String`.
31−
32−Now that we have an expression, we need to bind it to a name in a module. For this job, we use another monad, the `ModuleM` monad. It allows you to bind expressions to names and then generate
33−a module with those names.
34−
35−Here's how we generate our module:
36−
37−```haskell
38−myModule :: ModuleG
39−myModule = do
40− d <- addDecl (Ident "main") $ applyE2 bind' readNamesFile' putStrLn'
41− return $ Just [exportFun d]
42−```
43−
44−`ModuleG` is again a type synonym for an action in the `ModuleM` monad. It must either return Nothing (which omits the export list) or an export list. In this case, we export the "main" function, which we previously defined using `addDecl`.
45−
46−The only thing left to do is to generate the actual source code for the module, for which we
47−use the `generateModule` function, which takes the module name as an argument:
48−
49−```haskell
50−main :: IO ()
51−main = putStrLn $ generateModule myModule "Main"
52−```
53−
54−If you run the program, you'll get the following output:
55−
56−```haskell
57−module Main (main) where
58−import qualified GHC.Base
59−import qualified System.IO
60−main
61− = (GHC.Base.>>=) (System.IO.readFile ['n', 'a', 'm', 'e', 's'])
62− System.IO.putStrLn
63−```
64−
65−If you run this code, you'll get the contents of the "names" file. The code is a bit ugly and uses
66−qualified imports to avoid name clashes, but it works.
67−
68−## Importing functions
69−
70−Until now, we've only used the predefined expressions from `Language.Haskell.Generate.PreludeDef`, but often you'll want to use definitions from other modules that you might want to use.
71−
72−You can do that using the `useValue` from haskell-generate. Let's look at the type of `useValue`:
73−
74−```haskell
75−useValue :: String -> Name -> ExpG t
76−```
77−
78−`useValue` takes a module name in which the function is defined and the name of the function. It returns an expression of any type you which. This function is unsafe, because it cannot check that the returned type is actually the type of the function. That's why you usually given `useValue` an explicit type signature.
79−
80−For example, suppose we want to use the function `permutations` from Data.List. We write the following definition for it:
81−
82−```haskell
83−permutations' :: ExpG ([a] -> [[a]]) -- Here we given an explicit type for permutations'. This is not checked, so make sure it's actually right!
84−permutations' = useValue "Data.List" (Ident "permutations") -- "permutations" is an identifier, not a symbol, so we use the "Ident" constructor.
85−```
86−
87−## Using TH to automagically import functions
88−
89−If the function you want to import is already available at compile time, you can use the template haskell code from `Language.Haskell.Generate.TH` to generate the expression definitions. This is the approach we use for the Prelude, as an example.
90−
91−Using the example from the previous section, we could also import the `permutations` function like this:
92−
93−```haskell
94−-- at the top of the file:
95−{-# LANGUAGE TemplateHaskell #-} -- Enable template haskell
96−import Data.List (permutations) -- The function needs to be available at compile time
97−
98−declareFunction 'permutations -- This generates the same code as above, but is more type-safe because you don't have to specify the type yourself.
99−```
100−
101−
102−## Contributing
103−
104−If you have an idea, a question or a bug report, open an issue on github. You can also find me on freenode in the #haskell channel, my nick is bennofs.
haskell-generate.cabal+7−11
@@ -1,5 +1,5 @@
1name: haskell-generate
1name: haskell-generate
2−version: 0.2.4
2+version: 0.1
3license: BSD3
3license: BSD3
4category: Code Generation, Language
4category: Code Generation, Language
5cabal-version: >= 1.10
5cabal-version: >= 1.10
@@ -9,13 +9,9 @@ maintainer: Benno Fünfstück <benno.fuenfstueck@gmail.com>
9stability: experimental
9stability: experimental
10homepage: http://github.com/bennofs/haskell-generate/
10homepage: http://github.com/bennofs/haskell-generate/
11bug-reports: http://github.com/bennofs/haskell-generate/issues
11bug-reports: http://github.com/bennofs/haskell-generate/issues
12−copyright: Copyright (C) 2013-2015 Benno Fünfstück
12+copyright: Copyright (C) 2013 Benno Fünfstück
13−synopsis: Typesafe generation of haskell source code
13+synopsis: haskell-generate
14−description:
14+description: haskell-generate
15− This library provides an interface to generate haskell source code, verifying at compile time
16− that the resulting code typechecks.
17− See <https://github.com/bennofs/haskell-generate haskell-generate> for an
18− introduction explaining how to use the library.
19build-type: Custom
15build-type: Custom
20
16
21extra-source-files:
17extra-source-files:
@@ -41,11 +37,9 @@ library
41 , template-haskell
37 , template-haskell
42 exposed-modules:
38 exposed-modules:
43 Language.Haskell.Generate
39 Language.Haskell.Generate
44− Language.Haskell.Generate.Monad
40+ Language.Haskell.Generate.Base
45− Language.Haskell.Generate.Expression
46 Language.Haskell.Generate.TH
41 Language.Haskell.Generate.TH
47 Language.Haskell.Generate.PreludeDef
42 Language.Haskell.Generate.PreludeDef
48− other-extensions: TemplateHaskell
49
43
50test-suite doctests
44test-suite doctests
51 type: exitcode-stdio-1.0
45 type: exitcode-stdio-1.0
@@ -57,4 +51,6 @@ test-suite doctests
57 , doctest >= 0.9.1
51 , doctest >= 0.9.1
58 , filepath
52 , filepath
59 ghc-options: -Wall -threaded
53 ghc-options: -Wall -threaded
54+ if impl(ghc<7.6.1)
55+ ghc-options: -Werror
60 hs-source-dirs: tests
56 hs-source-dirs: tests
src/Language/Haskell/Generate.hs+1−2
@@ -2,6 +2,5 @@ module Language.Haskell.Generate
2 ( module X
2 ( module X
3 ) where
3 ) where
4
4
5−import Language.Haskell.Exts.Syntax as X
5+import Language.Haskell.Generate.Base as X
6−import Language.Haskell.Generate.Monad as X
7import Language.Haskell.Generate.PreludeDef as X
6import Language.Haskell.Generate.PreludeDef as X
src/Language/Haskell/Generate/Monad.hs → src/Language/Haskell/Generate/Base.hsrenamed+51−93
@@ -3,11 +3,9 @@
3{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE UndecidableInstances #-}
4{-# LANGUAGE UndecidableInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE CPP #-}
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
10− , returnE
11 , useValue, useCon, useVar
9 , useValue, useCon, useVar
12 , caseE
10 , caseE
13 , applyE, applyE2, applyE3, applyE4, applyE5, applyE6
11 , applyE, applyE2, applyE3, applyE4, applyE5, applyE6
@@ -21,7 +19,6 @@ module Language.Haskell.Generate.Monad
21 , addDecl
19 , addDecl
22 , runModuleM
20 , runModuleM
23 , generateModule
21 , generateModule
24− , generateExp
25 )
22 )
26 where
23 where
27
24
@@ -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
38−
39−import Prelude
40
34
41--------------------------------------------------------------------------------
35--------------------------------------------------------------------------------
42-- Generate expressions
36-- Generate expressions
43
37
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)
47−
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
51
42
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
54
46
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
58
50
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
62
53
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
71−#else
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
73−#endif
74− return $ Expression $ Case (runExpression v') alt'
59+ return $ Case v' alt'
75
60
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 "+"
83--
68--
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
88
73
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
94
79
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
98
83
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
105
90
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:
112−--
113−-- >>> putStrLn $ generateExp $ expr "I'm a string!"
114−-- ['I', '\'', 'm', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', '!']
115−--
116class GenExp t where
96class GenExp t where
117 type GenExpType t :: *
97 type GenExpType t :: *
118
98
@@ -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
125
105
126−instance GenExp (Expression t) where
127− type GenExpType (Expression t) = t
128− expr = return
129−
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
133
109
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
137
113
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
141
117
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)
145
121
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
152
128
153--------------------------------------------------------------------------------
129--------------------------------------------------------------------------------
154-- Apply functions
130-- Apply functions
155
131
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
161
136
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 <>$
167
142
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
173
147
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
179
152
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
185
157
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
191
162
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
197
167
198--------------------------------------------------------------------------------
168--------------------------------------------------------------------------------
199-- Generate modules
169-- Generate modules
@@ -210,35 +180,23 @@ data FunRef t = FunRef Name
210
180
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
214
184
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)
219−#else
220exportFun (FunRef name) = EVar (UnQual name)
187exportFun (FunRef name) = EVar (UnQual name)
221−#endif
222
188
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]])
229−#else
230− tell (mods, [FunBind [Match noLoc name [] Nothing (UnGuardedRhs $ runExpression body) $ BDecls []]])
193+ tell (mods, [FunBind [Match noLoc name [] Nothing (UnGuardedRhs body) $ BDecls []]])
231−#endif
232 return $ FunRef name
194 return $ FunRef name
233
195
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
239−#else
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
241−#endif
242 where (export, (imps, decls)) = runWriter act
200 where (export, (imps, decls)) = runWriter act
243
201
244-- | Generate the source code for a module.
202-- | Generate the source code for a module.
src/Language/Haskell/Generate/Expression.hsdeleted−12
@@ -1,12 +0,0 @@
1−module Language.Haskell.Generate.Expression
2− ( Expression(..)
3− , app
4− ) where
5−
6−import Language.Haskell.Exts.Syntax
7−
8−newtype Expression t = Expression { runExpression :: Exp }
9−
10−app :: Expression (a -> b) -> Expression a -> Expression b
11−app (Expression a) (Expression b) = Expression $ App a b
12−
src/Language/Haskell/Generate/PreludeDef.hs+8−9
@@ -6,7 +6,7 @@
6module Language.Haskell.Generate.PreludeDef where
6module Language.Haskell.Generate.PreludeDef where
7
7
8import Language.Haskell.Exts.Syntax
8import Language.Haskell.Exts.Syntax
9−import Language.Haskell.Generate.Monad
9+import Language.Haskell.Generate.Base
10import Language.Haskell.Generate.TH
10import Language.Haskell.Generate.TH
11
11
12--------------------------------------------------------------------------------
12--------------------------------------------------------------------------------
@@ -60,29 +60,28 @@ fmap concat $ mapM declareNamedSymbol
60 , ('(++), "append'")
60 , ('(++), "append'")
61 , ('(!!), "index'")
61 , ('(!!), "index'")
62 , ('(==), "equal'")
62 , ('(==), "equal'")
63− , ('(/=), "notequal'")
64 ]
63 ]
65
64
66(<>.) :: ExpG (b -> c) -> ExpG (a -> b) -> ExpG (a -> c)
65(<>.) :: ExpG (b -> c) -> ExpG (a -> b) -> ExpG (a -> c)
67(<>.) a b = dot' <>$ a <>$ b
66(<>.) a b = dot' <>$ a <>$ b
68
67
69tuple0 :: ExpG ()
68tuple0 :: ExpG ()
70−tuple0 = returnE $ Var $ Special UnitCon
69+tuple0 = return $ Var $ Special UnitCon
71
70
72tuple2 :: ExpG (a -> b -> (a,b))
71tuple2 :: ExpG (a -> b -> (a,b))
73−tuple2 = returnE $ Var $ Special $ TupleCon Boxed 2
72+tuple2 = return $ Var $ Special $ TupleCon Boxed 2
74
73
75tuple3 :: ExpG (a -> b -> c -> (a,b,c))
74tuple3 :: ExpG (a -> b -> c -> (a,b,c))
76−tuple3 = returnE $ Var $ Special $ TupleCon Boxed 3
75+tuple3 = return $ Var $ Special $ TupleCon Boxed 3
77
76
78tuple4 :: ExpG (a -> b -> c -> d -> (a,b,c,d))
77tuple4 :: ExpG (a -> b -> c -> d -> (a,b,c,d))
79−tuple4 = returnE $ Var $ Special $ TupleCon Boxed 4
78+tuple4 = return $ Var $ Special $ TupleCon Boxed 4
80
79
81tuple5 :: ExpG (a -> b -> c -> d -> (a,b,c,d,e))
80tuple5 :: ExpG (a -> b -> c -> d -> (a,b,c,d,e))
82−tuple5 = returnE $ Var $ Special $ TupleCon Boxed 5
81+tuple5 = return $ Var $ Special $ TupleCon Boxed 5
83
82
84cons :: ExpG (a -> [a] -> [a])
83cons :: ExpG (a -> [a] -> [a])
85−cons = returnE $ Var $ Special Cons
84+cons = return $ Var $ Special Cons
86
85
87instance Num t => Num (ExpG t) where
86instance Num t => Num (ExpG t) where
88 a + b = add' <>$ a <>$ b
87 a + b = add' <>$ a <>$ b
@@ -90,6 +89,6 @@ instance Num t => Num (ExpG t) where
90 a * b = mult' <>$ a <>$ b
89 a * b = mult' <>$ a <>$ b
91 negate a = negate' <>$ a
90 negate a = negate' <>$ a
92 abs a = abs' <>$ a
91 abs a = abs' <>$ a
93− fromInteger a = returnE $ Lit $ Int a
92+ fromInteger a = return $ Lit $ Int a
94 signum a = signum' <>$ a
93 signum a = signum' <>$ a
95
94
src/Language/Haskell/Generate/TH.hs+2−6
@@ -10,7 +10,7 @@ module Language.Haskell.Generate.TH
10
10
11import Data.Char
11import Data.Char
12import Language.Haskell.Exts.Syntax hiding (Name)
12import Language.Haskell.Exts.Syntax hiding (Name)
13−import Language.Haskell.Generate.Monad hiding (Name)
13+import Language.Haskell.Generate.Base hiding (Name)
14import Language.Haskell.TH
14import Language.Haskell.TH
15import Language.Haskell.TH.Syntax
15import Language.Haskell.TH.Syntax
16
16
@@ -36,13 +36,9 @@ declareNamedThing (thing, name, thingClass) = do
36 [| useValue $(lift md) $ $(conE thingClass) $(lift $ nameBase thing) |]
36 [| useValue $(lift md) $ $(conE thingClass) $(lift $ nameBase thing) |]
37 ]
37 ]
38
38
39− where overQuantifiedType f (ForallT bnds ctx t) = ForallT (map removeKind bnds) ctx $ overQuantifiedType f t
39+ where overQuantifiedType f (ForallT bnds ctx t) = ForallT bnds ctx $ overQuantifiedType f t
40 overQuantifiedType f x = f x
40 overQuantifiedType f x = f x
41
41
42− removeKind :: TyVarBndr -> TyVarBndr
43− removeKind (KindedTV n _) = PlainTV n
44− removeKind x = x
45−
46-- | Declare a symbol, using the given name for the definition.
42-- | Declare a symbol, using the given name for the definition.
47declareNamedSymbol :: (Name, String) -> DecsQ
43declareNamedSymbol :: (Name, String) -> DecsQ
48declareNamedSymbol (func, name) = declareNamedThing (func, name, 'Symbol)
44declareNamedSymbol (func, name) = declareNamedThing (func, name, 'Symbol)
tests/doctests.hsc+2−1
@@ -20,17 +20,18 @@ import Data.List
20import System.Directory
20import System.Directory
21import System.FilePath
21import System.FilePath
22import Test.DocTest
22import Test.DocTest
23−import Prelude
24
23
25##ifdef mingw32_HOST_ARCH
24##ifdef mingw32_HOST_ARCH
26##ifdef i386_HOST_ARCH
25##ifdef i386_HOST_ARCH
27##define USE_CP
26##define USE_CP
27+import Control.Applicative
28import Control.Exception
28import Control.Exception
29import Foreign.C.Types
29import Foreign.C.Types
30foreign import stdcall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool
30foreign import stdcall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool
31foreign import stdcall "windows.h GetConsoleCP" c_GetConsoleCP :: IO CUInt
31foreign import stdcall "windows.h GetConsoleCP" c_GetConsoleCP :: IO CUInt
32##elif defined(x86_64_HOST_ARCH)
32##elif defined(x86_64_HOST_ARCH)
33##define USE_CP
33##define USE_CP
34+import Control.Applicative
34import Control.Exception
35import Control.Exception
35import Foreign.C.Types
36import Foreign.C.Types
36foreign import ccall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool
37foreign import ccall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool