{-# LANGUAGE OverloadedStrings #-}
{-|
Module      : Htcc.Parser.AST.Core
Description : The AST data type and its utilities
Copyright   : (c) roki, 2019
License     : MIT
Maintainer  : falgon53@yahoo.co.jp
Stability   : experimental
Portability : POSIX

The AST data type and its utilities
-}
module Htcc.Parser.AST.Core (
    -- * Abstract tree types and its relational type class
    ATKindFor (..),
    ATKind (..),
    ATree (..),
    Treealizable (..),
    -- * Constructor
    atBinary, atUnary, atNoLeaf,
    atLVar, atGVar,
    atAssign, atNumLit, atMemberAcc, atExprStmt,
    atBlock, atNull, atDefFunc, atReturn,
    atIf, atElse, atWhile, atFor,
    atBreak, atContinue, atSwitch, atCase,
    atDefault, atGoto, atLabel, atComma,
    atConditional, atCast,
    -- * Utilities
    isATForInit,
    isATForCond,
    isATForStmt,
    isATForIncr,
    fromATKindFor,
    isComplexAssign,
    isEmptyExprStmt,
    isEmptyReturn,
    isNonEmptyReturn,
    mapATKind,
    modifyTypeATKind
) where

import           Control.Monad     ((>=>))
import qualified Data.Text         as T
import qualified Htcc.CRules.Types as CT

-- | Specially @for@ syntax tree type
data ATKindFor a = ATForkw -- ^ The @for@ keyword
    | ATForInit (ATree a) -- ^ The initial section of @for@ statement
    | ATForCond (ATree a) -- ^ The conditional section of @for@ statement
    | ATForIncr (ATree a) -- ^ The incremental section of @for@ statement
    | ATForStmt (ATree a) -- ^ The statement section of @for@ statement
    deriving Int -> ATKindFor a -> ShowS
[ATKindFor a] -> ShowS
ATKindFor a -> String
(Int -> ATKindFor a -> ShowS)
-> (ATKindFor a -> String)
-> ([ATKindFor a] -> ShowS)
-> Show (ATKindFor a)
forall a. Show a => Int -> ATKindFor a -> ShowS
forall a. Show a => [ATKindFor a] -> ShowS
forall a. Show a => ATKindFor a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ATKindFor a] -> ShowS
$cshowList :: forall a. Show a => [ATKindFor a] -> ShowS
show :: ATKindFor a -> String
$cshow :: forall a. Show a => ATKindFor a -> String
showsPrec :: Int -> ATKindFor a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> ATKindFor a -> ShowS
Show

