Skip to content

Commit 876f356

Browse files
committed
Added Predefined to Dhall.TH
1 parent 4d50fd6 commit 876f356

File tree

1 file changed

+46
-31
lines changed

1 file changed

+46
-31
lines changed

dhall/src/Dhall/TH.hs

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
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)
2425
import Data.Text (Text)
2526
import Dhall (FromDhall, ToDhall)
2627
import 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`.
223228
derivingGenericClause :: 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
349358
toConstructor
@@ -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

Comments
 (0)