module NHCBackend ( cNhc , hNhc --, genProcNHC ) where #if defined(__NHC__) || defined(__HBC__) import NonStdTrace #elif __GLASGOW_HASKELL__ >= 502 import Debug.Trace (trace) #else import IOExts (trace) #endif import Pretty import PrettyUtils (textline,vcatMap,vsepMap,vsep,commaList,ppList) import Decl (Decl(..), Sig, Call, CCode, Fail, Result) import DIS (DIS(..), expandDIS, DISEnv, simplify) import FillIn (fillinProc, Consts, genConsts) import Casm (BaseTy(..), baseTyToCall, baseTyToRtn, baseToCType) import Type (ppType, isPureType) import Maybe (fromMaybe) import Name import NameSupply cNhc, hNhc :: Bool -> DISEnv -> [String] -> Decl -> Doc cNhc dbg disEnv pre (Haskell _) = empty cNhc dbg disEnv pre (C c) = text c cNhc dbg disEnv pre (DisDef _ _ _) = empty cNhc dbg disEnv pre (Prefix _) = empty cNhc dbg disEnv pre (Include _) = error "%#include is obsolete." cNhc dbg disEnv pre (Constant ty ns) = --nyi "%const" vcat (map (cBit . fillinProc disEnv pre) (genConsts disEnv (ty,ns))) cNhc dbg disEnv pre (ProcSpec sig mbcall mbcode mbfail mbresult) = cBit $ fillinProc disEnv pre $ (sig, mbcall, mbcode, fromMaybe [] mbfail, mbresult) hNhc dbg disEnv pre (Haskell h) = text h hNhc dbg disEnv pre (C _) = empty hNhc dbg disEnv pre (DisDef _ _ _) = empty hNhc dbg disEnv pre (Prefix _) = empty hNhc dbg disEnv pre (Include _) = error "%#include is obsolete" hNhc dbg disEnv pre (Constant ty ns) = --nyi "%const" vcat (map (haskellBit dbg . fillinProc disEnv pre) (genConsts disEnv (ty,ns))) hNhc dbg disEnv pre (ProcSpec sig mbcall mbcode mbfail mbresult) = haskellBit dbg $ fillinProc disEnv pre $ (sig, mbcall, mbcode, fromMaybe [] mbfail, mbresult) cfn name = text "hs_" <> name --genProcNHC :: (Sig, Call, CCode, Fail, Result) -> (Doc, Doc, Doc) --genProcNHC arg = -- (haskellBit False arg, cBit arg, empty) haskellBit dbg ((name, typ), calls, code, fails, result) = let fnName = text name --arity = text (show (length argTypes)) primTypes = ppList (text " -> ") ( if isPureType typ then rtnType else text "IO" <+> rtnType) argTypes argDISs = map simplify calls rtnDIS = simplify result argTypes = concat $ fst $ initNS (mapM hargtypes argDISs) (nameSupply "a") (eqns,argPats) = fst $ initNS (hargpats argDISs) (nameSupply "tmp") argsCall = fst $ initNS (mapM hargcall argDISs) (nameSupply "arg") rtnType = fst $ initNS (hrtntype rtnDIS) (nameSupply "r") (bind,rtnCons) = fst $ initNS (hrtncon rtnDIS) (nameSupply "res") rtnPat = fst $ initNS (hrtnpat rtnDIS) (nameSupply "res") emit c x = if c then trace x else id in emit dbg ("*****ARGS:\n"++unlines (map show argDISs)) $ emit dbg ("*****RESULT:\n"++show rtnDIS++"\n") $ if clean rtnDIS && and (map clean argDISs) then text "foreign import ccall" <+> doubleQuotes (cfn fnName) <+> fnName <+> text "::" <+> primTypes else text "foreign import ccall" <+> cfn fnName <+> text "::" <+> primTypes $$ text "" $$ fnName <+> text "::" <+> ppType typ $$ fnName <+> hsep argPats <+> equals $$ nest 2 ( if isPureType typ then -- text "let" $$ -- nest 4 (vsep eqns $$ -- rtnPat <+> equals <+> cfn fnName <+> hsep argsCall) $$ -- text "in" <+> rtnCons vsep (map (<+> text "in") eqns) $$ text "let" <+> rtnPat <+> equals <+> cfn fnName <+> hsep argsCall <+> text "in" $$ rtnCons else -- ( if null eqns then text "do" -- else text "let" $$ -- nest 4 (vsep eqns) $$ -- text "in do" ) <+> text "do" <+> nest 4 ( vsep eqns $$ if clean rtnDIS then cfn fnName <+> hsep argsCall else rtnPat <+> text "<-" <+> cfn fnName <+> hsep argsCall $$ vsep bind $$ text "return" <+> rtnCons) ) $$ text "\n" cBit ((name, typ), calls, code, fails, result) = let argDecls = cdecls [] (map simplify calls) rtnDIS = simplify result rtnDecls = cdecls [] [rtnDIS] in text "" $$ ctype rtnDIS <+> cfn (text name) <+> parens (commaList argDecls) $$ cblock ( rtnDecls ++ [ vcatMap text code $$ if isVoid rtnDIS then text "return" else if simple rtnDIS then text "return" <+> fst (initNS (crtnpat rtnDIS) (nameSupply "res")) else text "return " <> crtn rtnDIS ] ) -------- hargtypes :: DIS -> NSM [Doc] hrtntype :: DIS -> NSM Doc hargpats :: [DIS] -> NSM ([Doc],[Doc]) hrtncon :: DIS -> NSM ([Doc],Doc) hargcall :: DIS -> NSM Doc hrtnpat :: DIS -> NSM Doc hargtypes (Apply (BaseDIS (Foreign _)) ds) = return $ [text "ForeignObj"] hargtypes (Apply (BaseDIS StablePtr) ds) = getNewName >>= \n-> return [text "StablePtr" <+> text n] hargtypes (Apply (BaseDIS Word) ds) = getNewName >>= \n-> return [text n] hargtypes (Apply (BaseDIS b) ds) = return $ [text (show b)] hargtypes (Apply d ds) = mapM hargtypes ds >>= return . concat hargtypes (BaseDIS b) = return $ [] hargtypes (Constructor c) = return $ [] hargtypes (Declare cty d) = return $ [] hargtypes (Exp e) = return $ [] hargtypes (Record n ns) = return $ [] hargtypes (Tuple) = return $ [text "()"] hargtypes (UserDIS _ f t) = return $ [] hargtypes (Var v) = return $ [] -- hrtntype (Apply (BaseDIS (Foreign _)) ds) = return $ text "ForeignObj" hrtntype (Apply (BaseDIS StablePtr) ds) = getNewName >>= return . (text "StablePtr" <+>) . text hrtntype (Apply (BaseDIS Word) ds) = getNewName >>= return . text hrtntype (Apply (BaseDIS b) ds) = return $ text (show b) hrtntype (Apply d [r]) = hrtntype r hrtntype (Apply d ds) = mapM hrtntype ds >>= return . parens . commaList hrtntype (BaseDIS b) = return $ empty hrtntype (Constructor c) = return $ empty hrtntype (Declare cty d) = return $ empty hrtntype (Exp e) = return $ empty hrtntype (Record n ns) = return $ empty hrtntype (Tuple) = return $ text "()" hrtntype (UserDIS _ f t) = return $ empty hrtntype (Var v) = return $ empty -- {- hargpat (Apply Tuple ds) = mapM hargpat ds >>= return . parens . commaList hargpat (Apply (Constructor c) ds) = mapM hargpat ds >>= \ps-> return $ parens (text c <+> hsep ps) hargpat (Apply (Record n ns) ds) = mapM hargpat ds >>= \ps-> return $ parens (text n <+> feqList ns ps) hargpat (Apply (UserDIS f t) ds) = mapM hargpat ds >>= return . hsep --hargpat (Apply (UserDIS f t) ds) = getNewName >>= return . text hargpat (Apply d ds) = mapM hargpat ds >>= return . hsep hargpat (BaseDIS b) = return $ empty hargpat (Constructor c) = return $ text c hargpat (Declare cty d) = hargpat d hargpat (Exp e) = getNewName >>= return . text hargpat (Record n ns) = return $ empty hargpat (Tuple) = return $ text "()" hargpat (UserDIS f t) = return $ empty hargpat (Var v) = return $ text v -} hargpats ds = mapM hargpat ds >>= \xs-> let (eqnss,pats) = unzip xs in return (concat eqnss, pats) hargpat (Apply (UserDIS True f t) ds) = getNewName >>= \n-> hargpats ds >>= \(eqns,pats)-> return ((text "let" <+> hsep pats <+> equals <+> text f <+> text n): eqns, text n) hargpat (Apply (UserDIS False f t) ds) = getNewName >>= \n-> hargpats ds >>= \(eqns,pats)-> return ((hsep pats <+> text "<-" <+> text f <+> text n): eqns, text n) hargpat (Apply Tuple ds) = hargpats ds >>= \(eqns,pats)-> return (eqns, parens (commaList pats)) hargpat (Apply (Constructor c) ds) = hargpats ds >>= \(eqns,pats)-> return (eqns, parens (text c <+> hsep pats)) hargpat (Apply (Record n ns) ds) = hargpats ds >>= \(eqns,pats)-> return (eqns, parens (text n <+> feqList ns pats)) hargpat (Apply d ds) = hargpats ds >>= \(eqns,pats)-> return (eqns, hsep pats) hargpat (BaseDIS b) = return $ ([],empty) hargpat (Constructor c) = return $ ([],text c) hargpat (Declare cty d) = hargpat d hargpat (Exp e) = getNewName >>= \n-> return ([],text n) hargpat (Record n ns) = return $ ([],empty) hargpat (Tuple) = return $ ([],text "()") hargpat (UserDIS _ f t) = return $ ([],empty) hargpat (Var v) = return $ ([],text v) -- hrtncons ds = mapM hrtncon ds >>= \xs-> let (eqnss,cs) = unzip xs in return (concat eqnss, cs) hrtncon (Apply Tuple ds) = hrtncons ds >>= \(eqns,cs)-> return $ (eqns, parens (commaList cs)) hrtncon (Apply (Constructor c) ds)= hrtncons ds >>= \(eqns,cs)-> return $ (eqns, parens (text c <+> hsep cs)) hrtncon (Apply (Record n ns) ds) = hrtncons ds >>= \(eqns,cs)-> return $ (eqns, parens (text n <+> feqList ns cs)) hrtncon (Apply (UserDIS True f t) ds)= hrtncons ds >>= \(eqns,cs)-> return $ (eqns, parens (text t <+> hsep cs)) hrtncon (Apply (UserDIS False f t) ds)= getNewName >>= \n-> hrtncons ds >>= \(eqns,cs)-> return $ ((text n <+> text "<-" <+> text t <+> hsep cs):eqns , text n) hrtncon (Apply d ds) = hrtncons ds >>= \(eqns,cs)-> return $ (eqns, hsep cs) hrtncon (BaseDIS b) = return $ ([], empty) hrtncon (Constructor c) = return $ ([], text c) hrtncon (Declare cty d) = hrtncon d hrtncon (Exp e) = getNewName >>= \n-> return ([], text n) hrtncon (Record n ns) = return $ ([], empty) hrtncon (Tuple) = getNewName >>= \n-> return ([], text n) -- return $ text "()" hrtncon (UserDIS _ f t) = return $ ([], empty) hrtncon (Var v) = return $ ([], text v) -- {-hargcall (Apply (Declare cty (Var v)) ds) = text v-} --hargcall (Apply (UserDIS f t) ds) = mapM hargcall ds >>= \as-> -- return $ parens (text f <+> hsep as) --hargcall (Apply (BaseDIS StablePtr) [d]) = hargcall d >>= return . parens . (text "StablePtr" <+>) hargcall (Apply d ds) = mapM hargcall ds >>= return . hsep hargcall (BaseDIS b) = return $ empty hargcall (Constructor c) = return $ empty hargcall (Declare cty d) = hargcall d hargcall (Exp e) = getNewName >>= return . text hargcall (Record n ns) = mapM (hargcall . Var) ns >>= return . hsep hargcall (Tuple) = return $ text "()" hargcall (UserDIS _ f t) = return $ empty hargcall (Var v) = return $ text v -- --hrtnpat (Apply (BaseDIS StablePtr) [r]) = hrtnpat r >>= return . parens . (text "StablePtr" <+>) hrtnpat (Apply d [r]) = hrtnpat r hrtnpat (Apply d ds) = mapM hrtnpat ds >>= return . parens . commaList hrtnpat (BaseDIS b) = return $ empty hrtnpat (Constructor c) = return $ empty hrtnpat (Declare cty d) = hrtnpat d hrtnpat (Exp e) = getNewName >>= return . text hrtnpat (Record n ns) = mapM (hrtnpat . Var) ns >>= return . parens . commaList hrtnpat (Tuple) = getNewName >>= return . text -- return $ text "()" hrtnpat (UserDIS _ f t) = return $ empty hrtnpat (Var v) = return $ text v -------- cdecls :: [String] -> [DIS] -> [Doc] --cdefs :: DIS -> [Doc] crtn :: DIS -> Doc cdecls env ((Apply d ds):rest) = cdecls env (d:ds++rest) cdecls env ((Declare cty (Var v)):ds) | v `notElem` env = (text cty <+> text v): cdecls (v:env) ds cdecls env (d:ds) = cdecls env ds cdecls env [] = [] ctype (Apply Tuple ds) = text "NodePtr" ctype (Apply (Var "iO") [d]) = ctype d ctype (Apply (UserDIS _ _ _) [d])= ctype d ctype (Apply (Constructor _) [d])= ctype d ctype (Apply d ds) = ctype d ctype (Declare cty (Var v)) = text cty ctype (Tuple) = text "void" ctype (BaseDIS b) = text (baseToCType b) ctype _ = text "NodePtr" -- --cdefs (Apply (BaseDIS b) [r]) = [collect b (baseToCType b) r] --cdefs (Apply d ds) = cdefs d ++ concatMap cdefs ds --cdefs d = [] -- --collect hty cty (Apply (Declare _ _) [r]) = collect hty cty r --collect hty cty (Declare cast d) = collect hty cast d --collect hty cty (Var v) = -- text v <+> equals <+> parens (text cty) <> text (baseTyToCall hty) --collect hty cty (Exp e) = -- text (pc e) <+> equals <+> parens (text cty) <> text (baseTyToCall hty) --collect hty cty d = error ("BaseDIS "++show hty++" applied to "++show d) pc :: String -> String pc = filter (/='%') -- crtn (Apply (BaseDIS b) [r]) = crtn' (baseTyToRtn b) r crtn (Apply d [r]) = crtn r crtn (Apply d ds) = let rs = map crtn ds n = length rs in text "nhc_mkTuple" <> text (show n) <> parens (commaList rs) crtn (Tuple) = text "nhc_mkUnit()" crtn d = empty crtn' wrap (Apply d [r]) = crtn' wrap r crtn' wrap (Declare cty d) = crtn' wrap d crtn' wrap (Exp e) = text (wrap (pc e)) crtn' wrap (Var v) = text (wrap v) crtn' wrap d = error ("BaseDIS applied to complex DIS: "++ wrap (show d)) crtnpat (Apply d [r]) = crtnpat r crtnpat (Declare cty d) = crtnpat d crtnpat (Exp e) = return $ text e crtnpat (Var v) = return $ text v -------- cblock :: [Doc] -> Doc cblock ds = text "{" $$ nest 2 (foldr (\a as-> a<>semi $$ as) empty ds) $$ text "}" $$ text "" feqList :: [Name] -> [Doc] -> Doc feqList ns pats = braces (commaList (zipWith feq ns pats)) where feq name pat = text name <> text "=" <> pat nyi s = error ("Not yet implemented: "++s) clean :: DIS -> Bool clean (Apply d ds) = clean d && and (map clean ds) --clean (BaseDIS StablePtr) = True -- previously False (until 1999-07-07) clean (BaseDIS StablePtr) = False -- back to False again! (1999-11-19) clean (BaseDIS b) = True clean (Constructor c) = False clean (Declare cty d) = True clean (Exp e) = True clean (Record n ns) = False clean (Tuple) = False -- previously True (until 2001-05-24) clean (UserDIS _ f t) = False clean (Var v) = True -- Following function is new and may not be correct yet. simple :: DIS -> Bool simple (Apply d [d']) = simple d && simple d' simple (Apply d ds) = False simple (BaseDIS StablePtr) = False simple (BaseDIS (Foreign _)) = False simple (BaseDIS b) = True simple (Constructor c) = True simple (Declare cty d) = simple d simple (Exp e) = True simple (Record n ns) = True simple (Tuple) = False simple (UserDIS _ f t) = True simple (Var v) = True isVoid :: DIS -> Bool isVoid (Apply (Var "iO") [Tuple]) = True isVoid (Tuple) = True isVoid _ = False --------