{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
{-|
Module      : Htcc.Parser.ConstructionData.Scope.Var
Description : The Data type of variables and its utilities used in parsing
Copyright   : (c) roki, 2019
License     : MIT
Maintainer  : falgon53@yahoo.co.jp
Stability   : experimental
Portability : POSIX

The Data type of variables and its utilities used in parsing
-}
module Htcc.Parser.ConstructionData.Scope.Var (
    -- * The classes
    Var (..),
    -- * The data type
    SomeVars,
    GVarInitWith (..),
    GVar (..),
    LVar (..),
    Literal (..),
    GlobalVars,
    LocalVars,
    Literals,
    Vars (..),
    -- * Functions for adding and searching for variables and literals
    lookupLVar,
    lookupGVar,
    lookupVar,
    addLVar,
    addGVarWith,
    addGVar,
    addLiteral,
    -- * Utilities
    initVars,
    resetLocal,
    fallBack
) where

import           Control.DeepSeq                                 (NFData (..))
import           Data.Bits                                       (Bits (..))
import qualified Data.ByteString                                 as B
import qualified Data.Map.Strict                                 as M
import qualified Data.Text                                       as T
import           GHC.Generics                                    (Generic,
                                                                  Generic1)
import           Numeric.Natural

import qualified Htcc.CRules.Types                               as CT
import           Htcc.Parser.AST.Core                            (ATKind (..),
                                                                  ATree (..),
                                                                  Treealizable (..),
                                                                  atGVar,
                                                                  atLVar)
import qualified Htcc.Parser.ConstructionData.Scope.ManagedScope as SM
import           Htcc.Parser.ConstructionData.Scope.Utils        (internalCE)
import qualified Htcc.Tokenizer.Token                            as HT
import           Htcc.Utils                                      (tshow)

-- | The type class of the type representing the variable
class Var a where
    -- | `vtype` returns the type of the variable
    vtype :: a i -> CT.StorageClass i

-- | The informations type about initial value of the global variable
data GVarInitWith i = GVarInitWithZero | GVarInitWithOG T.Text | GVarInitWithVal i
    deriving (GVarInitWith i -> GVarInitWith i -> Bool
(GVarInitWith i -> GVarInitWith i -> Bool)
-> (GVarInitWith i -> GVarInitWith i -> Bool)
-> Eq (GVarInitWith i)
forall i. Eq i => GVarInitWith i -> GVarInitWith i -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GVarInitWith i -> GVarInitWith i -> Bool
$c/= :: forall i. Eq i => GVarInitWith i -> GVarInitWith i -> Bool
== :: GVarInitWith i -> GVarInitWith i -> Bool
$c== :: forall i. Eq i => GVarInitWith i -> GVarInitWith i -> Bool
Eq, Eq (GVarInitWith i)
Eq (GVarInitWith i) =>
(GVarInitWith i -> GVarInitWith i -> Ordering)
-> (GVarInitWith i -> GVarInitWith i -> Bool)
-> (GVarInitWith i -> GVarInitWith i -> Bool)
-> (GVarInitWith i -> GVarInitWith i -> Bool)
-> (GVarInitWith i -> GVarInitWith i -> Bool)
-> (GVarInitWith i -> GVarInitWith i -> GVarInitWith i)
-> (GVarInitWith i -> GVarInitWith i -> GVarInitWith i)
-> Ord (GVarInitWith i)
GVarInitWith i -> GVarInitWith i -> Bool
GVarInitWith i -> GVarInitWith i -> Ordering
GVarInitWith i -> GVarInitWith i -> GVarInitWith i
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall i. Ord i => Eq (GVarInitWith i)
forall i. Ord i => GVarInitWith i -> GVarInitWith i -> Bool
forall i. Ord i => GVarInitWith i -> GVarInitWith i -> Ordering
forall i.
Ord i =>
GVarInitWith i -> GVarInitWith i -> GVarInitWith i
min :: GVarInitWith i -> GVarInitWith i -> GVarInitWith i
$cmin :: forall i.
Ord i =>
GVarInitWith i -> GVarInitWith i -> GVarInitWith i
max :: GVarInitWith i -> GVarInitWith i -> GVarInitWith i
$cmax :: forall i.
Ord i =>
GVarInitWith i -> GVarInitWith i -> GVarInitWith i
>= :: GVarInitWith i -> GVarInitWith i -> Bool
$c>= :: forall i. Ord i => GVarInitWith i -> GVarInitWith i -> Bool
> :: GVarInitWith i -> GVarInitWith i -> Bool
$c> :: forall i. Ord i => GVarInitWith i -> GVarInitWith i -> Bool
<= :: GVarInitWith i -> GVarInitWith i -> Bool
$c<= :: forall i. Ord i => GVarInitWith i -> GVarInitWith i -> Bool
< :: GVarInitWith i -> GVarInitWith i -> Bool
$c< :: forall i. Ord i => GVarInitWith i -> GVarInitWith i -> Bool
compare :: GVarInitWith i -> GVarInitWith i -> Ordering
$ccompare :: forall i. Ord i => GVarInitWith i -> GVarInitWith i -> Ordering
$cp1Ord :: forall i. Ord i => Eq (GVarInitWith i)
Ord, Int -> GVarInitWith i -> ShowS
[GVarInitWith i] -> ShowS
GVarInitWith i -> String
(Int -> GVarInitWith i -> ShowS)
-> (GVarInitWith i -> String)
-> ([GVarInitWith i] -> ShowS)
-> Show (GVarInitWith i)
forall i. Show i => Int -> GVarInitWith i -> ShowS
forall i. Show i => [GVarInitWith i] -> ShowS
forall i. Show i => GVarInitWith i -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GVarInitWith i] -> ShowS
$cshowList :: forall i. Show i => [GVarInitWith i] -> ShowS
show :: GVarInitWith i -> String
$cshow :: forall i. Show i => GVarInitWith i -> String
showsPrec :: Int -> GVarInitWith i -> ShowS
$cshowsPrec :: forall i. Show i => Int -> GVarInitWith i -> ShowS
Show, (forall x. GVarInitWith i -> Rep (GVarInitWith i) x)
-> (forall x. Rep (GVarInitWith i) x -> GVarInitWith i)
-> Generic (GVarInitWith i)
forall x. Rep (GVarInitWith i) x -> GVarInitWith i
forall x. GVarInitWith i -> Rep (GVarInitWith i) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall i x. Rep (GVarInitWith i) x -> GVarInitWith i
forall i x. GVarInitWith i -> Rep (GVarInitWith i) x
$cto :: forall i x. Rep (GVarInitWith i) x -> GVarInitWith i
$cfrom :: forall i x. GVarInitWith i -> Rep (GVarInitWith i) x
Generic)

