-- How to use: runghc testParser.hs

import Hajspy
import Parser (expr)
import ParserLib (Parser, (*>), (<*), eof, whitespaces, runParser)
import Prelude hiding ((<*), (*>))
import TestLib

run :: String -> Maybe Expr
run inp = runParser (whitespaces *> expr <* eof) inp

tests =
    [ "single var yt3b1b" ~:
      run "yt3b1b" ~?= Just (Var "yt3b1b")
    , "simple lambda" ~:
      run "x => y" ~?= Just (Lambda "x" (Var "y"))
    , "simple ifelse" ~:
      run "x if c else y" ~?= Just (Cond (Var "c") (Var "x") (Var "y"))
    , "lambda vs ifelse" ~:
      run "x => x if b else y"
      ~?=
      Just (Lambda "x" (Cond (Var "b") (Var "x") (Var "y")))
    , "if else if else" ~:
      run "x if b else y if c else z"
      ~?=
      Just (Cond (Var "b")
                 (Var "x")
                 (Cond (Var "c") (Var "y") (Var "z")))
    , "if if else else :trollface:" ~:
      run "x if b if a else c else y"
      ~?=
      Just (Cond (Cond (Var "a") (Var "b") (Var "c"))
                 (Var "x")
                 (Var "y"))
    , "ifelse lower than +,-" ~:
      run "x + y if b else y - x"
      ~?=
      Just (Cond (Var "b")
                 (Var "x" :+: Var "y")
                 (Var "y" :-: Var "x"))
    , "+, -, *, / precedence and left-assoc" ~:
      run "x * y / z + a / b * c - u / v / w + r * s * t"
      ~?=
      Just (Var "x" :*: Var "y" :/: Var "z"
            :+:
            Var "a" :/: Var "b" :*: Var "c"
            :-:
            Var "u" :/: Var "v" :/: Var "w"
            :+:
            Var "r" :*: Var "s" :*: Var "t")
    , "unary - vs *" ~:
      run "- x * - y" ~?= Just (Neg (Var "x") :*: Neg (Var "y"))
    , "moar unary -" ~:
      run "- - -x" ~?= Just (Neg (Neg (Neg (Var "x"))))
    , "app" ~:
      run "f x y" ~?= Just (Var "f" :@: Var "x" :@: Var "y")
    , "app vs unary -" ~:
      run "- f x" ~?= Just (Neg (Var "f" :@: Var "x"))
    , "basic paren" ~:
      run "(x)" ~?= Just (Var "x")
    , "parenthesized lambda vs ifelse" ~:
      run "(x => a) if b else (z => c)"
      ~?=
      Just (Cond (Var "b")
                 (Lambda "x" (Var "a"))
                 (Lambda "z" (Var "c")))
    ]

main = testlibMain tests