module Dhall.Lint
(
lint
) where
import Data.List.NonEmpty (NonEmpty(..))
import Data.Semigroup ((<>))
import Dhall.Core (Binding(..), Expr(..), Import, Var(..), subExpressions)
import qualified Dhall.Core
import qualified Dhall.Optics
lint :: Expr s Import -> Expr t Import
lint = postproc . linting . preproc
where
preproc = Dhall.Optics.rewriteOf subExpressions unfoldNestedLets . Dhall.Core.denote
linting = Dhall.Optics.rewriteOf subExpressions removeUnusedBindings
postproc = Dhall.Optics.rewriteOf subExpressions removeLetInLet
removeLetInLet :: Eq a => Expr s a -> Maybe (Expr s a)
removeLetInLet (Let a (Let b c)) = Just (Let (a <> b) c)
removeLetInLet _ = Nothing
removeUnusedBindings :: Eq a => Expr s a -> Maybe (Expr s a)
removeUnusedBindings (Let (Binding a _ _ :| []) d)
| not (V a 0 `Dhall.Core.freeIn` d) =
Just (Dhall.Core.shift (-1) (V a 0) d)
removeUnusedBindings _ = Nothing
unfoldNestedLets :: Expr s a -> Maybe (Expr s a)
unfoldNestedLets (Let (b :| (l : ls)) d) = Just (Let (b :| []) (Let (l :| ls) d))
unfoldNestedLets _ = Nothing