packages feed

cimple-0.0.30: test/Language/Cimple/AstSpec.hs

{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns      #-}
module Language.Cimple.AstSpec where

import           Data.Bifunctor       (Bifunctor (..))
import           Data.Fix             (Fix (..))
import           Data.Functor.Compose (Compose (..))
import           Test.Hspec           (Spec, describe, it, shouldBe,
                                       shouldSatisfy)

import           Language.Cimple      (AlexPosn (..), AnnotF (..),
                                       AssignOp (..), BinaryOp (..),
                                       CommentF (..), CommentStyle (..),
                                       Lexeme (..), LexemeClass (..),
                                       LiteralType (..), NodeF (..),
                                       Nullability (..), Scope (..),
                                       UnaryOp (..), addAnnot, removeAnnot)
import           Language.Cimple.IO   (parseText)


spec :: Spec
spec = do
    describe "Node" $ do
        it "can be annotated" $ do
            let Right [ast] = parseText "const int a = 3;"
            addAnnot ast `shouldBe`
                Fix (Compose (Annot () (
                    ConstDefn Global
                        (Fix (Compose (Annot () (
                            TyConst (Fix (Compose (Annot () (
                                TyStd (L (AlexPn 6 1 7) IdStdType "int")))))))))
                        (L (AlexPn 10 1 11) IdVar "a")
                        (Fix (Compose (Annot () (
                            LiteralExpr Int (L (AlexPn 14 1 15) LitInteger "3"))))))))

            removeAnnot (addAnnot ast) `shouldBe` ast

            addAnnot ast `shouldSatisfy` \case
                (removeAnnot -> Fix (ConstDefn Global
                    (Fix (TyConst (Fix (TyStd (L (AlexPn 6 1 7) IdStdType "int")))))
                    (L (AlexPn 10 1 11) IdVar "a")
                    (Fix (LiteralExpr Int (L (AlexPn 14 1 15) LitInteger "3"))))) -> True
                _ -> False

    describe "Bifunctor NodeF" $ do
        it "bimap maps lexemes and children" $ do
            let fl l = "l-" ++ l
            let fa a = "a-" ++ a
            let test n e = bimap fl fa n `shouldBe` e

            -- Preprocessor
            test (PreprocInclude "inc") (PreprocInclude "l-inc")
            test (PreprocDefine "def") (PreprocDefine "l-def")
            test (PreprocDefineConst "def" "const") (PreprocDefineConst "l-def" "a-const")
            test (PreprocDefineMacro "def" ["p1", "p2"] "body") (PreprocDefineMacro "l-def" ["a-p1", "a-p2"] "a-body")
            test (PreprocIf "cond" ["as"] "else") (PreprocIf "a-cond" ["a-as"] "a-else")
            test (PreprocIfdef "def" ["as"] "else") (PreprocIfdef "l-def" ["a-as"] "a-else")
            test (PreprocIfndef "def" ["as"] "else") (PreprocIfndef "l-def" ["a-as"] "a-else")
            test (PreprocElse ["as"]) (PreprocElse ["a-as"])
            test (PreprocElif "cond" ["as"] "else") (PreprocElif "a-cond" ["a-as"] "a-else")
            test (PreprocUndef "def") (PreprocUndef "l-def")
            test (PreprocDefined "def") (PreprocDefined "l-def")
            test (PreprocScopedDefine "a" ["as"] "a'") (PreprocScopedDefine "a-a" ["a-as"] "a-a'")
            test (MacroBodyStmt "a") (MacroBodyStmt "a-a")
            test (MacroBodyFunCall "a") (MacroBodyFunCall "a-a")
            test (MacroParam "l") (MacroParam "l-l")
            test (StaticAssert "a" "l") (StaticAssert "a-a" "l-l")

            -- Comments
            test (LicenseDecl "l" ["as"]) (LicenseDecl "l-l" ["a-as"])
            test (CopyrightDecl "l" (Just "ml") ["ls"]) (CopyrightDecl "l-l" (Just "l-ml") ["l-ls"])
            test (Comment Regular "l" ["ls"] "l'") (Comment Regular "l-l" ["l-ls"] "l-l'")
            test (CommentSection "a" ["as"] "a'") (CommentSection "a-a" ["a-as"] "a-a'")
            test (CommentSectionEnd "l") (CommentSectionEnd "l-l")
            test (Commented "a" "a'") (Commented "a-a" "a-a'")
            test (CommentInfo (Fix (DocWord "l"))) (CommentInfo (Fix (DocWord "l-l")))

            -- Namespace-like blocks
            test (ExternC ["as"]) (ExternC ["a-as"])
            test (Group ["as"]) (Group ["a-as"])

            -- Statements
            test (CompoundStmt ["as"]) (CompoundStmt ["a-as"])
            test Break Break
            test (Goto "l") (Goto "l-l")
            test Continue Continue
            test (Return (Just "ma")) (Return (Just "a-ma"))
            test (SwitchStmt "a" ["as"]) (SwitchStmt "a-a" ["a-as"])
            test (IfStmt "a" "a'" (Just "ma''")) (IfStmt "a-a" "a-a'" (Just "a-ma''"))
            test (ForStmt "a" "a'" "a''" "a'''") (ForStmt "a-a" "a-a'" "a-a''" "a-a'''")
            test (WhileStmt "a" "as") (WhileStmt "a-a" "a-as")
            test (DoWhileStmt "a" "a'") (DoWhileStmt "a-a" "a-a'")
            test (Case "a" "a'") (Case "a-a" "a-a'")
            test (Default "a") (Default "a-a")
            test (Label "l" "a") (Label "l-l" "a-a")
            test (ExprStmt "a") (ExprStmt "a-a")

            -- Variable declarations
            test (VLA "a" "l" "a'") (VLA "a-a" "l-l" "a-a'")
            test (VarDeclStmt "a" (Just "ma")) (VarDeclStmt "a-a" (Just "a-ma"))
            test (VarDecl "a" "l" ["as"]) (VarDecl "a-a" "l-l" ["a-as"])
            test (DeclSpecArray NullabilityUnspecified (Just "ma")) (DeclSpecArray NullabilityUnspecified (Just "a-ma"))

            -- Expressions
            test (InitialiserList ["as"]) (InitialiserList ["a-as"])
            test (UnaryExpr UopNot "a") (UnaryExpr UopNot "a-a")
            test (BinaryExpr "a" BopEq "a'") (BinaryExpr "a-a" BopEq "a-a'")
            test (TernaryExpr "a" "a'" "a''") (TernaryExpr "a-a" "a-a'" "a-a''")
            test (AssignExpr "a" AopEq "a'") (AssignExpr "a-a" AopEq "a-a'")
            test (ParenExpr "a") (ParenExpr "a-a")
            test (CastExpr "a" "a'") (CastExpr "a-a" "a-a'")
            test (CompoundLiteral "a" "a'") (CompoundLiteral "a-a" "a-a'")
            test (SizeofExpr "a") (SizeofExpr "a-a")
            test (SizeofType "a") (SizeofType "a-a")
            test (LiteralExpr Int "l") (LiteralExpr Int "l-l")
            test (VarExpr "l") (VarExpr "l-l")
            test (MemberAccess "a" "l") (MemberAccess "a-a" "l-l")
            test (PointerAccess "a" "l") (PointerAccess "a-a" "l-l")
            test (ArrayAccess "a" "a'") (ArrayAccess "a-a" "a-a'")
            test (FunctionCall "a" ["as"]) (FunctionCall "a-a" ["a-as"])
            test (CommentExpr "a" "a'") (CommentExpr "a-a" "a-a'")

            -- Type definitions
            test (EnumConsts (Just "ml") ["as"]) (EnumConsts (Just "l-ml") ["a-as"])
            test (EnumDecl "l" ["as"] "l'") (EnumDecl "l-l" ["a-as"] "l-l'")
            test (Enumerator "l" (Just "ma")) (Enumerator "l-l" (Just "a-ma"))
            test (AggregateDecl "a") (AggregateDecl "a-a")
            test (Typedef "a" "l" ["as"]) (Typedef "a-a" "l-l" ["a-as"])
            test (TypedefFunction "a") (TypedefFunction "a-a")
            test (Struct "l" ["as"]) (Struct "l-l" ["a-as"])
            test (Union "l" ["as"]) (Union "l-l" ["a-as"])
            test (MemberDecl "a" (Just "ml")) (MemberDecl "a-a" (Just "l-ml"))
            test (TyBitwise "a") (TyBitwise "a-a")
            test (TyForce "a") (TyForce "a-a")
            test (TyConst "a") (TyConst "a-a")
            test (TyOwner "a") (TyOwner "a-a")
            test (TyNonnull "a") (TyNonnull "a-a")
            test (TyNullable "a") (TyNullable "a-a")
            test (TyPointer "a") (TyPointer "a-a")
            test (TyStruct "l") (TyStruct "l-l")
            test (TyUnion "l") (TyUnion "l-l")
            test (TyFunc "l") (TyFunc "l-l")
            test (TyStd "l") (TyStd "l-l")
            test (TyUserDefined "l") (TyUserDefined "l-l")

            -- Functions
            test (AttrPrintf "l" "l'" "a") (AttrPrintf "l-l" "l-l'" "a-a")
            test (FunctionDecl Global "a") (FunctionDecl Global "a-a")
            test (FunctionDefn Global "a" "a'") (FunctionDefn Global "a-a" "a-a'")
            test (FunctionPrototype "a" "l" ["as"]) (FunctionPrototype "a-a" "l-l" ["a-as"])
            test (CallbackDecl "l" "l'") (CallbackDecl "l-l" "l-l'")
            test Ellipsis Ellipsis
            test (NonNull ["ls"] ["ls'"] "a") (NonNull ["l-ls"] ["l-ls'"] "a-a")
            test (NonNullParam "a") (NonNullParam "a-a")
            test (NullableParam "a") (NullableParam "a-a")

            -- Constants
            test (ConstDecl "a" "l") (ConstDecl "a-a" "l-l")
            test (ConstDefn Global "a" "l" "a'") (ConstDefn Global "a-a" "l-l" "a-a'")

    describe "Bifunctor CommentF" $ do
        it "bimap maps lexemes and children" $ do
            let fl l = "l-" ++ l
            let fa a = "a-" ++ a
            let test n e = bimap fl fa n `shouldBe` e

            test (DocComment ["as"]) (DocComment ["a-as"])
            test DocAttention DocAttention
            test DocBrief DocBrief
            test DocDeprecated DocDeprecated
            test (DocExtends "l") (DocExtends "l-l")
            test DocFile DocFile
            test (DocImplements "l") (DocImplements "l-l")
            test DocNote DocNote
            test (DocParam (Just "ml") "l") (DocParam (Just "l-ml") "l-l")
            test DocReturn DocReturn
            test DocRetval DocRetval
            test (DocSection "l") (DocSection "l-l")
            test (DocSecurityRank "l" (Just "ml") "l'") (DocSecurityRank "l-l" (Just "l-ml") "l-l'")
            test (DocSee "l") (DocSee "l-l")
            test (DocSubsection "l") (DocSubsection "l-l")
            test DocPrivate DocPrivate
            test (DocLine ["as"]) (DocLine ["a-as"])
            test (DocCode "l" ["as"] "l'") (DocCode "l-l" ["a-as"] "l-l'")
            test (DocWord "l") (DocWord "l-l")
            test (DocRef "l") (DocRef "l-l")
            test (DocP "l") (DocP "l-l")