-- UUAGC 0.9.50.2 (build/103/lib-ehc/UHC/Light/Compiler/CoreRun.ag) module UHC.Light.Compiler.CoreRun(module UHC.Light.Compiler.CoreRun.Prim , Mod (..), SExp (..), Exp (..), Alt (..), Pat (..) , Meta (..), MetaL, DataCon (..), DataConL , CRArray, CRMArray, emptyCRArray, crarrayToList, crarrayFromList, craLength, craAssocs, craAssocs', craReverseAssocs' , Bind , dbgs, dbg , mbSExpr , exp2sexp , RRef (..), noRRef , rrefToDif , Ref2Nm , Nm2RefMp, emptyNm2RefMp, nm2refUnion, nm2RefMpInverse, ref2nmEmpty, ref2nmUnion , mkLocLevRef, mkLocDifRef, mkGlobRef , mkExp, mkVar, mkVar', mkInt, mkInt', mkChar, mkChar', mkString, mkString' , mkDbg, mkDbg' , mkApp, mkApp', mkTup, mkTup', mkEval, mkTail, mkCase, mkLam, mkLam', mkLet, mkLet', mkFFI, mkFFI' , mkMetaDataCon, mkMetaDataType , mkMod, mkMod', mkMod'' , mkInteger, mkInteger') where import UHC.Light.Compiler.Base.Common import UHC.Light.Compiler.Base.Target import UHC.Util.Utils import UHC.Light.Compiler.Ty import qualified Data.Map as Map import Data.Maybe import Data.Char import Data.List import qualified Data.Vector as V import qualified Data.Vector.Mutable as MV import Control.Applicative import UHC.Light.Compiler.CoreRun.Prim import UHC.Light.Compiler.Foreign -- | Fast access sequence type CRArray x = V.Vector x type CRMArray x = MV.IOVector x -- | Wrapper (rename) around vector<->list conversion crarrayFromList :: [x] -> CRArray x -- crarrayFromList = mkCRArrayLwb 0 crarrayFromList = V.fromList {-# INLINE crarrayFromList #-} -- | Wrapper (rename) around vector<->list conversion crarrayToList :: CRArray x -> [x] crarrayToList = V.toList {-# INLINE crarrayToList #-} emptyCRArray :: CRArray x emptyCRArray = V.empty -- mkCRArray [] {-# INLINE emptyCRArray #-} craLength :: CRArray x -> Int craLength = V.length -- a = h + 1 - l -- where (l,h) = bounds a {-# INLINE craLength #-} -- | Content of array as association list, starting index at 'lwb' craAssocs' :: Int -> CRArray x -> [(Int,x)] craAssocs' lwb = zip [lwb ..] . crarrayToList {-# INLINE craAssocs' #-} -- | Content of array as association list, starting index at 'lwb', but reversed craReverseAssocs' :: Int -> CRArray x -> [(Int,x)] craReverseAssocs' lwb v = zip [hi, hi-1 ..] $ V.toList v where hi = lwb + V.length v - 1 {-# INLINE craReverseAssocs' #-} -- | Content of array as association list, starting index at 0 craAssocs :: CRArray x -> [(Int,x)] craAssocs = craAssocs' 0 {-# INLINE craAssocs #-} -- | Bind, just an Exp, addressing is left implicit type Bind = Exp -- | Equivalent of '()' unit :: Exp unit = Exp_Tup 0 emptyCRArray -- | Debug info is embedded in SExp dbgs = SExp_Dbg dbg = Exp_SExp . dbgs -- | Is exp a SExp? mbSExpr :: Exp -> Maybe SExp mbSExpr (Exp_SExp s) = Just s mbSExpr _ = Nothing -- | Convert to SExp exp2sexp :: Exp -> SExp exp2sexp = maybe (dbgs "CoreRun.exp2sexp") id . mbSExpr -- | Identifier references for use during running CoreRun data RRef -- | global reference to module and its entry = RRef_Glb { rrefMod :: !Int -- ^ module , rrefEntry :: !Int -- ^ entry inside module } -- | local reference to on stack value, not interpreted during running, if used must be converted with 'rrefToDif' before running; may become obsolete. | RRef_Loc { rrefLev :: !Int -- ^ level when used statically , rrefEntry :: !Int -- ^ entry inside level } -- | local reference to on stack value, but measured relative to level of from where is referenced, used at runtime | RRef_LDf { rrefLevDiff :: !Int -- ^ offset/difference in levels when used at runtime , rrefEntry :: !Int -- ^ entry inside level } -- | tag of memory/constructor node referred to by other ref | RRef_Tag { rrefRef :: !RRef -- ^ of what this is the tag } -- | fld of memory/constructor node referred to by other ref | RRef_Fld { rrefRef :: !RRef -- ^ of what this is a field , rrefEntry :: !Int -- ^ entry inside level } -- | debug variant, holding original name | RRef_Dbg { rrefNm :: !HsName } deriving (Eq,Ord) instance Show RRef where show _ = "RRef" noRRef = RRef_Dbg hsnUnknown -- | Convert to RRef_Loc to RRef_LDf, i.e. absolute level to relative (to current) level rrefToDif curlev r@(RRef_Loc l o ) = RRef_LDf (curlev - l) o rrefToDif curlev r@(RRef_Fld {rrefRef=r'}) = r {rrefRef = rrefToDif curlev r'} rrefToDif curlev r@(RRef_Tag {rrefRef=r'}) = r {rrefRef = rrefToDif curlev r'} rrefToDif _ r = r -- | RRef to HsName mapping for use during running when a more informative name is required. -- The representation is lazily via function type Ref2Nm = RRef -> Maybe HsName -- | HsName to RRef mapping for resolving references during translation to CoreRun type Nm2RefMp = Map.Map HsName RRef emptyNm2RefMp :: Nm2RefMp emptyNm2RefMp = Map.empty nm2refUnion :: Nm2RefMp -> Nm2RefMp -> Nm2RefMp nm2refUnion = Map.union -- | Inverse of a `Nm2RefMp` nm2RefMpInverse :: Nm2RefMp -> Ref2Nm nm2RefMpInverse m | Map.null m = const Nothing | otherwise = flip Map.lookup inv where inv = Map.fromList [ (r,n) | (n,r) <- Map.toList m ] -- | Empty Ref2Nm ref2nmEmpty :: Ref2Nm ref2nmEmpty = const Nothing -- | Union, left-biased ref2nmUnion :: Ref2Nm -> Ref2Nm -> Ref2Nm ref2nmUnion m1 m2 = \r -> m1 r <|> m2 r -- ************************************** -- Construction: references -- ************************************** -- | 'RRef' to local or outside scoped, using absolute level and offset (this is to be converted to a level difference + offset encoding for running, see 'mkLocDifRef') mkLocLevRef :: Int -> Int -> RRef mkLocLevRef = RRef_Loc -- | 'RRef' to local or outside scoped, using level difference (to a current) and offset mkLocDifRef :: Int -> Int -> RRef mkLocDifRef = RRef_LDf -- | 'RRef' to global from module, using module nr and offset mkGlobRef :: Int -> Int -> RRef mkGlobRef = RRef_Glb -- ************************************** -- Construction: constants as SExp or Exp -- ************************************** -- | Lift 'SExp' into 'Exp' mkExp :: SExp -> Exp mkExp = Exp_SExp -- | Var ref as 'SExp' mkVar' :: RRef -> SExp mkVar' = SExp_Var -- | Var ref as 'Exp' mkVar :: RRef -> Exp mkVar = mkExp . mkVar' -- | Int constant as 'SExp' mkInt' :: Int -> SExp mkInt' = SExp_Int -- | Int constant as 'Exp' mkInt :: Int -> Exp mkInt = mkExp . mkInt' -- | Char constant as 'SExp' mkChar' :: Char -> SExp mkChar' = SExp_Char -- | Char constant as 'Exp' mkChar :: Char -> Exp mkChar = mkExp . mkChar' -- | String constant as 'SExp' mkString' :: String -> SExp mkString' = SExp_String -- | String constant as 'Exp' mkString :: String -> Exp mkString = mkExp . mkString' -- | Debug info as 'SExp', will make an interpreter stop with displaying the message mkDbg' :: String -> SExp mkDbg' = dbgs -- | Debug info as 'Exp' mkDbg :: String -> Exp mkDbg = dbg -- | Integer constant as 'SExp' mkInteger' :: Integer -> SExp mkInteger' = SExp_Integer -- | Integer constant as 'Exp' mkInteger :: Integer -> Exp mkInteger = mkExp . mkInteger' -- ************************************** -- Construction: Exp -- ************************************** -- | Application mkApp' :: Exp -> CRArray SExp -> Exp mkApp' = Exp_App -- | Application mkApp :: Exp -> [SExp] -> Exp mkApp f as = mkApp' f (crarrayFromList as) -- | Tuple, Node mkTup' :: Int -> CRArray SExp -> Exp mkTup' = Exp_Tup -- | Tuple, Node mkTup :: Int -> [SExp] -> Exp mkTup t as = mkTup' t (crarrayFromList as) -- | Force evaluation mkEval :: Exp -> Exp mkEval = Exp_Force -- | Set tail call context mkTail :: Exp -> Exp mkTail = Exp_Tail -- | Case mkCase :: SExp -> [Exp] -> Exp mkCase scrut alts = Exp_Case scrut $ crarrayFromList $ map (Alt_Alt ref2nmEmpty) alts -- | Lambda mkLam' :: Maybe HsName -- ^ a name for this lambda, to be used for pretty printing -> Int -- ^ nr of arguments, 0 encodes a thunk/CAF -> Int -- ^ total stack size, including arguments, locals, expression calculation -> Exp -- ^ body -> Exp mkLam' mbNm nrArgs stackDepth body = Exp_Lam mbNm nrArgs stackDepth ref2nmEmpty body -- | Lambda mkLam :: Int -- ^ nr of arguments, 0 encodes a thunk/CAF -> Int -- ^ total stack size, including arguments, locals, expression calculation -> Exp -- ^ body -> Exp mkLam nrArgs stackDepth body = mkLam' Nothing nrArgs stackDepth body -- | Let mkLet' :: Int -- ^ stackoffset to place bound value -> CRArray Exp -- ^ bound terms -> Exp -- ^ body -> Exp mkLet' firstoff bs b = Exp_Let firstoff ref2nmEmpty bs b -- | Let mkLet :: Int -- ^ stackoffset to place bound value -> [Exp] -- ^ bound terms -> Exp -- ^ body -> Exp mkLet firstoff bs b = mkLet' firstoff (crarrayFromList bs) b -- | FFI mkFFI' :: String -- ^ name of foreign entity, if unknown results in debug expr -> CRArray SExp -- ^ args -> Exp mkFFI' fe as = case Map.lookup fe allRunPrimMp of Just p -> Exp_FFI p as _ -> dbg $ "CoreRun.mkFFI: " ++ fe -- | FFI mkFFI :: String -- ^ name of foreign entity, if unknown results in debug expr -> [SExp] -- ^ args -> Exp mkFFI fe as = mkFFI' fe (crarrayFromList as) -- ************************************** -- Construction: Meta info -- ************************************** -- | Meta: datatype constructor info mkMetaDataCon :: HsName -- ^ constructor name (without module qualifier, name must be globally unique) -> Int -- ^ constructor tag -> DataCon mkMetaDataCon = DataCon_Con -- | Meta: datatype constructor info mkMetaDataType :: HsName -- ^ datatype name (fully qualified) -> [DataCon] -- ^ constructor tag -> Meta mkMetaDataType = Meta_Data -- ************************************** -- Construction: Top level module -- ************************************** -- | Module, with meta info mkMod'' :: HsName -- ^ module name -> Int -- ^ module number -> Int -- ^ total stack size, including globals of module, their setup (see semantics), and the main startup part kicking of evaluation -> [Meta] -- ^ meta info -> CRArray Bind -- ^ bound expressions -> Exp -- ^ body of main -> Mod mkMod'' modNm modNr stkDepth metas binds body = Mod_Mod ref2nmEmpty modNm modNr stkDepth metas binds body -- | Module mkMod' :: HsName -- ^ module name -> Int -- ^ module number -> Int -- ^ total stack size, including globals of module, their setup (see semantics), and the main startup part kicking of evaluation -> CRArray Bind -- ^ bound expressions -> Exp -- ^ body of main -> Mod mkMod' modNm modNr stkDepth binds body = mkMod'' modNm modNr stkDepth [] binds body -- | Module mkMod :: HsName -- ^ module name -> Int -- ^ module number -> Int -- ^ total stack size, including globals of module, their setup (see semantics), and the main startup part kicking of evaluation -> [Bind] -- ^ bound expressions -> Exp -- ^ body of main -> Mod mkMod modNm modNr stkDepth binds body = mkMod' modNm modNr stkDepth (crarrayFromList binds) body -- Alt --------------------------------------------------------- data Alt = Alt_Alt {ref2nm_Alt_Alt :: !(Ref2Nm),expr_Alt_Alt :: !(Exp)} -- DataCon ----------------------------------------------------- data DataCon = DataCon_Con {conNm_DataCon_Con :: !(HsName),tagNr_DataCon_Con :: !(Int)} -- DataConL ---------------------------------------------------- type DataConL = [DataCon] -- Exp --------------------------------------------------------- data Exp = Exp_SExp {sexpr_Exp_SExp :: !(SExp)} | Exp_Tup {tag_Exp_Tup :: !(Int),args_Exp_Tup :: !((CRArray SExp))} | Exp_Let {firstOff_Exp_Let :: !(Int),ref2nm_Exp_Let :: !(Ref2Nm),binds_Exp_Let :: !((CRArray Bind)),body_Exp_Let :: !(Exp)} | Exp_App {func_Exp_App :: !(Exp),args_Exp_App :: !((CRArray SExp))} | Exp_Lam {mbNm_Exp_Lam :: !((Maybe HsName)),nrArgs_Exp_Lam :: !(Int),stkDepth_Exp_Lam :: !(Int),ref2nm_Exp_Lam :: !(Ref2Nm),body_Exp_Lam :: !(Exp)} | Exp_Force {expr_Exp_Force :: !(Exp)} | Exp_Tail {expr_Exp_Tail :: !(Exp)} | Exp_Case {expr_Exp_Case :: !(SExp),alts_Exp_Case :: !((CRArray Alt))} | Exp_FFI {prim_Exp_FFI :: !(RunPrim),args_Exp_FFI :: !((CRArray SExp))} -- Meta -------------------------------------------------------- data Meta = Meta_Data {tyNm_Meta_Data :: !(HsName),dataCons_Meta_Data :: !(DataConL)} -- MetaL ------------------------------------------------------- type MetaL = [Meta] -- Mod --------------------------------------------------------- data Mod = Mod_Mod {ref2nm_Mod_Mod :: !(Ref2Nm),moduleNm_Mod_Mod :: !(HsName),moduleNr_Mod_Mod :: !(Int),stkDepth_Mod_Mod :: !(Int),metas_Mod_Mod :: !(MetaL),binds_Mod_Mod :: !((CRArray Bind)),body_Mod_Mod :: !(Exp)} -- Pat --------------------------------------------------------- data Pat = Pat_Con {tag_Pat_Con :: !(Int)} | Pat_BoolExpr {expr_Pat_BoolExpr :: !(Exp)} -- SExp -------------------------------------------------------- data SExp = SExp_Var {ref_SExp_Var :: !(RRef)} | SExp_Int {int_SExp_Int :: !(Int)} | SExp_Char {char_SExp_Char :: !(Char)} | SExp_String {str_SExp_String :: !(String)} | SExp_Integer {integer_SExp_Integer :: !(Integer)} | SExp_Dbg {msg_SExp_Dbg :: !(String)}