instance NFData i => NFData (GVarInitWith i)

-- | The data type of the global variable
data GVar i = GVar -- ^ The constructor of the global variable
    {
        GVar i -> StorageClass i
gvtype   :: CT.StorageClass i, -- ^ The type of the global variable
        GVar i -> GVarInitWith i
initWith :: GVarInitWith i -- ^ The informations about initial value of the global variable
    } deriving (GVar i -> GVar i -> Bool
(GVar i -> GVar i -> Bool)
-> (GVar i -> GVar i -> Bool) -> Eq (GVar i)
forall i. Eq i => GVar i -> GVar i -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GVar i -> GVar i -> Bool
$c/= :: forall i. Eq i => GVar i -> GVar i -> Bool
== :: GVar i -> GVar i -> Bool
$c== :: forall i. Eq i => GVar i -> GVar i -> Bool
Eq, Eq (GVar i)
Eq (GVar i) =>
(GVar i -> GVar i -> Ordering)
-> (GVar i -> GVar i -> Bool)
-> (GVar i -> GVar i -> Bool)
-> (GVar i -> GVar i -> Bool)
-> (GVar i -> GVar i -> Bool)
-> (GVar i -> GVar i -> GVar i)
-> (GVar i -> GVar i -> GVar i)
-> Ord (GVar i)
GVar i -> GVar i -> Bool
GVar i -> GVar i -> Ordering
GVar i -> GVar i -> GVar i
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall i. Ord i => Eq (GVar i)
forall i. Ord i => GVar i -> GVar i -> Bool
forall i. Ord i => GVar i -> GVar i -> Ordering
forall i. Ord i => GVar i -> GVar i -> GVar i
min :: GVar i -> GVar i -> GVar i
$cmin :: forall i. Ord i => GVar i -> GVar i -> GVar i
max :: GVar i -> GVar i -> GVar i
$cmax :: forall i. Ord i => GVar i -> GVar i -> GVar i
>= :: GVar i -> GVar i -> Bool
$c>= :: forall i. Ord i => GVar i -> GVar i -> Bool
> :: GVar i -> GVar i -> Bool
$c> :: forall i. Ord i => GVar i -> GVar i -> Bool
<= :: GVar i -> GVar i -> Bool
$c<= :: forall i. Ord i => GVar i -> GVar i -> Bool
< :: GVar i -> GVar i -> Bool
$c< :: forall i. Ord i => GVar i -> GVar i -> Bool
compare :: GVar i -> GVar i -> Ordering
$ccompare :: forall i. Ord i => GVar i -> GVar i -> Ordering
$cp1Ord :: forall i. Ord i => Eq (GVar i)
Ord, Int -> GVar i -> ShowS
[GVar i] -> ShowS
GVar i -> String
(Int -> GVar i -> ShowS)
-> (GVar i -> String) -> ([GVar i] -> ShowS) -> Show (GVar i)
forall i. Show i => Int -> GVar i -> ShowS
forall i. Show i => [GVar i] -> ShowS
forall i. Show i => GVar i -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GVar i] -> ShowS
$cshowList :: forall i. Show i => [GVar i] -> ShowS
show :: GVar i -> String
$cshow :: forall i. Show i => GVar i -> String
showsPrec :: Int -> GVar i -> ShowS
$cshowsPrec :: forall i. Show i => Int -> GVar i -> ShowS
Show, (forall x. GVar i -> Rep (GVar i) x)
-> (forall x. Rep (GVar i) x -> GVar i) -> Generic (GVar i)
forall x. Rep (GVar i) x -> GVar i
forall x. GVar i -> Rep (GVar i) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall i x. Rep (GVar i) x -> GVar i
forall i x. GVar i -> Rep (GVar i) x
$cto :: forall i x. Rep (GVar i) x -> GVar i
$cfrom :: forall i x. GVar i -> Rep (GVar i) x
Generic)

