content: {-# language OverloadedStrings, TemplateHaskell #-}
  {-# language DataKinds #-}
  module Syntax (syntaxTests) where
  
  import Hedgehog
  
  import Control.Lens.Iso (from)
  import Control.Lens.Getter ((^.))
  import Control.Lens.Review ((#))
  import Control.Monad (void)
  
  import Language.Python.DSL
  import Language.Python.Optics
  import Language.Python.Parse (parseModule, parseStatement, parseExpr)
  import Language.Python.Render (showStatement, showExpr)
  import Language.Python.Syntax.Ann
  import Language.Python.Syntax.CommaSep
  import Language.Python.Syntax.Expr
  import Language.Python.Syntax.Punctuation
  import Language.Python.Syntax.Statement
  import Language.Python.Syntax.Strings
  import Language.Python.Syntax.Whitespace
  
  import Helpers
    ( shouldBeParseSuccess, shouldBeFailure, shouldBeSuccess
    , syntaxValidateExpr, syntaxValidateStatement, syntaxValidateModule
    )
  
  syntaxTests :: Group
  syntaxTests = $$discover
  
  prop_syntax_1 :: Property
  prop_syntax_1 =
    withTests 1 . property $ do
      let
        e =
          -- lambda *: None
          Lambda (Ann ())
            [Space]
            (CommaSepMany (UnnamedStarParam (Ann ()) []) (MkComma []) CommaSepNone)
            (MkColon [Space])
            (None (Ann ()) [])
      res <- syntaxValidateExpr e
      shouldBeFailure res
  
  prop_syntax_2 :: Property
  prop_syntax_2 =
    withTests 1 . property $ do
      let
        i = replicate 4 Space ^. from indentWhitespaces
        e :: Statement '[] ()
        e =
          CompoundStatement .
          Fundef (Ann ()) []
            (Indents mempty (Ann ()))
            Nothing
            (pure Space)
              "test"
              [] CommaSepNone [] Nothing .
            SuiteMany (Ann ()) (MkColon []) Nothing LF $
            Block []
              (SmallStatement (Indents [i] (Ann ())) $
               MkSmallStatement (Pass (Ann ()) []) [] Nothing Nothing Nothing)
              [Right . SmallStatement (Indents [i] (Ann ())) $
               MkSmallStatement (Pass (Ann ()) []) [] Nothing Nothing Nothing]
      res <- shouldBeParseSuccess parseStatement (showStatement e)
      res' <- shouldBeParseSuccess parseStatement (showStatement res)
      void res === void res'
  
  prop_syntax_3 :: Property
  prop_syntax_3 =
    withTests 1 . property $ do
      let
        s = "@a\ndef a():\n pass\n @a\n class a: return "
      e <- shouldBeParseSuccess parseModule s
      shouldBeFailure =<< syntaxValidateModule (() <$ e)
  
  prop_syntax_4 :: Property
  prop_syntax_4 =
    withTests 1 . property $ do
      let
        e :: Expr '[] ()
        e =
          String (Ann ()) . pure $
          StringLiteral (Ann ())
            Nothing
          ShortString SingleQuote
          [Char_lit '\\', Char_lit 'u']
          []
      res <- shouldBeParseSuccess parseExpr (showExpr e)
      res' <- shouldBeParseSuccess parseExpr (showExpr res)
      void res === void res'
  
  prop_syntax_5 :: Property
  prop_syntax_5 =
    withTests 1 . property $ do
      let
        e :: Expr '[] ()
        e =
          String (Ann ()) . pure $
          StringLiteral (Ann ())
            Nothing
          ShortString SingleQuote
          [Char_lit '\\', Char_lit 'x']
          []
      res <- shouldBeParseSuccess parseExpr (showExpr e)
      res' <- shouldBeParseSuccess parseExpr (showExpr res)
      void res === void res'
  
  prop_syntax_6 :: Property
  prop_syntax_6 =
    withTests 1 . property $ do
      let s= "async def a():\n class a(await None):\n  pass"
      e <- shouldBeParseSuccess parseModule s
      void . shouldBeSuccess =<< syntaxValidateModule (() <$ e)
  
  prop_syntax_7 :: Property
  prop_syntax_7 =
    withTests 1 . property $ do
      let
        s = "def a(b): global b"
      e <- shouldBeParseSuccess parseModule s
      shouldBeFailure =<< syntaxValidateModule (() <$ e)
  
  prop_syntax_8 :: Property
  prop_syntax_8 =
    withTests 1 . property $ do
      let
        s = "def a(*): pass"
      e <- shouldBeParseSuccess parseModule s
      shouldBeFailure =<< syntaxValidateModule (() <$ e)
  
  prop_syntax_9 :: Property
  prop_syntax_9 =
    withTests 1 . property $ do
      let
        s = "def a(*, b=None): pass"
      e <- shouldBeParseSuccess parseModule s
      void . shouldBeSuccess =<< syntaxValidateModule (() <$ e)
  
  prop_syntax_10 :: Property
  prop_syntax_10 =
    withTests 1 . property $ do
      let e = _Fundef # def_ "a" [s_ "b", s_ "c"] [line_ pass_]
      void . shouldBeFailure =<< syntaxValidateStatement e
  
  prop_syntax_11 :: Property
  prop_syntax_11 =
    withTests 1 . property $ do
      let e = lambda_ [s_ "a", s_ "b"] (var_ "a")
      void . shouldBeFailure =<< syntaxValidateExpr e
  
  prop_syntax_12 :: Property
  prop_syntax_12 =
    withTests 1 . property $ do
      let e = _Fundef # def_ "a" [star_, s_ "b"] [line_ pass_]
      void . shouldBeFailure =<< syntaxValidateStatement e
  
  prop_syntax_13 :: Property
  prop_syntax_13 =
    withTests 1 . property $ do
      let e = lambda_ [star_, s_ "a"] (var_ "b")
      void . shouldBeFailure =<< syntaxValidateExpr e
  
  prop_syntax_14 :: Property
  prop_syntax_14 =
    withTests 1 . property $ do
      let e = _Fundef # def_ "a" [star_, k_ "b" none_, s_ "c"] [line_ pass_]
      void . shouldBeFailure =<< syntaxValidateStatement e
  
  prop_syntax_15 :: Property
  prop_syntax_15 =
    withTests 1 . property $ do
      let e = lambda_ [star_, k_ "a" none_, s_ "b"] (var_ "c")
      void . shouldBeFailure =<< syntaxValidateExpr e
  
  prop_syntax_16 :: Property
  prop_syntax_16 =
    withTests 1 . property $ do
      let e = lambda_ [star_, star_, k_ "a" none_] (var_ "c")
      void . shouldBeFailure =<< syntaxValidateExpr e
  