wxcore-0.10.2: wxdirect/src/CompileHeader.hs
-----------------------------------------------------------------------------------------
{-| Module : CompileHeader
Copyright : (c) Daan Leijen 2003
License : BSD-style
Maintainer : daan@cs.uu.nl
Stability : provisional
Portability : portable
Module that compiles typed C definitions from untyped ones.
-}
-----------------------------------------------------------------------------------------
module CompileHeader( compileHeader ) where
import qualified Set
import qualified Map
import qualified MultiSet
import Data.Time( getCurrentTime)
import Data.Char( toUpper, isUpper )
import Data.List( isPrefixOf, sort, sortBy, intersperse, zipWith4 )
import Types
import HaskellNames
import Classes( isClassName, classNames, classExtends )
import ParseC( parseC )
import DeriveTypes( deriveTypesAll, classifyName, Name(..), Method(..), ClassName, MethodName, PropertyName )
{-----------------------------------------------------------------------------------------
Compile
-----------------------------------------------------------------------------------------}
compileHeader :: Bool -> FilePath -> [FilePath] -> IO ()
compileHeader showIgnore outputFile inputFiles
= do declss <- mapM parseC inputFiles
time <- getCurrentTime
let decls = deriveTypesAll showIgnore (sortBy cmpDecl (concat declss))
typeDecls = cTypeDecls decls
methodCount = length decls
let output = unlines (["#ifndef WXC_GLUE_H"
,"#define WXC_GLUE_H"]
++ typeDecls ++
[""
,"#endif /* WXC_GLUE_H */"
,""]
)
putStrLn ("generating: " ++ outputFile)
writeFile outputFile output
putStrLn ("generated " ++ show methodCount ++ " declarations.")
putStrLn ("ok.\n")
cmpDecl decl1 decl2
= compare (haskellDeclName (declName decl1)) (haskellDeclName (declName decl2))
exportComma = exportSpaces ++ ","
exportSpaces = " "
{-----------------------------------------------------------------------------------------
Translate declarations to a c type declarations
-----------------------------------------------------------------------------------------}
cTypeDecls :: [Decl] -> [String]
cTypeDecls decls
= let classMap = Map.fromList (map (\name -> (name,[])) (Set.elems classNames ++ ["Events","Null","Misc."]))
methodMap = Map.map (map snd) (Map.map sort (Map.fromListWith (++) (map typeDef decls)))
tdeclMap = Map.mapWithKey (addMethods methodMap) classMap
eventEntry = case Map.lookup "Events" tdeclMap of
Just entry -> [("Events",entry)]
Nothing -> []
miscEntry = case Map.lookup "Misc." tdeclMap of
Just entry -> [("Misc.",entry)]
Nothing -> []
nullEntry = case Map.lookup "Null" tdeclMap of
Just entry -> [("Null",entry)]
Nothing -> []
in (concatMap toDecls (nullEntry ++ eventEntry ++ miscEntry)
++
concatMap toDecls (Map.toAscList (Map.delete "Null" (Map.delete "Misc." (Map.delete "Events" tdeclMap))))
)
where
addMethods methodMap className classDecls
= heading className ++
(case Map.lookup className classExtends of
Nothing -> []
Just "" -> ["TClassDef(" ++ className ++ ")"]
Just ext -> ["TClassDefExtend(" ++ className ++ "," ++ ext ++ ")"]
)
++ classDecls ++
(case Map.lookup className methodMap of
Nothing -> []
Just decls -> decls)
toDecls (classname,decls)
= decls
typeDef decl
= (case classifyName (declName decl) of
Name name | isPrefixOf "expEVT_" name -> "Events"
| isPrefixOf "Null_" name -> "Null"
| otherwise -> "Misc."
Create name -> name
Method name _ -> name
, [(declName decl, cTypeDecl decl)])
heading msg
= ["","/* " ++ msg ++ " */"]
{-----------------------------------------------------------------------------------------
Translate a declaration to a c type declaration
-----------------------------------------------------------------------------------------}
-- | Generate a full c type declaration
cTypeDecl :: Decl -> String
cTypeDecl decl
= cTypeSignature decl
-- | Generate a haskell type signature
cTypeSignature :: Decl -> String
cTypeSignature decl
= fill 10 (cRetType decl (declRet decl)) ++
" _stdcall " ++ declName decl ++
"( " ++ concat (intersperse ", " (cTypeArgs decl (declArgs decl) ++ cOutArg (declRet decl))) ++ " );"
fill n s
| length s >= n = s
| otherwise = s ++ replicate (n - length s) ' '
cTypeArgs decl []
= []
cTypeArgs decl (arg:args)
= cTypeArg decl className arg : map (cTypeArg decl "") args
where
className = case classifyName (declName decl) of
Method cname m -> cname
otherwise -> ""
cRetType decl tp
= case tp of
-- out
String _ -> "TStringLen"
ArrayString _ -> "TArrayLen"
ArrayObject _ _ -> "TArrayLen"
Vector _ -> "void"
Point _ -> "void"
Size _ -> "void"
Rect _ -> "void"
RefObject name -> "void"
-- typedefs
EventId -> "int"
-- basic
Bool -> "TBool"
Char -> "TChar"
Int CLong -> "long"
Int TimeT -> "time_t"
Int SizeT -> "size_t"
Int other -> "int"
Void -> "void"
Double -> "double"
Float -> "float"
Ptr Void -> "void*"
Ptr t -> cRetType decl t ++ "*"
Object name -> "TClass(" ++ name ++ ")"
other -> traceError ("unknown return type (" ++ show tp ++ ")") decl $
"void"
cOutArg tp
= case tp of
Vector ctp -> ["TVectorOut" ++ ctypeSpec CInt ctp ++ "(_vx,_vy)"]
Point ctp -> ["TPointOut" ++ ctypeSpec CInt ctp ++ "(_x,_y)"]
Size ctp -> ["TSizeOut" ++ ctypeSpec CInt ctp ++ "(_w,_h)"]
String ctp -> ["TStringOut" ++ ctypeSpec CChar ctp ++ " _buf"]
Rect ctp -> ["TRectOut" ++ ctypeSpec CInt ctp ++ "(_x,_y,_w,_h)" ]
RefObject name -> ["TClassRef(" ++ name ++ ") _ref"]
ArrayString ctp -> ["TArrayString" ++ ctypeSpec CChar ctp ++ " _strs"]
ArrayObject name ctp -> ["TArrayObject" ++ ctypeSpec CObject ctp ++ "(" ++ name ++ ") _objs"]
other -> []
-- type def. for clarity
cTypeArg decl className arg
= case argType arg of
-- basic
Bool -> "TBool " ++ argName arg
Char -> "TChar " ++ argName arg
Int CLong -> "long " ++ argName arg
Int TimeT -> "time_t " ++ argName arg
Int SizeT -> "size_t " ++ argName arg
Int other -> "int " ++ argName arg
Void -> "void " ++ argName arg
Double -> "double " ++ argName arg
Float -> "float " ++ argName arg
Ptr Void -> "void* " ++ argName arg
Ptr t -> cRetType decl t ++ "* " ++ argName arg
-- typedefs
EventId -> "int"
-- special
Vector ctp -> "TVector" ++ ctypeSpec CInt ctp ++ argNameTuple
Point ctp -> "TPoint" ++ ctypeSpec CInt ctp ++ argNameTuple
Size ctp -> "TSize" ++ ctypeSpec CInt ctp ++ argNameTuple
String ctp -> "TString" ++ ctypeSpec CChar ctp ++ " " ++ argName arg
Rect ctp -> "TRect" ++ ctypeSpec CInt ctp ++ argNameTuple
Fun f -> "TClosureFun " ++ argName arg
ArrayString ctp -> "TArrayString" ++ ctypeSpec CChar ctp ++ " " ++ argName arg
ArrayObject name ctp -> "TArrayObject" ++ ctypeSpec CObject ctp ++ "(" ++ name ++ ") " ++ argName arg
RefObject name -> "TClassRef(" ++ name ++ ") " ++ argName arg
Object name | className == name -> "TSelf(" ++ name ++ ") " ++ argName arg
| otherwise -> "TClass(" ++ name ++ ") " ++ argName arg
-- temporary types (can this ever happen?)
StringLen -> "TStringLen " ++ argName arg
StringOut ctp -> "TStringOut" ++ ctypeSpec CChar ctp ++ " " ++ argName arg
ArrayLen -> "TArrayLen " ++ argName arg
ArrayStringOut ctp -> "TArrayStringOut" ++ ctypeSpec CChar ctp ++ " " ++ argName arg
ArrayObjectOut name ctp -> "TArrayObjectOut" ++ ctypeSpec CObject ctp ++ "(" ++ name ++ ") " ++ argName arg
PointOut ctp -> "TPointOut" ++ ctypeSpec CInt ctp ++ argNameTuple
SizeOut ctp -> "TSizeOut" ++ ctypeSpec CInt ctp ++ argNameTuple
VectorOut ctp -> "TVectorOut" ++ ctypeSpec CInt ctp ++ argNameTuple
RectOut ctp -> "TRectOut" ++ ctypeSpec CInt ctp ++ argNameTuple
{-
other -> traceError ("unknown argument type (" ++ show (argType arg) ++ ")") decl $
"ctypeSpec"
-}
where
argNameTuple
= "(" ++ concat (intersperse "," (argNames arg)) ++ ")"
ctypeSpec deftp ctp
| deftp==ctp = ""
| otherwise = case ctp of
CInt -> "Int"
CLong -> "Long"
CChar -> "Char"
CVoid -> "Void"
other -> ""