instance NFData i => NFData (GVar i)

instance Var GVar where
    vtype :: GVar i -> StorageClass i
vtype = GVar i -> StorageClass i
forall i. GVar i -> StorageClass i
gvtype

instance SM.ManagedScope (GVar i) where
    lookup :: Text -> Map Text (GVar i) -> Maybe (GVar i)
lookup = Text -> Map Text (GVar i) -> Maybe (GVar i)
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup
    fallBack :: Map Text (GVar i) -> Map Text (GVar i) -> Map Text (GVar i)
fallBack = Map Text (GVar i) -> Map Text (GVar i) -> Map Text (GVar i)
forall a b. a -> b -> a
const
    initial :: Map Text (GVar i)
initial = Map Text (GVar i)
forall k a. Map k a
M.empty

-- | The data type of local variable
data LVar a = LVar -- ^ The constructor of local variable
    {
        LVar a -> StorageClass a
lvtype    :: CT.StorageClass a, -- ^ The type of the local variable
        LVar a -> a
rbpOffset :: !a, -- ^ The offset value from RBP
        LVar a -> Natural
nestDepth :: !Natural -- ^ The nest depth of a local variable
    } deriving (LVar a -> LVar a -> Bool
(LVar a -> LVar a -> Bool)
-> (LVar a -> LVar a -> Bool) -> Eq (LVar a)
forall a. Eq a => LVar a -> LVar a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LVar a -> LVar a -> Bool
$c/= :: forall a. Eq a => LVar a -> LVar a -> Bool
== :: LVar a -> LVar a -> Bool
$c== :: forall a. Eq a => LVar a -> LVar a -> Bool
Eq, Eq (LVar a)
Eq (LVar a) =>
(LVar a -> LVar a -> Ordering)
-> (LVar a -> LVar a -> Bool)
-> (LVar a -> LVar a -> Bool)
-> (LVar a -> LVar a -> Bool)
-> (LVar a -> LVar a -> Bool)
-> (LVar a -> LVar a -> LVar a)
-> (LVar a -> LVar a -> LVar a)
-> Ord (LVar a)
LVar a -> LVar a -> Bool
LVar a -> LVar a -> Ordering
LVar a -> LVar a -> LVar a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (LVar a)
forall a. Ord a => LVar a -> LVar a -> Bool
forall a. Ord a => LVar a -> LVar a -> Ordering
forall a. Ord a => LVar a -> LVar a -> LVar a
min :: LVar a -> LVar a -> LVar a
$cmin :: forall a. Ord a => LVar a -> LVar a -> LVar a
max :: LVar a -> LVar a -> LVar a
$cmax :: forall a. Ord a => LVar a -> LVar a -> LVar a
>= :: LVar a -> LVar a -> Bool
$c>= :: forall a. Ord a => LVar a -> LVar a -> Bool
> :: LVar a -> LVar a -> Bool
$c> :: forall a. Ord a => LVar a -> LVar a -> Bool
<= :: LVar a -> LVar a -> Bool
$c<= :: forall a. Ord a => LVar a -> LVar a -> Bool
< :: LVar a -> LVar a -> Bool
$c< :: forall a. Ord a => LVar a -> LVar a -> Bool
compare :: LVar a -> LVar a -> Ordering
$ccompare :: forall a. Ord a => LVar a -> LVar a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (LVar a)
Ord, Int -> LVar a -> ShowS
[LVar a] -> ShowS
LVar a -> String
(Int -> LVar a -> ShowS)
-> (LVar a -> String) -> ([LVar a] -> ShowS) -> Show (LVar a)
forall a. Show a => Int -> LVar a -> ShowS
forall a. Show a => [LVar a] -> ShowS
forall a. Show a => LVar a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LVar a] -> ShowS
$cshowList :: forall a. Show a => [LVar a] -> ShowS
show :: LVar a -> String
$cshow :: forall a. Show a => LVar a -> String
showsPrec :: Int -> LVar a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> LVar a -> ShowS
Show, (forall x. LVar a -> Rep (LVar a) x)
-> (forall x. Rep (LVar a) x -> LVar a) -> Generic (LVar a)
forall x. Rep (LVar a) x -> LVar a
forall x. LVar a -> Rep (LVar a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (LVar a) x -> LVar a
forall a x. LVar a -> Rep (LVar a) x
$cto :: forall a x. Rep (LVar a) x -> LVar a
$cfrom :: forall a x. LVar a -> Rep (LVar a) x
Generic)

instance NFData a => NFData (LVar a)

