jsonnet-0.3.0.1: src/Language/Jsonnet/Check.hs
{- |
Module : Language.Jsonnet.Check
Copyright : (c) 2020-2021 Alexandre Moreno
SPDX-License-Identifier : BSD-3-Clause OR Apache-2.0
Maintainer : Alexandre Moreno <alexmorenocano@gmail.com>
Stability : experimental
Portability : non-portable
-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
module Language.Jsonnet.Check where
import Control.Monad.Except
import Data.Fix
import Data.Functor.Identity
import Data.List
import qualified Data.List.NonEmpty as NE
import Language.Jsonnet.Annotate
import Language.Jsonnet.Common hiding (span)
import Language.Jsonnet.Core
import Language.Jsonnet.Error
import Language.Jsonnet.Parser.SrcSpan
import Language.Jsonnet.Syntax
import Unbound.Generics.LocallyNameless
type Check = ExceptT Error IO
check :: Ann ExprF SrcSpan -> Check ()
check = foldFixM alg
where
alg (AnnF f a) = withExceptT (`CheckError` (Just a)) $ case f of
ELocal bnds _ -> checkLocal (NE.toList $ fst <$> bnds)
EFun ps _ -> checkFun (fst <$> ps)
EApply _ (Args as _) -> checkApply as
_ -> pure ()
checkLocal names = case dups names of
[] -> pure ()
(xs : _) -> throwError $ DuplicateBinding (head xs)
checkFun names = case dups names of
[] -> pure ()
(xs : _) -> throwError $ DuplicateParam (head xs)
checkApply args = case f args of
[] -> pure ()
(x : _) -> throwError $ PosAfterNamedParam
where
f args = filter isPos ns
isPos = \case
Pos _ -> True
_ -> False
(ps, ns) = span isPos args
dups = filter ((> 1) . length) . group . sort