{-# language DataKinds, TypeOperators #-}
{-# language DeriveFunctor #-}
{-# language FlexibleContexts #-}
{-# language RankNTypes #-}
{-# language LambdaCase #-}
{-# language OverloadedLists #-}
{-# language ScopedTypeVariables, TypeApplications #-}
{-# language MultiParamTypeClasses #-}
module Language.Python.Validate.Scope
( module Data.Validation
, module Language.Python.Validate.Scope.Error
, Scope, ValidateScope, runValidateScope
, validateModuleScope
, validateStatementScope
, validateExprScope
, Level(..), Entry(..)
, runValidateScope'
, definitionScope
, controlScope
, inScope
, lookupScope
, localScope
, extendScope
, validateArgScope
, validateAssignExprScope
, validateBlockScope
, validateCompoundStatementScope
, validateComprehensionScope
, validateDecoratorScope
, validateDictItemScope
, validateExceptAsScope
, validateIdentScope
, validateListItemScope
, validateParamScope
, validateSetItemScope
, validateSimpleStatementScope
, validateSubscriptScope
, validateSuiteScope
, validateTupleItemScope
)
where
import Data.Validation
import Control.Lens.Cons (snoc)
import Control.Lens.Fold ((^..), toListOf, folded)
import Control.Lens.Getter ((^.), to, getting)
import Control.Lens.Plated (cosmos)
import Control.Lens.Prism (_Right, _Just)
import Control.Lens.Review ((#))
import Control.Lens.Setter (mapped, over)
import Control.Lens.Tuple (_2, _3)
import Control.Lens.Traversal (traverseOf)
import Control.Monad.State (State, evalState, modify, get, put)
import Control.Monad.Reader (ReaderT, runReaderT, ask, local)
import Data.Bitraversable (bitraverse)
import Data.ByteString (ByteString)
import Data.Coerce (coerce)
import Data.Foldable (toList, traverse_)
import Data.List.NonEmpty (NonEmpty(..))
import Data.Map.Strict (Map)
import Data.Maybe (isJust)
import Data.Sequence ((|>), Seq)
import Data.String (fromString)
import Data.Type.Set (Nub)
import Data.Validate.Monadic
(ValidateM(..), runValidateM, bindVM, liftVM0, liftVM1, errorVM1)
import Unsafe.Coerce (unsafeCoerce)
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Map.Strict as Map
import Data.Sequence as Seq
import Language.Python.Optics
import Language.Python.Optics.Validated (unvalidated)
import Language.Python.Syntax.Ann
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 Level
= Toplevel
| Definition
| Control
deriving (Eq, Show)
data Entry a
= Entry
{ _entryValue :: a
, _entryPath :: !(Seq Level)
} deriving (Eq, Show, Functor)
type ValidateScope ann e
= ValidateM
(NonEmpty e)
(ReaderT (Seq Level) (State (Map ByteString (Entry ann))))
runValidateScope :: ValidateScope ann e a -> Validation (NonEmpty e) a
runValidateScope = runValidateScope' [Toplevel] mempty
runValidateScope' ::
Seq Level ->
Map ByteString (Entry ann) ->
ValidateScope ann e a ->
Validation (NonEmpty e) a
runValidateScope' path s = flip evalState s . flip runReaderT path . runValidateM
localScope ::
(Map ByteString (Entry ann) -> Map ByteString (Entry ann)) ->
ValidateScope ann e a ->
ValidateScope ann e a
localScope f m =
liftVM0 get `bindVM` \s ->
liftVM0 (modify f) *>
m <* liftVM0 (put s)
definitionScope :: ValidateScope ann e a -> ValidateScope ann e a
definitionScope = liftVM1 (local (|> Definition)) . localScope id
controlScope :: ValidateScope ann e a -> ValidateScope ann e a
controlScope = liftVM1 (local (|> Control))
extendScope :: [Ident v ann] -> ValidateScope ann e ()
extendScope entries =
liftVM0 ask `bindVM` \path ->
liftVM0 . modify $ \scope ->
foldr
(\ident ->
Map.insert (fromString $ _identValue ident) (Entry (ident ^. annot_) path))
scope
entries
inScope :: String -> ValidateScope ann e Bool
inScope = fmap isJust . lookupScope
lookupScope :: String -> ValidateScope ann e (Maybe (Entry ann))
lookupScope s = Map.lookup (fromString s) <$> liftVM0 get
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
parallel2 ::
ValidateScope a e x ->
ValidateScope a e y ->
ValidateScope a e (x, y)
parallel2 a b =
liftVM0 get `bindVM` \st ->
((,) <$>
((,) <$ liftVM0 (put st) <*> a <*> liftVM0 get) <*>
((,) <$ liftVM0 (put st) <*> b <*> liftVM0 get)) `bindVM`
\((ares, ast), (bres, bst)) ->
(ares, bres) <$
liftVM0
(put $
Map.unionWith
(\e1 e2 ->
if Seq.length (_entryPath e1) < Seq.length (_entryPath e2)
then e2
else e1)
ast
bst)
parallelList ::
(x -> ValidateScope a e y) ->
[x] ->
ValidateScope a e [y]
parallelList _ [] = pure []
parallelList f (x:xs) = uncurry (:) <$> parallel2 (f x) (parallelList f xs)
parallelNonEmpty ::
(x -> ValidateScope a e y) ->
NonEmpty x ->
ValidateScope a e (NonEmpty y)
parallelNonEmpty f (x:|xs) = uncurry (:|) <$> parallel2 (f x) (parallelList f xs)
parallel3 ::
ValidateScope a e x1 ->
ValidateScope a e x2 ->
ValidateScope a e x3 ->
ValidateScope a e (x1, x2, x3)
parallel3 a b c = (\(a', (b', c')) -> (a', b', c')) <$> parallel2 a (parallel2 b c)
parallel4 ::
ValidateScope a e x1 ->
ValidateScope a e x2 ->
ValidateScope a e x3 ->
ValidateScope a e x4 ->
ValidateScope a e (x1, x2, x3, x4)
parallel4 a b c d =
(\(a', (b', c', d')) -> (a', b', c', d')) <$> parallel2 a (parallel3 b c 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) =
(\decos' -> Fundef a decos' idnts asyncWs ws1 (coerce name) ws2) <$>
traverse validateDecoratorScope decos <*>
traverse validateParamScope params <*>
pure ws3 <*>
traverseOf (traverse._2) validateExprScope mty <*>
definitionScope
(extendScope (name : toListOf (folded.getting paramName) params) *>
validateSuiteScope s) <*
extendScope [name]
validateCompoundStatementScope (If idnts a ws1 e b elifs melse) =
(\e' (b', elifs', melse') -> If idnts a ws1 e' b' elifs' melse') <$>
validateExprScope e <*>
parallel3
(controlScope $ validateSuiteScope b)
(parallelList
(\(a, b, c, d) ->
(,,,) a b <$>
validateExprScope c <*>
controlScope (validateSuiteScope d))
elifs)
(traverseOf (traverse._3) (controlScope . validateSuiteScope) melse)
validateCompoundStatementScope (While idnts a ws1 e b els) =
While idnts a ws1 <$>
validateExprScope e <*>
controlScope (validateSuiteScope b) <*>
traverseOf (traverse._3) (controlScope . validateSuiteScope) els
validateCompoundStatementScope (TryExcept idnts a b e f k l) =
(\(e', f', k', l') -> TryExcept idnts a b e' f' k' l') <$>
parallel4
(controlScope $ validateSuiteScope e)
(parallelNonEmpty
(\(idnts, ws, g, h) ->
(,,,) idnts ws <$>
traverse validateExceptAsScope g <*>
controlScope
(extendScope (toListOf (folded.exceptAsName._Just._2) g) *>
validateSuiteScope h))
f)
(traverseOf (traverse._3) (controlScope . validateSuiteScope) k)
(traverseOf (traverse._3) (controlScope . validateSuiteScope) l)
validateCompoundStatementScope (TryFinally idnts a b e idnts2 f i) =
(\(e', i') -> TryFinally idnts a b e' idnts2 f i') <$>
parallel2
(controlScope $ validateSuiteScope e)
(controlScope $ validateSuiteScope i)
validateCompoundStatementScope (For idnts a asyncWs b c d e h i) =
let
cs = c ^.. unvalidated.cosmos._Ident
in
(\c' d' e' (h', i') -> For idnts a asyncWs b c' d' e' h' i') <$>
(unsafeCoerce c <$
traverse
(\s ->
inScope (s ^. identValue) `bindVM` \res ->
if res then errorVM1 (_BadShadowing # coerce s) else pure ())
cs) <*>
pure d <*>
traverse validateExprScope e <*>
parallel2
(controlScope $
extendScope (toList cs) *>
validateSuiteScope h)
(traverseOf (traverse._3) (controlScope . validateSuiteScope) i)
validateCompoundStatementScope (ClassDef a decos idnts b c d g) =
(\decos' -> ClassDef a decos' idnts b (coerce c)) <$>
traverse validateDecoratorScope decos <*>
traverseOf (traverse._2.traverse.traverse) validateArgScope d <*>
definitionScope (validateSuiteScope g) <*
extendScope [c]
validateCompoundStatementScope (With a b asyncWs c d e) =
let
names =
d ^..
folded.unvalidated.to _withItemBinder.folded._2.
assignTargets
in
With a b asyncWs c <$>
traverse
(\(WithItem a b c) ->
WithItem @(Nub (Scope ': v)) a <$>
validateExprScope b <*>
traverseOf (traverse._2) validateAssignExprScope c)
d <*
extendScope names <*>
controlScope (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) =
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))
validateSimpleStatementScope (AugAssign a l aa r) =
(\l' -> AugAssign a l' aa) <$>
validateExprScope l <*>
validateExprScope r
validateSimpleStatementScope (Global a _ _) = errorVM1 (_FoundGlobal # getAnn a)
validateSimpleStatementScope (Nonlocal a _ _) = errorVM1 (_FoundNonlocal # getAnn a)
validateSimpleStatementScope (Del a ws cs) =
Del a ws <$
traverse_
(\case; Ident a _ -> errorVM1 (_DeletedIdent # getAnn a); _ -> 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 =
lookupScope (_identValue i) `bindVM` \res ->
liftVM0 ask `bindVM` \curPath ->
case res of
Nothing -> errorVM1 (_NotInScope # (i ^. unvalidated))
Just (Entry ann path) ->
coerce i <$
if Seq.length curPath < Seq.length path
then errorVM1 (_FoundDynamic # (ann, i ^. unvalidated))
else pure ()
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) =
controlScope $
(\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 (c ^.. unvalidated.assignTargets)
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 (Ident a (MkIdent b c d)) =
lookupScope c `bindVM` \res ->
liftVM0 ask `bindVM` \curPath ->
Ident a (MkIdent b c d) <$
case res of
Nothing -> extendScope [MkIdent b c d]
Just (Entry _ path)->
if Seq.length curPath < Seq.length path
then extendScope [MkIdent b c d]
else pure ()
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@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 a i) = Ident a <$> 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