@@ -17,38 +17,51 @@ import Nix.Parser
1717
1818quoteExprExp :: String -> ExpQ
1919quoteExprExp s = do
20- expr <-
21- either
22- (fail . show )
23- pure
24- (parseNixText $ toText s)
20+ expr <- parseExpr s
2521 dataToExpQ
26- (const Nothing `extQ` metaExp (freeVars expr) `extQ` (pure . (TH. lift :: Text -> Q Exp )))
22+ (extQOnFreeVars metaExp expr `extQ` (pure . (TH. lift :: Text -> Q Exp )))
2723 expr
2824
2925quoteExprPat :: String -> PatQ
3026quoteExprPat s = do
31- expr <-
32- either
33- (fail . show )
34- pure
35- (parseNixText $ toText s)
27+ expr <- parseExpr s
3628 dataToPatQ
37- (const Nothing `extQ` metaPat (freeVars expr) )
29+ (extQOnFreeVars metaPat expr)
3830 expr
3931
32+ -- | Helper function.
33+ extQOnFreeVars
34+ :: ( Typeable b
35+ , Typeable loc
36+ )
37+ => ( Set VarName
38+ -> loc
39+ -> Maybe q
40+ )
41+ -> NExpr
42+ -> b
43+ -> Maybe q
44+ extQOnFreeVars f e = extQ (const Nothing ) (f $ freeVars e)
45+
46+ parseExpr :: (MonadFail m , ToText a ) => a -> m NExpr
47+ parseExpr s =
48+ either
49+ (fail . show )
50+ pure
51+ (parseNixText $ toText s)
52+
4053freeVars :: NExpr -> Set VarName
4154freeVars e = case unFix e of
4255 (NConstant _ ) -> mempty
4356 (NStr string ) -> mapFreeVars string
4457 (NSym var ) -> one var
4558 (NList list ) -> mapFreeVars list
46- (NSet NNonRecursive bindings) -> bindFreeVars bindings
47- (NSet NRecursive bindings) -> Set. difference ( bindFreeVars bindings) ( bindDefs bindings)
59+ (NSet NonRecursive bindings) -> bindFreeVars bindings
60+ (NSet Recursive bindings) -> diffBetween bindFreeVars bindDefs bindings
4861 (NLiteralPath _ ) -> mempty
4962 (NEnvPath _ ) -> mempty
5063 (NUnary _ expr ) -> freeVars expr
51- (NBinary _ left right ) -> ( (<>) `on` freeVars) left right
64+ (NBinary _ left right ) -> collectFreeVars left right
5265 (NSelect expr path orExpr) ->
5366 Set. unions
5467 [ freeVars expr
@@ -69,18 +82,22 @@ freeVars e = case unFix e of
6982 )
7083 (NLet bindings expr ) ->
7184 freeVars expr <>
72- Set. difference
73- (bindFreeVars bindings)
74- (bindDefs bindings)
85+ diffBetween bindFreeVars bindDefs bindings
7586 (NIf cond th el ) -> Set. unions $ freeVars <$> [cond, th, el]
7687 -- Evaluation is needed to find out whether x is a "real" free variable in `with y; x`, we just include it
7788 -- This also makes sense because its value can be overridden by `x: with y; x`
78- (NWith set expr ) -> ( (<>) `on` freeVars) set expr
79- (NAssert assertion expr ) -> ( (<>) `on` freeVars) assertion expr
89+ (NWith set expr ) -> collectFreeVars set expr
90+ (NAssert assertion expr ) -> collectFreeVars assertion expr
8091 (NSynHole _ ) -> mempty
8192
8293 where
8394
95+ diffBetween :: (a -> Set VarName ) -> (a -> Set VarName ) -> a -> Set VarName
96+ diffBetween g f b = Set. difference (g b) (f b)
97+
98+ collectFreeVars :: NExpr -> NExpr -> Set VarName
99+ collectFreeVars = (<>) `on` freeVars
100+
84101 bindDefs :: Foldable t => t (Binding NExpr ) -> Set VarName
85102 bindDefs = foldMap bind1Def
86103 where
0 commit comments