Skip to content

Commit e9f37ae

Browse files
authored
Dhall.TH: Call addDependentFile for each local import (#2620)
* Dhall.TH: Import Template Haskell module qualified as TH * Dhall.TH: Register local imports for recompiliation checking We call Language.Haskell.TH.addDependentFile for each local import so that GHC rebuilds if those files changes.
1 parent 3cf9506 commit e9f37ae

File tree

2 files changed

+60
-25
lines changed

2 files changed

+60
-25
lines changed

dhall/src/Dhall.hs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ module Dhall
5050
-- * Individual phases
5151
, parseWithSettings
5252
, resolveWithSettings
53+
, resolveAndStatusWithSettings
5354
, typecheckWithSettings
5455
, checkWithSettings
5556
, expectWithSettings
@@ -63,7 +64,7 @@ import Control.Applicative (Alternative, empty)
6364
import Control.Monad.Catch (MonadThrow, throwM)
6465
import Data.Either.Validation (Validation (..))
6566
import Data.Void (Void)
66-
import Dhall.Import (Imported (..))
67+
import Dhall.Import (Imported (..), Status)
6768
import Dhall.Parser (Src (..))
6869
import Dhall.Syntax (Expr (..), Import)
6970
import Dhall.TypeCheck (DetailedTypeError (..), TypeError)
@@ -262,7 +263,16 @@ expectWithSettings settings Decoder{..} expression = do
262263
`InputSettings`
263264
-}
264265
resolveWithSettings :: InputSettings -> Expr Src Import -> IO (Expr Src Void)
265-
resolveWithSettings settings expression = do
266+
resolveWithSettings settings expression =
267+
fst <$> resolveAndStatusWithSettings settings expression
268+
269+
-- | A version of 'resolveWithSettings' that also returns the import 'Status'
270+
-- together with the resolved expression.
271+
resolveAndStatusWithSettings
272+
:: InputSettings
273+
-> Expr Src Import
274+
-> IO (Expr Src Void, Status)
275+
resolveAndStatusWithSettings settings expression = do
266276
let InputSettings{..} = settings
267277

268278
let EvaluateSettings{..} = _evaluateSettings
@@ -274,9 +284,11 @@ resolveWithSettings settings expression = do
274284

275285
let status = transform (Dhall.Import.emptyStatusWithManager _newManager _rootDirectory)
276286

277-
resolved <- State.evalStateT (Dhall.Import.loadWith expression) status
287+
(resolved, status') <- State.runStateT (Dhall.Import.loadWith expression) status
288+
289+
let substituted = Dhall.Substitution.substitute resolved (view substitutions settings)
278290

279-
pure (Dhall.Substitution.substitute resolved (view substitutions settings))
291+
pure (substituted, status')
280292

281293
-- | Normalize an expression, using the supplied `InputSettings`
282294
normalizeWithSettings :: InputSettings -> Expr Src Void -> Expr Src Void

dhall/src/Dhall/TH.hs

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ module Dhall.TH
2020
, defaultGenerateOptions
2121
) where
2222

23+
import Control.Monad (forM_)
2324
import Data.Bifunctor (first)
2425
import Data.Text (Text)
2526
import Dhall (FromDhall, ToDhall)
2627
import Dhall.Syntax (Expr (..), FunctionBinding (..), Var (..))
2728
import GHC.Generics (Generic)
2829
import Language.Haskell.TH.Quote (QuasiQuoter (..), dataToExpQ)
30+
import Lens.Family (view)
2931
import Prettyprinter (Pretty)
3032

3133
import Language.Haskell.TH.Syntax
@@ -52,11 +54,12 @@ import qualified Data.Time as Time
5254
import qualified Data.Typeable as Typeable
5355
import qualified Dhall
5456
import qualified Dhall.Core as Core
57+
import qualified Dhall.Import
5558
import qualified Dhall.Map
5659
import qualified Dhall.Pretty
5760
import qualified Dhall.Util
5861
import qualified GHC.IO.Encoding
59-
import qualified Language.Haskell.TH.Syntax as Syntax
62+
import qualified Language.Haskell.TH.Syntax as TH
6063
import qualified Numeric.Natural
6164
import qualified Prettyprinter.Render.String as Pretty
6265
import qualified System.IO
@@ -88,15 +91,35 @@ import qualified System.IO
8891
-}
8992
staticDhallExpression :: Text -> Q Exp
9093
staticDhallExpression text = do
91-
Syntax.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)
94+
TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)
9295

