axel-0.0.7: test/Axel/Test/ParseSpec.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeApplications #-}
module Axel.Test.ParseSpec where
import Axel.Error
import Axel.Parse
import Axel.Utils.String
import Control.Monad.Freer as Eff
import qualified Control.Monad.Freer.Error as Effs
import Test.Tasty.Hspec
{-# ANN module "HLint: ignore Redundant do" #-}
spec_Parse :: SpecWith ()
spec_Parse = do
describe "parseSingle" $ do
it "can parse a character literal" $ do
let result = LiteralChar 'a'
case Eff.run . Effs.runError @Error $ parseSingle "#\\a" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse an integer literal" $ do
let result = LiteralInt 123
case Eff.run . Effs.runError @Error $ parseSingle "123" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse a list literal" $ do
let result = SExpression [Symbol "list", LiteralInt 1, LiteralChar 'a']
case Eff.run . Effs.runError @Error $ parseSingle "[1 #\\a]" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse a string literal" $ do
let result = LiteralString "a \"b"
case Eff.run . Effs.runError @Error $ parseSingle "\"a \\\"b\"" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse a quasiquoted expression" $ do
let result =
SExpression
[Symbol "quasiquote", SExpression [Symbol "foo", Symbol "bar"]]
case Eff.run . Effs.runError @Error $ parseSingle "`(foo bar)" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse an s-expression" $ do
let result = SExpression [Symbol "foo", Symbol "bar"]
case Eff.run . Effs.runError @Error $ parseSingle "(foo bar)" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse a splice-unquoted expression" $ do
let result =
SExpression
[ Symbol "unquoteSplicing"
, SExpression [Symbol "foo", Symbol "bar"]
]
case Eff.run . Effs.runError @Error $ parseSingle "~@(foo bar)" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse a symbol" $ do
let result = Symbol "abc123'''"
case Eff.run . Effs.runError @Error $ parseSingle "abc123'''" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse a macro name" $ do
let result = Symbol ",;foo"
case Eff.run . Effs.runError @Error $ parseSingle ",;foo" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can parse an unquoted expression" $ do
let result =
SExpression
[Symbol "unquote", SExpression [Symbol "foo", Symbol "bar"]]
case Eff.run . Effs.runError @Error $ parseSingle "~(foo bar)" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can quote a character character" $ do
let result = SExpression [Symbol "AST.LiteralChar", LiteralChar 'a']
case Eff.run . Effs.runError @Error $ parseSingle "'#\\a" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can quote an integer literal" $ do
let result = SExpression [Symbol "AST.LiteralInt", LiteralInt 123]
case Eff.run . Effs.runError @Error $ parseSingle "'123" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can quote a list literal" $ do
let result =
SExpression
[ Symbol "AST.SExpression"
, SExpression
[ Symbol "list"
, SExpression [Symbol "AST.Symbol", LiteralString "list"]
, SExpression [Symbol "AST.LiteralInt", LiteralInt 1]
, SExpression [Symbol "AST.LiteralInt", LiteralInt 2]
]
]
case Eff.run . Effs.runError @Error $ parseSingle "'[1 2]" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can quote a string literal" $ do
let result = SExpression [Symbol "AST.LiteralString", LiteralString "foo"]
case Eff.run . Effs.runError @Error $ parseSingle "'\"foo\"" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can quote an s-expression" $ do
let result =
SExpression
[ Symbol "AST.SExpression"
, SExpression
[ Symbol "list"
, SExpression [Symbol "AST.LiteralInt", LiteralInt 1]
, SExpression [Symbol "AST.LiteralInt", LiteralInt 2]
]
]
case Eff.run . Effs.runError @Error $ parseSingle "'(1 2)" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can quote a symbol" $ do
let result = SExpression [Symbol "AST.Symbol", LiteralString "foo"]
case Eff.run . Effs.runError @Error $ parseSingle "'foo" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
it "can quote a quoted expression" $ do
let result =
SExpression
[ Symbol "AST.SExpression"
, SExpression
[ Symbol "list"
, SExpression [Symbol "AST.Symbol", LiteralString "quote"]
, SExpression [Symbol "AST.Symbol", LiteralString "foo"]
]
]
case Eff.run . Effs.runError @Error $ parseSingle "''foo" of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
describe "parseMultiple" $ do
it "can parse multiple expressions" $ do
let input =
[s|
(foo 1 2 3)
(bar
x
y
z)
|]
let result =
[ SExpression
[Symbol "foo", LiteralInt 1, LiteralInt 2, LiteralInt 3]
, SExpression [Symbol "bar", Symbol "x", Symbol "y", Symbol "z"]
]
case Eff.run . Effs.runError @Error $ parseMultiple input of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result
describe "parseSource" $ do
it "can parse a source file" $ do
let input =
[s|
(foo 1 2 3) -- This is a comment
-- Another comment! (bar x y z)
|]
let result =
SExpression
[ Symbol "begin"
, SExpression
[Symbol "foo", LiteralInt 1, LiteralInt 2, LiteralInt 3]
]
case Eff.run . Effs.runError @Error $ parseSource input of
Left err -> expectationFailure $ show err
Right x -> x `shouldBe` result