packages feed

egison-pattern-src-haskell-mode-0.1.0.0: test/Language/Egison/Parser/Pattern/Mode/HaskellSpec.hs

module Language.Egison.Parser.Pattern.Mode.HaskellSpec
  ( test_atom_patterns
  , test_pattern_operators
  , test_special_pattern_operators
  , test_comments
  )
where

import           TestImport

import           Test.Tasty
import           Test.Tasty.HUnit

import           Data.Functor                   ( void )
import           Language.Haskell.Exts.Build    ( name
                                                , sym
                                                , op
                                                , paren
                                                , infixApp
                                                , intE
                                                )


makeAssertion
  :: (String -> Either (Errors String) (Expr (QName ()) (Name ()) (Exp ())))
  -> String
  -> Expr (QName ()) (Name ()) (Exp ())
  -> Assertion
makeAssertion parser content expected = case parser content of
  Left  err -> fail $ show err
  Right got -> assertEqual ("while parsing \"" ++ content ++ "\"") expected got

assertParseExpr :: String -> Expr (QName ()) (Name ()) (Exp ()) -> Assertion
assertParseExpr = makeAssertion $ fmap (mapValueExpr void) . testParseExpr

assertParseExprSpecialFixities
  :: String -> Expr (QName ()) (Name ()) (Exp ()) -> Assertion
assertParseExprSpecialFixities =
  makeAssertion $ fmap (mapValueExpr void) . testParseExprSpecialFixities


uqname :: String -> QName ()
uqname = UnQual () . name

qname :: String -> String -> QName ()
qname modName = Qual () (ModuleName () modName) . name

uqsym :: String -> QName ()
uqsym = UnQual () . sym

qsym :: String -> String -> QName ()
qsym modName = Qual () (ModuleName () modName) . sym

test_atom_patterns :: [TestTree]
test_atom_patterns =
  [ testCase "wildcard pattern" $ assertParseExpr "_" Wildcard
  , testCase "variable pattern" $ assertParseExpr "$x" (Variable $ name "x")
  , testCase "variable pattern of symbols"
    $ assertParseExpr "$(%)" (Variable $ sym "%")
  , testCase "value pattern" $ assertParseExpr "#10" (Value $ intE 10)
  , testCase "value pattern between parentheses" $ assertParseExpr
    "#(1 + 2)"
    (Value . paren $ infixApp (intE 1) (op $ sym "+") (intE 2))
  , testCase "predicate pattern" $ assertParseExpr "?10" (Predicate $ intE 10)
  , testCase "constructor pattern" $ assertParseExpr
    "(ctor _ _ _)"
    (Pattern (uqname "ctor") [Wildcard, Wildcard, Wildcard])
  , testCase "constructor pattern with data constructor" $ assertParseExpr
    "(Ctor _ _ _)"
    (Pattern (uqname "Ctor") [Wildcard, Wildcard, Wildcard])
  , testCase "constructor pattern with qualified name" $ assertParseExpr
    "(Mod.ctor _ _ _)"
    (Pattern (qname "Mod" "ctor") [Wildcard, Wildcard, Wildcard])
  , testCase "constructor pattern that the symbol is between parentheses"
    $ assertParseExpr "((++) _ _)" (Pattern (uqsym "++") [Wildcard, Wildcard])
  , testCase
      "constructor pattern that the qualified symbol is between parentheses"
    $ assertParseExpr "((Mod.++) _ _)"
                      (Pattern (qsym "Mod" "++") [Wildcard, Wildcard])
  , testCase "constructor pattern without arguments"
    $ assertParseExpr "nil" (Pattern (uqname "nil") [])
  , testCase "constructor pattern with qualified name without arguments"
    $ assertParseExpr "Mod.nil" (Pattern (qname "Mod" "nil") [])
  , testCase "constructor pattern between parentheses"
    $ assertParseExpr "((c _))" (Pattern (uqname "c") [Wildcard])
  , testCase "wildcard pattern between parentheses"
    $ assertParseExpr "((_))" Wildcard
  , testCase "constructor pattern without arguments between parentheses"
    $ assertParseExpr "((c))" (Pattern (uqname "c") [])
  , testCase
      "constructor pattern with qualified name without arguments between parentheses"
    $ assertParseExpr "((Mod.c))" (Pattern (qname "Mod" "c") [])
  ]

test_pattern_operators :: [TestTree]
test_pattern_operators =
  [ testCase "right associativity" $ assertParseExpr
    "_ && _ && _"
    (Infix (uqsym "&&") Wildcard (Infix (uqsym "&&") Wildcard Wildcard))
  , testCase "left associativity" $ assertParseExpr
    "_ >> _ >> _"
    (Infix (uqsym ">>") (Infix (uqsym ">>") Wildcard Wildcard) Wildcard)
  , testCase "precedence (right associativity)" $ assertParseExpr
    "_ . _ ^ _"
    (Infix (uqsym "^") (Infix (uqsym ".") Wildcard Wildcard) Wildcard)
  , testCase "precedence (left associativity)" $ assertParseExpr
    "_ * _ !! _"
    (Infix (uqsym "*") Wildcard (Infix (uqsym "!!") Wildcard Wildcard))
  , testCase "precedence (mixed)" $ assertParseExpr
    "_ $ _ >> _"
    (Infix (uqsym "$") Wildcard (Infix (uqsym ">>") Wildcard Wildcard))
  , testCase "non-symbol"
    $ assertParseExpr "_ `mod` _" (Infix (uqname "mod") Wildcard Wildcard)
  ]

test_special_pattern_operators :: [TestTree]
test_special_pattern_operators =
  [ testCase "cons pattern" $ assertParseExprSpecialFixities
    "_ : _"
    (Infix (uqsym ":") Wildcard Wildcard)
  , testCase "join pattern" $ assertParseExprSpecialFixities
    "_ ++ _"
    (Infix (uqsym "++") Wildcard Wildcard)
  , testCase "nested cons pattern" $ assertParseExprSpecialFixities
    "_ : _ : _"
    (Infix (uqsym ":") Wildcard (Infix (uqsym ":") Wildcard Wildcard))
  , testCase "nested join pattern" $ assertParseExprSpecialFixities
    "_ ++ _ ++ _"
    (Infix (uqsym "++") Wildcard (Infix (uqsym "++") Wildcard Wildcard))
  , testCase "nested join, cons pattern" $ assertParseExprSpecialFixities
    "_ ++ _ : _"
    (Infix (uqsym "++") Wildcard (Infix (uqsym ":") Wildcard Wildcard))
  , testCase "nested cons, join pattern" $ assertParseExprSpecialFixities
    "_ : _ ++ _"
    (Infix (uqsym ":") Wildcard (Infix (uqsym "++") Wildcard Wildcard))
  ]

test_comments :: [TestTree]
test_comments =
  [ testCase "ignore a block comment"
    $ assertParseExpr "_ {- comment -} & _" (And Wildcard Wildcard)
  , testCase "ignore block comments" $ assertParseExpr
    "_ {- comment1 -}{- comment2 -} & (_ &{- comment3 -}_)"
    (And Wildcard (And Wildcard Wildcard))
  , testCase "ignore a block comment at beginning of line"
    $ assertParseExpr "{- comment -}_" Wildcard
  , testCase "ignore a line comment"
    $ assertParseExpr "_-- comment -- yeah" Wildcard
  , testCase "ignore a line comment at beginning of line"
    $ assertParseExpr "-- comment -- yeah \n_-- comment" Wildcard
  ]