content: {-# LANGUAGE OverloadedStrings #-}
  
  module Jikka.Python.Parse.HappySpec
    ( spec,
    )
  where
  
  import Jikka.Common.Error (Error)
  import Jikka.Common.Location
  import Jikka.Python.Language.Expr
  import Jikka.Python.Language.Util
  import Jikka.Python.Parse.Happy
  import qualified Jikka.Python.Parse.Token as L
  import Test.Hspec
  
  at :: a -> (Int, Int) -> WithLoc a
  at token (y, x) = WithLoc (Loc y x (-1)) token
  
  run' :: [[L.Token]] -> Either Error Program
  run' tokens = run . concat $ zipWith (\y -> zipWith (\x token -> token `at` (y, x)) [1 ..]) [1 ..] tokens
  
  spec :: Spec
  spec = describe "run" $ do
    it "works" $ do
      let input =
            [ [L.Def, L.Ident "solve", L.OpenParen, L.CloseParen, L.Arrow, L.Ident "int", L.Colon, L.Newline],
              [L.Indent, L.Return, L.Int 42, L.Newline],
              [L.Dedent]
            ]
      let parsed = [FunctionDef ("solve" `at` (1, 2)) emptyArguments [Return (Just (constIntExp 42 `at` (2, 3))) `at` (2, 2)] [] (Just $ Name ("int" `at` (1, 6)) `at` (1, 6)) `at` (1, 1)]
      run' input `shouldBe` Right parsed
    it "works on a small fun def" $ do
      let input =
            [ [L.Def, L.Ident "solve", L.OpenParen, L.Ident "p", L.CloseParen, L.Colon, L.Newline],
              [L.Indent, L.If, L.Ident "p", L.Colon, L.Newline],
              [L.Indent, L.Return, L.Int 0, L.Newline],
              [L.Dedent, L.Else, L.Colon, L.Newline],
              [L.Indent, L.Return, L.Int 1, L.Newline],
              [L.Dedent],
              [L.Dedent]
            ]
      let parsed =
            [FunctionDef ("solve" `at` (1, 2)) (emptyArguments {argsArgs = [("p" `at` (1, 4), Nothing)]}) [If (Name ("p" `at` (2, 3)) `at` (2, 3)) [Return (Just (constIntExp 0 `at` (3, 3))) `at` (3, 2)] [Return (Just (constIntExp 1 `at` (5, 3))) `at` (5, 2)] `at` (2, 2)] [] Nothing `at` (1, 1)]
      run' input `shouldBe` Right parsed
    it "works on a simple constant def" $ do
      let input = [[L.Ident "MOD", L.Colon, L.Ident "int", L.Equal, L.Int 1000000007, L.Newline]]
      let parsed =
            [AnnAssign (Name ("MOD" `at` (1, 1)) `at` (1, 1)) (Name ("int" `at` (1, 3)) `at` (1, 3)) (Just (constIntExp 1000000007 `at` (1, 5))) `at` (1, 1)]
      run' input `shouldBe` Right parsed
  