{-# language DataKinds #-} {-# language FlexibleContexts #-} {-# language MultiParamTypeClasses #-} {-# language FlexibleInstances #-} {-# language InstanceSigs, ScopedTypeVariables #-} {-# language PolyKinds #-} {-# language LambdaCase #-} {-| Module : Language.Python.Optics Copyright : (C) CSIRO 2017-2019 License : BSD3 Maintainer : Isaac Elliott Stability : experimental Portability : non-portable Optics for manipulating Python syntax trees -} module Language.Python.Optics ( module Language.Python.Optics.Validated -- * Identifiers , module Language.Python.Optics.Idents -- * Indentation , module Language.Python.Optics.Indents -- * Newlines , module Language.Python.Optics.Newlines -- * Simple statements -- ** Assignment , assignTargets -- * Compound statements , HasCompoundStatement(..) -- ** Function definitions , HasFundef(..) -- ** Class defintions , HasClassDef(..) -- ** @while@ statements , HasWhile(..) -- ** @for@ statements , HasFor(..) -- ** @with@ statements , HasWith(..) -- ** @if@ statements , HasIf(..) , _Elif -- ** @try@ statements , HasTryExcept(..) , HasTryFinally(..) , _Finally , _Except -- ** @else@ , _Else -- * Parameters , _PositionalParam , _KeywordParam , _UnnamedStarParam , _StarParam -- * Expressions -- ** Identifiers , _Ident -- ** @None@ , _None -- ** Function calls , _Call -- ** Tuples , _Tuple , _TupleUnpack , tupleItems -- ** Lists , _List , _ListUnpack , listItems ) where import Control.Lens.Getter ((^.), view) import Control.Lens.Iso (Iso', iso, from) import Control.Lens.Traversal (Traversal) import Control.Lens.Prism (Choice, Prism, prism) import Language.Python.Optics.Idents import Language.Python.Optics.Indents import Language.Python.Optics.Newlines import Language.Python.Optics.Validated import Language.Python.Syntax.Ann import Language.Python.Syntax.Expr import Language.Python.Syntax.Ident import Language.Python.Syntax.Statement import Language.Python.Syntax.Types import Language.Python.Syntax.Whitespace _TupleUnpack :: Prism (TupleItem v a) (TupleItem '[] a) (TupleUnpack v a) (TupleUnpack '[] a) _TupleUnpack = prism (\(MkTupleUnpack a b c d) -> TupleUnpack a b c d) (\case TupleUnpack a b c d -> Right $ MkTupleUnpack a b c d a -> Left $ a ^. unvalidated) _Tuple :: Prism (Expr v a) (Expr '[] a) (Tuple v a) (Tuple '[] a) _Tuple = prism (\(MkTuple a b c d) -> Tuple a b c d) (\case Tuple a b c d -> Right (MkTuple a b c d) a -> Left $ a ^. unvalidated) tupleItems :: Traversal (Tuple v a) (Tuple '[] a) (TupleItem v a) (TupleItem '[] a) tupleItems f (MkTuple a b c d) = (\b' d' -> MkTuple a b' c d') <$> f b <*> (traverse.traverse) f d _ListUnpack :: Prism (ListItem v a) (ListItem '[] a) (ListUnpack v a) (ListUnpack '[] a) _ListUnpack = prism (\(MkListUnpack a b c d) -> ListUnpack a b c d) (\case ListUnpack a b c d -> Right $ MkListUnpack a b c d a -> Left $ a ^. unvalidated) _List :: Prism (Expr v a) (Expr '[] a) (List v a) (List '[] a) _List = prism (\(MkList a b c d) -> List a b c d) (\case List a b c d -> Right (MkList a b c d) a -> Left $ a ^. unvalidated) listItems :: Traversal (List v a) (List '[] a) (ListItem v a) (ListItem '[] a) listItems f (MkList a b c d) = (\c' -> MkList a b c' d) <$> (traverse.traverse) f c _None :: Prism (Expr v a) (Expr '[] a) (None v a) (None '[] a) _None = prism (\(MkNone a b) -> None a b) (\case None a b -> Right (MkNone a b) a -> Left $ a ^. unvalidated) _KeywordParam :: Prism (Param v a) (Param '[] a) (KeywordParam v a) (KeywordParam '[] a) _KeywordParam = prism (\(MkKeywordParam a b c d e) -> KeywordParam a b c d e) (\case KeywordParam a b c d e -> Right (MkKeywordParam a b c d e) a -> Left $ a ^. unvalidated) _PositionalParam :: Prism (Param v a) (Param '[] a) (PositionalParam v a) (PositionalParam '[] a) _PositionalParam = prism (\(MkPositionalParam a b c) -> PositionalParam a b c) (\case PositionalParam a b c -> Right (MkPositionalParam a b c) a -> Left $ a ^. unvalidated) _StarParam :: Prism (Param v a) (Param '[] a) (StarParam v a) (StarParam '[] a) _StarParam = prism (\(MkStarParam a b c d) -> StarParam a b c d) (\case StarParam a b c d -> Right (MkStarParam a b c d) a -> Left $ a ^. unvalidated) _UnnamedStarParam :: Prism (Param v a) (Param '[] a) (UnnamedStarParam v a) (UnnamedStarParam '[] a) _UnnamedStarParam = prism (\(MkUnnamedStarParam a b) -> UnnamedStarParam a b) (\case UnnamedStarParam a b -> Right (MkUnnamedStarParam a b) a -> Left $ a ^. unvalidated) class HasCompoundStatement s where _CompoundStatement :: Prism (s v a) (s '[] a) (CompoundStatement v a) (CompoundStatement '[] a) instance HasCompoundStatement CompoundStatement where _CompoundStatement = id instance HasCompoundStatement Statement where _CompoundStatement = prism CompoundStatement (\case CompoundStatement a -> Right a a -> Left (a ^. unvalidated)) class HasFundef s where _Fundef :: Prism (s v a) (s '[] a) (Fundef v a) (Fundef '[] a) instance HasFundef Fundef where _Fundef = id instance HasFundef CompoundStatement where _Fundef = prism (\(MkFundef idnt a b c d e f g h i j) -> Fundef idnt a b c d e f g h i j) (\case Fundef idnt a b c d e f g h i j -> Right $ MkFundef idnt a b c d e f g h i j a -> Left $ a ^. unvalidated) instance HasFundef Statement where _Fundef = _CompoundStatement._Fundef class HasWhile s where _While :: Prism (s v a) (s '[] a) (While v a) (While '[] a) instance HasWhile While where _While = id instance HasWhile CompoundStatement where _While = prism (\(MkWhile a b c d e f) -> While a b c d e $ view _Else <$> f) (\case While a b c d e f -> Right . MkWhile a b c d e $ view (from _Else) <$> f a -> Left $ a ^. unvalidated) instance HasWhile Statement where _While = _CompoundStatement._While _Else :: Iso' (Else v a) (Indents a, [Whitespace], Suite v a) _Else = iso (\(MkElse a b c) -> (a, b, c)) (\(a, b, c) -> MkElse a b c) _Elif :: Iso' (Elif v a) (Indents a, [Whitespace], Expr v a, Suite v a) _Elif = iso (\(MkElif a b c d) -> (a, b, c, d)) (\(a, b, c, d) -> MkElif a b c d) _Finally :: Iso' (Finally v a) (Indents a, [Whitespace], Suite v a) _Finally = iso (\(MkFinally a b c) -> (a, b, c)) (\(a, b, c) -> MkFinally a b c) _Except :: Iso' (Except v a) (Indents a, [Whitespace], Maybe (ExceptAs v a), Suite v a) _Except = iso (\(MkExcept a b c d) -> (a, b, c, d)) (\(a, b, c, d) -> MkExcept a b c d) class HasIf s where _If :: Prism (s v a) (s '[] a) (If v a) (If '[] a) instance HasIf If where _If = id instance HasIf CompoundStatement where _If = prism (\(MkIf a b c d e f g) -> If a b c d e (view _Elif <$> f) (view _Else <$> g)) (\case If a b c d e f g -> Right $ MkIf a b c d e (view (from _Elif) <$> f) (view (from _Else) <$> g) a -> Left $ a ^. unvalidated) instance HasIf Statement where _If = _CompoundStatement._If class HasTryExcept s where _TryExcept :: Prism (s v a) (s '[] a) (TryExcept v a) (TryExcept '[] a) instance HasTryExcept TryExcept where _TryExcept = id instance HasTryExcept CompoundStatement where _TryExcept = prism (\(MkTryExcept a b c d e f g) -> TryExcept a b c d (view _Except <$> e) (view _Else <$> f) (view _Finally <$> g)) (\case TryExcept a b c d e f g -> Right $ MkTryExcept a b c d (view (from _Except) <$> e) (view (from _Else) <$> f) (view (from _Finally) <$> g) a -> Left $ a ^. unvalidated) instance HasTryExcept Statement where _TryExcept = _CompoundStatement._TryExcept class HasTryFinally s where _TryFinally :: Prism (s v a) (s '[] a) (TryFinally v a) (TryFinally '[] a) instance HasTryFinally TryFinally where _TryFinally = id instance HasTryFinally CompoundStatement where _TryFinally = prism (\(MkTryFinally a b c d e) -> (\(x, y, z) -> TryFinally a b c d x y z) (e ^. _Finally)) (\case TryFinally a b c d e f g -> Right $ MkTryFinally a b c d ((e, f, g) ^. from _Finally) a -> Left $ a ^. unvalidated) instance HasTryFinally Statement where _TryFinally = _CompoundStatement._TryFinally class HasFor s where _For :: Prism (s v a) (s '[] a) (For v a) (For '[] a) instance HasFor For where _For = id instance HasFor CompoundStatement where _For = prism (\(MkFor a b c d e f g h i) -> For a b c d e f g h (view _Else <$> i)) (\case For a b c d e f g h i -> Right $ MkFor a b c d e f g h (view (from _Else) <$> i) a -> Left $ a ^. unvalidated) instance HasFor Statement where _For = _CompoundStatement._For _Call :: Prism (Expr v a) (Expr '[] a) (Call v a) (Call '[] a) _Call = prism (\(MkCall a b c d e) -> Call a b c d e) (\case Call a b c d e -> Right $ MkCall a b c d e a -> Left $ a ^. unvalidated) class HasClassDef s where _ClassDef :: Prism (s v a) (s '[] a) (ClassDef v a) (ClassDef '[] a) instance HasClassDef ClassDef where _ClassDef = id instance HasClassDef CompoundStatement where _ClassDef = prism (\(MkClassDef a b c d e f g) -> ClassDef a b c d e f g) (\case ClassDef a b c d e f g -> Right $ MkClassDef a b c d e f g a -> Left $ a ^. unvalidated) instance HasClassDef Statement where _ClassDef = _CompoundStatement._ClassDef class HasWith s where _With :: Prism (s v a) (s '[] a) (With v a) (With '[] a) instance HasWith With where _With = id instance HasWith CompoundStatement where _With = prism (\(MkWith a b c d e f) -> With a b c d e f) (\case With a b c d e f -> Right $ MkWith a b c d e f a -> Left $ a ^. unvalidated) instance HasWith Statement where _With = _CompoundStatement._With -- | -- A faux-Prism for matching on the @Ident@ constructor of an 'Expr'. -- -- It's not a Prism because: -- -- When 'Control.Lens.Fold.preview'ing, it discards the 'Expr'\'s annotation, and when -- 'Control.Lens.Review.review'ing, it re-constructs an annotation from the supplied 'Language.Python.Syntax.Ident.Ident' -- -- @'_Ident' :: 'Prism' ('Expr' v a) ('Expr' '[] a) ('Ident' v a) ('Ident' '[] a)@ _Ident :: (Choice p, Applicative f) => p (Ident v a) (f (Ident '[] a)) -> p (Expr v a) (f (Expr '[] a)) _Ident = prism (\i -> Ident (i ^. annot) i) (\case Ident _ a -> Right a a -> Left $ a ^. unvalidated) -- | 'Traversal' targeting the variables that would modified as a result of an assignment -- -- Here are some examples of assignment targets: -- -- @ -- a = b -- ^ -- @ -- -- @ -- (a, b, c) = d -- ^ ^ ^ -- @ -- -- @ -- [a, b, *c] = d -- ^ ^ ^ -- @ -- -- These expressions have variables on the left hand side of the @=@, but those variables -- don't count as assignment targets: -- -- @ -- a[b] = c -- @ -- -- @ -- a(b) = c -- @ -- -- @ -- {a: b} = c -- @ assignTargets :: Traversal (Expr v a) (Expr '[] a) (Ident v a) (Ident '[] a) assignTargets f e = case e of List a b c d -> (\c' -> List a b c' d) <$> (traverse.traverse._Exprs.assignTargets) f c Parens a b c d -> (\c' -> Parens a b c' d) <$> assignTargets f c Ident a b -> Ident a <$> f b Tuple a b c d -> (\b' d' -> Tuple a b' c d') <$> (_Exprs.assignTargets) f b <*> (traverse.traverse._Exprs.assignTargets) f d Unit{} -> pure $ e ^. unvalidated Lambda{} -> pure $ e ^. unvalidated Yield{} -> pure $ e ^. unvalidated YieldFrom{} -> pure $ e ^. unvalidated Ternary{} -> pure $ e ^. unvalidated ListComp{} -> pure $ e ^. unvalidated Deref{} -> pure $ e ^. unvalidated Subscript{} -> pure $ e ^. unvalidated Call{} -> pure $ e ^. unvalidated None{} -> pure $ e ^. unvalidated Ellipsis{} -> pure $ e ^. unvalidated BinOp{} -> pure $ e ^. unvalidated UnOp{} -> pure $ e ^. unvalidated Int{} -> pure $ e ^. unvalidated Float{} -> pure $ e ^. unvalidated Imag{} -> pure $ e ^. unvalidated Bool{} -> pure $ e ^. unvalidated String{} -> pure $ e ^. unvalidated Not{} -> pure $ e ^. unvalidated DictComp{} -> pure $ e ^. unvalidated Dict{} -> pure $ e ^. unvalidated SetComp{} -> pure $ e ^. unvalidated Set{} -> pure $ e ^. unvalidated Generator{} -> pure $ e ^. unvalidated Await{} -> pure $ e ^. unvalidated