1+ {-# LANGUAGE BangPatterns #-}
12{-# LANGUAGE CPP #-}
23{-# LANGUAGE DeriveTraversable #-}
34{-# LANGUAGE FlexibleContexts #-}
@@ -20,7 +21,7 @@ module Dhall.TH
2021 , defaultGenerateOptions
2122 ) where
2223
23- import Data.Bifunctor ( first )
24+ import Data.Map ( Map )
2425import Data.Text (Text )
2526import Dhall (FromDhall , ToDhall )
2627import Dhall.Syntax (Expr (.. ), FunctionBinding (.. ), Var (.. ))
@@ -165,6 +166,22 @@ toNestedHaskellType typeParams haskellTypes = loop
165166 message dhallType = Pretty. renderString (Dhall.Pretty. layout (document dhallType))
166167
167168 loop dhallType = case dhallType of
169+ Var v
170+ | Just (V param index) <- List. find (v == ) typeParams -> do
171+ let name = Syntax. mkName $ (Text. unpack param) ++ (show index)
172+
173+ return (VarT name)
174+
175+ | otherwise -> fail $ message v
176+
177+ _ | Just haskellType <- List. find (predicate dhallType) haskellTypes ->
178+ case haskellType of
179+ Predefined {.. } -> return haskellSplice
180+ _ -> do
181+ let name = Syntax. mkName (Text. unpack (typeName haskellType))
182+
183+ return (ConT name)
184+
168185 Bool ->
169186 return (ConT ''Bool)
170187
@@ -205,19 +222,7 @@ toNestedHaskellType typeParams haskellTypes = loop
205222
206223 return (AppT haskellAppType haskellElementType)
207224
208- Var v
209- | Just (V param index) <- List. find (v == ) typeParams -> do
210- let name = Syntax. mkName $ (Text. unpack param) ++ (show index)
211-
212- return (VarT name)
213-
214- | otherwise -> fail $ message v
215-
216- _ | Just haskellType <- List. find (predicate dhallType) haskellTypes -> do
217- let name = Syntax. mkName (Text. unpack (typeName haskellType))
218-
219- return (ConT name)
220- | otherwise -> fail $ message dhallType
225+ _ -> fail $ message dhallType
221226
222227-- | A deriving clause for `Generic`.
223228derivingGenericClause :: DerivClause
@@ -256,12 +261,8 @@ toDeclaration globalGenerateOptions haskellTypes typ =
256261 SingleConstructorWith {.. } -> uncurry (fromSingle options typeName constructorName) $ getTypeParams code
257262 MultipleConstructors {.. } -> uncurry (fromMulti globalGenerateOptions typeName) $ getTypeParams code
258263 MultipleConstructorsWith {.. } -> uncurry (fromMulti options typeName) $ getTypeParams code
264+ Predefined {} -> return []
259265 where
260- getTypeParams = first numberConsecutive . getTypeParams_ []
261-
262- getTypeParams_ acc (Lam _ (FunctionBinding _ v _ _ _) rest) = getTypeParams_ (v: acc) rest
263- getTypeParams_ acc rest = (acc, rest)
264-
265266#if MIN_VERSION_template_haskell(2,21,0)
266267 toTypeVar (V n i) = Syntax. PlainTV (Syntax. mkName (Text. unpack n ++ show i)) Syntax. BndrInvis
267268#elif MIN_VERSION_template_haskell(2,17,0)
@@ -337,13 +338,21 @@ toDeclaration globalGenerateOptions haskellTypes typ =
337338 , " ... which is not a union type."
338339 ]
339340
340- -- | Number each variable, starting at 0
341- numberConsecutive :: [Text. Text ] -> [Var ]
342- numberConsecutive = snd . List. mapAccumR go Map. empty . reverse
341+ getTypeParams :: Expr s a -> ([Var ], Expr s a )
342+ getTypeParams = go []
343343 where
344- go m k =
345- let (i, m') = Map. updateLookupWithKey (\ _ j -> Just $ j + 1 ) k m
346- in maybe ((Map. insert k 0 m'), (V k 0 )) (\ i' -> (m', (V k i'))) i
344+ go :: [Text ] -> Expr s a -> ([Var ], Expr s a )
345+ go ! acc (Lam _ (FunctionBinding _ v _ _ _) rest) = go (v: acc) rest
346+ go ! acc rest = (numberConsecutive $ reverse acc, rest)
347+
348+ -- | Number each variable, starting at 0
349+ numberConsecutive :: [Text. Text ] -> [Var ]
350+ numberConsecutive = snd . List. mapAccumR numberVar Map. empty
351+
352+ numberVar :: Map Text Int -> Text -> (Map Text Int , Var )
353+ numberVar m k =
354+ let (i, m') = Map. updateLookupWithKey (\ _ j -> Just $ j + 1 ) k m
355+ in maybe ((Map. insert k 0 m'), (V k 0 )) (\ i' -> (m', (V k i'))) i
347356
348357-- | Convert a Dhall type to the corresponding Haskell constructor
349358toConstructor
@@ -439,8 +448,8 @@ data HaskellType code
439448 , code :: code
440449 -- ^ Dhall code that evaluates to a type
441450 }
442- -- | Generate a Haskell type with more than one constructor from a Dhall
443- -- union type.
451+ -- | Like 'MultipleConstructors', but also takes some 'GenerateOptions' to
452+ -- use for the generation of the Haskell type.
444453 | MultipleConstructorsWith
445454 { options :: GenerateOptions
446455 -- ^ The 'GenerateOptions' to use then generating the Haskell type.
@@ -449,10 +458,8 @@ data HaskellType code
449458 , code :: code
450459 -- ^ Dhall code that evaluates to a union type
451460 }
452- -- | Generate a Haskell type with one constructor from any Dhall type.
453- --
454- -- To generate a constructor with multiple named fields, supply a Dhall
455- -- record type. This does not support more than one anonymous field.
461+ -- | Like 'SingleConstructor', but also takes some 'GenerateOptions' to use
462+ -- for the generation of the Haskell type.
456463 | SingleConstructorWith
457464 { options :: GenerateOptions
458465 -- ^ The 'GenerateOptions' to use then generating the Haskell type.
@@ -463,6 +470,14 @@ data HaskellType code
463470 , code :: code
464471 -- ^ Dhall code that evaluates to a type
465472 }
473+ -- | Declare a predefined mapping from a Dhall type to an existing Haskell
474+ -- type.
475+ | Predefined
476+ { haskellSplice :: Type
477+ -- ^ An existing Haskell type
478+ , code :: code
479+ -- ^ Dhall code that evaluates to a type
480+ }
466481 deriving (Functor , Foldable , Traversable )
467482
468483-- | This data type holds various options that let you control several aspects
0 commit comments