1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
{-|
Derives @Read@. This is as defined by the Haskell report, except
there is no support for infix constructors. If you attempt to
derive @Read@ for a data type with infix constructors, the
constructors are handled as if they were prefix constructors, using
the @(@/consym/@)@ syntax.
-}
module Data.Derive.Read(makeRead) where
{-
import Prelude
example :: Custom
instance Read a => Read (Sample a) where
readsPrec p0 r =
readParen $(bracket 0) (\r0 -> $(comp 0 First )) r ++
readParen $(bracket 1) (\r0 -> $(comp 1 Second)) r ++
readParen $(bracket 2) (\r0 -> $(comp 2 Third )) r ++
[]
test :: Sample
instance Read a => Read (Sample a) where
readsPrec p0 r =
readParen (p0 > 10) (\r0 ->
[ (First, r1)
| ("First", r1) <- lex r0]) r
++
readParen (p0 > 10) (\r0 ->
[ (Second x1 x2, r3)
| ("Second", r1) <- lex r0
, (x1, r2) <- readsPrec 11 r1
, (x2, r3) <- readsPrec 11 r2]) r
++
readParen (p0 > 10) (\r0 ->
[ (Third x1, r2)
| ("Third", r1) <- lex r0
, (x1, r2) <- readsPrec 11 r1]) r
test :: Computer
instance Read Computer where
readsPrec _ r =
readParen False (\r0 ->
[ (Laptop x1 x2, r10)
| ("Laptop", r1) <- lex r0
, ("{", r2) <- lex r1
, ("weight", r3) <- lex r2
, ("=", r4) <- lex r3
, (x1, r5) <- readsPrec 0 r4
, (",", r6) <- lex r5
, ("speed", r7) <- lex r6
, ("=", r8) <- lex r7
, (x2, r9) <- readsPrec 0 r8
, ("}", r10) <- lex r9]) r
++
readParen False (\r0 ->
[ (Desktop x1, r6)
| ("Desktop", r1) <- lex r0
, ("{", r2) <- lex r1
, ("speed", r3) <- lex r2
, ("=", r4) <- lex r3
, (x1, r5) <- readsPrec 0 r4
, ("}", r6) <- lex r5]) r
test :: (:*:)
instance (Read a, Read b) => Read ((:*:) a b) where
readsPrec p0 r =
readParen (p0 > 10) (\r0 ->
[ ((:*:) x1 x2, r3)
| ("(:*:)", r1) <- lex r0
, (x1, r2) <- readsPrec 11 r1
, (x2, r3) <- readsPrec 11 r2]) r
-}
import Data.Derive.DSL.HSE
import qualified Language.Haskell as H
-- GENERATED START
import Data.Derive.DSL.DSL
import Data.Derive.Internal.Derivation
makeRead :: Derivation
makeRead = derivationCustomDSL "Read" custom $
List [Instance ["Read"] "Read" (List [App "InsDecl" (List [App
"FunBind" (List [List [App "Match" (List [App "Ident" (List [
String "readsPrec"]),List [App "PVar" (List [App "Ident" (List [
Concat (List [String "p",ShowInt (Int 0)])])]),App "PVar" (List [
App "Ident" (List [String "r"])])],App "Nothing" (List []),App
"UnGuardedRhs" (List [Fold (App "InfixApp" (List [Head,App
"QVarOp" (List [App "UnQual" (List [App "Symbol" (List [String
"++"])])]),Tail])) (Concat (List [MapCtor (Application (List [App
"Var" (List [App "UnQual" (List [App "Ident" (List [String
"readParen"])])]),App "SpliceExp" (List [App "ParenSplice" (List [
App "App" (List [App "Var" (List [App "UnQual" (List [App "Ident"
(List [String "bracket"])])]),App "Lit" (List [App "Int" (List [
CtorIndex])])])])]),App "Paren" (List [App "Lambda" (List [List [
App "PVar" (List [App "Ident" (List [Concat (List [String "r",
ShowInt (Int 0)])])])],App "SpliceExp" (List [App "ParenSplice" (
List [Application (List [App "Var" (List [App "UnQual" (List [App
"Ident" (List [String "comp"])])]),App "Lit" (List [App "Int" (
List [CtorIndex])]),App "Con" (List [App "UnQual" (List [App
"Ident" (List [CtorName])])])])])])])]),App "Var" (List [App
"UnQual" (List [App "Ident" (List [String "r"])])])])),List [App
"List" (List [List []])]]))]),App "BDecls" (List [List []])])]])])
])]
-- GENERATED STOP
custom = customSplice splice
getCtor d i = dataDeclCtors (snd d) !! fromIntegral i
hasFields c = any ((/=) "" . fst) $ ctorDeclFields c
splice :: FullDataDecl -> Exp -> Exp
splice d (H.App x (H.Lit (H.Int y))) | x ~= "bracket" =
if hasFields $ getCtor d y
then con "False"
else Paren $ InfixApp (var "p0") (QVarOp $ UnQual $ Symbol ">") (H.Lit $ H.Int 10)
splice d (H.App (H.App x (H.Lit (H.Int y))) _) | x ~= "comp" =
if hasFields c then readFields c else readCtor c
where c = getCtor d y
readCtor :: CtorDecl -> Exp
readCtor c =
ListComp (Tuple Boxed [cpat, var ('r':show (cn+1))]) $
matchStr (ctorDeclName c) 0 :
[QualStmt $ Generator sl
(PTuple Boxed [pVar $ v 'x' 0, pVar $ v 'r' 1])
(apps (var "readsPrec") [H.Lit $ H.Int 11, var $ v 'r' 0])
| i <- [1..cn], let v c j = c : show (i+j)]
where
cn = ctorDeclArity c
cpat = apps (Con $ UnQual $ ctorDeclName' c) $ map (var . ('x':) . show) [1..cn]
readFields :: CtorDecl -> Exp
readFields c =
ListComp (Tuple Boxed [cpat, var $ 'r':show ((cn*4)+2)]) $
matchStr (ctorDeclName c) 0 :
concat [
matchStr (r == 1 ? "{" $ ",") r :
matchStr fld (r+1) :
matchStr "=" (r+2) :
QualStmt (Generator sl
(PTuple Boxed [pVar $ 'x':show i, pVar $ 'r':show (r+4)])
(apps (var "readsPrec") [H.Lit $ H.Int 0, var $ 'r':show (r+3)]))
: []
| (i,r,(fld,_)) <- zip3 [1..] [1,5..] (ctorDeclFields c)
] ++
[matchStr "}" ((cn*4)+1)]
where
cn = ctorDeclArity c
cpat = apps (Con $ UnQual $ ctorDeclName' c) $ map (var . ('x':) . show) [1..cn]
matchStr :: String -> Int -> QualStmt
matchStr s i = QualStmt $ Generator sl (PTuple Boxed [PLit $ H.String s, pVar $ 'r':show (i+1)]) (var "lex" `H.App` var ('r':show i))
{-
read' dat = [instance_default "Read" dat [funN "readsPrec" [sclause [vr "p0", vr "r"] body]]]
where
body = (++::) [ readit ctr | ctr <- dataCtors dat ]
readit ctr = case ctorFields ctr of [] -> norm
fl -> flds fl
where
norm = lK "readParen"
[vr "p0" >: lit (10::Integer),
"r0" ->: runComp (pName . foldr (.) id (map (pRead 11) (ctv ctr 'x'))) (ctp ctr 'x'),
l0 "r"]
flds f = lK "readParen"
[false,
"r0" ->: runComp (pName . pLex "{" .
foldr (.) id (intersperse (pLex ",")
(zipWith pField (ctv ctr 'x') f)) .
pLex "}") (ctp ctr 'x'),
l0 "r"]
runComp fn ex = CompE $ fn (\k -> [ NoBindS (tup [ex, vrn 'r' k]) ]) 0
pArse pat fun ct k = BindS (tup [pat, vrn 'r' (k+1)]) (AppE fun (vrn 'r' k)) : ct (k+1)
pLex pat = pArse (lit pat) (l0 "lex")
name = ctorName ctr
pName | isAlpha (head name) || head name == '_' = pLex name
| otherwise = pLex "(" . pLex name . pLex ")"
pRead pc pat = pArse pat (l1 "readsPrec" (lit (pc :: Integer)))
pField pat fld = pLex fld . pLex "=" . pRead 0 pat
-}
|