{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoPolyKinds #-}
module Data.HList.RecordPuns (
pun
) where
import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Data.HList.Record
import Data.HList.FakePrelude
import Data.List
import Data.HList.HList
pun :: QuasiQuoter
pun :: QuasiQuoter
pun = QuasiQuoter {
quotePat :: String -> Q Pat
quotePat = forall {t}. (Tree -> t) -> Tree -> t
suppressWarning Tree -> Q Pat
mp forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Tree
parseRec,
quoteExp :: String -> Q Exp
quoteExp = forall {t}. (Tree -> t) -> Tree -> t
suppressWarning Tree -> Q Exp
me forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Tree
parseRec,
quoteDec :: String -> Q [Dec]
quoteDec = forall a. HasCallStack => String -> a
error String
"Data.HList.RecordPuns.quoteDec",
quoteType :: String -> Q Type
quoteType = forall a. HasCallStack => String -> a
error String
"Data.HList.RecordPuns.quoteType"
}
suppressWarning :: (Tree -> t) -> Tree -> t
suppressWarning Tree -> t
f (V String
a) = Tree -> t
f ([Tree] -> Tree
C [String -> Tree
V String
a])
suppressWarning Tree -> t
f Tree
x = Tree -> t
f Tree
x
[String]
xs = do
Name
record <- forall (m :: * -> *). Quote m => String -> m Name
newName String
"record"
forall (m :: * -> *). Quote m => [m Pat] -> m Exp -> m Exp
lamE [forall (m :: * -> *). Quote m => Name -> m Pat
varP Name
record] forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Quote m => [m Exp] -> m Exp
tupE
[ [| $(varE record) .!. $label |]
| String
x <- [String]
xs,
let label :: m Exp
label = [| Label :: Label $(litT (strTyLit x)) |],
String
x forall a. Eq a => a -> a -> Bool
/= String
"_"
]
mkPair :: String -> ExpQ -> ExpQ
mkPair :: String -> Q Exp -> Q Exp
mkPair String
x Q Exp
xe = [| (Label :: Label $(litT (strTyLit x))) .=. $xe |]
me :: Tree -> ExpQ
me :: Tree -> Q Exp
me (C [Tree]
as) = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(String
l,Q Exp
e) Q Exp
acc -> [| $(mkPair l e) .*. $acc |]) [| emptyRecord |] ([Tree] -> [(String, Q Exp)]
mes [Tree]
as)
me (D [Tree]
_as) = forall a. HasCallStack => String -> a
error String
"Data.HList.RecordPuns.mp impossible"
me Tree
a = do
String -> Q ()
reportWarning forall a b. (a -> b) -> a -> b
$ String
"Data.HList.RecordPuns.mp implicit {} added around:" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Tree
a
Tree -> Q Exp
me ([Tree] -> Tree
C [Tree
a])
mes :: [Tree] -> [(String, ExpQ)]
mes :: [Tree] -> [(String, Q Exp)]
mes (V String
a : V String
"@": Tree
b : [Tree]
c) = (String
a, [| $(me b) `hLeftUnion` $(dyn a) |]) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Exp)]
mes [Tree]
c
mes (V String
a : C [Tree]
b : [Tree]
c) = (String
a, Tree -> Q Exp
me ([Tree] -> Tree
C [Tree]
b)) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Exp)]
mes [Tree]
c
mes (V String
a : D [Tree]
b : [Tree]
c) = (String
a, Tree -> Q Exp
me ([Tree] -> Tree
C [Tree]
b)) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Exp)]
mes [Tree]
c
mes (V String
a : [Tree]
b) = (String
a, forall (m :: * -> *). Quote m => Name -> m Exp
varE (String -> Name
mkName String
a)) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Exp)]
mes [Tree]
b
mes [] = []
mes [Tree]
inp = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Data.HList.RecordPuns.mes: cannot translate remaining:" forall a. [a] -> [a] -> [a]
++
forall a. Show a => a -> String
show (forall a b. (a -> b) -> [a] -> [b]
map Tree -> String
ppTree [Tree]
inp)
mp :: Tree -> PatQ
mp :: Tree -> Q Pat
mp (C [Tree]
as) =
let extractPats :: [(String, Q Pat)]
extractPats = [Tree] -> [(String, Q Pat)]
mps [Tree]
as
tupleP :: Q Pat
tupleP = forall (m :: * -> *). Quote m => [m Pat] -> m Pat
tupP [ Q Pat
p | (String
binding, Q Pat
p) <- [(String, Q Pat)]
extractPats, String
binding forall a. Eq a => a -> a -> Bool
/= String
"_" ]
in forall (m :: * -> *). Quote m => m Exp -> m Pat -> m Pat
viewP (forall {m :: * -> *}. Quote m => [String] -> m Exp
extracts (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(String, Q Pat)]
extractPats)) Q Pat
tupleP
mp (D [Tree]
as) = forall (m :: * -> *). Quote m => Name -> [m Pat] -> m Pat
conP 'Record
[forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ( \ (String
n,Q Pat
p) Q Pat
xs -> forall (m :: * -> *). Quote m => Name -> [m Pat] -> m Pat
conP 'HCons
[ let ty :: Q Exp
ty
| String
n forall a. Eq a => a -> a -> Bool
== String
"_" = [| undefined :: Tagged anyLabel t |]
| Bool
otherwise = [| undefined :: Tagged $(litT (strTyLit n)) t |]
in forall (m :: * -> *). Quote m => m Exp -> m Pat -> m Pat
viewP [| \x -> x `asTypeOf` $ty |]
(forall (m :: * -> *). Quote m => Name -> [m Pat] -> m Pat
conP 'Tagged [Q Pat
p]),
Q Pat
xs])
(forall (m :: * -> *). Quote m => Name -> [m Pat] -> m Pat
conP 'HNil [])
([Tree] -> [(String, Q Pat)]
mps [Tree]
as)]
mp Tree
a = do
String -> Q ()
reportWarning forall a b. (a -> b) -> a -> b
$ String
"Data.HList.RecordPuns.mp implicit {} added around:" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Tree
a
Tree -> Q Pat
mp ([Tree] -> Tree
C [Tree
a])
mps :: [Tree] -> [(String, PatQ)]
mps :: [Tree] -> [(String, Q Pat)]
mps (V String
a : V String
"@" : Tree
b : [Tree]
c) = (String
a, forall (m :: * -> *). Quote m => Name -> m Pat -> m Pat
asP (String -> Name
mkName String
a) (Tree -> Q Pat
mp Tree
b)) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Pat)]
mps [Tree]
c
mps (V String
a : C [Tree]
b : [Tree]
c) = (String
a, Tree -> Q Pat
mp ([Tree] -> Tree
C [Tree]
b)) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Pat)]
mps [Tree]
c
mps (V String
a : D [Tree]
b : [Tree]
c) = (String
a, Tree -> Q Pat
mp ([Tree] -> Tree
D [Tree]
b)) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Pat)]
mps [Tree]
c
mps (V String
"_" : [Tree]
b) = (String
"_", forall (m :: * -> *). Quote m => m Pat
wildP) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Pat)]
mps [Tree]
b
mps (V String
a : [Tree]
b) = (String
a, forall (m :: * -> *). Quote m => Name -> m Pat
varP (String -> Name
mkName String
a)) forall a. a -> [a] -> [a]
: [Tree] -> [(String, Q Pat)]
mps [Tree]
b
mps [] = []
mps [Tree]
inp = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Data.HList.RecordPuns.mps: cannot translate remaining pattern:" forall a. [a] -> [a] -> [a]
++
forall a. Show a => a -> String
show (forall a b. (a -> b) -> [a] -> [b]
map Tree -> String
ppTree [Tree]
inp)
data Tree = C [Tree]
| D [Tree]
| V String
deriving Int -> Tree -> ShowS
[Tree] -> ShowS
Tree -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tree] -> ShowS
$cshowList :: [Tree] -> ShowS
show :: Tree -> String
$cshow :: Tree -> String
showsPrec :: Int -> Tree -> ShowS
$cshowsPrec :: Int -> Tree -> ShowS
Show
parseRec :: String -> Tree
parseRec :: String -> Tree
parseRec String
str = case Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' Int
0 Int
0 [[]] forall a b. (a -> b) -> a -> b
$ String -> [String]
lexing String
str of
[Tree
x] -> Tree
x
[Tree]
x -> [Tree] -> Tree
C (forall a. [a] -> [a]
reverse [Tree]
x)
parseRec' :: Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' :: Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' Int
n Int
m [[Tree]]
accum (String
"{" : [String]
rest) = Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' (Int
nforall a. Num a => a -> a -> a
+Int
1) Int
m ([] forall a. a -> [a] -> [a]
: [[Tree]]
accum) [String]
rest
parseRec' Int
n Int
m [[Tree]]
accum (String
"(" : [String]
rest) = Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' Int
n (Int
mforall a. Num a => a -> a -> a
+Int
1) ([] forall a. a -> [a] -> [a]
: [[Tree]]
accum) [String]
rest
parseRec' Int
n Int
m ([Tree]
a:[Tree]
b:[[Tree]]
c) (String
"}" : [String]
rest) = Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' (Int
nforall a. Num a => a -> a -> a
-Int
1) Int
m (([Tree] -> Tree
C (forall a. [a] -> [a]
reverse [Tree]
a) forall a. a -> [a] -> [a]
: [Tree]
b) forall a. a -> [a] -> [a]
: [[Tree]]
c) [String]
rest
parseRec' Int
n Int
m ([Tree]
a:[Tree]
b:[[Tree]]
c) (String
")" : [String]
rest) = Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' Int
n (Int
mforall a. Num a => a -> a -> a
-Int
1) (([Tree] -> Tree
D (forall a. [a] -> [a]
reverse [Tree]
a) forall a. a -> [a] -> [a]
: [Tree]
b) forall a. a -> [a] -> [a]
: [[Tree]]
c) [String]
rest
parseRec' Int
n Int
m ([Tree]
b:[[Tree]]
c) (String
a : [String]
rest)
| String
a forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [String
"{",String
"}",String
"(",String
")"] = Int -> Int -> [[Tree]] -> [String] -> [Tree]
parseRec' Int
n Int
m ((String -> Tree
V String
a forall a. a -> [a] -> [a]
: [Tree]
b) forall a. a -> [a] -> [a]
: [[Tree]]
c) [String]
rest
parseRec' Int
0 Int
0 ([Tree]
a:[[Tree]]
_) [] = [Tree]
a
parseRec' Int
_ Int
_ [[Tree]]
accum [String]
e = forall a. HasCallStack => String -> a
error (String
"Data.HList.RecordPuns.parseRec' unexpected: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show [String]
e
forall a. [a] -> [a] -> [a]
++ String
"\n parsed:" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall a. [a] -> [a]
reverse [[Tree]]
accum))
ppTree :: Tree -> String
ppTree :: Tree -> String
ppTree (C [Tree]
ts) = String
"{" forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords (forall a b. (a -> b) -> [a] -> [b]
map Tree -> String
ppTree [Tree]
ts) forall a. [a] -> [a] -> [a]
++ String
"}"
ppTree (D [Tree]
ts) = String
"(" forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords (forall a b. (a -> b) -> [a] -> [b]
map Tree -> String
ppTree [Tree]
ts) forall a. [a] -> [a] -> [a]
++ String
")"
ppTree (V String
x) = String
x
lexing :: String -> [String]
lexing = forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (\String
v -> case ReadS String
lex String
v of
(String
"", String
"") : [(String, String)]
_ -> forall a. Maybe a
Nothing
(String, String)
e : [(String, String)]
_ -> forall a. a -> Maybe a
Just (String, String)
e
[(String, String)]
_ -> forall a. Maybe a
Nothing)