%
% (c) The Foo Project, University of Glasgow, 1998
%
% @(#) $Docid: Dec. 1st 2003 06:57 Sigbjorn Finne $
% @(#) $Contactid: sof@galois.com $
%
Disjoint set of utilities for working with the @AbstractH@
type.
\begin{code}
module AbsHUtils
(
tyConst
, tyQConst
, libTyQConst
, mkTyConst
, deTyCon
, tyCon
, tyQCon
, mkTyCon
, tyVar
, uniqueTyVar
, tyQVar
, isTyVar
, generaliseTys
, overloadedTyVar
, ctxtTyApp
, ctxtClass
, mbCtxtTyApp
, tyList
, tyMaybe
, tyVariant
, tuple
, tyInt8Name, tyInt16Name, tyInt32Name, tyInt64Name, tyIntName
, tyInt8, tyInt16, tyInt32, tyInt64, tyInt
, tyInteger, tyIntegerName
, tyFloat, tyDouble, tyLongDouble
, tyAddr
, tyPtr
, anyTyPtr
, tyFunPtr
, tyForeignObj
, tyForeignPtr
, isFOTy
, isPtrTy
, isVARIANTTy
, toPtrTy
, tyStable
, tyString
, tyWString
, tyByte, tyChar, tyWChar
, tyBool
, tyWord8Name, tyWord16Name, tyWord32Name, tyWord64Name
, tyWord8, tyWord16, tyWord32, tyWord64
, funTy
, funTys
, io
, io_unit
, tyUnit
, purifyType
, isIOTy
, recCon
, recConBanged
, conDecl
, recToConDecl
, dataTy
, newTy
, tySyn
, conDeclToCon
, conDeclToPat
, splitFunTys
, hInstance
, hClass
, groundTyVars
, unconstrainType
, andDecl
, andDecls
, emptyDecl
, comment
, isEmptyDecl
, cCode
, typeSig
, genTypeSig
, mkTypeSig
, funDef
, valDef
, methodDef
, guardedFunDef
, prim
, primcst
, fexport
, extLabel
, conPat
, patVar
, patRec
, qpatVar
, litPat
, varPat
, tuplePat
, exprToPat
, wildPat
, isVarPat
, ret
, genBind
, bind
, bind_
, var
, varName
, qvar
, lam
, lit
, integerLit
, dataConst
, dataCon
, funApp
, contApply
, funApply
, infixOp
, binOp
, unaryOp
, tup
, hList
, hCase
, hIf
, alt
, genAlt
, defaultAlt
, equals
, hLet
, hLets
, intLit
, stringLit
, addPtr
, castPtr
, nothing
, just
, unit
, prefix
, prefixApp
, appendStr
, isVarsEq
, hModule
, hMeta
, cMeta
, hInclude
, hExport
, hImport
, hQImport
, ieModule
, ieValue
, ieClass
, ieType
, subst
, mkQVarName
, mkVarName
, mkConName
, mkQConName
, mkTyVar
, mkQTyVar
, mkQTyCon
, mkIntTy
, mkCharTy
, mkFloatTy
, findIncludes
, mkTySig
, replaceTyVar
) where
import AbstractH
import Literal
import BasicTypes
import LibUtils
import Opts ( optIntsEverywhere, optIntAsWord
, optIntIsInt, optLongLongIsInteger
, optNoWideStrings
)
import Maybe ( fromMaybe, isJust )
import Char ( isLower )
import List ( mapAccumL, intersperse )
infixl 9 `andDecl`
\end{code}
\begin{code}
tyConst :: String -> Type
tyConst con = TyCon (mkQualName Nothing con)
tyQConst :: Maybe String -> String -> Type
tyQConst m con = TyCon (mkQTyCon m con)
libTyQConst :: Maybe String -> Maybe String -> String -> Type
libTyQConst ty_mod marshall_mod con = TyCon ((mkQTyCon marshall_mod con){qDefModule=ty_mod})
libTyQName :: Maybe String -> Maybe String -> String -> QualName
libTyQName ty_mod marshall_mod con = (mkQTyCon marshall_mod con){qDefModule=ty_mod}
mkTyConst :: QualName -> Type
mkTyConst qv
| not (isJust (qModule qv)) &&
isLower (head (qName qv))
= TyVar False (mkTyVar (qName qv))
| length args > 1
= TyApply (TyCon (qv{qName=a})) (map ((TyVar False). mkTyVar) as)
| otherwise = TyCon qv
where
args@(a:as) = words (qName qv)
deTyCon :: Type -> QualName
deTyCon (TyCon c) = c
deTyCon _ = error "AbsHUtils.deTyCon: expected a tycon"
tyCon :: String -> [Type] -> Type
tyCon con args = TyApply (TyCon (mkQualName Nothing con)) args
tyQCon :: Maybe String -> String -> [Type] -> Type
tyQCon ty_mod con args = TyApply (TyCon (mkQTyCon ty_mod con)) args
mkTyCon :: QualName -> [Type] -> Type
mkTyCon qv args = TyApply (TyCon qv) args
tyVar :: String -> Type
tyVar nm = TyVar False (mkTyVar nm)
uniqueTyVar :: String -> Type
uniqueTyVar nm = TyVar True (mkTyVar nm)
overloadedTyVar :: ClassName -> String -> Type
overloadedTyVar c_name tv = TyCtxt (CtxtClass c_name [tvar]) tvar
where
tvar = TyVar False (mkTyVar tv)
ctxtClass :: ClassName -> [Type] -> Context
ctxtClass c ts = CtxtClass c ts
ctxtTyApp :: Context -> Type -> Type
ctxtTyApp ctxt t = TyCtxt ctxt t
mbCtxtTyApp :: Maybe Context -> Type -> Type
mbCtxtTyApp Nothing t = t
mbCtxtTyApp (Just c) t = TyCtxt c t
tyQVar :: Maybe String -> String -> Type
tyQVar ty_mod nm = TyVar False (mkQTyVar ty_mod nm)
isTyVar :: Type -> Bool
isTyVar (TyVar _ _) = True
isTyVar _ = False
isNonUniqTyVar :: Type -> Bool
isNonUniqTyVar (TyVar False _) = True
isNonUniqTyVar _ = False
unconstrainType :: Type -> ([(Context,TyVar)], Type)
unconstrainType tx = go [] tx
where
go acc t =
case t of
TyApply f args ->
let
(acc1, f') = go acc f
(acc2, args') = mapAccumL go acc1 args
in
(acc2, TyApply f' args')
TyTuple ts ->
let
(acc1, ts') = mapAccumL go acc ts
in
(acc1, TyTuple ts')
TyFun t1 t2 ->
let
(acc1, t1') = go acc t1
(acc2, t2') = go acc1 t2
in
(acc2, TyFun t1' t2')
TyList t1 ->
let
(acc1, t1') = go acc t1
in
(acc1, TyList t1')
TyCtxt ctxt t1@(TyVar _ tv) -> ((ctxt,tv):acc, t1)
_ -> (acc, t)
groundTyVars :: Type -> Type
groundTyVars t =
case t of
TyVar{} -> groundTyVar t
TyApply (TyCon tc) args | qName tc == "Maybe" -> TyApply (TyCon tc) (map groundTyVars args)
TyApply tc args -> TyApply tc (map groundTyVar args)
TyTuple ts -> TyTuple (map groundTyVars ts)
TyFun t1 t2 -> TyFun (groundTyVars t1) (groundTyVars t2)
TyList t1 -> TyList (groundTyVars t1)
TyCtxt _ _ -> t
_ -> t
where
groundTyVar ty
| isNonUniqTyVar ty = tyUnit
| otherwise =
case ty of
TyApply tc args -> TyApply tc (map groundTyVars args)
TyFun t1 t2 -> TyFun (groundTyVars t1) (groundTyVars t2)
_ -> ty
renameTyVar :: String -> Type -> Type
renameTyVar new_nm (TyVar x _) = TyVar x (mkTyVar new_nm)
renameTyVar _ t = t
replaceTyVar :: Type -> Type -> Type
replaceTyVar newTy ty =
case ty of
TyVar _ _ -> newTy
TyApply f args -> TyApply f (map (replaceTyVar newTy) args)
TyTuple ts -> TyTuple (map (replaceTyVar newTy) ts)
TyFun a b -> TyFun (replaceTyVar newTy a) (replaceTyVar newTy b)
_ -> ty
generaliseTys :: [Type] -> ([Type], Maybe Context)
generaliseTys tys =
case (go nm_supply [] tys) of
(ts, []) -> (ts, Nothing)
(ts, ls) -> (ts, Just (CtxtTuple (reverse ls)))
where
nm_supply = map (\ x -> 'a':show x) [(0::Int)..]
substCtxt s x (CtxtTuple ls) = CtxtTuple (map (substCtxt s x) ls)
substCtxt s x (CtxtClass c ts) = CtxtClass c (map (substTyVar s x) ts)
substTyVar o_t x t =
case t of
TyVar fixed n | not fixed && n == x -> o_t
TyApply t1 ty_args -> TyApply t' ty_args'
where
(t':ty_args') = map (substTyVar o_t x) (t1:ty_args)
TyList t1 -> TyList (substTyVar o_t x t1)
TyTuple ts -> TyTuple (map (substTyVar o_t x) ts)
TyFun a b -> TyFun (substTyVar o_t x a)
(substTyVar o_t x b)
TyCtxt c t1 -> TyCtxt (substCtxt o_t x c)
(substTyVar o_t x t1)
_ -> t
go _ acc [] = ([], acc)
go supply@(s:ss) acc_ctxt (x:xs) =
case x of
TyVar fixed _ | not fixed ->
let
x' = renameTyVar s x
(xs',acc) = go ss acc_ctxt xs
in
(x' : xs', acc)
TyCtxt ctxt tv@(TyVar fixed n) | not fixed ->
let
tv' = renameTyVar s tv
ctxt' = substCtxt tv' n ctxt
(xs',acc) = go ss (ctxt' : acc_ctxt) xs
in
(tv' : xs', acc)
TyApply t ty_args ->
let
(ts, acc) = go supply acc_ctxt (t:ty_args++xs)
(t':ty_args', rs) = splitAt (length ty_args + 1) ts
in
(TyApply t' ty_args' : rs, acc)
TyList t ->
let
(t':xs', acc) = go supply acc_ctxt (t:xs)
in
(TyList t' : xs' , acc)
TyTuple tuple_tys ->
let
(ts, acc) = go supply acc_ctxt (tuple_tys++xs)
(tys', rs) = splitAt (length tuple_tys) ts
in
(TyTuple tys' : rs, acc)
TyFun t1 t2 ->
let
(t1' : t2' : xs', acc) = go supply acc_ctxt (t1:t2:xs)
in
(TyFun t1' t2' : xs', acc)
_ ->
let
(xs', acc) = go supply acc_ctxt xs
in
(x:xs', acc)
go _ _ _ = error "generaliseTys"
tyList :: Type -> Type
tyList t = TyList t
tyMaybe :: Type -> Type
tyMaybe t = TyApply (TyCon maybeName) [t]
tyVariant :: Type
tyVariant = TyCon variantType
tuple :: [Type] -> Type
tuple [] = tyUnit
tuple [t] = t
tuple ts = TyTuple ts
tyInt8Name, tyInt16Name, tyInt32Name, tyInt64Name, tyIntName :: QualName
(tyInt8Name, tyInt16Name, tyInt32Name, tyInt64Name)
| optIntsEverywhere = (tyIntName, tyIntName, tyIntName, tyIntName)
| otherwise =
( libTyQName intLib hdirectLib "Int8"
, libTyQName intLib hdirectLib "Int16"
, libTyQName intLib hdirectLib "Int32"
, libTyQName intLib hdirectLib "Int64"
)
tyInt8, tyInt16, tyInt32, tyInt64, tyInt :: Type
tyInt8 = mkTyConst tyInt8Name
tyInt16 = mkTyConst tyInt16Name
tyInt32 = mkTyConst tyInt32Name
tyInt64 = mkTyConst tyInt64Name
tyIntName = libTyQName prelude hdirectLib "Int"
tyInt = mkTyConst tyIntName
tyIntegerName :: QualName
tyInteger :: Type
tyIntegerName = libTyQName prelude hdirectLib "Integer"
tyInteger = mkTyConst tyIntegerName
tyAddr :: Type
tyAddr = tyPtr tyUnit
tyPtr :: Type -> Type
tyPtr t = TyApply (libTyQConst ptrLib hdirectLib ptrName) [t]
anyTyPtr :: Type
anyTyPtr = tyPtr (uniqueTyVar "a")
tyStable :: Type
tyStable = mkTyCon (libTyQName foreignLib hdirectLib "StablePtr") [uniqueTyVar "a"]
tyForeignObj :: Type
tyForeignObj = tyForeignPtr tyUnit
tyForeignPtr :: Type -> Type
tyForeignPtr t = TyApply (libTyQConst foreignPtrLib hdirectLib foreignPtrName) [t]
tyFunPtr :: Type -> Type
tyFunPtr t = TyApply (libTyQConst ptrLib hdirectLib funPtrName) [t]
isFOTy :: Type -> Bool
isFOTy (TyApply (TyCon tc) _) = qName tc == foreignPtrName
isFOTy _ = False
isPtrTy :: Type -> Bool
isPtrTy (TyApply (TyCon tc) _) = nm == ptrName || nm == foreignPtrName
where
nm = qName tc
isPtrTy _ = False
toPtrTy :: Type -> Type
toPtrTy ty@(TyApply (TyCon tc) [t])
| qName tc == foreignPtrName = tyPtr (toPtrTy t)
| otherwise = ty
toPtrTy (TyApply tc ts) = TyApply tc (map toPtrTy ts)
toPtrTy t = t
isVARIANTTy :: Type -> Bool
isVARIANTTy (TyCon tc) = qName tc == "VARIANT"
isVARIANTTy _ = False
tyString :: Type
tyString = tyQConst prelude stringName
tyWString :: Type
tyWString
| optNoWideStrings = tyString
| otherwise = tyQConst wStringLib "WideString"
tyByte, tyBool, tyChar :: Type
tyChar = libTyQConst prelude hdirectLib "Char"
tyBool = libTyQConst prelude hdirectLib "Bool"
tyByte = tyWord8
tyWordName :: QualName
tyWordName = mkQualName wordLib "Word"
tyWord :: Type
tyWord = mkTyConst (tyWordName{qModule=hdirectLib})
tyWord8Name, tyWord16Name, tyWord32Name, tyWord64Name :: QualName
(tyWord8Name, tyWord16Name, tyWord32Name, tyWord64Name)
| optIntsEverywhere && optIntAsWord = (tyIntName, tyIntName, tyIntName, tyIntName)
| otherwise =
( libTyQName wordLib hdirectLib "Word8"
, libTyQName wordLib hdirectLib "Word16"
, libTyQName wordLib hdirectLib "Word32"
, libTyQName wordLib hdirectLib "Word64"
)
tyWord8, tyWord16, tyWord32, tyWord64 :: Type
tyWord8 = mkTyConst tyWord8Name
tyWord16 = mkTyConst tyWord16Name
tyWord32 = mkTyConst tyWord32Name
tyWord64 = mkTyConst tyWord64Name
tyWChar :: Type
tyWChar = tyWord16
tyFloat, tyDouble, tyLongDouble :: Type
tyFloat = libTyQConst prelude hdirectLib "Float"
tyDouble = libTyQConst prelude hdirectLib "Double"
tyLongDouble = libTyQConst prelude hdirectLib "Double"
\end{code}
\begin{code}
funTy :: Type -> Type -> Type
funTy a b = TyFun a b
funTys :: [Type] -> Type -> Type
funTys ls res = foldr TyFun res ls
io :: Type -> Type
io x = tyQCon prelude "IO" [x]
isIOTy :: Type -> Bool
isIOTy (TyApply (TyCon q) _)
| qName q == "IO" && qModule q == Just "Prelude" = True
isIOTy _ = False
purifyType :: Type -> Type
purifyType (TyFun x y@TyFun{}) = TyFun x (purifyType y)
purifyType t@(TyFun x y)
| isIOTy y = case y of { (TyApply _ [arg]) -> TyFun x arg ; _ -> t}
purifyType t = t
io_unit :: Type
io_unit = io tyUnit
tyUnit :: Type
tyUnit = tyConst "()"
\end{code}
Constructor decls:
\begin{code}
recCon :: Name -> [(Name, Type)] -> ConDecl
recCon nm fields = RecDecl nm (map (\ (x,t) -> (x,Unbanged t)) fields)
recConBanged :: Name -> [(Name, Type)] -> ConDecl
recConBanged nm fields = RecDecl nm (map (\ (x,t) -> (x,Banged t)) fields)
conDecl :: Name -> [Type] -> ConDecl
conDecl nm ls = ConDecl nm (map Unbanged ls)
recToConDecl :: ConDecl -> ConDecl
recToConDecl (RecDecl nm fs) = ConDecl nm (map snd fs)
recToConDecl c = c
dataTy :: Name -> [Name] -> [ConDecl] -> HDecl
dataTy dname tvs constrs = TyD (TyDecl Data dname tvs constrs [])
newTy :: Name -> [Name] -> ConDecl -> [QualName] -> HDecl
newTy dname tvs constr ls = TyD (TyDecl Newtype dname tvs [constr] ls)
hInstance :: Maybe [(ClassName,[TyVar])] -> ClassName -> Type -> [HDecl] -> HDecl
hInstance Nothing cname t decls = Instance (CtxtTuple []) cname t decls
hInstance (Just ls) cname t decls =
Instance (CtxtTuple (map (uncurry (\ x y -> CtxtClass x (map (TyVar False) y))) ls)) cname t decls
hClass :: Context -> ClassName -> [TyVar] -> [HDecl] -> HDecl
hClass ctxt nm tvs ds = Class ctxt nm tvs ds
tySyn :: Name -> [Name] -> Type -> HDecl
tySyn dname tvs ty = TyD (TypeSyn dname tvs ty)
conDeclToCon :: ConDecl -> Expr
conDeclToCon (ConDecl nm args) =
dataCon (mkConName nm) (zipWith (\ _ a -> var ('a':show a)) args [(1::Int)..])
conDeclToCon (RecDecl nm fields) =
dataCon (mkConName nm) (map (\ (f,_) -> var f) fields)
conDeclToPat :: ConDecl -> Pat
conDeclToPat (ConDecl nm args) =
conPat (mkConName nm) (zipWith (\ _ a -> patVar ('a':show a)) args [(1::Int)..])
conDeclToPat (RecDecl nm fields) =
conPat (mkConName nm) (map (\ (f,_) -> patVar f) fields)
splitFunTys :: Type -> ([Type], Type)
splitFunTys ty = split [] ty ty
where
split args _ (TyFun arg res) = split (arg:args) res res
split args orig_ty _ = (reverse args, orig_ty)
\end{code}
\begin{code}
andDecl :: HDecl -> HDecl -> HDecl
andDecl = AndDecl
andDecls :: [HDecl] -> HDecl
andDecls = foldr (andDecl) emptyDecl
isEmptyDecl :: HDecl -> Bool
isEmptyDecl EmptyDecl = True
isEmptyDecl _ = False
emptyDecl :: HDecl
emptyDecl = EmptyDecl
comment :: String -> HDecl
comment str = Haskell ('-':'-':' ':str)
cCode :: String -> HDecl
cCode s = CCode s
\end{code}
\begin{code}
typeSig :: String -> Type -> HDecl
typeSig nm ty = TypeSig nm Nothing ty
genTypeSig :: String -> Maybe Context -> Type -> HDecl
genTypeSig nm mb_ctxt ty = TypeSig nm mb_ctxt ty
mkTypeSig :: String -> [Type] -> Type -> HDecl
mkTypeSig nm pts rty = genTypeSig nm ctxt (foldr funTy rty' pts')
where
(rty':pts', ctxt) = generaliseTys (rty:pts)
funDef :: String -> [Pat] -> Expr -> HDecl
funDef nm pats rhs = ValDecl (mkVarName nm) pats [GExpr [] rhs]
valDef :: String -> Expr -> HDecl
valDef nm rhs = ValDecl (mkVarName nm) [] [GExpr [] rhs]
methodDef :: QualName -> [Pat] -> Expr -> HDecl
methodDef qnm pats rhs = ValDecl qnm pats [GExpr [] rhs]
guardedFunDef :: String -> [Pat] -> [(Expr,Expr)] -> HDecl
guardedFunDef nm pats grhs = ValDecl (mkVarName nm) pats (map (\ (g,e) -> GExpr [g] e) grhs)
prim :: CallConv -> LocSpec -> Name -> Type -> Bool -> [(Bool,String)] -> (Bool,String) -> HDecl
prim cc ls nm ty need_wrapper c_args c_res
= Primitive True cc ls nm ty need_wrapper c_args c_res
extLabel :: Name -> Name -> Type -> HDecl
extLabel cname hname t = ExtLabel cname hname t
primcst :: CallConv -> Name -> Type -> Bool -> [(Bool,String)] -> (Bool,String) -> HDecl
primcst cc nm ty need_wrapper c_args c_res
= PrimCast cc nm ty need_wrapper c_args c_res
fexport :: CallConv -> Maybe Name -> Name -> Type -> HDecl
fexport cc Nothing h_nm ty = Callback cc h_nm ty
fexport cc (Just c_nm) h_nm ty = Entry cc c_nm h_nm ty
\end{code}
\begin{code}
conPat :: ConName -> [Pat] -> Pat
conPat dc a = PatCon dc a
patVar :: Name -> Pat
patVar v = PatVar (mkVarName v)
isVarPat :: Pat -> Bool
isVarPat (PatVar _) = True
isVarPat _ = False
wildPat :: Pat
wildPat = PatWildCard
patRec :: VarName -> [(VarName, Pat)] -> Pat
patRec nm pats = PatRecord nm pats
qpatVar :: Maybe String -> Name -> Pat
qpatVar qmod v = PatVar (mkQVarName qmod v)
varPat :: Expr -> Pat
varPat (Var v) = PatVar v
varPat _ = error "varPat: no can do - wasn't passed a Var, guv."
litPat :: Literal -> Pat
litPat l = PatLit l
tuplePat :: [Pat] -> Pat
tuplePat [p] = p
tuplePat ps = PatTuple ps
exprToPat :: Expr -> Maybe Pat
exprToPat (Var v) = Just (PatVar v)
exprToPat (Con c) = Just (PatCon c [])
exprToPat (Apply (Con c) ls) = Just (PatCon c (map ((fromMaybe PatWildCard).exprToPat) ls))
exprToPat (Lit l) = Just (PatLit l)
exprToPat (List ls) = Just (PatList (map ((fromMaybe PatWildCard).exprToPat) ls))
exprToPat (Tup ls) = Just (tuplePat (map ((fromMaybe PatWildCard).exprToPat) ls))
exprToPat _ = Nothing
\end{code}
Expressions:
\begin{code}
ret :: Expr -> Expr
ret e = Return e
bind :: Expr -> Expr -> Expr -> Expr
bind m v n = Bind m (varPat v) n
genBind :: Expr -> Pat -> Expr -> Expr
genBind m p n = Bind m p n
bind_ :: Expr -> Expr -> Expr
bind_ m n = Bind_ m n
var :: Name -> Expr
var v = Var (mkVarName v)
varName :: VarName -> Expr
varName v = Var v
qvar :: Maybe String -> Name -> Expr
qvar qmod v = Var (mkQVarName qmod v)
lam :: [Pat] -> Expr -> Expr
lam pats e = Lam pats e
lit :: Literal -> Expr
lit l = Lit l
integerLit :: IntegerLit -> Expr
integerLit l = Lit (IntegerLit l)
dataConst :: ConName -> Expr
dataConst nm = Con nm
dataCon :: ConName -> [Expr] -> Expr
dataCon dc args = Apply (Con dc) args
funApp :: VarName -> [Expr] -> Expr
funApp f args = Apply (Var f) args
contApply :: Expr -> Expr -> Expr
contApply e1 e2 = RApply e1 e2
funApply :: Expr -> [Expr] -> Expr
funApply f args = Apply f args
binOp :: BinaryOp -> Expr -> Expr -> Expr
binOp bop e1 e2 = BinOp bop e1 e2
infixOp :: Expr -> VarName -> Expr -> Expr
infixOp e1 op e2 = InfixOp e1 op e2
unaryOp :: UnaryOp -> Expr -> Expr
unaryOp uop e1 = UnOp uop e1
tup :: [Expr] -> Expr
tup [e] = e
tup es = Tup es
hList :: [Expr] -> Expr
hList es = List es
hCase :: Expr -> [CaseAlt] -> Expr
hCase scrut alts = Case scrut alts
hIf :: Expr -> Expr -> Expr -> Expr
hIf c e1 e2 = If c e1 e2
alt :: Pat -> Expr -> CaseAlt
alt p e = Alt p [GExpr [] e]
genAlt :: Pat -> Expr -> Expr -> CaseAlt
genAlt p g e = Alt p [GExpr [g] e]
defaultAlt :: (Maybe VarName) -> Expr -> CaseAlt
defaultAlt b e = Default b e
equals :: Expr -> Expr -> Binding
equals (Var v) e = Binder (qName v) e
equals _ _ = error "equals: no can do - wasn't passed a Var, guv."
hLet :: Expr -> Expr -> Expr -> Expr
hLet v x y = Let [(equals v x)] y
hLets :: [(Expr,Expr)] -> Expr -> Expr
hLets bs e = Let (map (uncurry equals) bs) e
intLit :: Integral a => a -> Expr
intLit v = Lit (IntegerLit (ILit 10 (toInteger v)))
stringLit :: String -> Expr
stringLit v = Lit (StringLit v)
addPtr :: Expr -> Expr -> Expr
addPtr ptr off = funApp (mkQVarName hdirectLib "addNCastPtr") [ptr, off]
castPtr :: Expr -> Expr
castPtr ptr = funApp castPtrName [ptr]
nothing :: Expr
nothing = dataConst nothingName
just :: Expr -> Expr
just v = dataCon justName [v]
unit :: Expr
unit = tup []
prefix :: String -> TyCon -> VarName
prefix = prefixQName
prefixApp :: String -> TyCon -> VarName
prefixApp = prefixAppQName
appendStr :: String -> TyCon -> VarName
appendStr v tname = tname{qName=qName tname ++ v, qDefModule=Nothing}
isVarsEq :: Expr -> Expr -> Bool
isVarsEq (Var a) (Var b) = qName a == qName b
isVarsEq _ _ = error "isVarsEq"
\end{code}
Misc toplevel decls
\begin{code}
hModule :: Name -> Bool -> [HExport] -> [HImport] -> HDecl -> HTopDecl
hModule nm flg exps imps d = HMod (HModule nm flg exps imps d)
hMeta :: String -> HTopDecl
hMeta str = HLit str
cMeta :: String -> HTopDecl
cMeta str = CLit str
hInclude :: String -> HTopDecl
hInclude str = HInclude str
hExport :: HIEEntity -> Maybe String -> HExport
hExport ent comment_ = HExport ent comment_
hImport :: Name -> Bool -> [HIEEntity] -> HImport
hImport nm is_qualed ls =
HImport is_qualed Nothing nm $
case ls of
[] -> Nothing
_ -> Just ls
hQImport :: Name -> Maybe Name -> [HIEEntity] -> HImport
hQImport nm maybeAs stuff = HImport True maybeAs nm (Just stuff)
ieModule, ieValue, ieClass :: Name -> HIEEntity
ieModule nm = IEModule nm
ieValue nm = IEVal nm
ieClass nm = IEClass nm
ieType :: Name -> Bool -> HIEEntity
ieType nm abstractly = IEType nm abstractly
\end{code}
\begin{code}
subst :: Name -> Expr -> Expr -> Expr
subst nm e1 e2 = go e2
where
go e@(Var v)
| qName v == nm = e1
| otherwise = e
go e@(Con _) = e
go e@(Lit _) = e
go (Lam pats e) = Lam pats (go e)
go (Apply f args) = Apply (go f) (map go args)
go (RApply f x) = RApply (go f) (go x)
go (Tup es) = Tup (map go es)
go (BinOp op e_1 e_2) = BinOp op (go e_1) (go e_2)
go (UnOp op e) = UnOp op (go e)
go (Bind e_1 p e_2) = Bind (go e_1) p (go e_2)
go (Bind_ e_1 e_2) = Bind_ (go e_1) (go e_2)
go (List es) = List (map go es)
go (InfixOp op qnm e) = InfixOp op qnm (go e)
go (Return e) = Return (go e)
go (Case e alts) = Case (go e) (map substAlt alts)
go (If e_1 e_2 e_3) = If (go e_1) (go e_2) (go e_3)
go (Let binds e) = Let binds (go e)
go (WithTy e ty) = WithTy (go e) ty
substAlt (Alt p gs) = Alt p (map (\ (GExpr ls e) -> GExpr (map go ls) (go e)) gs)
substAlt (Default mb e) = Default mb (go e)
\end{code}
\begin{code}
mkQVarName :: Maybe String -> String -> VarName
mkQVarName qmod nm = mkQualName qmod nm
mkVarName :: String -> VarName
mkVarName nm = mkQualName Nothing nm
mkConName :: String -> ConName
mkConName nm = mkQualName Nothing nm
mkQConName :: Maybe String -> String -> ConName
mkQConName qmod nm = mkQualName qmod nm
mkTyVar :: String -> TyVar
mkTyVar nm = mkQualName Nothing nm
mkQTyVar :: Maybe String -> String -> TyVar
mkQTyVar qmod nm = mkQualName qmod nm
mkQTyCon :: Maybe String -> String -> TyCon
mkQTyCon qmod nm = mkQualName qmod nm
\end{code}
Generating a corresponding int type. Slightly awkward expressed, so
that we can easily retarget the mapping (and home) for the various
numeric types in AbsHUtils.
\begin{code}
type Signed = Bool
mkIntTy :: Size -> Signed -> Type
mkIntTy sz isSigned
| isSigned =
case sz of
Short -> tyInt16
Long -> tyInt32
Natural
| optIntIsInt -> tyInt
| otherwise -> tyInt32
LongLong
| optLongLongIsInteger -> tyInteger
| otherwise -> tyInt64
| otherwise =
case sz of
Short -> tyWord16
Long -> tyWord32
Natural
| optIntIsInt -> tyWord
| otherwise -> tyWord32
LongLong
| optLongLongIsInteger -> tyInteger
| otherwise -> tyWord64
\end{code}
Mapping for floats and chars
\begin{code}
mkFloatTy :: Size -> Type
mkFloatTy sz =
case sz of
Short -> tyFloat
Long -> tyDouble
LongLong -> tyLongDouble
Natural -> tyFloat
mkCharTy :: Signed -> Type
mkCharTy isSigned
| isSigned = tyInt8
| otherwise = tyChar
\end{code}
\begin{code}
findIncludes :: HDecl -> [String]
findIncludes d = whizz d []
where
whizz (AndDecl h1 h2) rs = whizz h1 (whizz h2 rs)
whizz (Include x) rs = x:rs
whizz _ rs = rs
\end{code}
\begin{code}
mkTySig :: [Type] -> Type -> String
mkTySig ps res = concat (intersperse "-" ls)
where
ls = map toSig (ps ++ [res])
toSig (TyCon tc) =
case qName tc of
'I':'n':'t':xs -> 'I':xs
'W':'o':'r':'d':xs -> 'W':xs
v -> v
toSig (TyVar _ tv) = qName tv
toSig (TyApply tc@TyCon{} ts) = concatMap toSig (tc:ts)
toSig _ = error "mkTySig: not supposed to happen"
\end{code}