instance Treealizable LVar where
    {-# INLINE treealize #-}
    treealize :: LVar i -> ATree i
treealize (LVar t :: StorageClass i
t o :: i
o _) = StorageClass i -> i -> ATree i
forall i. StorageClass i -> i -> ATree i
atLVar StorageClass i
t i
o

instance Var LVar where
    vtype :: LVar i -> StorageClass i
vtype = LVar i -> StorageClass i
forall i. LVar i -> StorageClass i
lvtype

instance SM.ManagedScope (LVar a) where
    lookup :: Text -> Map Text (LVar a) -> Maybe (LVar a)
lookup = Text -> Map Text (LVar a) -> Maybe (LVar a)
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup
    fallBack :: Map Text (LVar a) -> Map Text (LVar a) -> Map Text (LVar a)
fallBack = Map Text (LVar a) -> Map Text (LVar a) -> Map Text (LVar a)
forall a b. a -> b -> a
const
    initial :: Map Text (LVar a)
initial = Map Text (LVar a)
forall k a. Map k a
M.empty

-- | The literal
data Literal a = Literal -- ^ The literal constructor
    {
        Literal a -> StorageClass a
litype :: CT.StorageClass a, -- ^ The single literal type
        Literal a -> Natural
ln     :: !Natural, -- ^ The number of labels placed in the @.data@ section
        Literal a -> ByteString
lcts   :: B.ByteString -- ^ The content
    } deriving (Literal a -> Literal a -> Bool
(Literal a -> Literal a -> Bool)
-> (Literal a -> Literal a -> Bool) -> Eq (Literal a)
forall a. Eq a => Literal a -> Literal a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Literal a -> Literal a -> Bool
$c/= :: forall a. Eq a => Literal a -> Literal a -> Bool
== :: Literal a -> Literal a -> Bool
$c== :: forall a. Eq a => Literal a -> Literal a -> Bool
Eq, Int -> Literal a -> ShowS
[Literal a] -> ShowS
Literal a -> String
(Int -> Literal a -> ShowS)
-> (Literal a -> String)
-> ([Literal a] -> ShowS)
-> Show (Literal a)
forall a. Show a => Int -> Literal a -> ShowS
forall a. Show a => [Literal a] -> ShowS
forall a. Show a => Literal a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Literal a] -> ShowS
$cshowList :: forall a. Show a => [Literal a] -> ShowS
show :: Literal a -> String
$cshow :: forall a. Show a => Literal a -> String
showsPrec :: Int -> Literal a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Literal a -> ShowS
Show, (forall x. Literal a -> Rep (Literal a) x)
-> (forall x. Rep (Literal a) x -> Literal a)
-> Generic (Literal a)
forall x. Rep (Literal a) x -> Literal a
forall x. Literal a -> Rep (Literal a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Literal a) x -> Literal a
forall a x. Literal a -> Rep (Literal a) x
$cto :: forall a x. Rep (Literal a) x -> Literal a
$cfrom :: forall a x. Literal a -> Rep (Literal a) x
Generic)

instance NFData a => NFData (Literal a)

instance Var Literal where
    vtype :: Literal i -> StorageClass i
vtype = Literal i -> StorageClass i
forall i. Literal i -> StorageClass i
litype

-- | The type of variables
type SomeVars v = M.Map T.Text v

-- | The type of global variables
type GlobalVars a = SomeVars (GVar a)

-- | The type of global variables
type LocalVars a = SomeVars (LVar a)

-- | The type of literals
type Literals a = [Literal a]

-- | The data type of local variables
data Vars a = Vars -- ^ The constructor of variables
    {
        Vars a -> GlobalVars a
globals  :: GlobalVars a, -- ^ The global variables
        Vars a -> LocalVars a
locals   :: LocalVars a, -- ^ The local variables
        Vars a -> Literals a
literals :: Literals a -- ^ Literals
    } deriving (Int -> Vars a -> ShowS
[Vars a] -> ShowS
Vars a -> String
(Int -> Vars a -> ShowS)
-> (Vars a -> String) -> ([Vars a] -> ShowS) -> Show (Vars a)
forall a. Show a => Int -> Vars a -> ShowS
forall a. Show a => [Vars a] -> ShowS
forall a. Show a => Vars a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Vars a] -> ShowS
$cshowList :: forall a. Show a => [Vars a] -> ShowS
show :: Vars a -> String
$cshow :: forall a. Show a => Vars a -> String
showsPrec :: Int -> Vars a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Vars a -> ShowS
Show, (forall x. Vars a -> Rep (Vars a) x)
-> (forall x. Rep (Vars a) x -> Vars a) -> Generic (Vars a)
forall x. Rep (Vars a) x -> Vars a
forall x. Vars a -> Rep (Vars a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Vars a) x -> Vars a
forall a x. Vars a -> Rep (Vars a) x
$cto :: forall a x. Rep (Vars a) x -> Vars a
$cfrom :: forall a x. Vars a -> Rep (Vars a) x
Generic, (forall a. Vars a -> Rep1 Vars a)
-> (forall a. Rep1 Vars a -> Vars a) -> Generic1 Vars
forall a. Rep1 Vars a -> Vars a
forall a. Vars a -> Rep1 Vars a
forall k (f :: k -> *).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
$cto1 :: forall a. Rep1 Vars a -> Vars a
$cfrom1 :: forall a. Vars a -> Rep1 Vars a
Generic1)