{-# INLINE isATForInit #-}
-- | An utility of `ATForInit`. When an argument is `ATForInit`, return `True` otherwise `False`
isATForInit :: ATKindFor a -> Bool
isATForInit :: ATKindFor a -> Bool
isATForInit (ATForInit _) = Bool
True
isATForInit _             = Bool
False

{-# INLINE isATForCond #-}
-- | An utility of `ATForCond`. When an argument is `ATForCond`, return `True` otherwise `False`
isATForCond :: ATKindFor a -> Bool
isATForCond :: ATKindFor a -> Bool
isATForCond (ATForCond _) = Bool
True
isATForCond _             = Bool
False

{-# INLINE isATForStmt #-}
-- | An utility `ATForStmt`. When an argument is `ATForStmt`, return `True` otherwise `False`
isATForStmt :: ATKindFor a -> Bool
isATForStmt :: ATKindFor a -> Bool
isATForStmt (ATForStmt _) = Bool
True
isATForStmt _             = Bool
False

{-# INLINE isATForIncr #-}
-- | An utility `ATForIncr`. When an argument is `ATForIncr`, return `True` otherwise `False`
isATForIncr :: ATKindFor a -> Bool
isATForIncr :: ATKindFor a -> Bool
isATForIncr (ATForIncr _) = Bool
True
isATForIncr _             = Bool
False

{-# INLINE fromATKindFor #-}
-- | take ATree data from `ATKindFor`.
fromATKindFor :: ATKindFor a -> ATree a
fromATKindFor :: ATKindFor a -> ATree a
fromATKindFor (ATForInit x :: ATree a
x) = ATree a
x
fromATKindFor (ATForCond x :: ATree a
x) = ATree a
x
fromATKindFor (ATForIncr x :: ATree a
x) = ATree a
x
fromATKindFor (ATForStmt x :: ATree a
x) = ATree a
x
fromATKindFor _             = String -> ATree a
forall a. HasCallStack => String -> a
error "ATKindFor is ATForkw"

-- | The syntax tree type. Let \(x,y\in\mathbb{N}\), Let \(p\) and \(q\) be pointers to variables \(a\) and \(b\), respectively (@p=&a,q=&b@).
data ATKind a = ATAdd -- ^ \(x+y\): @x + y@
    | ATAddPtr -- ^ add operation for pointer \(p+x,x+p\): @p + x, x + p@
    | ATSub -- ^ \(x-y\): @x - y@
    | ATSubPtr -- ^ sub operation for pointer \(p-x\): @p - x@
    | ATPtrDis -- ^ The distance of pointers \(p-q\): @p - q@
    | ATMul -- ^ \(x\times y\): @x * y@
    | ATDiv -- ^ \(x\div y\): @x / y@
    | ATMod -- ^ \(x\bmod y\): @x % y@
    | ATAddAssign -- ^ addition assignment: @a += b@
    | ATSubAssign -- ^ subtraction assignment: @a -= b@
    | ATMulAssign -- ^ multiplication assignment: @a *= b@
    | ATDivAssign -- ^ division assignment: @a /= b@
    | ATAddPtrAssign -- ^ addition assignment for pointer: @p += q@
    | ATSubPtrAssign -- ^ subtraction assignment for pointer: @p -= q@
    | ATLAnd -- ^ logical and: @x && y@
    | ATLOr -- ^ logical or: @x || y@
    | ATAnd -- ^ bitwise and: @x & y@
    | ATAndAssign -- ^ bitwise and assignment: @a &= b@
    | ATOr -- ^ bitwise or: @x | y@
    | ATOrAssign -- ^ bitwise or assignment: @a |= b@
    | ATXor -- ^ bitwise xor: @x ^ y@
    | ATXorAssign -- ^ bitwise xor assignment: @a ^= b@
    | ATBitNot -- ^ bitwise not: @~x@
    | ATShl -- ^ left shift: @x << y@
    | ATShlAssign -- ^ left shift assignment: @a <<= b@
    | ATShr -- ^ right shift: @x >> y@
    | ATShrAssign -- ^ right shift assignment: @a >>= b@
    | ATLT  -- ^ \(x\lt y\): @x < y@
    | ATLEQ -- ^ \(x\leq y\): @x <= y@
    | ATGT  -- ^ \(x\gt y\): @x > y@
    | ATGEQ -- ^ \(x\geq y\): @x >= y@
    | ATEQ  -- ^ \(x=y\): @x == y@
    | ATNEQ -- ^ \(x\not= y\): @x != y@
    | ATNot -- ^ not operator @!@: @!x@
    | ATAddr -- ^ addressing operator @&@: @&x@
    | ATDeref -- ^ dereferencing operator @*@: @*p@
    | ATAssign -- ^ assign operator: @x=y@
    | ATPreInc -- ^ pre-increment operator: @++a@
    | ATPreDec -- ^ pre-decrement operator: @--a@
    | ATPostInc -- ^ post-increment operator: @a++@
    | ATPostDec -- ^ post-decrement operator: @a--@
    | ATNum a -- ^ The number
    | ATConditional (ATree a) (ATree a) (ATree a) -- ^ conditional operator: @a ? x : y;@. It has three AST (cond, then and else)
    | ATComma -- ^ comma operator: @x,b@
    | ATCast -- ^ the cast operation: @(type) x@
    | ATMemberAcc (CT.StructMember a) -- ^ accessing the member of the @struct@
    | ATReturn -- ^ the @return@ keyword
    | ATIf -- ^ the @if@ keyword
    | ATElse -- ^ the @else@ keyword
    | ATSwitch (ATree a) [ATree a] -- ^ the @switch@ keyword, it has the conditional expression and compound statement by @case@s or @default@s
    | ATCase a a -- ^ the @case@ keyword, it has the value of label number and a constant value
    | ATDefault a -- ^ the @default@ keyword
    | ATWhile -- ^ the @while@ keyword
    | ATFor [ATKindFor a] -- ^ the @for@ keyword
    | ATBreak -- ^ the @break@ keyword
    | ATContinue -- ^ the @continue@ keyword
    | ATGoto  T.Text -- ^ the @goto@ keyword, it has name of the target label
    | ATLabel T.Text -- ^ the label, it has name of label.
    | ATBlock [ATree a] -- ^ the compound statement
    | ATLVar (CT.StorageClass a) a -- ^ the local variable. It has a type information (as `CT.StorageClass`) and an offset value
    | ATGVar (CT.StorageClass a) T.Text -- ^ the global variable. It has a type information (as `CT.StorageClass`) and an name
    | ATDefFunc T.Text (Maybe [ATree a]) -- ^ the function definition
    | ATCallFunc T.Text (Maybe [ATree a]) -- ^ the function call. It has a offset value and arguments (`Maybe`)
    | ATExprStmt -- ^ the expression of a statement
    | ATStmtExpr [ATree a] -- ^ the statement of a expression (GNU extension)
    | ATNull (ATree a) -- ^ indicates nothing to do
    deriving Int -> ATKind a -> ShowS
[ATKind a] -> ShowS
ATKind a -> String
(Int -> ATKind a -> ShowS)
-> (ATKind a -> String) -> ([ATKind a] -> ShowS) -> Show (ATKind a)
forall a. Show a => Int -> ATKind a -> ShowS
forall a. Show a => [ATKind a] -> ShowS
forall a. Show a => ATKind a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ATKind a] -> ShowS
$cshowList :: forall a. Show a => [ATKind a] -> ShowS
show :: ATKind a -> String
$cshow :: forall a. Show a => ATKind a -> String
showsPrec :: Int -> ATKind a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> ATKind a -> ShowS
Show

{-# INLINE fromATVar #-}
-- | Take its type when it is ATIVar or ATIVar.
fromATVar :: ATKind i -> Maybe (CT.StorageClass i)
fromATVar :: ATKind i -> Maybe (StorageClass i)
fromATVar (ATLVar s :: StorageClass i
s _) = StorageClass i -> Maybe (StorageClass i)
forall a. a -> Maybe a
Just StorageClass i
s
fromATVar (ATGVar s :: StorageClass i
s _) = StorageClass i -> Maybe (StorageClass i)
forall a. a -> Maybe a
Just StorageClass i
s
fromATVar _            = Maybe (StorageClass i)
forall a. Maybe a
Nothing

instance CT.IncompleteBase ATKind where
    isIncompleteArray :: ATKind i -> Bool
isIncompleteArray = Bool -> (StorageClass i -> Bool) -> Maybe (StorageClass i) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False StorageClass i -> Bool
forall (a :: * -> *) i. IncompleteBase a => a i -> Bool
CT.isIncompleteArray (Maybe (StorageClass i) -> Bool)
-> (ATKind i -> Maybe (StorageClass i)) -> ATKind i -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ATKind i -> Maybe (StorageClass i)
forall i. ATKind i -> Maybe (StorageClass i)
fromATVar
    isIncompleteStruct :: ATKind i -> Bool
isIncompleteStruct = Bool -> (StorageClass i -> Bool) -> Maybe (StorageClass i) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False StorageClass i -> Bool
forall (a :: * -> *) i. IncompleteBase a => a i -> Bool
CT.isIncompleteStruct (Maybe (StorageClass i) -> Bool)
-> (ATKind i -> Maybe (StorageClass i)) -> ATKind i -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ATKind i -> Maybe (StorageClass i)
forall i. ATKind i -> Maybe (StorageClass i)
fromATVar
    fromIncompleteArray :: ATKind i -> Maybe (TypeKind i)
fromIncompleteArray = ATKind i -> Maybe (StorageClass i)
forall i. ATKind i -> Maybe (StorageClass i)
fromATVar (ATKind i -> Maybe (StorageClass i))
-> (StorageClass i -> Maybe (TypeKind i))
-> ATKind i
-> Maybe (TypeKind i)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> StorageClass i -> Maybe (TypeKind i)
forall (a :: * -> *) i.
IncompleteBase a =>
a i -> Maybe (TypeKind i)
CT.fromIncompleteArray
    fromIncompleteStruct :: ATKind i -> Maybe Text
fromIncompleteStruct = ATKind i -> Maybe (StorageClass i)
forall i. ATKind i -> Maybe (StorageClass i)
fromATVar (ATKind i -> Maybe (StorageClass i))
-> (StorageClass i -> Maybe Text) -> ATKind i -> Maybe Text
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> StorageClass i -> Maybe Text
forall (a :: * -> *) i. IncompleteBase a => a i -> Maybe Text
CT.fromIncompleteStruct
    isValidIncomplete :: ATKind i -> Bool
isValidIncomplete = Bool -> (StorageClass i -> Bool) -> Maybe (StorageClass i) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False StorageClass i -> Bool
forall (a :: * -> *) i. (IncompleteBase a, Ord i) => a i -> Bool
CT.isValidIncomplete (Maybe (StorageClass i) -> Bool)
-> (ATKind i -> Maybe (StorageClass i)) -> ATKind i -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ATKind i -> Maybe (StorageClass i)
forall i. ATKind i -> Maybe (StorageClass i)
fromATVar

{-# INLINE isComplexAssign #-}
-- | Returns True if the given `ATKind` is an assignment operator other than simple assignment.
-- Otherwise, returns `False`.
isComplexAssign :: ATKind a -> Bool
isComplexAssign :: ATKind a -> Bool
isComplexAssign ATAddAssign    = Bool
True
isComplexAssign ATSubAssign    = Bool
True
isComplexAssign ATMulAssign    = Bool
True
isComplexAssign ATDivAssign    = Bool
True
isComplexAssign ATAddPtrAssign = Bool
True
isComplexAssign ATSubPtrAssign = Bool
True
isComplexAssign ATOrAssign     = Bool
True
isComplexAssign ATAndAssign    = Bool
True
isComplexAssign ATXorAssign    = Bool
True
isComplexAssign ATShlAssign    = Bool
True
isComplexAssign ATShrAssign    = Bool
True
isComplexAssign _              = Bool
False

-- | The data structure of abstract syntax tree
data ATree a = ATEmpty -- ^ The empty node
    | ATNode {
    ATree a -> ATKind a
atkind :: ATKind a, -- ^ The kind of abstract tree
    ATree a -> StorageClass a
atype  :: CT.StorageClass a, -- ^ The data type
    ATree a -> ATree a
atL    :: ATree a, -- ^ The left hand side abstract tree
    ATree a -> ATree a
atR    :: ATree a -- ^ The right hand side abstract tree
    } -- ^ `ATKind` representing the kind of node and the two branches `ATree` it has
    deriving Int -> ATree a -> ShowS
[ATree a] -> ShowS
ATree a -> String
(Int -> ATree a -> ShowS)
-> (ATree a -> String) -> ([ATree a] -> ShowS) -> Show (ATree a)
forall a. Show a => Int -> ATree a -> ShowS
forall a. Show a => [ATree a] -> ShowS
forall a. Show a => ATree a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ATree a] -> ShowS
$cshowList :: forall a. Show a => [ATree a] -> ShowS
show :: ATree a -> String
$cshow :: forall a. Show a => ATree a -> String
showsPrec :: Int -> ATree a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> ATree a -> ShowS
Show

-- | A class whose type can be converted to ATree
class Treealizable a where
    -- | Convert to `ATree`
    treealize :: a i -> ATree i

{-# INLINE isEmptyExprStmt #-}
-- | `isEmptyExprStmt` returns `True` only if both sides of `ATExprStmt` are `ATEmpty`. Otherwise, returns `False`.
isEmptyExprStmt :: ATree a -> Bool
isEmptyExprStmt :: ATree a -> Bool
isEmptyExprStmt (ATNode ATExprStmt _ ATEmpty ATEmpty) = Bool
True
isEmptyExprStmt _                                     = Bool
False

{-# INLINE isNonEmptyReturn #-}
-- | `isNonEmptyReturn` returns `True` only if the `ATKind` of the given argument is `ATReturn` and the left side hand node of the given argument is not `ATEmpty`.
-- Otherwise, returns `False`.
isNonEmptyReturn :: ATree a -> Bool
isNonEmptyReturn :: ATree a -> Bool
isNonEmptyReturn (ATNode ATReturn _ ATEmpty _) = Bool
False
isNonEmptyReturn (ATNode ATReturn _ _ _)       = Bool
True
isNonEmptyReturn _                             = Bool
False

{-# INLINE isEmptyReturn #-}
-- | `isEmptyReturn` returns `True` only if the `ATKind` of the given argument is `ATReturn` and the left side hand node of the given argument is `ATEmpty`.
-- Otherwise, returns `False`.
isEmptyReturn :: ATree a -> Bool
isEmptyReturn :: ATree a -> Bool
isEmptyReturn (ATNode ATReturn _ ATEmpty _) = Bool
True
isEmptyReturn _                             = Bool
False

{-# INLINE atBinary #-}
-- | `atBinary` is equivalent to `ATNode`
atBinary :: ATKind i -> CT.StorageClass i -> ATree i -> ATree i -> ATree i
atBinary :: ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
atBinary = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
ATNode

{-# INLINE atUnary #-}
-- | `atUnary` is a shortcut for unary node
atUnary :: ATKind i -> CT.StorageClass i -> ATree i -> ATree i
atUnary :: ATKind i -> StorageClass i -> ATree i -> ATree i
atUnary k :: ATKind i
k t :: StorageClass i
t n :: ATree i
n = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
atBinary ATKind i
k StorageClass i
t ATree i
n ATree i
forall a. ATree a
ATEmpty

{-# INLINE atNoLeaf #-}
-- | `atNoLeaf` is equivalent to @ATNode k t ATEmpty ATEmpty@
atNoLeaf :: ATKind i -> CT.StorageClass i -> ATree i
atNoLeaf :: ATKind i -> StorageClass i -> ATree i
atNoLeaf k :: ATKind i
k t :: StorageClass i
t = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
ATNode ATKind i
k StorageClass i
t ATree i
forall a. ATree a
ATEmpty ATree i
forall a. ATree a
ATEmpty

{-# INLINE atLVar #-}
-- | `atLVar` is a shortcut for local variable node
atLVar :: CT.StorageClass i -> i -> ATree i
atLVar :: StorageClass i -> i -> ATree i
atLVar t :: StorageClass i
t rbpO :: i
rbpO = ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (StorageClass i -> i -> ATKind i
forall a. StorageClass a -> a -> ATKind a
ATLVar StorageClass i
t i
rbpO) StorageClass i
t

{-# INLINE atGVar #-}
-- | `atGVar` is a shortcut for global variable node
atGVar :: CT.StorageClass i -> T.Text -> ATree i
atGVar :: StorageClass i -> Text -> ATree i
atGVar t :: StorageClass i
t ident :: Text
ident = ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (StorageClass i -> Text -> ATKind i
forall a. StorageClass a -> Text -> ATKind a
ATGVar StorageClass i
t Text
ident) StorageClass i
t

{-# INLINE atNumLit #-}
-- | `atNumLit` is a shortcut for constructing a numeric literal node
atNumLit :: i -> ATree i
atNumLit :: i -> ATree i
atNumLit = (ATKind i -> StorageClass i -> ATree i)
-> StorageClass i -> ATKind i -> ATree i
forall a b c. (a -> b -> c) -> b -> a -> c
flip ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCAuto (TypeKind i -> StorageClass i) -> TypeKind i -> StorageClass i
forall a b. (a -> b) -> a -> b
$ TypeKind i -> TypeKind i
forall i. TypeKind i -> TypeKind i
CT.CTLong TypeKind i
forall i. TypeKind i
CT.CTInt) (ATKind i -> ATree i) -> (i -> ATKind i) -> i -> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. i -> ATKind i
forall a. a -> ATKind a
ATNum

{-# INLINE atAssign #-}
-- | `atAssign` is a shortcut for constructing a assign node
atAssign :: ATree i -> ATree i -> ATree i
atAssign :: ATree i -> ATree i -> ATree i
atAssign lhs :: ATree i
lhs = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
atBinary ATKind i
forall a. ATKind a
ATAssign (ATree i -> StorageClass i
forall a. ATree a -> StorageClass a
atype ATree i
lhs) ATree i
lhs

{-# INLINE atMemberAcc #-}
-- | `atMemberAcc` is a shortcut for constructing a `ATMemberAcc` node
atMemberAcc :: CT.StructMember i -> ATree i -> ATree i
atMemberAcc :: StructMember i -> ATree i -> ATree i
atMemberAcc sm :: StructMember i
sm = ATKind i -> StorageClass i -> ATree i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i -> ATree i
atUnary (StructMember i -> ATKind i
forall a. StructMember a -> ATKind a
ATMemberAcc StructMember i
sm) (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCAuto (TypeKind i -> StorageClass i) -> TypeKind i -> StorageClass i
forall a b. (a -> b) -> a -> b
$ StructMember i -> TypeKind i
forall i. StructMember i -> TypeKind i
CT.smType StructMember i
sm)

{-# INLINE atExprStmt #-}
-- | `atExprStmt` is a shortcut for constructing a expression statement node
atExprStmt :: ATree i -> ATree i
atExprStmt :: ATree i -> ATree i
atExprStmt = ATKind i -> StorageClass i -> ATree i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i -> ATree i
atUnary ATKind i
forall a. ATKind a
ATExprStmt (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef)

{-# INLINE atBlock #-}
-- | `atBlock` is a shortcut for constructing a block node
atBlock :: [ATree i] -> ATree i
atBlock :: [ATree i] -> ATree i
atBlock atl :: [ATree i]
atl = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
ATNode ([ATree i] -> ATKind i
forall a. [ATree a] -> ATKind a
ATBlock [ATree i]
atl) (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef) ATree i
forall a. ATree a
ATEmpty ATree i
forall a. ATree a
ATEmpty

{-# INLINE atNull #-}
-- | `atNull` is a shortcut for constructing a null node
atNull :: ATree i -> ATree i
atNull :: ATree i -> ATree i
atNull at :: ATree i
at = ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (ATree i -> ATKind i
forall a. ATree a -> ATKind a
ATNull ATree i
at) (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef)

{-# INLINE atDefFunc #-}
-- | `atDefFunc` is a shortcut for constructing a function node
atDefFunc :: T.Text -> Maybe [ATree i] -> CT.StorageClass i -> ATree i -> ATree i
atDefFunc :: Text -> Maybe [ATree i] -> StorageClass i -> ATree i -> ATree i
atDefFunc = (ATKind i -> StorageClass i -> ATree i -> ATree i)
-> (Maybe [ATree i] -> ATKind i)
-> Maybe [ATree i]
-> StorageClass i
-> ATree i
-> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) ATKind i -> StorageClass i -> ATree i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i -> ATree i
atUnary ((Maybe [ATree i] -> ATKind i)
 -> Maybe [ATree i] -> StorageClass i -> ATree i -> ATree i)
-> (Text -> Maybe [ATree i] -> ATKind i)
-> Text
-> Maybe [ATree i]
-> StorageClass i
-> ATree i
-> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe [ATree i] -> ATKind i
forall a. Text -> Maybe [ATree a] -> ATKind a
ATDefFunc

{-# INLINE atReturn #-}
-- | `atReturn` is a shortcut for constructing a @return@ node
atReturn :: CT.StorageClass i -> ATree i -> ATree i
atReturn :: StorageClass i -> ATree i -> ATree i
atReturn = ATKind i -> StorageClass i -> ATree i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i -> ATree i
atUnary ATKind i
forall a. ATKind a
ATReturn

{-# INLINE atIf #-}
-- | `atIf` is a shortcut for constructing a @if@ node
atIf :: ATree i -> ATree i -> ATree i
atIf :: ATree i -> ATree i -> ATree i
atIf = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
atBinary ATKind i
forall a. ATKind a
ATIf (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef)

{-# INLINE atElse #-}
-- | `atElse` is a shortcut for constructing a @else@ node
atElse :: ATree i -> ATree i -> ATree i
atElse :: ATree i -> ATree i -> ATree i
atElse = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
atBinary ATKind i
forall a. ATKind a
ATElse (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef)

{-# INLINE atWhile #-}
-- | `atWhile` is a shortcut for constructing a @while@ node
atWhile :: ATree i -> ATree i -> ATree i
atWhile :: ATree i -> ATree i -> ATree i
atWhile = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
atBinary ATKind i
forall a. ATKind a
ATWhile (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef)

{-# INLINE atFor #-}
-- | `atFor` is a shortcut for constructing a @for@ node
atFor :: [ATKindFor i] -> ATree i
atFor :: [ATKindFor i] -> ATree i
atFor = (ATKind i -> StorageClass i -> ATree i)
-> StorageClass i -> ATKind i -> ATree i
forall a b c. (a -> b -> c) -> b -> a -> c
flip ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef) (ATKind i -> ATree i)
-> ([ATKindFor i] -> ATKind i) -> [ATKindFor i] -> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ATKindFor i] -> ATKind i
forall a. [ATKindFor a] -> ATKind a
ATFor

{-# INLINE atBreak #-}
-- | `atBreak` is a shortcut for constructing a @break@ node
atBreak :: ATree i
atBreak :: ATree i
atBreak = ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf ATKind i
forall a. ATKind a
ATBreak (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef)

{-# INLINE atContinue #-}
-- | `atContinue` is a shortcut for constructing a @continue@ node
atContinue :: ATree i
atContinue :: ATree i
atContinue = ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf ATKind i
forall a. ATKind a
ATContinue (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef)

{-# INLINE atSwitch #-}
-- | `atSwitch` is a shortcut for constructing a @switch@ node
atSwitch :: ATree i -> [ATree i] -> CT.StorageClass i -> ATree i
atSwitch :: ATree i -> [ATree i] -> StorageClass i -> ATree i
atSwitch = (ATKind i -> StorageClass i -> ATree i)
-> ([ATree i] -> ATKind i)
-> [ATree i]
-> StorageClass i
-> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (([ATree i] -> ATKind i) -> [ATree i] -> StorageClass i -> ATree i)
-> (ATree i -> [ATree i] -> ATKind i)
-> ATree i
-> [ATree i]
-> StorageClass i
-> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ATree i -> [ATree i] -> ATKind i
forall a. ATree a -> [ATree a] -> ATKind a
ATSwitch

{-# INLINE atCase #-}
-- | `atCase` is a shortcut for constructing a @case@ node
atCase :: i -> i -> ATree i -> ATree i
atCase :: i -> i -> ATree i -> ATree i
atCase = (ATKind i -> ATree i -> ATree i)
-> (i -> ATKind i) -> i -> ATree i -> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (ATKind i -> StorageClass i -> ATree i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i -> ATree i
`atUnary` TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef) ((i -> ATKind i) -> i -> ATree i -> ATree i)
-> (i -> i -> ATKind i) -> i -> i -> ATree i -> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. i -> i -> ATKind i
forall a. a -> a -> ATKind a
ATCase

{-# INLINE atDefault #-}
-- | `atDefault` is a shortcut for constructing a @default@ node
atDefault :: i -> ATree i -> ATree i
atDefault :: i -> ATree i -> ATree i
atDefault = (ATKind i -> StorageClass i -> ATree i -> ATree i)
-> StorageClass i -> ATKind i -> ATree i -> ATree i
forall a b c. (a -> b -> c) -> b -> a -> c
flip ATKind i -> StorageClass i -> ATree i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i -> ATree i
atUnary (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef) (ATKind i -> ATree i -> ATree i)
-> (i -> ATKind i) -> i -> ATree i -> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. i -> ATKind i
forall a. a -> ATKind a
ATDefault

{-# INLINE atGoto #-}
-- | `atGoto` is a shortcut for constructing a @goto@ node
atGoto :: T.Text -> ATree i
atGoto :: Text -> ATree i
atGoto = (ATKind i -> StorageClass i -> ATree i)
-> StorageClass i -> ATKind i -> ATree i
forall a b c. (a -> b -> c) -> b -> a -> c
flip ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef) (ATKind i -> ATree i) -> (Text -> ATKind i) -> Text -> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ATKind i
forall a. Text -> ATKind a
ATGoto

{-# INLINE atLabel #-}
-- | `atLabel` is a shortcut for constructing a @label@ node
atLabel :: T.Text -> ATree i
atLabel :: Text -> ATree i
atLabel = (ATKind i -> StorageClass i -> ATree i)
-> StorageClass i -> ATKind i -> ATree i
forall a b c. (a -> b -> c) -> b -> a -> c
flip ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (TypeKind i -> StorageClass i
forall i. TypeKind i -> StorageClass i
CT.SCUndef TypeKind i
forall i. TypeKind i
CT.CTUndef) (ATKind i -> ATree i) -> (Text -> ATKind i) -> Text -> ATree i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ATKind i
forall a. Text -> ATKind a
ATLabel

{-# INLINE atComma #-}
-- | `atComma` is a shortcut for constructing a @,@ node
atComma :: CT.StorageClass i -> ATree i -> ATree i -> ATree i
atComma :: StorageClass i -> ATree i -> ATree i -> ATree i
atComma = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
atBinary ATKind i
forall a. ATKind a
ATComma

{-# INLINE atConditional #-}
-- | `atConditional` is a shortcut for constructing a @?:@ node
atConditional :: CT.StorageClass i -> ATree i -> ATree i -> ATree i -> ATree i
atConditional :: StorageClass i -> ATree i -> ATree i -> ATree i -> ATree i
atConditional ty :: StorageClass i
ty c :: ATree i
c t :: ATree i
t f :: ATree i
f = ATKind i -> StorageClass i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i
atNoLeaf (ATree i -> ATree i -> ATree i -> ATKind i
forall a. ATree a -> ATree a -> ATree a -> ATKind a
ATConditional ATree i
c ATree i
t ATree i
f) StorageClass i
ty

{-# INLINE atCast #-}
-- | `atCast` is a shortcut for constructing a cast node
atCast :: CT.StorageClass i -> ATree i -> ATree i
atCast :: StorageClass i -> ATree i -> ATree i
atCast = ATKind i -> StorageClass i -> ATree i -> ATree i
forall i. ATKind i -> StorageClass i -> ATree i -> ATree i
atUnary ATKind i
forall a. ATKind a
ATCast

-- | mapping for `ATKind`
mapATKind :: (ATKind i -> ATKind i) -> ATree i -> ATree i
mapATKind :: (ATKind i -> ATKind i) -> ATree i -> ATree i
mapATKind f :: ATKind i -> ATKind i
f (ATNode atk :: ATKind i
atk t :: StorageClass i
t l :: ATree i
l r :: ATree i
r) = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
ATNode (ATKind i -> ATKind i
f ATKind i
atk) StorageClass i
t ((ATKind i -> ATKind i) -> ATree i -> ATree i
forall i. (ATKind i -> ATKind i) -> ATree i -> ATree i
mapATKind ATKind i -> ATKind i
f ATree i
l) ((ATKind i -> ATKind i) -> ATree i -> ATree i
forall i. (ATKind i -> ATKind i) -> ATree i -> ATree i
mapATKind ATKind i -> ATKind i
f ATree i
r)
mapATKind _ ATEmpty = ATree i
forall a. ATree a
ATEmpty

-- | applying for `Htcc.CRules.Types.StorageClass.StorageClass` of `ATLVar` or `ATGVar`
modifyTypeATKind :: (CT.StorageClass i -> CT.StorageClass i) -> ATKind i -> ATKind i
modifyTypeATKind :: (StorageClass i -> StorageClass i) -> ATKind i -> ATKind i
modifyTypeATKind f :: StorageClass i -> StorageClass i
f (ATLVar t :: StorageClass i
t o :: i
o) = StorageClass i -> i -> ATKind i
forall a. StorageClass a -> a -> ATKind a
ATLVar (StorageClass i -> StorageClass i
f StorageClass i
t) i
o
modifyTypeATKind f :: StorageClass i -> StorageClass i
f (ATGVar t :: StorageClass i
t o :: Text
o) = StorageClass i -> Text -> ATKind i
forall a. StorageClass a -> Text -> ATKind a
ATGVar (StorageClass i -> StorageClass i
f StorageClass i
t) Text
o
modifyTypeATKind _ _            = ATree i -> ATKind i
forall a. ATree a -> ATKind a
ATNull ATree i
forall a. ATree a
ATEmpty