packages feed

Hs2lib-0.4.8: WinDll/Structs/PrettyPrinting.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Windll
-- Copyright   :  (c) Tamar Christina 2009 - 2010
-- License     :  BSD3
-- 
-- Maintainer  :  tamar@zhox.com
-- Stability   :  experimental
-- Portability :  portable
--
-- Pretty printing function for the internal datastructures
--
-----------------------------------------------------------------------------

module WinDll.Structs.PrettyPrinting where

import WinDll.Structs.Structures
import WinDll.Structs.MShow.HaskellSrcExts
import WinDll.Structs.MShow.MShow
import WinDll.Lib.NativeMapping
import WinDll.Version ( verStr )

import Data.Foldable (foldl')
import Data.List(isPrefixOf,sort)

instance Show Export where
    showsPrec d (Export name exported types _) = 
        showString "foreign export stdcall " .
        showString (show exported)           .
        showString " "                       .
        showString name                      .
        showString " :: "                   .
        showString (mshow types)
          
        
instance Show Header where
    showsPrec d (Header name exports) =
        showString "-- | Autogenerated by WinDll, Do not change unless you know what you're doing \n" .
        showString "module "                .
        showString (name++"FFI")            .
        (if null exports 
            then id
            else (showString "(" .
                  showString 
                    (foldl1 (\a b->a++", "++b) exports) .
                  showString ")"))          .
        showString " where"
        
instance Show Function where
    showsPrec d (Function name argc types _ _) =
        showString name                      .
        showString " :: "                    .
        showString (mshow types)             .  
        showString "\n"                      .
        showString name                      .
        showString " "                       .
        showString (unwords args)            .
        showString " = toFFI $ "             .
        showString name                      .
        showString " "                       .
        showString (unwords $ map (\a->"(fromFFI "++a++")") args)
       where args = (zipWith ((. show) . (++)) (replicate argc "a") [1..])
       
instance Show DataType where
    showsPrec d (NewType name types body tag)  =
        printData True d name types [body]
    showsPrec d (DataType name types body tag) =
        printData False d name types body
    showsPrec d (Constr name types) = 
        showString name                     .
        showString " "                      .
        showString (mshow types)
        
-- | used above to abstract between dataypes and newtypes
printData nbe d name types body = 
        showString (if nbe then 
                    "newtype " else
                    "data ")                .
        showString name                     .
        showString " "                      .
        showString (unwords types)          .
        showString " = "                    .
        (mkBody body)                       .
        showString "\ntype "                .
        showString name                     .
        showString " "                      .
        showString (unwords types)          .
        (if null types 
           then showString " = Ptr "
           else showString " = Ptr (")      .
        showString name                     .
        (if null types then id
            else showString " "             .
                 showString (unwords types) .
                 showString ")")
       where indent = length name + 2 * (length types) + 7
             space  = replicate indent ' '
             mkConst a = showString "\n"    .
                         showString space   . 
                         showString "| "    .
                         showsPrec d a
             mkBody []     = id
             mkBody (x:xs) = showString "" . showsPrec d x . (foldl' (.) id (map mkConst xs))
        
instance Show Module where
    showsPrec d (Module header path imports exports datatypes functions _ _) =
        showsPrec d header                                      .
        showString "\n\n-- @@Generated from \""                 .
        showString path                                         .
        showString ("\" by WinDll version " ++ verStr ++ " \n") .
        showString (unlines $ map mkImport (sort imports))      .
        showString "\n"                                         .
        showString (mkPrec exports "")                          .
        showString "\n"                                         .
        --showString (mkPrec datatypes "\n")                    .
        --showString "\n"                                       .
        showString (mkPrec functions "\n")        
      where mkImport p = "import " ++ p
            mkPrec p0 v  = (unlines (map (\a->(showsPrec d a) v) p0))
        
-- | FFI Types need to be strict, This converts the type if needed
mkStrict :: TypeName -> TypeName
mkStrict a = if "!" `isPrefixOf` a then a else "!"++a
    
-- | Look up and convert the list of types back to a function signature to be printed. 
-- Admittedly this only supports simple functions, but these are enough for now (I don't know how FFI deals with functions as arguments)
showTypes :: String -> [TypeName] -> String
showTypes _ []     = []
showTypes f types  = foldl1 (\a b->a++f++b) types

-- | Generate the export list from the given module.
generateExportList :: Module -> String
generateExportList (Module _ _ _ export _ _ _ _) = showString "EXPORTS\n" (unlines list)
  where gmap f []                = []
        gmap f ((Export n _ _ _):xs) = f n:gmap f xs
        nums = [1..(length export)]
        list = (zipWith ($) (gmap (\a b->"\t"++a++"\t@"++show b) export) nums)