Class.hs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE OverloadedLists #-}
  3. {-# LANGUAGE TypeSynonymInstances #-}
  4. {-# LANGUAGE FlexibleInstances #-}
  5. {-# LANGUAGE FlexibleContexts #-}
  6. {-# LANGUAGE TypeOperators #-}
  7. {-# LANGUAGE ScopedTypeVariables #-}
  8. {-# LANGUAGE DefaultSignatures #-}
  9. {-# LANGUAGE DataKinds #-}
  10. {-# LANGUAGE GADTs #-}
  11. module Data.Adnot.Class where
  12. import Control.Monad ((>=>))
  13. import Data.Adnot.Parse
  14. import Data.Adnot.Type
  15. import Data.Adnot.Emit
  16. import Data.Int
  17. import Data.Word
  18. import qualified Data.ByteString as BS
  19. import qualified Data.ByteString.Lazy as BSL
  20. import qualified Data.Foldable as F
  21. import qualified Data.List.NonEmpty as NE
  22. import qualified Data.Map.Lazy as ML
  23. import qualified Data.Map.Strict as MS
  24. import qualified Data.Sequence as Seq
  25. import qualified Data.Text as T
  26. import qualified Data.Text.Lazy as TL
  27. import qualified Data.Vector as V
  28. import GHC.Generics
  29. import GHC.TypeLits (KnownSymbol)
  30. encode :: ToAdnot a => a -> BSL.ByteString
  31. encode = encodeValue . toAdnot
  32. class GenToAdnot f where
  33. genToAdnot :: f p -> Value
  34. instance (GenToAdnot l, GenToAdnot r) => GenToAdnot (l :+: r) where
  35. genToAdnot (L1 x) = genToAdnot x
  36. genToAdnot (R1 y) = genToAdnot y
  37. instance ToAdnot x => GenToAdnot (K1 i x) where
  38. genToAdnot (K1 x) = toAdnot x
  39. instance (GatherSequence f, Constructor name) => GenToAdnot (C1 name f) where
  40. genToAdnot (M1 x) = Sum (T.pack (conName c)) (V.fromList (gatherSequence x))
  41. where c :: M1 c name f ()
  42. c = undefined
  43. instance (GenToAdnot f) => GenToAdnot (S1 name f) where
  44. genToAdnot (M1 x) = genToAdnot x
  45. instance (GenToAdnot f) => GenToAdnot (D1 name f) where
  46. genToAdnot (M1 x) = genToAdnot x
  47. instance (GatherSequence l, GatherSequence r) => GenToAdnot (l :*: r) where
  48. genToAdnot x = List (V.fromList (gatherSequence x))
  49. class GatherRecord f where
  50. gatherRecord :: f p -> [(T.Text, Value)]
  51. instance (GatherRecord l, GatherRecord r) => GatherRecord (l :*: r) where
  52. gatherRecord (x :*: y) = gatherRecord x ++ gatherRecord y
  53. instance (GenToAdnot f, Selector name) => GatherRecord (S1 name f) where
  54. gatherRecord (M1 x) = [(T.pack (selName s), genToAdnot x)]
  55. where s :: S1 name f ()
  56. s = undefined
  57. instance GatherRecord U1 where
  58. gatherRecord U1 = []
  59. class GatherSequence f where
  60. gatherSequence :: f p -> [Value]
  61. instance GatherSequence U1 where
  62. gatherSequence U1 = []
  63. instance (GatherSequence l, GatherSequence r) => GatherSequence (l :*: r) where
  64. gatherSequence (x :*: y) = gatherSequence x ++ gatherSequence y
  65. instance ToAdnot x => GatherSequence (K1 i x) where
  66. gatherSequence (K1 x) = [toAdnot x]
  67. instance GenToAdnot f => GatherSequence (S1 name f) where
  68. gatherSequence (M1 x) = [genToAdnot x]
  69. instance GenToAdnot f => GatherSequence (D1 name f) where
  70. gatherSequence (M1 x) = [genToAdnot x]
  71. instance GenToAdnot U1 where
  72. genToAdnot U1 = List []
  73. genericToAdnot :: (GenToAdnot (Rep t), Generic t) => t -> Value
  74. genericToAdnot x = genToAdnot (from x)
  75. class ToAdnot a where
  76. toAdnot :: a -> Value
  77. default toAdnot :: (Generic a, GenToAdnot (Rep a)) => a -> Value
  78. toAdnot = genericToAdnot
  79. -- Integral types
  80. instance ToAdnot Int where
  81. toAdnot n = Integer (fromIntegral n)
  82. instance ToAdnot Integer where
  83. toAdnot n = Integer n
  84. instance ToAdnot Int8 where
  85. toAdnot n = Integer (fromIntegral n)
  86. instance ToAdnot Int16 where
  87. toAdnot n = Integer (fromIntegral n)
  88. instance ToAdnot Int32 where
  89. toAdnot n = Integer (fromIntegral n)
  90. instance ToAdnot Int64 where
  91. toAdnot n = Integer (fromIntegral n)
  92. instance ToAdnot Word where
  93. toAdnot n = Integer (fromIntegral n)
  94. instance ToAdnot Word8 where
  95. toAdnot n = Integer (fromIntegral n)
  96. instance ToAdnot Word16 where
  97. toAdnot n = Integer (fromIntegral n)
  98. instance ToAdnot Word32 where
  99. toAdnot n = Integer (fromIntegral n)
  100. instance ToAdnot Word64 where
  101. toAdnot n = Integer (fromIntegral n)
  102. -- Rational/Floating types
  103. instance ToAdnot Double where
  104. toAdnot d = Double d
  105. instance ToAdnot Float where
  106. toAdnot d = Double (fromRational (toRational d))
  107. -- String types
  108. instance {-# INCOHERENT #-} ToAdnot String where
  109. toAdnot s = String (T.pack s)
  110. instance ToAdnot T.Text where
  111. toAdnot s = String s
  112. instance ToAdnot TL.Text where
  113. toAdnot s = String (TL.toStrict s)
  114. instance ToAdnot Char where
  115. toAdnot c = String (T.singleton c)
  116. -- List types
  117. instance ToAdnot a => ToAdnot [a] where
  118. toAdnot ls = List (fmap toAdnot (V.fromList ls))
  119. instance ToAdnot a => ToAdnot (V.Vector a) where
  120. toAdnot ls = List (fmap toAdnot ls)
  121. instance ToAdnot a => ToAdnot (Seq.Seq a) where
  122. toAdnot ls = List (V.fromList (F.toList (fmap toAdnot ls)))
  123. instance ToAdnot a => ToAdnot (NE.NonEmpty a) where
  124. toAdnot ls = List (V.fromList (F.toList (fmap toAdnot ls)))
  125. -- Mapping types
  126. instance ToAdnot a => ToAdnot (MS.Map T.Text a) where
  127. toAdnot ls = Product (fmap toAdnot ls)
  128. -- Tuples
  129. instance ToAdnot () where
  130. toAdnot () = List []
  131. instance (ToAdnot a, ToAdnot b) => ToAdnot (a, b) where
  132. toAdnot (a, b) = List [toAdnot a, toAdnot b]
  133. instance (ToAdnot a, ToAdnot b, ToAdnot c) => ToAdnot (a, b, c) where
  134. toAdnot (a, b, c) = List [toAdnot a, toAdnot b, toAdnot c]
  135. instance (ToAdnot a, ToAdnot b, ToAdnot c, ToAdnot d)
  136. => ToAdnot (a, b, c, d) where
  137. toAdnot (a, b, c, d) = List [toAdnot a, toAdnot b, toAdnot c, toAdnot d]
  138. -- Common Haskell algebraic data types
  139. instance ToAdnot a => ToAdnot (Maybe a) where
  140. toAdnot Nothing = Sum "Nothing" []
  141. toAdnot (Just x) = Sum "Just" [toAdnot x]
  142. instance (ToAdnot a, ToAdnot b) => ToAdnot (Either a b) where
  143. toAdnot (Left x) = Sum "Left" [toAdnot x]
  144. toAdnot (Right y) = Sum "Right" [toAdnot y]
  145. instance ToAdnot Bool where
  146. toAdnot True = Symbol "True"
  147. toAdnot False = Symbol "False"
  148. -- Parsing
  149. decode :: FromAdnot a => BS.ByteString -> Either String a
  150. decode = decodeValue >=> parseAdnot
  151. type ParseError = String
  152. type Parser a = Either ParseError a
  153. withSum :: String -> (T.Text -> Array -> Parser a) -> Value -> Parser a
  154. withSum n k val = case val of
  155. Sum t as -> k t as
  156. _ -> Left ("Expected sum in " ++ n)
  157. withSumNamed :: String -> T.Text -> (Array -> Parser a) -> Value -> Parser a
  158. withSumNamed n tag k val = case val of
  159. Sum t as
  160. | tag == t -> k as
  161. | otherwise -> Left $ unwords
  162. [ "Expected tag", T.unpack tag, "in", n, "but found", T.unpack t ]
  163. _ -> Left ("Expected sum in " ++ n)
  164. withProduct :: String -> (Product -> Parser a) -> Value -> Parser a
  165. withProduct n k val = case val of
  166. Product ps -> k ps
  167. _ -> Left ("Expected product in " ++ n)
  168. withList :: String -> (Array -> Parser a) -> Value -> Parser a
  169. withList n k val = case val of
  170. List ls -> k ls
  171. _ -> Left ("Expected list in " ++ n)
  172. withInteger :: String -> (Integer -> Parser a) -> Value -> Parser a
  173. withInteger n k val = case val of
  174. Integer i -> k i
  175. _ -> Left ("Expected integer in " ++ n)
  176. withDouble :: String -> (Double -> Parser a) -> Value -> Parser a
  177. withDouble n k val = case val of
  178. Double d -> k d
  179. Integer i -> k (fromIntegral i)
  180. _ -> Left ("Expected double in " ++ n)
  181. withSymbol :: String -> (T.Text -> Parser a) -> Value -> Parser a
  182. withSymbol n k val = case val of
  183. Symbol s -> k s
  184. _ -> Left ("Expected symbol in " ++ n)
  185. withString :: String -> (T.Text -> Parser a) -> Value -> Parser a
  186. withString n k val = case val of
  187. String s -> k s
  188. _ -> Left ("Expected string in " ++ n)
  189. (.:) :: FromAdnot a => Product -> T.Text -> Parser a
  190. map .: key = case MS.lookup key map of
  191. Just x -> parseAdnot x
  192. Nothing -> Left ("Missing key " ++ show key)
  193. (.:?) :: FromAdnot a => Product -> T.Text -> Parser (Maybe a)
  194. map .:? key = case MS.lookup key map of
  195. Just x -> Just <$> parseAdnot x
  196. Nothing -> return Nothing
  197. (.!=) :: Parser (Maybe a) -> a -> Parser a
  198. c .!= r = fmap (maybe r id) c
  199. class FromAdnot a where
  200. parseAdnot :: Value -> Parser a
  201. instance FromAdnot Value where
  202. parseAdnot = return
  203. -- Integer Types
  204. instance FromAdnot Int where
  205. parseAdnot = withInteger "Int" (return . fromIntegral)
  206. instance FromAdnot Integer where
  207. parseAdnot = withInteger "Int" return
  208. instance FromAdnot Int8 where
  209. parseAdnot = withInteger "Int8" (return . fromIntegral)
  210. instance FromAdnot Int16 where
  211. parseAdnot = withInteger "Int16" (return . fromIntegral)
  212. instance FromAdnot Int32 where
  213. parseAdnot = withInteger "Int32" (return . fromIntegral)
  214. instance FromAdnot Int64 where
  215. parseAdnot = withInteger "Int64" (return . fromIntegral)
  216. instance FromAdnot Word where
  217. parseAdnot = withInteger "Word" (return . fromIntegral)
  218. instance FromAdnot Word8 where
  219. parseAdnot = withInteger "Word8" (return . fromIntegral)
  220. instance FromAdnot Word16 where
  221. parseAdnot = withInteger "Word16" (return . fromIntegral)
  222. instance FromAdnot Word32 where
  223. parseAdnot = withInteger "Word32" (return . fromIntegral)
  224. instance FromAdnot Word64 where
  225. parseAdnot = withInteger "Word64" (return . fromIntegral)
  226. -- Rational/Floating types
  227. instance FromAdnot Double where
  228. parseAdnot = withDouble "Double" return
  229. instance FromAdnot Float where
  230. parseAdnot =
  231. withDouble "Float" (return . fromRational . toRational)
  232. -- String types
  233. instance {-# INCOHERENT #-} FromAdnot String where
  234. parseAdnot = withString "String" (return . T.unpack)
  235. instance FromAdnot T.Text where
  236. parseAdnot = withString "Text" return
  237. instance FromAdnot TL.Text where
  238. parseAdnot = withString "Text" (return . TL.fromStrict)
  239. instance FromAdnot Char where
  240. parseAdnot = withString "Char" $ \s -> case T.uncons s of
  241. Just (c, "") -> return c
  242. _ -> Left "Expected a single-element string"
  243. -- List types
  244. instance FromAdnot a => FromAdnot [a] where
  245. parseAdnot = withList "List" $ \ls ->
  246. F.toList <$> mapM parseAdnot ls
  247. instance FromAdnot a => FromAdnot (V.Vector a) where
  248. parseAdnot = withList "Vector" $ \ls ->
  249. mapM parseAdnot ls
  250. instance FromAdnot a => FromAdnot (Seq.Seq a) where
  251. parseAdnot = withList "Seq" $ \ls ->
  252. Seq.fromList . F.toList <$> mapM parseAdnot ls
  253. instance FromAdnot a => FromAdnot (NE.NonEmpty a) where
  254. parseAdnot = withList "NonEmpty" $ \ls -> do
  255. lst <- mapM parseAdnot ls
  256. case F.toList lst of
  257. [] -> Left "Expected non-empty sequence"
  258. (x:xs) -> Right (x NE.:| xs)
  259. -- Mapping types
  260. instance FromAdnot a => FromAdnot (MS.Map T.Text a) where
  261. parseAdnot = withProduct "Map" $ \ms -> do
  262. lst <- mapM parseAdnot ms
  263. return (MS.fromList (F.toList lst))
  264. -- Tuples
  265. instance FromAdnot () where
  266. parseAdnot = withList "()" $ \ls ->
  267. case ls of
  268. [] -> return ()
  269. _ -> Left "Expected empty list"
  270. instance (FromAdnot a, FromAdnot b) => FromAdnot (a, b) where
  271. parseAdnot = withList "(a, b)" $ \ls ->
  272. case ls of
  273. [a, b] -> (,) <$> parseAdnot a <*> parseAdnot b
  274. _ -> Left "Expected two-element list"
  275. instance (FromAdnot a, FromAdnot b, FromAdnot c) => FromAdnot (a, b, c) where
  276. parseAdnot = withList "(a, b, c)" $ \ls ->
  277. case ls of
  278. [a, b, c] -> (,,) <$> parseAdnot a <*> parseAdnot b <*> parseAdnot c
  279. _ -> Left "Expected three-element list"
  280. instance (FromAdnot a, FromAdnot b, FromAdnot c, FromAdnot d)
  281. => FromAdnot (a, b, c, d) where
  282. parseAdnot = withList "(a, b, c, d)" $ \ls ->
  283. case ls of
  284. [a, b, c, d] -> (,,,) <$> parseAdnot a <*> parseAdnot b
  285. <*> parseAdnot c <*> parseAdnot d
  286. _ -> Left "Expected four-element list"
  287. -- Common Haskell algebraic data types
  288. instance FromAdnot a => FromAdnot (Maybe a) where
  289. parseAdnot = withSum "Maybe" go
  290. where go "Nothing" [] = return Nothing
  291. go "Just" [x] = Just <$> parseAdnot x
  292. go _ _ = Left "Invalid Maybe"
  293. instance (FromAdnot a, FromAdnot b) => FromAdnot (Either a b) where
  294. parseAdnot = withSum "Either" go
  295. where go "Left" [x] = Left <$> parseAdnot x
  296. go "Right" [x] = Right <$> parseAdnot x
  297. go _ _ = Left "Invalid Either"
  298. instance FromAdnot Bool where
  299. parseAdnot = withSymbol "Bool" go
  300. where go "True" = return True
  301. go "False" = return False
  302. go _ = Left "Invalid Bool"