<commit_before>-- | Our extended FCode monad.

-- We add a mapping from names to CmmExpr, to support local variable names in
-- the concrete C-- code.  The unique supply of the underlying FCode monad
-- is used to grab a new unique for each local variable.

-- In C--, a local variable can be declared anywhere within a proc,
-- and it scopes from the beginning of the proc to the end.  Hence, we have
-- to collect declarations as we parse the proc, and feed the environment
-- back in circularly (to avoid a two-pass algorithm).

module StgCmmExtCode (
        CmmParse, unEC,
        Named(..), Env,
        
        loopDecls,
        getEnv,

        newLocal,
        newLabel,
        newBlockId,
        newFunctionName,
        newImport,
        lookupLabel,
        lookupName,

        code,
        emit, emitLabel, emitAssign, emitStore,
        getCode, getCodeR,
        emitOutOfLine,
        withUpdFrameOff, getUpdFrameOff
)

where

import qualified StgCmmMonad as F
import StgCmmMonad (FCode, newUnique)

import Cmm
import CLabel
import MkGraph

-- import BasicTypes
import BlockId
import DynFlags
import FastString
import Module
import UniqFM
import Unique


-- | The environment contains variable definitions or blockids.
data Named      
        = VarN CmmExpr          -- ^ Holds CmmLit(CmmLabel ..) which gives the label type,
                                --      eg, RtsLabel, ForeignLabel, CmmLabel etc. 

        | FunN   PackageId      -- ^ A function name from this package
        | LabelN BlockId                -- ^ A blockid of some code or data.
        
-- | An environment of named things.
type Env        = UniqFM Named

-- | Local declarations that are in scope during code generation.
type Decls      = [(FastString,Named)]

-- | Does a computation in the FCode monad, with a current environment
--      and a list of local declarations. Returns the resulting list of declarations.
newtype CmmParse a      
        = EC { unEC :: Env -> Decls -> FCode (Decls, a) }

type ExtCode = CmmParse ()

returnExtFC :: a -> CmmParse a
returnExtFC a   = EC $ \_ s -> return (s, a)

