ddc-core-tetra-0.4.3.1: DDC/Core/Tetra/Convert/Boxing.hs
-- | Punned data type and constructor definitions for boxed numeric objects.
--
-- Boxed numeric objects are treated abstractly by the source language, and
-- aren't really algebraic data, but we define them as such so that we can
-- re-use the to-salt conversion code for algebraic data.
--
-- Each primitive numeric type like (Nat#) induces a data type and data
-- constructor of the same name.
--
-- The data constructor has a single unboxed field (U# Nat#) and produces
-- a boxed result type (B# Nat#). Note that the name of the data type (Nat#)
-- is different from the result type (B# Nat#), which is unlike real algebraic
-- data types.
--
module DDC.Core.Tetra.Convert.Boxing
( isSomeRepType
, isBoxedRepType
, isUnboxedRepType
, isNumericType
, isVectorType
, isTextLitType
, makeBoxedPrimDataType
, makeBoxedPrimDataCtor)
where
import DDC.Core.Tetra.Prim
import DDC.Core.Tetra.Compounds
import DDC.Type.DataDef
-- Predicates -----------------------------------------------------------------
-- | Check if this is a representable type.
-- This is the union of `isBoxedRepType` and `isUnboxedRepType`.
isSomeRepType :: Type Name -> Bool
isSomeRepType tt
= isBoxedRepType tt || isUnboxedRepType tt
-- | Check if some representation type is boxed.
-- The type must have kind Data, otherwise bogus result.
--
-- A "representation type" is the sort of type we get after applying the
-- Boxing transform, which works out how to represent everything.
--
-- The boxed representation types are:
-- 1) 'a -> b' -- the function type
-- 1) 'a' -- polymorphic types.
-- 2) 'forall ...' -- abstract types.
-- 3) 'Unit' -- the unit data type.
-- 5) User defined data types.
--
isBoxedRepType :: Type Name -> Bool
isBoxedRepType tt
| Just _ <- takeTFun tt
= True
| TVar{} <- tt = True
| TForall{} <- tt = True
-- Unit data type.
| Just (TyConSpec TcConUnit, _) <- takeTyConApps tt
= True
-- User defined data types.
| Just (TyConBound (UName _) _, _) <- takeTyConApps tt
= True
-- Boxed numeric types
| isNumericType tt
= True
-- The primitive vector type.
| isVectorType tt
= True
| otherwise
= False
-- | Check if some representation type is unboxed.
-- The type must have kind Data, otherwise bogus result.
--
-- A "representation type" is the sort of type we get after applying the
-- Boxing transform, which works out how to represent everything.
--
-- The unboxed representation are are:
-- 1) 'U# T' -- unboxed numeric types, where T is a boxable type.
--
isUnboxedRepType :: Type Name -> Bool
isUnboxedRepType tt
| Just ( NameTyConTetra TyConTetraU
, [ti]) <- takePrimTyConApps tt
, isNumericType ti || isTextLitType ti
= True
| otherwise
= False
-- | Check if some type is a numeric or other primtitype.
isNumericType :: Type Name -> Bool
isNumericType tt
| Just (NamePrimTyCon n, []) <- takePrimTyConApps tt
= case n of
PrimTyConBool -> True
PrimTyConNat -> True
PrimTyConInt -> True
PrimTyConSize -> True
PrimTyConWord _ -> True
PrimTyConFloat _ -> True
PrimTyConTextLit -> True
_ -> False
| otherwise = False
-- | Check if some type is the boxed vector type.
isVectorType :: Type Name -> Bool
isVectorType tt
| Just (NameTyConTetra n, _) <- takePrimTyConApps tt
= case n of
TyConTetraVector -> True
_ -> False
| otherwise = False
-- | Check if this is the string type.
isTextLitType :: Type Name -> Bool
isTextLitType tt
| Just (NamePrimTyCon n, []) <- takePrimTyConApps tt
= case n of
PrimTyConTextLit -> True
_ -> False
| otherwise = False
-- Punned Defs ----------------------------------------------------------------
-- | Generic data type definition for a primitive numeric type.
makeBoxedPrimDataType :: Type Name -> Maybe (DataType Name)
makeBoxedPrimDataType tt
| Just (n@NamePrimTyCon{}, []) <- takePrimTyConApps tt
= Just $ DataType
{ dataTypeName = n
, dataTypeParams = []
, dataTypeMode = DataModeLarge
, dataTypeIsAlgebraic = False }
| otherwise
= Nothing
-- | Generic data constructor definition for a primtive numeric type.
makeBoxedPrimDataCtor :: Type Name -> Maybe (DataCtor Name)
makeBoxedPrimDataCtor tt
| Just (n@NamePrimTyCon{}, []) <- takePrimTyConApps tt
= Just $ DataCtor
{ dataCtorName = n
, dataCtorTag = 0
, dataCtorFieldTypes = [tUnboxed tt]
, dataCtorResultType = tt
, dataCtorTypeName = n
, dataCtorTypeParams = [] }
| otherwise
= Nothing