93-
expression <- Syntax.runIO (Dhall.inputExpr text)
96+
(expression, status) <- TH.runIO $ do
97+
parsed <- Dhall.parseWithSettings Dhall.defaultInputSettings text
98+
99+
(resolved, status) <- Dhall.resolveAndStatusWithSettings Dhall.defaultInputSettings parsed
100+
101+
_ <- Dhall.typecheckWithSettings Dhall.defaultInputSettings resolved
102+
103+
let normalized = Dhall.normalizeWithSettings Dhall.defaultInputSettings resolved
104+
105+
pure (normalized, status)
106+
107+
forM_ (Dhall.Map.keys (view Dhall.Import.cache status)) $ \chained ->
108+
case Dhall.Import.chainedImport chained of
109+
Core.Import
110+
{ importHashed = Core.ImportHashed
111+
{ importType = Core.Local prefix file
112+
}
113+
} -> do
114+
fp <- Dhall.Import.localToPath prefix file
115+
TH.addDependentFile fp
116+
_ -> return ()
94117

95118
dataToExpQ (fmap liftText . Typeable.cast) expression
96119
where
97120
-- A workaround for a problem in TemplateHaskell (see
98121
-- https://stackoverflow.com/questions/38143464/cant-find-inerface-file-declaration-for-variable)
99-
liftText = fmap (AppE (VarE 'Text.pack)) . Syntax.lift . Text.unpack
122+
liftText = fmap (AppE (VarE 'Text.pack)) . TH.lift . Text.unpack
100123

101124
{-| A quasi-quoter for Dhall expressions.
102125
@@ -207,14 +230,14 @@ toNestedHaskellType typeParams haskellTypes = loop
207230

208231
Var v
209232
| Just (V param index) <- List.find (v ==) typeParams -> do
210-
let name = Syntax.mkName $ (Text.unpack param) ++ (show index)
233+
let name = TH.mkName $ (Text.unpack param) ++ (show index)
211234

212235
return (VarT name)
213236

214237
| otherwise -> fail $ message v
215238

216239
_ | Just haskellType <- List.find (predicate dhallType) haskellTypes -> do
217-
let name = Syntax.mkName (Text.unpack (typeName haskellType))
240+
let name = TH.mkName (Text.unpack (typeName haskellType))
218241

219242
return (ConT name)
220243
| otherwise -> fail $ message dhallType
@@ -225,7 +248,7 @@ derivingGenericClause = DerivClause (Just StockStrategy) [ ConT ''Generic ]
225248

226249
-- | Generates a `FromDhall` instances.
227250
fromDhallInstance
228-
:: Syntax.Name -- ^ The name of the type the instances is for
251+
:: TH.Name -- ^ The name of the type the instances is for
229252
-> Q Exp -- ^ A TH splice generating some `Dhall.InterpretOptions`
230253
-> Q [Dec]
231254
fromDhallInstance n interpretOptions = [d|
@@ -235,7 +258,7 @@ fromDhallInstance n interpretOptions = [d|
235258

236259
-- | Generates a `ToDhall` instances.
237260
toDhallInstance
238-
:: Syntax.Name -- ^ The name of the type the instances is for
261+
:: TH.Name -- ^ The name of the type the instances is for
239262
-> Q Exp -- ^ A TH splice generating some `Dhall.InterpretOptions`
240263
-> Q [Dec]
241264
toDhallInstance n interpretOptions = [d|
@@ -265,15 +288,15 @@ toDeclaration generateOptions@GenerateOptions{..} haskellTypes typ =
265288
interpretOptions = generateToInterpretOptions generateOptions typ
266289

267290
#if MIN_VERSION_template_haskell(2,21,0)
268-
toTypeVar (V n i) = Syntax.PlainTV (Syntax.mkName (Text.unpack n ++ show i)) Syntax.BndrReq
291+
toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) TH.BndrReq
269292
#elif MIN_VERSION_template_haskell(2,17,0)
270-
toTypeVar (V n i) = Syntax.PlainTV (Syntax.mkName (Text.unpack n ++ show i)) ()
293+
toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) ()
271294
#else
272-
toTypeVar (V n i) = Syntax.PlainTV (Syntax.mkName (Text.unpack n ++ show i))
295+
toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i))
273296
#endif
274297

275298
toDataD typeName typeParams constructors = do
276-
let name = Syntax.mkName (Text.unpack typeName)
299+
let name = TH.mkName (Text.unpack typeName)
277300

278301
let params = fmap toTypeVar typeParams
279302

@@ -355,7 +378,7 @@ toConstructor
355378
-- ^ @(constructorName, fieldType)@
356379
-> Q Con
357380
toConstructor typeParams GenerateOptions{..} haskellTypes outerTypeName (constructorName, maybeAlternativeType) = do
358-
let name = Syntax.mkName (Text.unpack $ constructorModifier constructorName)
381+
let name = TH.mkName (Text.unpack $ constructorModifier constructorName)
359382

360383
let strictness = if makeStrict then SourceStrict else NoSourceStrictness
361384

@@ -368,15 +391,15 @@ toConstructor typeParams GenerateOptions{..} haskellTypes outerTypeName (constru
368391
&& typeName haskellType /= outerTypeName
369392
, Just haskellType <- List.find predicate haskellTypes -> do
370393
let innerName =
371-
Syntax.mkName (Text.unpack (typeName haskellType))
394+
TH.mkName (Text.unpack (typeName haskellType))
372395

373396
return (NormalC name [ (bang, ConT innerName) ])
374397

375398
Just (Record kts) -> do
376399
let process (key, dhallFieldType) = do
377400
haskellFieldType <- toNestedHaskellType typeParams haskellTypes dhallFieldType
378401

379-
return (Syntax.mkName (Text.unpack $ fieldModifier key), bang, haskellFieldType)
402+
return (TH.mkName (Text.unpack $ fieldModifier key), bang, haskellFieldType)
380403

381404
varBangTypes <- traverse process (Dhall.Map.toList $ Core.recordFieldValue <$> kts)
382405

@@ -508,16 +531,16 @@ generateToInterpretOptions GenerateOptions{..} haskellType = [| Dhall.InterpretO
508531
mkMatch n = Match (textToPat $ f n) (NormalB $ textToExp n) []
509532

510533
nameE :: Exp
511-
nameE = Syntax.VarE $ Syntax.mkName "n"
534+
nameE = TH.VarE $ TH.mkName "n"
512535

513536
nameP :: Pat
514-
nameP = Syntax.VarP $ Syntax.mkName "n"
537+
nameP = TH.VarP $ TH.mkName "n"
515538

516539
textToExp :: Text -> Exp
517-
textToExp = Syntax.LitE . Syntax.StringL . Text.unpack
540+
textToExp = TH.LitE . TH.StringL . Text.unpack
518541

519542
textToPat :: Text -> Pat
520-
textToPat = Syntax.LitP . Syntax.StringL . Text.unpack
543+
textToPat = TH.LitP . TH.StringL . Text.unpack
521544

522545
-- | Generate a Haskell datatype declaration with one constructor from a Dhall
523546
-- type.
@@ -605,8 +628,8 @@ makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions
605628
-- > makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions
606629
makeHaskellTypesWith :: GenerateOptions -> [HaskellType Text] -> Q [Dec]
607630
makeHaskellTypesWith generateOptions haskellTypes = do
608-
Syntax.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)
631+
TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)
609632

610-
haskellTypes' <- traverse (traverse (Syntax.runIO . Dhall.inputExpr)) haskellTypes
633+
haskellTypes' <- traverse (traverse (TH.runIO . Dhall.inputExpr)) haskellTypes
611634

612635
concat <$> traverse (toDeclaration generateOptions haskellTypes') haskellTypes'

0 commit comments

Comments
 (0)