instance NFData a => NFData (Vars a)

{-# INLINE initVars #-}
-- | Helper function representing an empty variables
initVars :: Vars a
initVars :: Vars a
initVars = GlobalVars a -> LocalVars a -> Literals a -> Vars a
forall a. GlobalVars a -> LocalVars a -> Literals a -> Vars a
Vars GlobalVars a
forall a. ManagedScope a => Map Text a
SM.initial LocalVars a
forall a. ManagedScope a => Map Text a
SM.initial []

{-# INLINE resetLocal #-}
-- | `resetLocal` initialize the local variable list for `Vars`
resetLocal :: Vars a -> Vars a
resetLocal :: Vars a -> Vars a
resetLocal vs :: Vars a
vs = Vars a
vs { locals :: LocalVars a
locals = LocalVars a
forall k a. Map k a
M.empty }

{-# INLINE lookupGVar #-}
-- | Search for a global variable with a given name
lookupGVar :: T.Text -> Vars a -> Maybe (GVar a)
lookupGVar :: Text -> Vars a -> Maybe (GVar a)
lookupGVar s :: Text
s vars :: Vars a
vars = Text -> Map Text (GVar a) -> Maybe (GVar a)
forall a. ManagedScope a => Text -> Map Text a -> Maybe a
SM.lookup Text
s (Map Text (GVar a) -> Maybe (GVar a))
-> Map Text (GVar a) -> Maybe (GVar a)
forall a b. (a -> b) -> a -> b
$ Vars a -> Map Text (GVar a)
forall a. Vars a -> GlobalVars a
globals Vars a
vars

{-# INLINE lookupLVar #-}
-- | Search for a local variable with a given name
lookupLVar :: T.Text -> Vars a -> Maybe (LVar a)
lookupLVar :: Text -> Vars a -> Maybe (LVar a)
lookupLVar s :: Text
s vars :: Vars a
vars = Text -> Map Text (LVar a) -> Maybe (LVar a)
forall a. ManagedScope a => Text -> Map Text a -> Maybe a
SM.lookup Text
s (Map Text (LVar a) -> Maybe (LVar a))
-> Map Text (LVar a) -> Maybe (LVar a)
forall a b. (a -> b) -> a -> b
$ Vars a -> Map Text (LVar a)
forall a. Vars a -> LocalVars a
locals Vars a
vars

{-# INLINE lookupVar #-}
-- | First, search for local variables, and if not found, search for global variables. If nothing is found, Nothing is returned
lookupVar :: T.Text -> Vars a -> Maybe (Either (GVar a) (LVar a))
lookupVar :: Text -> Vars a -> Maybe (Either (GVar a) (LVar a))
lookupVar s :: Text
s vars :: Vars a
vars = Maybe (Either (GVar a) (LVar a))
-> (LVar a -> Maybe (Either (GVar a) (LVar a)))
-> Maybe (LVar a)
-> Maybe (Either (GVar a) (LVar a))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (GVar a -> Either (GVar a) (LVar a)
forall a b. a -> Either a b
Left (GVar a -> Either (GVar a) (LVar a))
-> Maybe (GVar a) -> Maybe (Either (GVar a) (LVar a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Vars a -> Maybe (GVar a)
forall a. Text -> Vars a -> Maybe (GVar a)
lookupGVar Text
s Vars a
vars) (Either (GVar a) (LVar a) -> Maybe (Either (GVar a) (LVar a))
forall a. a -> Maybe a
Just (Either (GVar a) (LVar a) -> Maybe (Either (GVar a) (LVar a)))
-> (LVar a -> Either (GVar a) (LVar a))
-> LVar a
-> Maybe (Either (GVar a) (LVar a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LVar a -> Either (GVar a) (LVar a)
forall a b. b -> Either a b
Right) (Maybe (LVar a) -> Maybe (Either (GVar a) (LVar a)))
-> Maybe (LVar a) -> Maybe (Either (GVar a) (LVar a))
forall a b. (a -> b) -> a -> b
$ Text -> Vars a -> Maybe (LVar a)
forall a. Text -> Vars a -> Maybe (LVar a)
lookupLVar Text
s Vars a
vars

{-# INLINE maximumOffset #-}
maximumOffset :: (Num a, Ord a) => M.Map T.Text (LVar a) -> a
maximumOffset :: Map Text (LVar a) -> a
maximumOffset m :: Map Text (LVar a)
m
    | Map Text (LVar a) -> Bool
forall k a. Map k a -> Bool
M.null Map Text (LVar a)
m = 0
    | Bool
otherwise = [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ (LVar a -> a) -> [LVar a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map LVar a -> a
forall a. LVar a -> a
rbpOffset ([LVar a] -> [a]) -> [LVar a] -> [a]
forall a b. (a -> b) -> a -> b
$ Map Text (LVar a) -> [LVar a]
forall k a. Map k a -> [a]
M.elems Map Text (LVar a)
m

{-# INLINE fallBack #-}
-- | Organize variable list state after scoping
fallBack :: Vars a -> Vars a -> Vars a
fallBack :: Vars a -> Vars a -> Vars a
fallBack pre :: Vars a
pre post :: Vars a
post = Vars a
pre { literals :: Literals a
literals = Vars a -> Literals a
forall a. Vars a -> Literals a
literals Vars a
post }

-- | If the specified token is `HT.TKIdent` and the local variable does not exist in the list, `addLVar` adds a new local variable to the list,
-- constructs a pair with the node representing the variable, wraps it in `Right` and return it. Otherwise, returns an error message and token pair wrapped in `Left`.
addLVar :: (Integral i, Bits i) => Natural -> CT.StorageClass i -> HT.TokenLC i -> Vars i -> Either (SM.ASTError i) (ATree i, Vars i)
addLVar :: Natural
-> StorageClass i
-> TokenLC i
-> Vars i
-> Either (ASTError i) (ATree i, Vars i)
addLVar cnd :: Natural
cnd t :: StorageClass i
t cur :: TokenLC i
cur@(_, HT.TKIdent ident :: Text
ident) vars :: Vars i
vars = case Text -> Vars i -> Maybe (LVar i)
forall a. Text -> Vars a -> Maybe (LVar a)
lookupLVar Text
ident Vars i
vars of
    Just foundedVar :: LVar i
foundedVar
        | LVar i -> Natural
forall a. LVar a -> Natural
nestDepth LVar i
foundedVar Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
/= Natural
cnd -> Either (ASTError i) (ATree i, Vars i)
forall a. Either a (ATree i, Vars i)
varnat
        | StorageClass i -> Bool
forall (a :: * -> *) i. IncompleteBase a => a i -> Bool
CT.isIncompleteArray (LVar i -> StorageClass i
forall i. LVar i -> StorageClass i
lvtype LVar i
foundedVar) -> Either (ASTError i) (ATree i, Vars i)
forall a. Either a (ATree i, Vars i)
varnat
        | Bool
otherwise -> ASTError i -> Either (ASTError i) (ATree i, Vars i)
forall a b. a -> Either a b
Left ("redeclaration of '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ident Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "' with no linkage", TokenLC i
cur) -- ODR
    Nothing -> Either (ASTError i) (ATree i, Vars i)
forall a. Either a (ATree i, Vars i)
varnat
    where
        ofs :: i
ofs = i -> i -> i
forall a. Num a => a -> a -> a
(+) (Natural -> i
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Natural -> i) -> Natural -> i
forall a b. (a -> b) -> a -> b
$ StorageClass i -> Natural
forall a. CType a => a -> Natural
CT.sizeof StorageClass i
t) (i -> i) -> i -> i
forall a b. (a -> b) -> a -> b
$ i -> i -> i
forall a. (Bits a, Num a, Enum a) => a -> a -> a
CT.alignas (Map Text (LVar i) -> i
forall a. (Num a, Ord a) => Map Text (LVar a) -> a
maximumOffset (Map Text (LVar i) -> i) -> Map Text (LVar i) -> i
forall a b. (a -> b) -> a -> b
$ Vars i -> Map Text (LVar i)
forall a. Vars a -> LocalVars a
locals Vars i
vars) (i -> i) -> i -> i
forall a b. (a -> b) -> a -> b
$ Natural -> i
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Natural -> i) -> Natural -> i
forall a b. (a -> b) -> a -> b
$ StorageClass i -> Natural
forall a. CType a => a -> Natural
CT.alignof StorageClass i
t
        varnat :: Either a (ATree i, Vars i)
varnat = let lvar :: LVar i
lvar = StorageClass i -> i -> Natural -> LVar i
forall a. StorageClass a -> a -> Natural -> LVar a
LVar StorageClass i
t i
ofs Natural
cnd in
            (ATree i, Vars i) -> Either a (ATree i, Vars i)
forall a b. b -> Either a b
Right (StorageClass i -> i -> ATree i
forall i. StorageClass i -> i -> ATree i
atLVar (LVar i -> StorageClass i
forall i. LVar i -> StorageClass i
lvtype LVar i
lvar) (LVar i -> i
forall a. LVar a -> a
rbpOffset LVar i
lvar), Vars i
vars { locals :: Map Text (LVar i)
locals = Text -> LVar i -> Map Text (LVar i) -> Map Text (LVar i)
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
ident LVar i
lvar (Map Text (LVar i) -> Map Text (LVar i))
-> Map Text (LVar i) -> Map Text (LVar i)
forall a b. (a -> b) -> a -> b
$ Vars i -> Map Text (LVar i)
forall a. Vars a -> LocalVars a
locals Vars i
vars })
addLVar _ _ _ _ = ASTError i -> Either (ASTError i) (ATree i, Vars i)
forall a b. a -> Either a b
Left (Text
internalCE, TokenLC i
forall i. Num i => TokenLC i
HT.emptyToken)


-- | If the specified token is `HT.TKIdent` and the global variable does not exist in the list, `addLVar` adds a new global variable to the list,
-- constructs a pair with the node representing the variable, wraps it in `Right` and return it. Otherwise, returns an error message and token pair wrapped in `Left`.
addGVarWith :: Num i => CT.StorageClass i -> HT.TokenLC i -> GVarInitWith i -> Vars i -> Either (SM.ASTError i) (ATree i, Vars i)
addGVarWith :: StorageClass i
-> TokenLC i
-> GVarInitWith i
-> Vars i
-> Either (ASTError i) (ATree i, Vars i)
addGVarWith t :: StorageClass i
t cur :: TokenLC i
cur@(_, HT.TKIdent ident :: Text
ident) iw :: GVarInitWith i
iw vars :: Vars i
vars = (Either (ASTError i) (ATree i, Vars i)
 -> Maybe (GVar i) -> Either (ASTError i) (ATree i, Vars i))
-> Maybe (GVar i)
-> Either (ASTError i) (ATree i, Vars i)
-> Either (ASTError i) (ATree i, Vars i)
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Either (ASTError i) (ATree i, Vars i)
 -> (GVar i -> Either (ASTError i) (ATree i, Vars i))
 -> Maybe (GVar i)
 -> Either (ASTError i) (ATree i, Vars i))
-> (GVar i -> Either (ASTError i) (ATree i, Vars i))
-> Either (ASTError i) (ATree i, Vars i)
-> Maybe (GVar i)
-> Either (ASTError i) (ATree i, Vars i)
forall a b c. (a -> b -> c) -> b -> a -> c
flip Either (ASTError i) (ATree i, Vars i)
-> (GVar i -> Either (ASTError i) (ATree i, Vars i))
-> Maybe (GVar i)
-> Either (ASTError i) (ATree i, Vars i)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ((GVar i -> Either (ASTError i) (ATree i, Vars i))
 -> Either (ASTError i) (ATree i, Vars i)
 -> Maybe (GVar i)
 -> Either (ASTError i) (ATree i, Vars i))
-> (GVar i -> Either (ASTError i) (ATree i, Vars i))
-> Either (ASTError i) (ATree i, Vars i)
-> Maybe (GVar i)
-> Either (ASTError i) (ATree i, Vars i)
forall a b. (a -> b) -> a -> b
$ Either (ASTError i) (ATree i, Vars i)
-> GVar i -> Either (ASTError i) (ATree i, Vars i)
forall a b. a -> b -> a
const (Either (ASTError i) (ATree i, Vars i)
 -> GVar i -> Either (ASTError i) (ATree i, Vars i))
-> Either (ASTError i) (ATree i, Vars i)
-> GVar i
-> Either (ASTError i) (ATree i, Vars i)
forall a b. (a -> b) -> a -> b
$ ASTError i -> Either (ASTError i) (ATree i, Vars i)
forall a b. a -> Either a b
Left ("redeclaration of '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ident Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "' with no linkage", TokenLC i
cur)) (Text -> Vars i -> Maybe (GVar i)
forall a. Text -> Vars a -> Maybe (GVar a)
lookupGVar Text
ident Vars i
vars) (Either (ASTError i) (ATree i, Vars i)
 -> Either (ASTError i) (ATree i, Vars i))
-> Either (ASTError i) (ATree i, Vars i)
-> Either (ASTError i) (ATree i, Vars i)
forall a b. (a -> b) -> a -> b
$ -- ODR
    (ATree i, Vars i) -> Either (ASTError i) (ATree i, Vars i)
forall a b. b -> Either a b
Right (StorageClass i -> Text -> ATree i
forall i. StorageClass i -> Text -> ATree i
atGVar (GVar i -> StorageClass i
forall i. GVar i -> StorageClass i
gvtype GVar i
gvar) Text
ident, Vars i
vars { globals :: GlobalVars i
globals = Text -> GVar i -> GlobalVars i -> GlobalVars i
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Text
ident GVar i
gvar (GlobalVars i -> GlobalVars i) -> GlobalVars i -> GlobalVars i
forall a b. (a -> b) -> a -> b
$ Vars i -> GlobalVars i
forall a. Vars a -> GlobalVars a
globals Vars i
vars })
    where
        gvar :: GVar i
gvar = StorageClass i -> GVarInitWith i -> GVar i
forall i. StorageClass i -> GVarInitWith i -> GVar i
GVar StorageClass i
t GVarInitWith i
iw
addGVarWith _ _ _ _ = ASTError i -> Either (ASTError i) (ATree i, Vars i)
forall a b. a -> Either a b
Left (Text
internalCE, (i -> i -> TokenLCNums i
forall i. i -> i -> TokenLCNums i
HT.TokenLCNums 0 0, Token i
forall i. Token i
HT.TKEmpty))

-- | If the specified token is `HT.TKIdent` and the global variable does not exist in the list, `addLVar` adds a new global variable that will be initialized by zero to the list,
-- constructs a pair with the node representing the variable, wraps it in `Right` and return it. Otherwise, returns an error message and token pair wrapped in `Left`.
addGVar :: Num i => CT.StorageClass i -> HT.TokenLC i -> Vars i -> Either (SM.ASTError i) (ATree i, Vars i)
addGVar :: StorageClass i
-> TokenLC i -> Vars i -> Either (ASTError i) (ATree i, Vars i)
addGVar t :: StorageClass i
t ident :: TokenLC i
ident = StorageClass i
-> TokenLC i
-> GVarInitWith i
-> Vars i
-> Either (ASTError i) (ATree i, Vars i)
forall i.
Num i =>
StorageClass i
-> TokenLC i
-> GVarInitWith i
-> Vars i
-> Either (ASTError i) (ATree i, Vars i)
addGVarWith StorageClass i
t TokenLC i
ident GVarInitWith i
forall i. GVarInitWith i
GVarInitWithZero

-- | If the specified token is `HT.TKString`, `addLiteral` adds a new literal to the list,
-- constructs a pair with the node representing the variable, wraps it in `Right` and return it. Otherwise, returns an error message and token pair wrapped in `Left`.
addLiteral :: (Ord i, Num i) => CT.StorageClass i -> HT.TokenLC i -> Vars i -> Either (SM.ASTError i) (ATree i, Vars i)
addLiteral :: StorageClass i
-> TokenLC i -> Vars i -> Either (ASTError i) (ATree i, Vars i)
addLiteral t :: StorageClass i
t (_, HT.TKString cont :: ByteString
cont) vars :: Vars i
vars
    | [Literal i] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Vars i -> [Literal i]
forall a. Vars a -> Literals a
literals Vars i
vars) = let lit :: Literal i
lit = StorageClass i -> Natural -> ByteString -> Literal i
forall a. StorageClass a -> Natural -> ByteString -> Literal a
Literal (StorageClass i -> StorageClass i
forall a. CType a => a -> a
CT.removeAllExtents StorageClass i
t) 0 ByteString
cont; nat :: ATree i
nat = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
ATNode (StorageClass i -> Text -> ATKind i
forall a. StorageClass a -> Text -> ATKind a
ATGVar StorageClass i
t ".L.data.0") StorageClass i
t ATree i
forall a. ATree a
ATEmpty ATree i
forall a. ATree a
ATEmpty in
        (ATree i, Vars i) -> Either (ASTError i) (ATree i, Vars i)
forall a b. b -> Either a b
Right (ATree i
nat, Vars i
vars { literals :: [Literal i]
literals = Literal i
lit Literal i -> [Literal i] -> [Literal i]
forall a. a -> [a] -> [a]
: Vars i -> [Literal i]
forall a. Vars a -> Literals a
literals Vars i
vars })
    | Bool
otherwise = let ln' :: Natural
ln' = Natural -> Natural
forall a. Enum a => a -> a
succ (Natural -> Natural) -> Natural -> Natural
forall a b. (a -> b) -> a -> b
$ Literal i -> Natural
forall a. Literal a -> Natural
ln (Literal i -> Natural) -> Literal i -> Natural
forall a b. (a -> b) -> a -> b
$ [Literal i] -> Literal i
forall a. [a] -> a
head ([Literal i] -> Literal i) -> [Literal i] -> Literal i
forall a b. (a -> b) -> a -> b
$ Vars i -> [Literal i]
forall a. Vars a -> Literals a
literals Vars i
vars; lit :: Literal i
lit = StorageClass i -> Natural -> ByteString -> Literal i
forall a. StorageClass a -> Natural -> ByteString -> Literal a
Literal (StorageClass i -> StorageClass i
forall a. CType a => a -> a
CT.removeAllExtents StorageClass i
t) Natural
ln' ByteString
cont; nat :: ATree i
nat = ATKind i -> StorageClass i -> ATree i -> ATree i -> ATree i
forall a.
ATKind a -> StorageClass a -> ATree a -> ATree a -> ATree a
ATNode (StorageClass i -> Text -> ATKind i
forall a. StorageClass a -> Text -> ATKind a
ATGVar StorageClass i
t (".L.data." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Natural -> Text
forall a. Show a => a -> Text
tshow Natural
ln')) StorageClass i
t ATree i
forall a. ATree a
ATEmpty ATree i
forall a. ATree a
ATEmpty in
        (ATree i, Vars i) -> Either (ASTError i) (ATree i, Vars i)
forall a b. b -> Either a b
Right (ATree i
nat, Vars i
vars { literals :: [Literal i]
literals = Literal i
lit Literal i -> [Literal i] -> [Literal i]
forall a. a -> [a] -> [a]
: Vars i -> [Literal i]
forall a. Vars a -> Literals a
literals Vars i
vars })
addLiteral _ _ _ = ASTError i -> Either (ASTError i) (ATree i, Vars i)
forall a b. a -> Either a b
Left (Text
internalCE, (i -> i -> TokenLCNums i
forall i. i -> i -> TokenLCNums i
HT.TokenLCNums 0 0, Token i
forall i. Token i
HT.TKEmpty))