ascii-th (empty) → 1.0.0.0
raw patch · 4 files changed
+309/−0 lines, 4 filesdep +ascii-chardep +ascii-supersetdep +base
Dependencies added: ascii-char, ascii-superset, base, template-haskell
Files
- ASCII/QuasiQuoters.hs +120/−0
- ASCII/TemplateHaskell.hs +135/−0
- ascii-th.cabal +41/−0
- license.txt +13/−0
+ ASCII/QuasiQuoters.hs view
@@ -0,0 +1,120 @@+module ASCII.QuasiQuoters ( char, string ) where++import ASCII.Char ( Char )+import ASCII.Superset ( toCharMaybe, toCharListMaybe )+import ASCII.TemplateHaskell ( isCharExp, isCharPat, isStringExp, isStringPat )+import Control.Monad ( (>=>), return )+import Control.Monad.Fail ( MonadFail, fail )+import Data.Maybe ( Maybe (..) )+import Language.Haskell.TH.Quote ( QuasiQuoter (..) )+import Language.Haskell.TH.Syntax ( Q, Exp, Pat )++import qualified Data.Char as Unicode+import qualified Data.String as Unicode++{- $setup++>>> :set -fno-warn-overlapping-patterns+>>> :set -XNoQuasiQuotes+>>> :set -XNoViewPatterns+>>> import qualified ASCII+>>> import qualified Data.String+>>> import qualified Data.Text+>>> import qualified Data.ByteString.Builder+>>> import Data.Word (Word8)+>>> import ASCII.Char+>>> import ASCII.QuasiQuoters++-}++{- | Produces an expression or a pattern corresponding to an ASCII character.++The result will have an 'ASCII.Superset.IsChar' constraint; since this is polymorphic, use with a type signature to specify the particular you want is recommended.++The quasi-quoted string must consist of a single character that is within the ASCII character set.++>>> :set -XQuasiQuotes++>>> [char|e|] :: ASCII.Char+SmallLetterE++>>> [char|e|] :: Word8+101++Use in a pattern context requires enabling the @ViewPatterns@ language extension.++>>> :set -XViewPatterns++>>> case Tilde of [char|@|] -> 1; [char|~|] -> 2; _ -> 3+2++-}++char :: QuasiQuoter+char = expPatQQ requireOneAscii isCharExp isCharPat++{- | Produces an expression or a pattern corresponding to an ASCII string.++The result will have an 'ASCII.Superset.IsString' constraint; since this is polymorphic, use with a type signature to specify the particular you want is recommended.++The quasi-quoted string must consist only of characters are within the ASCII character set.++>>> :set -XQuasiQuotes++>>> [string|Hello!|] :: [ASCII.Char]+[CapitalLetterH,SmallLetterE,SmallLetterL,SmallLetterL,SmallLetterO,ExclamationMark]++>>> [string|Hello!|] :: Data.String.String+"Hello!"++>>> [string|Hello!|] :: Data.Text.Text+"Hello!"++>>> Data.ByteString.Builder.toLazyByteString [string|Hello!|]+"Hello!"+++Use in a pattern context requires enabling the @ViewPatterns@ language extension.++>>> :set -XViewPatterns++>>> case [CapitalLetterH, SmallLetterI] of [string|Bye|] -> 1; [string|Hi|] -> 2; _ -> 3+2++-}++string :: QuasiQuoter+string = expPatQQ requireAsciiList isStringExp isStringPat++requireOneAscii :: Unicode.String -> Q Char+requireOneAscii = requireOne >=> requireAscii++oneMaybe :: [a] -> Maybe a+oneMaybe xs = case xs of [x] -> Just x; _ -> Nothing++requireOne :: Unicode.String -> Q Unicode.Char+requireOne = oneMaybe || "Must be exactly one character."++requireAscii :: Unicode.Char -> Q Char+requireAscii = toCharMaybe || "Must be an ASCII character."++requireAsciiList :: Unicode.String -> Q [Char]+requireAsciiList = toCharListMaybe || "Must be only ASCII characters."++(||) :: (a -> Maybe b) -> Unicode.String -> a -> Q b+f || msg = \a -> case f a of Just b -> return b; Nothing -> fail msg++expPatQQ :: (Unicode.String -> Q a) -> (a -> Q Exp) -> (a -> Q Pat) -> QuasiQuoter+expPatQQ f a b =+ QuasiQuoter+ { quoteExp = f >=> a+ , quotePat = f >=> b+ , quoteType = notType+ , quoteDec = notDec+ }++notType :: MonadFail m => a -> m b+notType _ = fail "Cannot be used in a type context."++notDec :: MonadFail m => a -> m b+notDec _ = fail "Cannot be used in a declaration context."
+ ASCII/TemplateHaskell.hs view
@@ -0,0 +1,135 @@+module ASCII.TemplateHaskell (++ {- * Characters -} charExp, charPat,+ {- * Character lists -} charListExp, charListPat,+ {- * Character supersets -} isCharExp, isCharPat,+ {- * String supersets -} isStringExp, isStringPat++ ) where++import qualified ASCII.Char as ASCII+import qualified ASCII.Superset as S++import Data.Data ( Data )+import Data.Maybe ( Maybe (..) )+import Language.Haskell.TH.Syntax ( Q, Exp, Pat, dataToExpQ, dataToPatQ )++{- $setup++>>> :set -XNoViewPatterns+>>> import ASCII.Char (Char (..))+>>> import ASCII.Refinement (ASCII)+>>> import ASCII.Superset (toCharOrFail)+>>> import ASCII.TemplateHaskell (charExp)+>>> import Control.Monad ((>>=))+>>> import Data.Word (Word8)++-}++exp :: Data a => a -> Q Exp+exp = dataToExpQ (\_ -> Nothing)++pat :: Data a => a -> Q Pat+pat = dataToPatQ (\_ -> Nothing)++{- |++>>> $(toCharOrFail 'F' >>= charExp)+CapitalLetterF++>>> $(toCharOrFail '\DEL' >>= charExp)+Delete++-}++charExp :: ASCII.Char -> Q Exp+charExp = exp++{- |++>>> :{+>>> case SmallLetterS of+>>> $(toCharOrFail 'r' >>= charPat) -> 1+>>> $(toCharOrFail 's' >>= charPat) -> 2+>>> _ -> 3+>>> :}+2++This is the same as:++>>> :{+>>> case SmallLetterS of+>>> SmallLetterR -> 1+>>> SmallLetterS -> 2+>>> _ -> 3+>>> :}+2++-}++charPat :: ASCII.Char -> Q Pat+charPat = pat++{- |++>>> $(charListExp [CapitalLetterH, SmallLetterI])+[CapitalLetterH,SmallLetterI]++-}++charListExp :: [ASCII.Char] -> Q Exp+charListExp = exp++{- |++>>> :{+>>> case [CapitalLetterH, SmallLetterI] of+>>> $(charListPat [CapitalLetterH, SmallLetterA]) -> 1+>>> $(charListPat [CapitalLetterH, SmallLetterI]) -> 2+>>> _ -> 3+>>> :}+2++-}++charListPat :: [ASCII.Char] -> Q Pat+charListPat = pat++{- |++>>> $(isCharExp CapitalLetterA) :: ASCII.Char+CapitalLetterA++>>> $(isCharExp CapitalLetterA) :: Word8+65++>>> $(isCharExp CapitalLetterA) :: ASCII Word8+asciiUnsafe 65++-}++isCharExp :: ASCII.Char -> Q Exp+isCharExp x = [| S.fromChar $(charExp x) |]++{- |++>>> :set -XViewPatterns++>>> :{+>>> case (66 :: Word8) of+>>> $(isCharPat CapitalLetterA) -> 1+>>> $(isCharPat CapitalLetterB) -> 2+>>> _ -> 3+>>> :}+2++-}++isCharPat :: ASCII.Char -> Q Pat+isCharPat x = [p| (S.toCharMaybe -> Just $(charPat x)) |]++isStringExp :: [ASCII.Char] -> Q Exp+isStringExp xs = [| S.fromCharList $(charListExp xs) |]++isStringPat :: [ASCII.Char] -> Q Pat+isStringPat xs = [p| (S.toCharListMaybe -> Just $(charListPat xs)) |]
+ ascii-th.cabal view
@@ -0,0 +1,41 @@+cabal-version: 2.0++name: ascii-th+version: 1.0.0.0+synopsis: Template Haskell support for ASCII+category: Data, Text++description: This package defines Template Haskell support for ASCII, including quasi-quoters for expressing ASCII strings.++license: Apache-2.0+license-file: license.txt++author: Chris Martin+maintainer: Chris Martin, Julie Moronuki++homepage: https://github.com/typeclasses/ascii+bug-Reports: https://github.com/typeclasses/ascii/issues++build-type: Simple++tested-with: GHC == 8.8.1, GHC == 8.6.5, GHC == 8.4.3++source-repository head+ type: git+ location: git://github.com/typeclasses/ascii.git++library+ default-language: Haskell2010+ default-extensions: NoImplicitPrelude+ default-extensions: TemplateHaskell+ default-extensions: QuasiQuotes+ default-extensions: ViewPatterns+ ghc-options: -Wall++ build-depends: ascii-char >= 1.0 && < 1.1+ build-depends: ascii-superset >= 1.0 && < 1.1+ build-depends: base >= 4.11 && < 4.14+ build-depends: template-haskell >= 2.13 && < 2.16++ exposed-modules: ASCII.TemplateHaskell+ exposed-modules: ASCII.QuasiQuoters
+ license.txt view
@@ -0,0 +1,13 @@+Copyright 2020 Typeclass Consulting LLC++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.