module Fact (factExpr) where
import CoreSyn hiding (mkLet)
import CoreUtils
import MkId
import BasicTypes
import Id
import Type
import TyCon
import Name
import TysWiredIn
import TysWiredIn
import FastString
import Literal
import Unique
import DataCon
-- | A core expression of type Nat that evaluates to fact n in unary presentation.
factExpr :: Int -> CoreExpr
factExpr n =
mkRFun plus [x,y] (
Case (Var x) b natTy [(DataAlt dcZero, [], Var y)
,(DataAlt dcSucc, [z], Var dcSuccWrk `App` (Var plus `App` Var z `App` Var y))]
) $
mkRFun times [x,y] (
Case (Var x) b natTy [(DataAlt dcZero, [], Var dcZeroWrk)
,(DataAlt dcSucc, [z], Var plus `App` Var y `App` (Var times `App` Var z `App` Var y))]
) $
mkRFun fact [x] (
Case (Var x) b natTy [(DataAlt dcZero, [], Var dcSuccWrk `App` Var dcZeroWrk)
,(DataAlt dcSucc, [z], Var times `App` Var b `App` (Var fact `App` Var z))]
) $
mkRFun deepseq [x,y] (
Case (Var x) b natTy [(DataAlt dcZero, [], Var y)
,(DataAlt dcSucc, [z], Var deepseq `App` Var z `App` Var y)]
) $
mkLet x (Var fact `App` ((iterate (Var dcSuccWrk `App`) (Var dcZeroWrk)) !! n)) $
Var deepseq `App` Var x `App` Var x
-- Build IDs. use mkTemplateLocal, more predictable than proper uniques
plus, times, deepseq, fact, x, y, z, b:: Id
[plus, times, deepseq, fact, x, y, z, b] = mkTestIds
(words "plus times deepseq fact x y z b")
[ mkFunTys [natTy, natTy] natTy
, mkFunTys [natTy, natTy] natTy
, mkFunTys [natTy, natTy] natTy
, mkFunTys [natTy] natTy
, natTy
, natTy
, natTy
, natTy
]
-- Build DataCons. This is involved
dcZero :: DataCon
dcZero = mkDataCon
dcZeroName
False
dcZeroName
[] [] [] [] [] [] [] []
natTy
NoRRI
natTyCon
[]
dcZeroWrk
NoDataConRep
dcZeroName :: Name
dcZeroName = mkSystemName (mkBuiltinUnique 100) (mkDataOcc "Zero")
dcZeroWrkName :: Name
dcZeroWrkName = mkSystemName (mkBuiltinUnique 101) (mkVarOcc "Zero")
dcZeroWrk :: Id
dcZeroWrk = mkDataConWorkId dcZeroWrkName dcZero
dcSucc :: DataCon
dcSucc = mkDataCon
dcSuccName
False
dcSuccName
[] [] [] [] [] [] [] [natTy]
natTy
NoRRI
natTyCon
[]
dcSuccWrk
NoDataConRep
dcSuccName :: Name
dcSuccName = mkSystemName (mkBuiltinUnique 102) (mkDataOcc "Succ")
dcSuccWrkName :: Name
dcSuccWrkName = mkSystemName (mkBuiltinUnique 103) (mkVarOcc "Succ")
dcSuccWrk :: Id
dcSuccWrk = mkDataConWorkId dcSuccWrkName dcSucc
natTy :: Type
natTy = mkTyConTy natTyCon
natTcName :: Name
natTcName = mkSystemName (mkBuiltinUnique 104) (mkTcOcc "Nat")
natTyCon :: TyCon
natTyCon = mkAlgTyCon
natTcName
[]
liftedTypeKind
[]
Nothing
[]
(DataTyCon [dcZero, dcSucc] False)
(VanillaAlgTyCon natTcName)
False
-- Utilities
mkLApps :: Id -> [Integer] -> CoreExpr
mkLApps v = mkApps (Var v) . map mkLit
mkTestId :: Int -> String -> Type -> Id
mkTestId i s ty = mkSysLocal (mkFastString s) (mkBuiltinUnique i) ty
mkTestIds :: [String] -> [Type] -> [Id]
mkTestIds ns tys = zipWith3 mkTestId [0..] ns tys
mkLet :: Id -> CoreExpr -> CoreExpr -> CoreExpr
mkLet v rhs body = Let (NonRec v rhs) body
mkRLet :: Id -> CoreExpr -> CoreExpr -> CoreExpr
mkRLet v rhs body = Let (Rec [(v, rhs)]) body
mkFun :: Id -> [Id] -> CoreExpr -> CoreExpr -> CoreExpr
mkFun v xs rhs body = mkLet v (mkLams xs rhs) body
mkRFun :: Id -> [Id] -> CoreExpr -> CoreExpr -> CoreExpr
mkRFun v xs rhs body = mkRLet v (mkLams xs rhs) body
mkLit :: Integer -> CoreExpr
mkLit i = Lit (mkLitInteger i intTy)