{-# LANGUAGE LambdaCase #-}
-- | The parts of statements and expressions.
module Tokstyle.C.Analysis.Syntax
    ( exprChildren
    , statExprs
    , initExprs
    , localDecls
    , stats
    ) where

import           Language.C.Syntax.AST

exprChildren :: CExpr -> [CExpr]
exprChildren :: CExpr -> [CExpr]
exprChildren = \case
    CComma [CExpr]
es NodeInfo
_     -> [CExpr]
es
    CAssign CAssignOp
_ CExpr
l CExpr
r NodeInfo
_ -> [CExpr
l, CExpr
r]
    CCond CExpr
c Maybe CExpr
t CExpr
e NodeInfo
_   -> CExpr
c CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: [CExpr] -> (CExpr -> [CExpr]) -> Maybe CExpr -> [CExpr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CExpr -> [CExpr]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe CExpr
t [CExpr] -> [CExpr] -> [CExpr]
forall a. [a] -> [a] -> [a]
++ [CExpr
e]
    CBinary CBinaryOp
_ CExpr
l CExpr
r NodeInfo
_ -> [CExpr
l, CExpr
r]
    CCast CDeclaration NodeInfo
_ CExpr
e NodeInfo
_     -> [CExpr
e]
    CUnary CUnaryOp
_ CExpr
e NodeInfo
_    -> [CExpr
e]
    CIndex CExpr
b CExpr
i NodeInfo
_    -> [CExpr
b, CExpr
i]
    CCall CExpr
f [CExpr]
args NodeInfo
_  -> CExpr
f CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: [CExpr]
args
    CMember CExpr
e Ident
_ Bool
_ NodeInfo
_ -> [CExpr
e]
    CSizeofExpr CExpr
e NodeInfo
_ -> [CExpr
e]
    CExpr
_               -> []

-- | Every expression a statement evaluates, including in nested statements.
statExprs :: CStat -> [CExpr]
statExprs :: CStat -> [CExpr]
statExprs = \case
    CExpr Maybe CExpr
e NodeInfo
_ -> [CExpr] -> (CExpr -> [CExpr]) -> Maybe CExpr -> [CExpr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CExpr -> [CExpr]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe CExpr
e
    CReturn Maybe CExpr
e NodeInfo
_ -> [CExpr] -> (CExpr -> [CExpr]) -> Maybe CExpr -> [CExpr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CExpr -> [CExpr]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe CExpr
e
    CCompound [Ident]
_ [CCompoundBlockItem NodeInfo]
items NodeInfo
_ -> (CCompoundBlockItem NodeInfo -> [CExpr])
-> [CCompoundBlockItem NodeInfo] -> [CExpr]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CCompoundBlockItem NodeInfo -> [CExpr]
item [CCompoundBlockItem NodeInfo]
items
    CIf CExpr
c CStat
t Maybe CStat
e NodeInfo
_ -> CExpr
c CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: CStat -> [CExpr]
statExprs CStat
t [CExpr] -> [CExpr] -> [CExpr]
forall a. [a] -> [a] -> [a]
++ [CExpr] -> (CStat -> [CExpr]) -> Maybe CStat -> [CExpr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CStat -> [CExpr]
statExprs Maybe CStat
e
    CSwitch CExpr
c CStat
s NodeInfo
_ -> CExpr
c CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: CStat -> [CExpr]
statExprs CStat
s
    CWhile CExpr
c CStat
s Bool
_ NodeInfo
_ -> CExpr
c CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: CStat -> [CExpr]
statExprs CStat
s
    CFor Either (Maybe CExpr) (CDeclaration NodeInfo)
i Maybe CExpr
c Maybe CExpr
st CStat
s NodeInfo
_ -> (Maybe CExpr -> [CExpr])
-> (CDeclaration NodeInfo -> [CExpr])
-> Either (Maybe CExpr) (CDeclaration NodeInfo)
-> [CExpr]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ([CExpr] -> (CExpr -> [CExpr]) -> Maybe CExpr -> [CExpr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CExpr -> [CExpr]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure) CDeclaration NodeInfo -> [CExpr]
declExprs Either (Maybe CExpr) (CDeclaration NodeInfo)
i [CExpr] -> [CExpr] -> [CExpr]
forall a. [a] -> [a] -> [a]
++ [CExpr] -> (CExpr -> [CExpr]) -> Maybe CExpr -> [CExpr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CExpr -> [CExpr]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe CExpr
c [CExpr] -> [CExpr] -> [CExpr]
forall a. [a] -> [a] -> [a]
++ [CExpr] -> (CExpr -> [CExpr]) -> Maybe CExpr -> [CExpr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CExpr -> [CExpr]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe CExpr
st [CExpr] -> [CExpr] -> [CExpr]
forall a. [a] -> [a] -> [a]
++ CStat -> [CExpr]
statExprs CStat
s
    CLabel Ident
_ CStat
s [CAttribute NodeInfo]
_ NodeInfo
_ -> CStat -> [CExpr]
statExprs CStat
s
    CCase CExpr
e CStat
s NodeInfo
_ -> CExpr
e CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: CStat -> [CExpr]
statExprs CStat
s
    CCases CExpr
a CExpr
b CStat
s NodeInfo
_ -> CExpr
a CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: CExpr
b CExpr -> [CExpr] -> [CExpr]
forall a. a -> [a] -> [a]
: CStat -> [CExpr]
statExprs CStat
s
    CDefault CStat
s NodeInfo
_ -> CStat -> [CExpr]
statExprs CStat
s
    CStat
_ -> []
  where
    item :: CCompoundBlockItem NodeInfo -> [CExpr]
item = \case
        CBlockDecl CDeclaration NodeInfo
d -> CDeclaration NodeInfo -> [CExpr]
declExprs CDeclaration NodeInfo
d
        CBlockStmt CStat
s -> CStat -> [CExpr]
statExprs CStat
s
        CCompoundBlockItem NodeInfo
_            -> []

declExprs :: CDecl -> [CExpr]
declExprs :: CDeclaration NodeInfo -> [CExpr]
declExprs = \case
    CDecl [CDeclarationSpecifier NodeInfo]
_ [(Maybe (CDeclarator NodeInfo), Maybe (CInitializer NodeInfo),
  Maybe CExpr)]
ds NodeInfo
_ -> [[CExpr]] -> [CExpr]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ CInitializer NodeInfo -> [CExpr]
initExprs CInitializer NodeInfo
ini | (Maybe (CDeclarator NodeInfo)
_, Just CInitializer NodeInfo
ini, Maybe CExpr
_) <- [(Maybe (CDeclarator NodeInfo), Maybe (CInitializer NodeInfo),
  Maybe CExpr)]
ds ]
    CDeclaration NodeInfo
_            -> []

initExprs :: CInit -> [CExpr]
initExprs :: CInitializer NodeInfo -> [CExpr]
initExprs = \case
    CInitExpr CExpr
e NodeInfo
_ -> [CExpr
e]
    CInitList CInitializerList NodeInfo
l NodeInfo
_ -> (([CPartDesignator NodeInfo], CInitializer NodeInfo) -> [CExpr])
-> CInitializerList NodeInfo -> [CExpr]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (CInitializer NodeInfo -> [CExpr]
initExprs (CInitializer NodeInfo -> [CExpr])
-> (([CPartDesignator NodeInfo], CInitializer NodeInfo)
    -> CInitializer NodeInfo)
-> ([CPartDesignator NodeInfo], CInitializer NodeInfo)
-> [CExpr]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([CPartDesignator NodeInfo], CInitializer NodeInfo)
-> CInitializer NodeInfo
forall a b. (a, b) -> b
snd) CInitializerList NodeInfo
l

-- | The statements of a function body, recursively.
stats :: CStat -> [CStat]
stats :: CStat -> [CStat]
stats CStat
s = CStat
s CStat -> [CStat] -> [CStat]
forall a. a -> [a] -> [a]
: case CStat
s of
    CLabel Ident
_ CStat
t [CAttribute NodeInfo]
_ NodeInfo
_      -> CStat -> [CStat]
stats CStat
t
    CCase CExpr
_ CStat
t NodeInfo
_         -> CStat -> [CStat]
stats CStat
t
    CCases CExpr
_ CExpr
_ CStat
t NodeInfo
_      -> CStat -> [CStat]
stats CStat
t
    CDefault CStat
t NodeInfo
_        -> CStat -> [CStat]
stats CStat
t
    CCompound [Ident]
_ [CCompoundBlockItem NodeInfo]
items NodeInfo
_ -> [[CStat]] -> [CStat]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ CStat -> [CStat]
stats CStat
t | CBlockStmt CStat
t <- [CCompoundBlockItem NodeInfo]
items ]
    CIf CExpr
_ CStat
t Maybe CStat
e NodeInfo
_         -> CStat -> [CStat]
stats CStat
t [CStat] -> [CStat] -> [CStat]
forall a. [a] -> [a] -> [a]
++ [CStat] -> (CStat -> [CStat]) -> Maybe CStat -> [CStat]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CStat -> [CStat]
stats Maybe CStat
e
    CSwitch CExpr
_ CStat
t NodeInfo
_       -> CStat -> [CStat]
stats CStat
t
    CWhile CExpr
_ CStat
t Bool
_ NodeInfo
_      -> CStat -> [CStat]
stats CStat
t
    CFor Either (Maybe CExpr) (CDeclaration NodeInfo)
_ Maybe CExpr
_ Maybe CExpr
_ CStat
t NodeInfo
_      -> CStat -> [CStat]
stats CStat
t
    CStat
_                   -> []

-- | The declarations in a function body, in the order they appear.
localDecls :: CStat -> [CDecl]
localDecls :: CStat -> [CDeclaration NodeInfo]
localDecls = \case
    CCompound [Ident]
_ [CCompoundBlockItem NodeInfo]
items NodeInfo
_ -> (CCompoundBlockItem NodeInfo -> [CDeclaration NodeInfo])
-> [CCompoundBlockItem NodeInfo] -> [CDeclaration NodeInfo]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CCompoundBlockItem NodeInfo -> [CDeclaration NodeInfo]
item [CCompoundBlockItem NodeInfo]
items
    CIf CExpr
_ CStat
t Maybe CStat
e NodeInfo
_         -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
t [CDeclaration NodeInfo]
-> [CDeclaration NodeInfo] -> [CDeclaration NodeInfo]
forall a. [a] -> [a] -> [a]
++ [CDeclaration NodeInfo]
-> (CStat -> [CDeclaration NodeInfo])
-> Maybe CStat
-> [CDeclaration NodeInfo]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] CStat -> [CDeclaration NodeInfo]
localDecls Maybe CStat
e
    CSwitch CExpr
_ CStat
s NodeInfo
_       -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
    CWhile CExpr
_ CStat
s Bool
_ NodeInfo
_      -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
    CFor Either (Maybe CExpr) (CDeclaration NodeInfo)
i Maybe CExpr
_ Maybe CExpr
_ CStat
s NodeInfo
_      -> (Maybe CExpr -> [CDeclaration NodeInfo])
-> (CDeclaration NodeInfo -> [CDeclaration NodeInfo])
-> Either (Maybe CExpr) (CDeclaration NodeInfo)
-> [CDeclaration NodeInfo]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ([CDeclaration NodeInfo] -> Maybe CExpr -> [CDeclaration NodeInfo]
forall a b. a -> b -> a
const []) CDeclaration NodeInfo -> [CDeclaration NodeInfo]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Either (Maybe CExpr) (CDeclaration NodeInfo)
i [CDeclaration NodeInfo]
-> [CDeclaration NodeInfo] -> [CDeclaration NodeInfo]
forall a. [a] -> [a] -> [a]
++ CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
    CLabel Ident
_ CStat
s [CAttribute NodeInfo]
_ NodeInfo
_      -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
    CCase CExpr
_ CStat
s NodeInfo
_         -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
    CCases CExpr
_ CExpr
_ CStat
s NodeInfo
_      -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
    CDefault CStat
s NodeInfo
_        -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
    CStat
_                   -> []
  where
    item :: CCompoundBlockItem NodeInfo -> [CDeclaration NodeInfo]
item = \case
        CBlockDecl CDeclaration NodeInfo
d -> [CDeclaration NodeInfo
d]
        CBlockStmt CStat
s -> CStat -> [CDeclaration NodeInfo]
localDecls CStat
s
        CCompoundBlockItem NodeInfo
_            -> []