% % (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 ) -- This should be the default, but older versions (e.g., Jan 98) of -- Hugs insist on this one.. 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} {- Slightly magic in that it transforms "Foo.Bar a" into a type application. -} 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 (TyCon tc) args -- | qName tc == "Maybe" -> TyApply (TyCon tc) (map groundTyVars args) 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 lifts out embedded contexts and renames type variables so as to make them unique. -} 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" -- -- [Foo a, Foo b, Foo a] ==> [Foo a0, Foo b, Foo a0] -- {- I suspect this is no longer needed - leaving it out for now. relabelTypes :: [Type] -> [Type] relabelTypes ts = case (go supply [] ts) of (ts,_,_) -> ts where supply = map (\ x -> 'a':show x) [0..] go s acc [] = ([],s,acc) go supply@(s:ss) acc (x:xs) = case x of TyVar fixed v -> case lookup v acc of Nothing -> let (xs',s',acc') = go ss ((v,s):acc) xs in ((TyVar fixed (mkTyVar s)):xs',s',acc') Just tv -> let (xs',s',acc') = go supply acc xs in (TyVar fixed (mkTyVar tv) : xs',s',acc') TyApply t tvs -> let ([t'], supply', acc') = go supply acc [t] (tvs',supply'', acc'') = go supply' acc' tvs (xs', supply''', acc''') = go supply'' acc'' xs in (TyApply t' tvs' : xs', supply''', acc''') TyTuple ts -> let (ts', supply', acc') = go supply acc ts (xs', supply'', acc'') = go supply' acc' xs in (TyTuple ts' : xs', supply'', acc'') TyList ts -> let ([ts'], supply', acc') = go supply acc [ts] (xs', supply'', acc'') = go supply' acc' xs in (TyList ts' : xs', supply'', acc'') TyFun f a -> let ([f'], supply', acc') = go supply acc [f] ([a'], supply'', acc'') = go supply' acc' [a] (xs', supply''', acc''') = go supply'' acc'' xs in ((TyFun f' a') : xs', supply''', acc''') TyCtxt c t -> let ([t'], supply', acc') = go supply acc [t] in ([TyCtxt c t'], supply', acc') _ -> let (xs', ss , acc') = go supply acc xs in (x : xs', ss, acc') go _ _ _ = error "relabelTypes" -} 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 = libTyQConst addrLib hdirectLib "Addr" 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" -- best we can do at the mo'. \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 --unparameterised type synonym. tySyn :: Name -> [Name] -> Type -> HDecl tySyn dname tvs ty = TyD (TypeSyn dname tvs ty) -- (Foo T1 T2 T3) ==> (Foo a1 a2 a3) -- (Foo {f1::T1,f2::T2}) ==> (Foo f1 f2) 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) -- prelude/Type.lhs rip-off 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 -- hoists out the contexts before constructing the tysig. 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 -- right-assoc function application. 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{-a Var-} -> 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 [] --dataConst (mkConName "()") 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 -- don't worry about capture..yet. 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) -- weaken once debugged. toSig _ = error "mkTySig: not supposed to happen" \end{code}