thenExtFC :: CmmParse a -> (a -> CmmParse b) -> CmmParse b
thenExtFC (EC m) k = EC $ \e s -> do (s',r) <- m e s; unEC (k r) e s'

instance Monad CmmParse where
  (>>=) = thenExtFC
  return = returnExtFC

instance HasDynFlags CmmParse where
    getDynFlags = EC (\_ d -> do dflags <- getDynFlags
                                 return (d, dflags))


-- | Takes the variable decarations and imports from the monad
--      and makes an environment, which is looped back into the computation.  
--      In this way, we can have embedded declarations that scope over the whole
--      procedure, and imports that scope over the entire module.
--      Discards the local declaration contained within decl'
--
loopDecls :: CmmParse a -> CmmParse a
loopDecls (EC fcode) =
      EC $ \e globalDecls -> do
        (_, a) <- F.fixC (\ ~(decls, _) -> fcode (addListToUFM e (decls ++ globalDecls)) globalDecls)
        return (globalDecls, a)


-- | Get the current environment from the monad.
getEnv :: CmmParse Env
getEnv  = EC $ \e s -> return (s, e)


-- | Add a new variable to the list of local declarations. 
--      The CmmExpr says where the value is stored. 
addVarDecl :: FastString -> CmmExpr -> ExtCode
addVarDecl var expr 
        = EC $ \_ s -> return ((var, VarN expr):s, ())

-- | Add a new label to the list of local declarations.
addLabel :: FastString -> BlockId -> ExtCode
addLabel name block_id 
        = EC $ \_ s -> return ((name, LabelN block_id):s, ())


-- | Create a fresh local variable of a given type.
newLocal <commit_msg>Don't duplicate decls unnecessarily in the environment<commit_after>-- | Our extended FCode monad.

-- We add a mapping from names to CmmExpr, to support local variable names in
-- the concrete C-- code.  The unique supply of the underlying FCode monad
-- is used to grab a new unique for each local variable.

-- In C--, a local variable can be declared anywhere within a proc,
-- and it scopes from the beginning of the proc to the end.  Hence, we have
-- to collect declarations as we parse the proc, and feed the environment
-- back in circularly (to avoid a two-pass algorithm).

module StgCmmExtCode (
        CmmParse, unEC,
        Named(..), Env,
        
        loopDecls,
        getEnv,

        newLocal,
        newLabel,
        newBlockId,
        newFunctionName,
        newImport,
        lookupLabel,
        lookupName,

        code,
        emit, emitLabel, emitAssign, emitStore,
        getCode, getCodeR,
        emitOutOfLine,
        withUpdFrameOff, getUpdFrameOff
)

where

import qualified StgCmmMonad as F
import StgCmmMonad (FCode, newUnique)

import Cmm
import CLabel
import MkGraph

-- import BasicTypes
import BlockId
import DynFlags
import FastString
import Module
import UniqFM
import Unique


-- | The environment contains variable definitions or blockids.
data Named      
        = VarN CmmExpr          -- ^ Holds CmmLit(CmmLabel ..) which gives the label type,
                                --      eg, RtsLabel, ForeignLabel, CmmLabel etc. 

        | FunN   PackageId      -- ^ A function name from this package
        | LabelN BlockId                -- ^ A blockid of some code or data.
        
-- | An environment of named things.
type Env        = UniqFM Named

-- | Local declarations that are in scope during code generation.
type Decls      = [(FastString,Named)]

-- | Does a computation in the FCode monad, with a current environment
--      and a list of local declarations. Returns the resulting list of declarations.
newtype CmmParse a      
        = EC { unEC :: Env -> Decls -> FCode (Decls, a) }

type ExtCode = CmmParse ()

returnExtFC :: a -> CmmParse a
returnExtFC a   = EC $ \_ s -> return (s, a)

thenExtFC :: CmmParse a -> (a -> CmmParse b) -> CmmParse b
thenExtFC (EC m) k = EC $ \e s -> do (s',r) <- m e s; unEC (k r) e s'

instance Monad CmmParse where
  (>>=) = thenExtFC
  return = returnExtFC

instance HasDynFlags CmmParse where
    getDynFlags = EC (\_ d -> do dflags <- getDynFlags
                                 return (d, dflags))


-- | Takes the variable decarations and imports from the monad
--      and makes an environment, which is looped back into the computation.  
--      In this way, we can have embedded declarations that scope over the whole
--      procedure, and imports that scope over the entire module.
--      Discards the local declaration contained within decl'
--
loopDecls :: CmmParse a -> CmmParse a
loopDecls (EC fcode) =
      EC $ \e globalDecls -> do
        (_, a) <- F.fixC (\ ~(decls, _) -> fcode (addListToUFM e decls) globalDecls)
        return (globalDecls, a)


-- | Get the current environment from the monad.
getEnv :: CmmParse Env
getEnv  = EC $ \e s -> return (s, e)


-- | Add a new variable to the list of local declarations. 
--      The CmmExpr says where the value is stored. 
addVarDecl :: FastString -> CmmExpr -> ExtCode
addVarDecl var expr 
        = EC $ \_ s -> return ((var, VarN expr):s, ())

-- | Add a new label to the list of local declarations.
addLabel :: FastString -> BlockId -> ExtCode
addLabel name block_id 
        = EC $ \_ s -> return ((name, LabelN block_id):s, ())


-- | Create a fresh local variable of a given type.
newLocal 
{'fraction_non_alphanumeric': 0.08571817934041974, 'fraction_numerical': 0.0, 'mean_word_length': 2.3404642694583524, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6180490', 'n_tokens_mistral': 2200, 'n_tokens_neox': 2134, 'n_words': 907}