packages feed

antiquoter (empty) → 0.1.0.0

raw patch · 7 files changed

+370/−0 lines, 7 filesdep +basedep +sybdep +template-haskellsetup-changed

Dependencies added: base, syb, template-haskell

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Lars Corbijn++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Lars Corbijn nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ antiquoter.cabal view
@@ -0,0 +1,51 @@+name:           antiquoter+version:        0.1.0.0+synopsis:       Combinator library for quasi- and anti-quoting.+description:    A combinator library to improve the building of anti-quoters.+                Especially aimed at making user extensible antiquoters and+                removing copy-and-paste programming from their definition.+                .+                The modules are+                .+                * "Language.Haskell.AntiQuoter.Base" basic type aliases for+                  building antiquoters.+                .+                * "Language.Haskell.AntiQuoter.ExpPat" making antiquoters which+                  can result in expressions as well as patters. Therefore only+                  one antiquoter has to be defined in stead of two.+                .+                * "Language.Haskell.AntiQuoter.Combinators" more useful+                  combinators to use with the functions from+                  "Language.Haskell.AntiQuoter.ExpPat".+license:        BSD3+license-file:   LICENSE++author:         Lars Corbijn+maintainer:     aspergesoepje@gmail.com+copyright:      Lars Corbijn++category:       Template Haskell+build-type:     Simple++cabal-version:  >=1.8+tested-with:    GHC == 7.4.1, GHC == 7.6.2++library+  exposed-modules:+    Language.Haskell.AntiQuoter+    Language.Haskell.AntiQuoter.Base+    Language.Haskell.AntiQuoter.Combinators+    Language.Haskell.AntiQuoter.ExpPat+  other-modules:+  build-depends:+    base >=4 && <5,+    -- This seems to be the first version with Language.Haskell.TH.Quote.+    template-haskell >= 2.3,+    -- No apparent restrictions.+    syb+  hs-source-dirs: src+  ghc-options: -Wall++source-repository head+    type:       git+    location:   https://github.com/Laar/antiquoter
+ src/Language/Haskell/AntiQuoter.hs view
@@ -0,0 +1,10 @@+module Language.Haskell.AntiQuoter (++    module Language.Haskell.AntiQuoter.Base,+    module Language.Haskell.AntiQuoter.Combinators,+    module Language.Haskell.AntiQuoter.ExpPat,+) where++import Language.Haskell.AntiQuoter.Base hiding (WrappedAQResult(..))+import Language.Haskell.AntiQuoter.Combinators+import Language.Haskell.AntiQuoter.ExpPat hiding (EPV(..))
+ src/Language/Haskell/AntiQuoter/Base.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes #-}+-- | Base module for `AntiQuoter`s, which transform parsed syntax into+-- template-haskell syntax to make `QuasiQuoter`s.+module Language.Haskell.AntiQuoter.Base(+    -- * AntiQuoters+    AntiQuoterPass,+    AntiQuoter,+    mkQuasiQuoter,+    AQResult,+    fromPass, (<<>), (<>>),+    -- ** Convenience reexport+    -- | WARNING: when combining AntiQuoter(Pass)es using `extQ` only the+    -- WARNING: when combining AntiQuoter(Pass)es using `extQ` only the+    -- last (rightmost) pass will be used for any source type. The `<<>`+    -- and `<>>` don't suffer from this problem.+    extQ,+    -- ** Internals+    WrappedAQResult(..),+) where++import Control.Monad+import Data.Generics+import Language.Haskell.TH+import Language.Haskell.TH.Quote++infixl 1 <<>+infixr 2 <>>++-- | Result of an `AntiQuoterPass`+type AQResult q = Maybe (Q q)++-- | Wrapper for `AQResult`, needed for the typechecker.+newtype WrappedAQResult q = AQRW { unAQRW :: AQResult q }++-- | A single quotation pass possibly transforming an @e@ into a @q@.+type AntiQuoterPass e q = e -> Maybe (Q q)++-- | An `AntiQuoter` is the combination of several `AntiQuoterPass`es, trying+-- each of them in order until one passes.+type AntiQuoter q = forall e. Typeable e => AntiQuoterPass e q++-- | Create an `AntiQuoter` from an single pass.+fromPass :: Typeable e => AntiQuoterPass e q -> AntiQuoter q+fromPass aqp = mkQ Nothing aqp++-- | Combine an existing `AntiQuoter` with an extra pass, where the extra pass+-- is tried if the current quoter fails.+(<<>) :: Typeable e => AntiQuoter q -> AntiQuoterPass e q -> AntiQuoter q+aq <<> aqp = \e -> aq e `mplus` fromPass aqp e+-- | Like `<>>` with flipped arguments, but also trying the extra pass before+-- the quoter.+(<>>) :: Typeable e => AntiQuoterPass e q -> AntiQuoter q -> AntiQuoter q+aqp <>> aq = \e -> fromPass aqp e `mplus` aq e++-- | Create an QuasiQuoter for expressions and patterns from a parser and two+-- antiquoters.+mkQuasiQuoter :: Data a+    => (String -> Q a)+    -> AntiQuoter Exp+    -> AntiQuoter Pat+    -> QuasiQuoter+mkQuasiQuoter parse aqExp aqPat+    = QuasiQuoter+    { quoteExp = parse >=> dataToExpQ aqExp+    , quotePat = parse >=> dataToPatQ aqPat+-- To prevent warnings+#if MIN_VERSION_template_haskell(2,5,0)+    , quoteType = error $ "Language.Haskell.Antiquoter: can't handle types"+    , quoteDec  = error $ "Language.Haskell.Antiquoter: can't handle decls"+#endif+    }
+ src/Language/Haskell/AntiQuoter/Combinators.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE RankNTypes #-}+-- | Several combinators for `AntiQuoters`.+module Language.Haskell.AntiQuoter.Combinators(+    -- * Lifted constructors.+    varQ, conQ, litQ, tupQ, listQ,++    -- * Ignoring+    ignore, ignorePat, onlyExp, ignoreExp, onlyPat,+    -- * Unsorted+    splice, wild,+    nonsenseP, nonsenseE,+) where++import Language.Haskell.TH++import Language.Haskell.AntiQuoter.Base+import Language.Haskell.AntiQuoter.ExpPat++varQ :: EP q => Name -> Q q+varQ = return . var++conQ :: EP q => Name -> [Q q] -> Q q+conQ n = fmap (con n) . sequence++litQ :: EP q => Lit -> Q q+litQ = return . lit++tupQ, listQ :: EP q => [Q q] -> Q q+tupQ  = fmap tup  . sequence+listQ = fmap list . sequence++-- | Uses/Binds a variable of the given name.+--+-- >  splice = varQ . mkName+--+splice :: EP q => String -> Q q+splice =  varQ . mkName++-- | Use a wildcard in pattern context and the given expression in expression+-- contexts. Consider for example the folowing constructor+--+-- > EX SrcLoc OtherType+--+-- When pattern matching the pattern should look like @EX _ x@, using a+-- wildcard for the source location. On the other hand making an expression+-- should use some result say resulting in @EX someSrcLoc x@. With the `wild`+-- function this general quoter can be written as+--+-- > con ''EX [wild someSrcLoc', splice "x"]+--+-- Assuming that @someSrcLoc' :: ExpQ@ and that its result is of type @SrcLoc@.+wild :: EP q => Q Exp -> Q q+wild e = epValue e wildP++-- | An results that does not output anything.+ignore :: AQResult q+ignore = Nothing++-- | Yielding only a result for expressions and ignoring in patterns.+ignorePat, onlyExp :: EP q => AQResult Exp -> AQResult q+ignorePat e = epResult e ignore+-- | Alias for `ignorePat`.+onlyExp = ignorePat++-- | Yielding only a result for patterns and ignoring in expressions.+ignoreExp, onlyPat :: EP q => AQResult Pat -> AQResult q+ignoreExp = epResult ignore+-- | Alias for `ignoreExp`.+onlyPat = ignoreExp++-- | A `fail`ing result for patterns, useful for when a the pattern matched by+-- the using functions should never happen when antiquoting patterns.+nonsenseP :: EP q => String -> AQResult Exp -> AQResult q+nonsenseP msg e = e `epResult` (Just $ fail msg)++-- | See `nonsenseP` but failing on expresions.+nonsenseE :: EP q => String -> AQResult Pat -> AQResult q+nonsenseE msg p = (Just $ fail msg) `epResult` p
+ src/Language/Haskell/AntiQuoter/ExpPat.hs view
@@ -0,0 +1,127 @@+-- | Tools for writing one `AntiQuoter` which can be used for both expressions+-- and patterns, thereby reducing copy-and-paste programming.+--+-- For example in the original paper on quasi quoting <http://www.eecs.harvard.edu/~mainland/ghc-quasiquoting/mainland07quasiquoting.pdf>+-- antiquoting is demonstrated by defining the following antiquoters:+--+-- @+-- antiVarE :: Var -> Maybe ExpQ+-- antiVarE (AV v ) = Just $ varE $ mkName v+-- antiVarE _ = Nothing+-- antiVarP :: Var -> Maybe PatQ+-- antiVarP (AV v ) = Just $ varP $ mkName v+-- antiVarP _ = Nothing+-- @+--+-- and a simmilar pair for antiquoting variables. The problem is that the+-- definition for the pattern antiquoter is almost a duplicate of the one for+-- expressions. This similarity between antiquoting expressions and patterns+-- is captured in the `EP` class which can be used to write antiquoters which+-- can yield both expressions and patterns. Using the combinators defined on+-- top of this class (see "Language.Haskell.AntiQuoter.Combinators") the+-- example can be rewritten as+--+-- @+-- antiVar :: EP q => Var ->  Maybe (Q q) -- equivalent to antiVar :: EPAntiQuoterPass Var+-- antiVar (AV v) = Just $ varQ $ mkName v+-- antiVar _      = Nothing+-- @++{-# LANGUAGE RankNTypes #-}+module Language.Haskell.AntiQuoter.ExpPat (++    -- * Template syntax class+    EP(..), EPAntiQuoter, EPAntiQuoterPass,+    mkEPQuasiQuoter,+    epPass, epPass', epPass'',+    epResult, epValue, epPure,++    -- ** Internal+    EPV(..),+) where++import Data.Data+import Language.Haskell.TH+import Language.Haskell.TH.Quote++import Language.Haskell.AntiQuoter.Base+++-- | Container for a @f@ of both an `Exp` and a `Pat`. Used internally when the+-- result for `Exp` and `Pat` differ.+data EPV f = EPV+    { eep :: f Exp+    , pep :: f Pat+    }++-- | Typeclass with the common constructors of `Exp` and `Pat`, useful for+-- building `EPAntiQuoter`s.+class EP q where+    -- | Variable+    var     :: Name -> q+    -- | Constructor with arguments+    con     :: Name -> [q] -> q+    -- | Literal value+    lit     :: Lit -> q+    -- | Tuple+    tup     :: [q] -> q+    -- | List+    list    :: [q] -> q+    -- | Internal unwrapper when the implementation for `Exp` and `Pat` should+    -- differ.+    fromEPV :: EPV f -> f q++-- | As `mkQuasiQuoter` but uses an generalized `AntiQuoter`.+mkEPQuasiQuoter :: Data a+    => (String -> Q a)+    -> EPAntiQuoter+    -> QuasiQuoter+mkEPQuasiQuoter parse aq = mkQuasiQuoter parse aq aq++-- | An `AntiQuoter` that works for `Exp` and `Pat`s.+type EPAntiQuoter       = forall q. EP q => AntiQuoter q+type EPAntiQuoterPass e = forall q. EP q => AntiQuoterPass e q++-- | Combine two `AntiQuoterPass`es, one for expression context and another for+-- pattern context, into a single pass for an expression of patter context.+epPass :: Typeable e => AntiQuoterPass e Exp -> AntiQuoterPass e Pat+    -> EPAntiQuoterPass e+epPass pe pp = \e -> epResult (pe e) (pp e)++-- | See `epPass`.+epPass' :: Typeable e => (e -> Maybe (Q Exp, Q Pat)) -> EPAntiQuoterPass e+epPass' f = epPass (fmap fst . f) (fmap snd . f)++-- | See `epPass`.+epPass'' :: Typeable e => AntiQuoterPass e (Exp, Pat) -> EPAntiQuoterPass e+epPass'' f = epPass ((fmap $ fmap fst) . f) ((fmap $ fmap snd) . f)++-- | Make a context dependent result for expression and pattern contexts.+epResult :: EP q => AQResult Exp -> AQResult Pat -> AQResult q+epResult e p = unAQRW . fromEPV $ EPV (AQRW e) (AQRW p)++-- | Make an context dependent value for expression and pattern contexts.+epValue :: EP q => Q Exp -> Q Pat -> Q q+epValue e p = fromEPV $ EPV e p++newtype Identity a = Identity { runIdentity :: a }++-- | Constructs an `EP` value by choosing from an `Exp` of `Pat` as+-- appropriate in the context.+epPure :: EP q => Exp -> Pat -> q+epPure e p = runIdentity . fromEPV $ EPV (Identity e) (Identity p)++instance EP Exp where+    var     = VarE+    con     = foldl AppE . ConE+    lit     = LitE+    tup     = TupE+    list    = ListE+    fromEPV = eep+instance EP Pat where+    var     = VarP+    con     = ConP+    lit     = LitP+    tup     = TupP+    list    = ListP+    fromEPV = pep