ddc-core-salt-0.4.2.1: DDC/Core/Salt/Name/PrimTyCon.hs
module DDC.Core.Salt.Name.PrimTyCon
( PrimTyCon (..)
, pprPrimTyConStem
, readPrimTyCon
, readPrimTyConStem
, primTyConIsIntegral
, primTyConIsFloating
, primTyConIsUnsigned
, primTyConIsSigned
, primTyConWidth)
where
import DDC.Core.Salt.Platform
import DDC.Data.ListUtils
import DDC.Base.Pretty
import Control.DeepSeq
import Data.Char
import Data.List
-- | Primitive type constructors.
data PrimTyCon
-- | @Void#@ the Void type has no values.
= PrimTyConVoid
-- | @Bool#@ unboxed booleans.
| PrimTyConBool
-- | @Nat#@ natural numbers.
-- Enough precision to count every object in the heap,
-- but NOT necessearily enough precision to count every byte of memory.
| PrimTyConNat
-- | @Int#@ signed integers.
-- Enough precision to count every object in the heap,
-- but NOT necessearily enough precision to count every byte of memory.
-- If N is the total number of objects that can exist in the heap,
-- then the range of @Int#@ is at least (-N .. +N) inclusive.
| PrimTyConInt
-- | @Size#@ unsigned sizes.
-- Enough precision to count every addressable bytes of memory.
| PrimTyConSize
-- | @WordN#@ machine words of the given width.
| PrimTyConWord Int
-- | @FloatN#@ floating point numbers of the given width.
| PrimTyConFloat Int
-- | @VecN#@ a packed vector of N values.
-- This is intended to have kind (Data -> Data),
-- so we use concrete vector types like @Vec4# Word32#@.
| PrimTyConVec Int
-- | @Addr#@ a relative or absolute machine address.
-- Enough precision to count every byte of memory.
-- Unlike pointers below, an absolute @Addr#@ need not refer to
-- memory owned by the current process.
| PrimTyConAddr
-- | @Ptr#@ like @Addr#@, but with a region and element type annotation.
-- In particular, a value of a type like (Ptr# r Word32#) must be at least
-- 4-byte aligned and point to memory owned by the current process.
| PrimTyConPtr
-- | @TextLit#@ type of a text literal, which is represented as a pointer
-- to the literal data in static memory.
| PrimTyConTextLit
-- | @Tag#@ data constructor tags.
-- Enough precision to count every possible alternative of an
-- enumerated type.
| PrimTyConTag
deriving (Eq, Ord, Show)
instance NFData PrimTyCon where
rnf tc
= case tc of
PrimTyConWord i -> rnf i
PrimTyConFloat i -> rnf i
_ -> ()
instance Pretty PrimTyCon where
ppr tc = pprPrimTyConStem tc <> text "#"
-- | Pretty print a primitive type constructor,
-- without the '#' suffix.
pprPrimTyConStem :: PrimTyCon -> Doc
pprPrimTyConStem tc
= case tc of
PrimTyConVoid -> text "Void"
PrimTyConBool -> text "Bool"
PrimTyConNat -> text "Nat"
PrimTyConInt -> text "Int"
PrimTyConSize -> text "Size"
PrimTyConWord bits -> text "Word" <> int bits
PrimTyConFloat bits -> text "Float" <> int bits
PrimTyConVec arity -> text "Vec" <> int arity
PrimTyConTag -> text "Tag"
PrimTyConAddr -> text "Addr"
PrimTyConPtr -> text "Ptr"
PrimTyConTextLit -> text "TextLit"
-- | Read a primitive type constructor.
--
-- Words are limited to 8, 16, 32, or 64 bits.
--
-- Floats are limited to 32 or 64 bits.
readPrimTyCon :: String -> Maybe PrimTyCon
readPrimTyCon str
| Just stem <- stripSuffix "#" str
= readPrimTyConStem stem
| otherwise
= Nothing
-- | Read a primitive type constructor, without the '#' suffix.
readPrimTyConStem :: String -> Maybe PrimTyCon
readPrimTyConStem str
| str == "Void" = Just $ PrimTyConVoid
| str == "Bool" = Just $ PrimTyConBool
| str == "Nat" = Just $ PrimTyConNat
| str == "Int" = Just $ PrimTyConInt
| str == "Size" = Just $ PrimTyConSize
| str == "Tag" = Just $ PrimTyConTag
| str == "Addr" = Just $ PrimTyConAddr
| str == "Ptr" = Just $ PrimTyConPtr
| str == "TextLit" = Just $ PrimTyConTextLit
-- WordN#
| Just rest <- stripPrefix "Word" str
, (ds, "") <- span isDigit rest
, not $ null ds
, n <- read ds
, elem n [8, 16, 32, 64]
= Just $ PrimTyConWord n
-- FloatN#
| Just rest <- stripPrefix "Float" str
, (ds, "") <- span isDigit rest
, not $ null ds
, n <- read ds
, elem n [32, 64]
= Just $ PrimTyConFloat n
-- VecN#
| Just rest <- stripPrefix "Vec" str
, (ds, "") <- span isDigit rest
, not $ null ds
, n <- read ds
, elem n [2, 4, 8, 16]
= Just $ PrimTyConVec n
| otherwise
= Nothing
-- | Integral constructors are the ones that we can reasonably
-- convert from integers of the same size.
--
-- These are @Bool#@, @Nat#@, @Int#@, @Size@, @WordN#@ and @Tag#@.
--
primTyConIsIntegral :: PrimTyCon -> Bool
primTyConIsIntegral tc
= case tc of
PrimTyConBool -> True
PrimTyConNat -> True
PrimTyConInt -> True
PrimTyConSize -> True
PrimTyConWord{} -> True
PrimTyConTag -> True
_ -> False
-- | Floating point types.
--
-- These are @FloatN#@.
primTyConIsFloating :: PrimTyCon -> Bool
primTyConIsFloating tc
= case tc of
PrimTyConFloat{} -> True
_ -> False
-- | Unsigned types.
--
-- These are @Bool#@ @Nat#@ @Size#@ @WordN@ @Tag@.
primTyConIsUnsigned :: PrimTyCon -> Bool
primTyConIsUnsigned tc
= case tc of
PrimTyConBool -> True
PrimTyConNat -> True
PrimTyConSize -> True
PrimTyConWord{} -> True
PrimTyConTag -> True
_ -> False
-- | Signed integral constructors.
--
-- This is just @Int@.
primTyConIsSigned :: PrimTyCon -> Bool
primTyConIsSigned tc
= case tc of
PrimTyConInt -> True
PrimTyConFloat{} -> True
_ -> False
-- | Get the representation width of a primitive type constructor,
-- in bits. This is how much space it takes up in an object payload.
--
-- Bools are representable with a single bit, but we unpack
-- them into a whole word.
--
-- The constructors @Void@ and @VecN#@ and @String@ have no width.
--
primTyConWidth :: Platform -> PrimTyCon -> Maybe Integer
primTyConWidth pp tc
= case tc of
PrimTyConVoid -> Nothing
PrimTyConBool -> Just $ 8 * platformNatBytes pp
PrimTyConNat -> Just $ 8 * platformNatBytes pp
PrimTyConInt -> Just $ 8 * platformNatBytes pp
PrimTyConSize -> Just $ 8 * platformNatBytes pp
PrimTyConWord bits -> Just $ fromIntegral bits
PrimTyConFloat bits -> Just $ fromIntegral bits
PrimTyConTag -> Just $ 8 * platformTagBytes pp
PrimTyConAddr -> Just $ 8 * platformAddrBytes pp
PrimTyConPtr -> Just $ 8 * platformAddrBytes pp
-- The string literal itself does not have a width associated with it.
-- In the object code string literals are represented by pointers to
-- static data. The static data is an array of Word8s, but the pointer
-- itself is the width of an address on our machine.
PrimTyConTextLit -> Nothing
PrimTyConVec _ -> Nothing