HsWebots-0.1.0.0: app/Main.hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import System.IO
import System.Environment
import Data.Generics
import Data.List
import Language.C
import Language.C.System.GCC
import Language.C.Data
import Language.C.Data.Ident
import Text.PrettyPrint
import Control.Monad
import Text.Shakespeare.Text
import qualified Data.Text.IO as T
whenM cond exp = if cond then exp else pure ()
main = do
(filename:[]) <- getArgs
parseMyFile filename >>= \i -> do
case i of
CTranslUnit v a -> do
forM_ v $ \i -> do
printFunc filename i
parseMyFile :: FilePath -> IO CTranslUnit
parseMyFile input_file =
do parse_result <- parseCFile (newGCC "gcc") Nothing ["-Ideps/webots/include"] input_file
case parse_result of
Left parse_err -> error (show parse_err)
Right ast -> return ast
class CIdent a where
toIdent :: a -> String
instance CIdent Ident where
toIdent a = identToString a
instance CIdent (CStorageSpecifier NodeInfo) where
toIdent a = render $ pretty a
instance CIdent (CTypeSpecifier NodeInfo) where
toIdent a = render $ pretty a
instance CIdent (CTypeQualifier NodeInfo) where
toIdent a = render $ pretty a
instance CIdent (CFunctionSpecifier NodeInfo) where
toIdent a = render $ pretty a
instance CIdent (CAlignmentSpecifier NodeInfo) where
toIdent a = render $ pretty a
instance CIdent (CDeclarationSpecifier NodeInfo) where
toIdent a = render $ pretty a
instance CIdent (CDeclaration NodeInfo) where
toIdent (CDecl [CStorageSpec a] _ _) = toIdent a
toIdent (CDecl [CTypeSpec a] _ _) = toIdent a
toIdent (CDecl [CTypeQual a] _ _) = toIdent a
toIdent (CDecl [CFunSpec a] _ _) = toIdent a
toIdent (CDecl [CAlignSpec a] _ _) = toIdent a
toIdent (CDecl a _ _) = intercalate "," $ map toIdent a
toIdent a = "not-parsed"
csnd (CDecl [CStorageSpec a] b _) = b
csnd (CDecl [CTypeSpec a] b _) = b
csnd (CDecl [CTypeQual a] b _) = b
csnd (CDecl [CFunSpec a] b _) = b
csnd (CDecl [CAlignSpec a] b _) = b
csnd (CDecl a b _) = b
csnd a = undefined
getArgIds [] = []
getArgIds ((Just (CDeclr
(Just arg)
_
_
_
_
)):xs) = toIdent arg : getArgIds xs
getArgIds (_:xs) = "xxx" : getArgIds xs
printFunc :: FilePath -> CExternalDeclaration NodeInfo -> IO ()
printFunc path (CDeclExt (CDecl
rets
[(Just (CDeclr
(Just func_name)
(CFunDeclr (Right (args,_)) _ _:_)
_
_
_
)
,_
,_)]
(NodeInfo pos _ _)
)
) = whenM (path == posFile pos) $ do
T.putStr [st|
#{toIdent func_name} :: #{argsH}IO #{retH}
#{toIdent func_name} #{argIds} =
#{bra} #{retC} { #{toIdent func_name}(#{argsC}) } #{ket}
|]
where
bra = "[C.exp|"
ket = "|]"
retH = case map toIdent rets of
["void"] -> "()"
["char"] -> "CBool"
["int"] -> "CInt"
["double"] -> "CDouble"
["const","char"] -> "String"
["const","double"] -> "Ptr CDouble"
[a] -> a
_ -> "UnKnown"
retC = case map toIdent rets of
["void"] -> "void"
["char"] -> "bool"
["int"] -> "int"
["double"] -> "double"
["const","char"] -> "const char*"
["const","double"] -> "const double*"
[a] -> a
argH arg = case arg of
"void" -> "()"
"char" -> "CBool"
"int" -> "CInt"
"double" -> "CDouble"
"const,char" -> "String"
"const,double" -> "Ptr CDouble"
a -> a
_ -> "UnKnown"
argsH =
case map (\(i :: CDeclaration NodeInfo) -> argH (toIdent i)) args of
[] -> ""
a -> (intercalate " -> " a) ++ " -> "
argC arg = case arg of
"void" -> "void"
"char" -> "bool"
"int" -> "int"
"double" -> "double"
"const,char" -> "const char*"
"const,double" -> "const double*"
a -> a
args' = getArgIds (map (\(a,b,c) -> a) $ concat $ map (\a -> csnd a) args)
argsC =
case (map (\(i :: CDeclaration NodeInfo) -> argC (toIdent i)) args,args') of
([],_) -> ""
(_,[]) -> ""
(a,b) -> intercalate ", " $ map (\(aa,bb) -> "$("++ aa ++ " " ++ bb ++")" ) $ zip a b
argIds = intercalate " " args'
printFunc path (CDeclExt a@(CDecl ret body (NodeInfo pos _ _))) = return ()
-- whenM (path == posFile pos) $ print a
printFunc path (CDeclExt a@(CStaticAssert exp lit _)) = return ()
printFunc path (CFDefExt a) = return ()
printFunc path (CAsmExt a _) = return ()