{-# language DataKinds, TypeOperators #-}
{-# language GeneralizedNewtypeDeriving #-}
{-# language TemplateHaskell, TypeFamilies, FlexibleInstances, MultiParamTypeClasses #-}
{-# language FlexibleContexts #-}
{-# language RankNTypes #-}
{-# language LambdaCase #-}
{-# language ScopedTypeVariables, TypeApplications #-}
module Language.Python.Validate.Scope
( module Data.Validation
, module Language.Python.Validate.Scope.Error
, Scope, ValidateScope, runValidateScope
, validateModuleScope
, validateStatementScope
, validateExprScope
, ScopeContext(..), scGlobalScope, scLocalScope, scImmediateScope
, runValidateScope'
, initialScopeContext
, Binding(..)
, inScope
, extendScope
, locallyOver
, locallyExtendOver
, validateArgScope
, validateAssignExprScope
, validateBlockScope
, validateCompoundStatementScope
, validateComprehensionScope
, validateDecoratorScope
, validateDictItemScope
, validateExceptAsScope
, validateIdentScope
, validateListItemScope
, validateParamScope
, validateSetItemScope
, validateSimpleStatementScope
, validateSubscriptScope
, validateSuiteScope
, validateTupleItemScope
)
where
import Data.Validation
import Control.Arrow ((&&&))
import Control.Applicative ((<|>))
import Control.Lens.Cons (snoc)
import Control.Lens.Fold ((^..), toListOf, folded)
import Control.Lens.Getter ((^.), to, getting, use)
import Control.Lens.Lens (Lens')
import Control.Lens.Plated (cosmos)
import Control.Lens.Prism (_Right, _Just)
import Control.Lens.Review ((#))
import Control.Lens.Setter ((%~), (.~), Setter', mapped, over)
import Control.Lens.TH (makeLenses)
import Control.Lens.Tuple (_2, _3)
import Control.Lens.Traversal (traverseOf)
import Control.Monad.State (MonadState, State, evalState, modify)
import Data.Bitraversable (bitraverse)
import Data.ByteString (ByteString)
import Data.Coerce (coerce)
import Data.Foldable (traverse_)
import Data.Functor.Compose (Compose(..))
import Data.List.NonEmpty (NonEmpty(..))
import Data.Map.Strict (Map)
import Data.String (fromString)
import Data.Type.Set (Nub)
import Data.Validate.Monadic (ValidateM(..), runValidateM, bindVM, liftVM0, errorVM1)
import Unsafe.Coerce (unsafeCoerce)
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Map.Strict as Map
import Language.Python.Optics
import Language.Python.Optics.Validated (unvalidated)
import Language.Python.Syntax.Statement
import Language.Python.Syntax.Expr
import Language.Python.Syntax.Ident
import Language.Python.Syntax.Module
import Language.Python.Validate.Scope.Error
data Scope
data Binding = Clean | Dirty
deriving (Eq, Ord, Show)
data ScopeContext a
= ScopeContext
{ _scGlobalScope :: !(Map ByteString a)
, _scLocalScope :: !(Map ByteString a)
, _scImmediateScope :: !(Map ByteString a)
}
deriving (Eq, Show)
makeLenses ''ScopeContext
initialScopeContext :: ScopeContext a
initialScopeContext = ScopeContext Map.empty Map.empty Map.empty
type ValidateScope ann e = ValidateM (NonEmpty e) (State (ScopeContext ann))
runValidateScope :: ValidateScope ann e a -> Validation (NonEmpty e) a
runValidateScope = runValidateScope' initialScopeContext
runValidateScope' :: ScopeContext ann -> ValidateScope ann e a -> Validation (NonEmpty e) a
runValidateScope' s = flip evalState s . runValidateM
extendScope
:: Setter' (ScopeContext ann) (Map ByteString ann)
-> [(ann, String)]
-> ValidateScope ann e ()
extendScope l s =
liftVM0 $ do
gs <- use scGlobalScope
let t = buildMap gs Map.empty
modify (over l (t `unionL`))
where
buildMap gs t =
foldr
(\(ann, a) b ->
let
a' = fromString a
in
if Map.member a' gs
then b
else Map.insert a' ann b)
t
s
locallyOver
:: Lens' (ScopeContext ann) b
-> (b -> b)
-> ValidateScope ann e a
-> ValidateScope ann e a
locallyOver l f m =
ValidateM . Compose $ do
before <- use l
modify (l %~ f)
getCompose (unValidateM m) <* modify (l .~ before)
locallyExtendOver
:: Lens' (ScopeContext ann) (Map ByteString ann)
-> [(ann, String)]
-> ValidateScope ann e a
-> ValidateScope ann e a
locallyExtendOver l s m = locallyOver l id $ extendScope l s *> m
inScope
:: MonadState (ScopeContext ann) m
=> String
-> m (Maybe (Binding, ann))
inScope s = do
gs <- use scGlobalScope
ls <- use scLocalScope
is <- use scImmediateScope
let
s' = fromString s
inls = Map.lookup s' ls
ings = Map.lookup s' gs
pure $
((,) Clean <$> Map.lookup s' is) <|>
(ings *> ((,) Clean <$> inls)) <|>
((,) Clean <$> ings) <|>
((,) Dirty <$> inls)
validateExceptAsScope
:: AsScopeError e a
=> ExceptAs v a
-> ValidateScope a e (ExceptAs (Nub (Scope ': v)) a)
validateExceptAsScope (ExceptAs ann e f) =
ExceptAs ann <$>
validateExprScope e <*>
pure (over (mapped._2) coerce f)
validateSuiteScope
:: AsScopeError e a
=> Suite v a
-> ValidateScope a e (Suite (Nub (Scope ': v)) a)
validateSuiteScope (SuiteMany ann a b c d) = SuiteMany ann a b c <$> validateBlockScope d
validateSuiteScope (SuiteOne ann a b) =
SuiteOne ann a <$> validateSmallStatementScope b
validateDecoratorScope
:: AsScopeError e a
=> Decorator v a
-> ValidateScope a e (Decorator (Nub (Scope ': v)) a)
validateDecoratorScope (Decorator a b c d e f g) =
(\d' -> Decorator a b c d' e f g) <$>
validateExprScope d
validateCompoundStatementScope
:: forall e v a
. AsScopeError e a
=> CompoundStatement v a
-> ValidateScope a e (CompoundStatement (Nub (Scope ': v)) a)
validateCompoundStatementScope (Fundef a decos idnts asyncWs ws1 name ws2 params ws3 mty s) =
(locallyOver scLocalScope (const Map.empty) $
locallyOver scImmediateScope (const Map.empty) $
(\decos' -> Fundef a decos' idnts asyncWs ws1 (coerce name) ws2) <$>
traverse validateDecoratorScope decos <*>
traverse validateParamScope params <*>
pure ws3 <*>
traverseOf (traverse._2) validateExprScope mty <*>
locallyExtendOver
scGlobalScope
((_identAnn &&& _identValue) name :
toListOf (folded.getting paramName.to (_identAnn &&& _identValue)) params)
(validateSuiteScope s)) <*
extendScope scLocalScope [(_identAnn &&& _identValue) name] <*
extendScope scImmediateScope [(_identAnn &&& _identValue) name]
validateCompoundStatementScope (If idnts a ws1 e b elifs melse) =
use scLocalScope `bindVM` (\ls ->
use scImmediateScope `bindVM` (\is ->
locallyOver scGlobalScope (`unionR` unionR ls is) $
locallyOver scImmediateScope (const Map.empty)
(If idnts a ws1 <$>
validateExprScope e <*>
validateSuiteScope b <*>
traverse
(\(a, b, c, d) ->
(\c' -> (,,,) a b c') <$>
validateExprScope c <*>
validateSuiteScope d)
elifs <*>
traverseOf (traverse._3) validateSuiteScope melse)))
validateCompoundStatementScope (While idnts a ws1 e b els) =
use scLocalScope `bindVM` (\ls ->
use scImmediateScope `bindVM` (\is ->
locallyOver scGlobalScope (`unionR` unionR ls is) $
locallyOver scImmediateScope (const Map.empty)
(While idnts a ws1 <$>
validateExprScope e <*>
validateSuiteScope b <*>
traverseOf (traverse._3) validateSuiteScope els)))
validateCompoundStatementScope (TryExcept idnts a b e f k l) =
use scLocalScope `bindVM` (\ls ->
use scImmediateScope `bindVM` (\is ->
locallyOver scGlobalScope (`unionR` unionR ls is) $
locallyOver scImmediateScope (const Map.empty)
(TryExcept idnts a b <$>
validateSuiteScope e <*>
traverse
(\(idnts, ws, g, h) ->
(,,,) idnts ws <$>
traverse validateExceptAsScope g <*>
locallyExtendOver
scGlobalScope
(toListOf (folded.exceptAsName._Just._2.to (_identAnn &&& _identValue)) g)
(validateSuiteScope h))
f <*>
traverseOf (traverse._3) validateSuiteScope k <*>
traverseOf (traverse._3) validateSuiteScope l)))
validateCompoundStatementScope (TryFinally idnts a b e idnts2 f i) =
use scLocalScope `bindVM` (\ls ->
use scImmediateScope `bindVM` (\is ->
locallyOver scGlobalScope (`unionR` unionR ls is) $
locallyOver scImmediateScope (const Map.empty)
(TryFinally idnts a b <$>
validateSuiteScope e <*>
pure idnts2 <*>
pure f <*>
validateSuiteScope i)))
validateCompoundStatementScope (For idnts a asyncWs b c d e h i) =
use scLocalScope `bindVM` (\ls ->
use scImmediateScope `bindVM` (\is ->
locallyOver scGlobalScope (`unionR` unionR ls is) $
locallyOver scImmediateScope (const Map.empty) $
For @(Nub (Scope ': v)) idnts a asyncWs b <$>
(unsafeCoerce c <$
traverse
(\s ->
inScope (s ^. identValue) `bindVM` \res ->
maybe (pure ()) (\_ -> errorVM1 (_BadShadowing # coerce s)) res)
(c ^.. unvalidated.cosmos._Ident)) <*>
pure d <*>
traverse validateExprScope e <*>
(let
ls = c ^.. unvalidated.cosmos._Ident.to (_identAnn &&& _identValue)
in
extendScope scLocalScope ls *>
extendScope scImmediateScope ls *>
validateSuiteScope h) <*>
traverseOf (traverse._3) validateSuiteScope i))
validateCompoundStatementScope (ClassDef a decos idnts b c d g) =
(\decos' -> ClassDef @(Nub (Scope ': v)) a decos' idnts b (coerce c)) <$>
traverse validateDecoratorScope decos <*>
traverseOf (traverse._2.traverse.traverse) validateArgScope d <*>
validateSuiteScope g <*
extendScope scImmediateScope [c ^. to (_identAnn &&& _identValue)]
validateCompoundStatementScope (With a b asyncWs c d e) =
let
names =
d ^..
folded.unvalidated.to _withItemBinder.folded._2.
assignTargets.to (_identAnn &&& _identValue)
in
With @(Nub (Scope ': v)) a b asyncWs c <$>
traverse
(\(WithItem a b c) ->
WithItem @(Nub (Scope ': v)) a <$>
validateExprScope b <*>
traverseOf (traverse._2) validateAssignExprScope c)
d <*
extendScope scLocalScope names <*
extendScope scImmediateScope names <*>
validateSuiteScope e
validateSimpleStatementScope
:: AsScopeError e a
=> SimpleStatement v a
-> ValidateScope a e (SimpleStatement (Nub (Scope ': v)) a)
validateSimpleStatementScope (Assert a b c d) =
Assert a b <$>
validateExprScope c <*>
traverseOf (traverse._2) validateExprScope d
validateSimpleStatementScope (Raise a ws f) =
Raise a ws <$>
traverse
(\(b, c) ->
(,) <$>
validateExprScope b <*>
traverseOf (traverse._2) validateExprScope c)
f
validateSimpleStatementScope (Return a ws e) = Return a ws <$> traverse validateExprScope e
validateSimpleStatementScope (Expr a e) = Expr a <$> validateExprScope e
validateSimpleStatementScope (Assign a l rs) =
let
ls =
(l : (snd <$> NonEmpty.init rs)) ^..
folded.unvalidated.assignTargets.to (_identAnn &&& _identValue)
in
Assign a <$>
validateAssignExprScope l <*>
((\a b -> case a of; [] -> b :| []; a : as -> a :| snoc as b) <$>
traverseOf (traverse._2) validateAssignExprScope (NonEmpty.init rs) <*>
(\(ws, b) -> (,) ws <$> validateExprScope b) (NonEmpty.last rs)) <*
extendScope scLocalScope ls <*
extendScope scImmediateScope ls
validateSimpleStatementScope (AugAssign a l aa r) =
(\l' -> AugAssign a l' aa) <$>
validateExprScope l <*>
validateExprScope r
validateSimpleStatementScope (Global a _ _) = errorVM1 (_FoundGlobal # a)
validateSimpleStatementScope (Nonlocal a _ _) = errorVM1 (_FoundNonlocal # a)
validateSimpleStatementScope (Del a ws cs) =
Del a ws <$
traverse_
(\case; Ident a -> errorVM1 (_DeletedIdent # (a ^. identAnn)); _ -> pure ())
cs <*>
traverse validateExprScope cs
validateSimpleStatementScope s@Pass{} = pure $ unsafeCoerce s
validateSimpleStatementScope s@Break{} = pure $ unsafeCoerce s
validateSimpleStatementScope s@Continue{} = pure $ unsafeCoerce s
validateSimpleStatementScope s@Import{} = pure $ unsafeCoerce s
validateSimpleStatementScope s@From{} = pure $ unsafeCoerce s
validateSmallStatementScope
:: AsScopeError e a
=> SmallStatement v a
-> ValidateScope a e (SmallStatement (Nub (Scope ': v)) a)
validateSmallStatementScope (MkSmallStatement s ss sc cmt nl) =
(\s' ss' -> MkSmallStatement s' ss' sc cmt nl) <$>
validateSimpleStatementScope s <*>
traverseOf (traverse._2) validateSimpleStatementScope ss
validateStatementScope
:: AsScopeError e a
=> Statement v a
-> ValidateScope a e (Statement (Nub (Scope ': v)) a)
validateStatementScope (CompoundStatement c) =
CompoundStatement <$> validateCompoundStatementScope c
validateStatementScope (SmallStatement idnts a) =
SmallStatement idnts <$> validateSmallStatementScope a
validateIdentScope
:: AsScopeError e a
=> Ident v a
-> ValidateScope a e (Ident (Nub (Scope ': v)) a)
validateIdentScope i =
inScope (_identValue i) `bindVM`
\context ->
case context of
Just (Clean, _) -> pure $ coerce i
Just (Dirty, ann)-> errorVM1 (_FoundDynamic # (ann, i ^. unvalidated))
Nothing -> errorVM1 (_NotInScope # (i ^. unvalidated))
validateArgScope
:: AsScopeError e a
=> Arg v a
-> ValidateScope a e (Arg (Nub (Scope ': v)) a)
validateArgScope (PositionalArg a e) =
PositionalArg a <$> validateExprScope e
validateArgScope (KeywordArg a ident ws2 expr) =
KeywordArg a (coerce ident) ws2 <$> validateExprScope expr
validateArgScope (StarArg a ws e) =
StarArg a ws <$> validateExprScope e
validateArgScope (DoubleStarArg a ws e) =
DoubleStarArg a ws <$> validateExprScope e
validateParamScope
:: AsScopeError e a
=> Param v a
-> ValidateScope a e (Param (Nub (Scope ': v)) a)
validateParamScope (PositionalParam a ident mty) =
PositionalParam a (coerce ident) <$>
traverseOf (traverse._2) validateExprScope mty
validateParamScope (KeywordParam a ident mty ws2 expr) =
KeywordParam a (coerce ident) <$>
traverseOf (traverse._2) validateExprScope mty <*>
pure ws2 <*>
validateExprScope expr
validateParamScope (StarParam a b c d) =
StarParam a b (coerce c) <$>
traverseOf (traverse._2) validateExprScope d
validateParamScope (UnnamedStarParam a b) = pure $ UnnamedStarParam a b
validateParamScope (DoubleStarParam a b c d) =
DoubleStarParam a b (coerce c) <$>
traverseOf (traverse._2) validateExprScope d
validateBlockScope
:: AsScopeError e a
=> Block v a
-> ValidateScope a e (Block (Nub (Scope ': v)) a)
validateBlockScope (Block x b bs) =
Block x <$>
validateStatementScope b <*>
traverseOf (traverse._Right) validateStatementScope bs
validateComprehensionScope
:: AsScopeError e a
=> (ex v a -> ValidateScope a e (ex (Nub (Scope ': v)) a))
-> Comprehension ex v a
-> ValidateScope a e (Comprehension ex (Nub (Scope ': v)) a)
validateComprehensionScope f (Comprehension a b c d) =
locallyOver scGlobalScope id $
(\c' d' b' -> Comprehension a b' c' d') <$>
validateCompForScope c <*>
traverse (bitraverse validateCompForScope validateCompIfScope) d <*>
f b
where
validateCompForScope
:: AsScopeError e a
=> CompFor v a
-> ValidateScope a e (CompFor (Nub (Scope ': v)) a)
validateCompForScope (CompFor a b c d e) =
(\c' -> CompFor a b c' d) <$>
validateAssignExprScope c <*>
validateExprScope e <*
extendScope scGlobalScope
(c ^.. unvalidated.assignTargets.to (_identAnn &&& _identValue))
validateCompIfScope
:: AsScopeError e a
=> CompIf v a
-> ValidateScope a e (CompIf (Nub (Scope ': v)) a)
validateCompIfScope (CompIf a b c) =
CompIf a b <$> validateExprScope c
validateAssignExprScope
:: AsScopeError e a
=> Expr v a
-> ValidateScope a e (Expr (Nub (Scope ': v)) a)
validateAssignExprScope (Subscript a e1 ws1 e2 ws2) =
(\e1' e2' -> Subscript a e1' ws1 e2' ws2) <$>
validateAssignExprScope e1 <*>
traverse validateSubscriptScope e2
validateAssignExprScope (List a ws1 es ws2) =
List a ws1 <$>
traverseOf (traverse.traverse) listItem es <*>
pure ws2
where
listItem (ListItem a b) = ListItem a <$> validateAssignExprScope b
listItem (ListUnpack a b c d) = ListUnpack a b c <$> validateAssignExprScope d
validateAssignExprScope (Deref a e ws1 r) =
Deref a <$>
validateExprScope e <*>
pure ws1 <*>
validateIdentScope r
validateAssignExprScope (Parens a ws1 e ws2) =
Parens a ws1 <$>
validateAssignExprScope e <*>
pure ws2
validateAssignExprScope (Tuple a b ws d) =
Tuple a <$>
tupleItem b <*>
pure ws <*>
traverseOf (traverse.traverse) tupleItem d
where
tupleItem (TupleItem a b) = TupleItem a <$> validateAssignExprScope b
tupleItem (TupleUnpack a b c d) = TupleUnpack a b c <$> validateAssignExprScope d
validateAssignExprScope e@Unit{} = pure $ unsafeCoerce e
validateAssignExprScope e@Lambda{} = pure $ unsafeCoerce e
validateAssignExprScope e@Yield{} = pure $ unsafeCoerce e
validateAssignExprScope e@YieldFrom{} = pure $ unsafeCoerce e
validateAssignExprScope e@Not{} = pure $ unsafeCoerce e
validateAssignExprScope e@ListComp{} = pure $ unsafeCoerce e
validateAssignExprScope e@Call{} = pure $ unsafeCoerce e
validateAssignExprScope e@UnOp{} = pure $ unsafeCoerce e
validateAssignExprScope e@BinOp{} = pure $ unsafeCoerce e
validateAssignExprScope e@Ident{} = pure $ unsafeCoerce e
validateAssignExprScope e@None{} = pure $ unsafeCoerce e
validateAssignExprScope e@Ellipsis{} = pure $ unsafeCoerce e
validateAssignExprScope e@Int{} = pure $ unsafeCoerce e
validateAssignExprScope e@Float{} = pure $ unsafeCoerce e
validateAssignExprScope e@Imag{} = pure $ unsafeCoerce e
validateAssignExprScope e@Bool{} = pure $ unsafeCoerce e
validateAssignExprScope e@String{} = pure $ unsafeCoerce e
validateAssignExprScope e@DictComp{} = pure $ unsafeCoerce e
validateAssignExprScope e@Dict{} = pure $ unsafeCoerce e
validateAssignExprScope e@SetComp{} = pure $ unsafeCoerce e
validateAssignExprScope e@Set{} = pure $ unsafeCoerce e
validateAssignExprScope e@Generator{} = pure $ unsafeCoerce e
validateAssignExprScope e@Await{} = pure $ unsafeCoerce e
validateAssignExprScope e@Ternary{} = pure $ unsafeCoerce e
validateDictItemScope
:: AsScopeError e a
=> DictItem v a
-> ValidateScope a e (DictItem (Nub (Scope ': v)) a)
validateDictItemScope (DictItem a b c d) =
(\b' -> DictItem a b' c) <$>
validateExprScope b <*>
validateExprScope d
validateDictItemScope (DictUnpack a b c) =
DictUnpack a b <$> validateExprScope c
validateSubscriptScope
:: AsScopeError e a
=> Subscript v a
-> ValidateScope a e (Subscript (Nub (Scope ': v)) a)
validateSubscriptScope (SubscriptExpr e) = SubscriptExpr <$> validateExprScope e
validateSubscriptScope (SubscriptSlice a b c d) =
(\a' -> SubscriptSlice a' b) <$>
traverse validateExprScope a <*>
traverse validateExprScope c <*>
traverseOf (traverse._2.traverse) validateExprScope d
validateListItemScope
:: AsScopeError e a
=> ListItem v a
-> ValidateScope a e (ListItem (Nub (Scope ': v)) a)
validateListItemScope (ListItem a b) = ListItem a <$> validateExprScope b
validateListItemScope (ListUnpack a b c d) = ListUnpack a b c <$> validateExprScope d
validateSetItemScope
:: AsScopeError e a
=> SetItem v a
-> ValidateScope a e (SetItem (Nub (Scope ': v)) a)
validateSetItemScope (SetItem a b) = SetItem a <$> validateExprScope b
validateSetItemScope (SetUnpack a b c d) = SetUnpack a b c <$> validateExprScope d
validateTupleItemScope
:: AsScopeError e a
=> TupleItem v a
-> ValidateScope a e (TupleItem (Nub (Scope ': v)) a)
validateTupleItemScope (TupleItem a b) = TupleItem a <$> validateExprScope b
validateTupleItemScope (TupleUnpack a b c d) = TupleUnpack a b c <$> validateExprScope d
validateExprScope
:: AsScopeError e a
=> Expr v a
-> ValidateScope a e (Expr (Nub (Scope ': v)) a)
validateExprScope (Lambda a b c d e) =
Lambda a b <$>
traverse validateParamScope c <*>
pure d <*>
validateExprScope e
validateExprScope (Yield a b c) =
Yield a b <$> traverse validateExprScope c
validateExprScope (YieldFrom a b c d) =
YieldFrom a b c <$> validateExprScope d
validateExprScope (Ternary a b c d e f) =
(\b' d' f' -> Ternary a b' c d' e f') <$>
validateExprScope b <*>
validateExprScope d <*>
validateExprScope f
validateExprScope (Subscript a b c d e) =
(\b' d' -> Subscript a b' c d' e) <$>
validateExprScope b <*>
traverse validateSubscriptScope d
validateExprScope (Not a ws e) = Not a ws <$> validateExprScope e
validateExprScope (List a ws1 es ws2) =
List a ws1 <$>
traverseOf (traverse.traverse) validateListItemScope es <*>
pure ws2
validateExprScope (ListComp a ws1 comp ws2) =
ListComp a ws1 <$>
validateComprehensionScope validateExprScope comp <*>
pure ws2
validateExprScope (Generator a comp) =
Generator a <$>
validateComprehensionScope validateExprScope comp
validateExprScope (Await a ws expr) = Await a ws <$> validateExprScope expr
validateExprScope (Deref a e ws1 r) =
Deref a <$>
validateExprScope e <*>
pure ws1 <*>
validateIdentScope r
validateExprScope (Call a e ws1 as ws2) =
Call a <$>
validateExprScope e <*>
pure ws1 <*>
traverseOf (traverse.traverse) validateArgScope as <*>
pure ws2
validateExprScope (BinOp a l op r) =
BinOp a <$>
validateExprScope l <*>
pure op <*>
validateExprScope r
validateExprScope (UnOp a op e) =
UnOp a op <$>
validateExprScope e
validateExprScope (Parens a ws1 e ws2) =
Parens a ws1 <$>
validateExprScope e <*>
pure ws2
validateExprScope (Ident i) = Ident <$> validateIdentScope i
validateExprScope (Tuple a b ws d) =
Tuple a <$>
validateTupleItemScope b <*>
pure ws <*>
traverseOf (traverse.traverse) validateTupleItemScope d
validateExprScope e@None{} = pure $ unsafeCoerce e
validateExprScope e@Ellipsis{} = pure $ unsafeCoerce e
validateExprScope e@Int{} = pure $ unsafeCoerce e
validateExprScope e@Float{} = pure $ unsafeCoerce e
validateExprScope e@Imag{} = pure $ unsafeCoerce e
validateExprScope e@Bool{} = pure $ unsafeCoerce e
validateExprScope e@String{} = pure $ unsafeCoerce e
validateExprScope e@Unit{} = pure $ unsafeCoerce e
validateExprScope (DictComp a ws1 comp ws2) =
DictComp a ws1 <$>
validateComprehensionScope validateDictItemScope comp <*>
pure ws2
validateExprScope (Dict a b c d) =
(\c' -> Dict a b c' d) <$> traverseOf (traverse.traverse) validateDictItemScope c
validateExprScope (SetComp a ws1 comp ws2) =
SetComp a ws1 <$>
validateComprehensionScope validateSetItemScope comp <*>
pure ws2
validateExprScope (Set a b c d) =
(\c' -> Set a b c' d) <$> traverse validateSetItemScope c
validateModuleScope
:: AsScopeError e a
=> Module v a
-> ValidateScope a e (Module (Nub (Scope ': v)) a)
validateModuleScope m =
case m of
ModuleEmpty -> pure ModuleEmpty
ModuleBlankFinal a -> pure $ ModuleBlankFinal a
ModuleBlank a b c -> ModuleBlank a b <$> validateModuleScope c
ModuleStatement a b ->
ModuleStatement <$>
validateStatementScope a <*>
validateModuleScope b
unionL :: Ord k => Map k v -> Map k v -> Map k v
unionL = Map.unionWith const
unionR :: Ord k => Map k v -> Map k v -> Map k v
unionR = Map.unionWith (const id)