summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-11-19 21:53:11 -0500
committerJoe Crayne <joe@jerkface.net>2018-11-19 21:53:11 -0500
commitd7897ff1c2ac599a133b09bc48134a7f74af3d03 (patch)
treea7ea6d476c57263142de71cae925398dc326468f
parentd52b9beb1c8735b0915a0fa6a9e27ccd33478532 (diff)
Compilable output.
-rw-r--r--c2haskell.hs180
1 files changed, 153 insertions, 27 deletions
diff --git a/c2haskell.hs b/c2haskell.hs
index d3075e4..2fbbfc2 100644
--- a/c2haskell.hs
+++ b/c2haskell.hs
@@ -20,6 +20,7 @@ import qualified Data.Set as Set
20import Language.C.Data.Ident as C 20import Language.C.Data.Ident as C
21import Language.C as C hiding (prettyUsingInclude) 21import Language.C as C hiding (prettyUsingInclude)
22import Language.C.System.GCC 22import Language.C.System.GCC
23import Language.Haskell.Exts.Parser as HS
23import Language.Haskell.Exts.Pretty as HS 24import Language.Haskell.Exts.Pretty as HS
24import Language.Haskell.Exts.Syntax as HS 25import Language.Haskell.Exts.Syntax as HS
25import Language.Haskell.TH 26import Language.Haskell.TH
@@ -63,6 +64,7 @@ specs _ = []
63declrSym :: CDeclarator t -> Maybe Ident 64declrSym :: CDeclarator t -> Maybe Ident
64declrSym (CDeclr m _ _ _ _) = m 65declrSym (CDeclr m _ _ _ _) = m
65 66
67-- Used by update to add a symbols to the database.
66sym :: CExternalDeclaration a -> [Maybe Ident] 68sym :: CExternalDeclaration a -> [Maybe Ident]
67sym (CFDefExt (CFunDef specs m _ _ _)) = [ declrSym m ] 69sym (CFDefExt (CFunDef specs m _ _ _)) = [ declrSym m ]
68sym (CDeclExt (CDecl specs ms _)) = ms >>= \(m,_,_) -> maybe [] (pure . declrSym) m 70sym (CDeclExt (CDecl specs ms _)) = ms >>= \(m,_,_) -> maybe [] (pure . declrSym) m
@@ -152,7 +154,9 @@ grokSymbol d k msi =
152 , symbolSource = d : symbolSource si 154 , symbolSource = d : symbolSource si
153 } 155 }
154 156
155-- update :: CExternalDeclaration a -> Transpile -> Transpile 157update :: CExternalDeclaration NodeInfo
158 -> Transpile [CExternalDeclaration NodeInfo]
159 -> Transpile [CExternalDeclaration NodeInfo]
156update d transpile = transpile 160update d transpile = transpile
157 { syms = foldr (\k m -> Map.alter (grokSymbol d k) k m) (syms transpile) 161 { syms = foldr (\k m -> Map.alter (grokSymbol d k) k m) (syms transpile)
158 $ map (maybe "" identToString) $ sym d 162 $ map (maybe "" identToString) $ sym d
@@ -168,23 +172,40 @@ hsMkName str = HS.UnQual () (foo () str)
168 where 172 where
169 foo = HS.Ident -- alternative: HS.Symbol 173 foo = HS.Ident -- alternative: HS.Symbol
170 174
171hsTypeSpec :: CDeclarationSpecifier t -> [String] 175
172hsTypeSpec (CTypeSpec (CTypeDef (C.Ident "uint8_t" _ _) _)) = ["Word8"] 176notKnown "Word8" = False
173hsTypeSpec (CTypeSpec (CTypeDef (C.Ident "uint16_t" _ _) _)) = ["Word16"] 177notKnown "Word16" = False
174hsTypeSpec (CTypeSpec (CTypeDef (C.Ident "uint32_t" _ _) _)) = ["Word32"] 178notKnown "Word32" = False
175hsTypeSpec (CTypeSpec (CTypeDef ctyp _)) = [capitalize . identToString $ ctyp] 179notKnown "Bool" = False
176hsTypeSpec (CTypeSpec (CBoolType _)) = ["Bool"] 180notKnown "Int" = False
177hsTypeSpec (CTypeSpec (CIntType _)) = ["Int"] 181notKnown "Char" = False
178hsTypeSpec (CTypeSpec (CCharType _)) = ["Char"] 182notKnown "()" = False
179hsTypeSpec (CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)) = maybeToList $ fmap (capitalize . identToString) mctyp 183notKnown _ = True
180hsTypeSpec (CTypeSpec unhandled) = trace ("hsTypeSpec unhandled: "++ show (const () <$> unhandled)) 184
181 $ [] 185hsTypeSpec :: CDeclarationSpecifier t -> [Either Ident String]
182hsTypeSpec _ = [] 186hsTypeSpec (CTypeSpec (CVoidType _)) = [ Right "()" ]
187hsTypeSpec (CTypeSpec (CTypeDef (C.Ident "uint8_t" _ _) _)) = [ Right "Word8"]
188hsTypeSpec (CTypeSpec (CTypeDef (C.Ident "uint16_t" _ _) _)) = [ Right "Word16"]
189hsTypeSpec (CTypeSpec (CTypeDef (C.Ident "uint32_t" _ _) _)) = [ Right "Word32"]
190hsTypeSpec (CTypeSpec (CTypeDef ctyp _)) = [ Left ctyp ]
191hsTypeSpec (CTypeSpec (CBoolType _)) = [ Right "Bool"]
192hsTypeSpec (CTypeSpec (CIntType _)) = [ Right "Int"]
193hsTypeSpec (CTypeSpec (CCharType _)) = [ Right "Char"]
194hsTypeSpec (CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)) = maybeToList $ fmap Left mctyp
195
196hsTypeSpec (CTypeSpec unhandled) = trace ("hsTypeSpec unhandled: "++ show (const () <$> unhandled)) $ []
197hsTypeSpec _ = []
198
183 199
184-- hsTransField :: [CDeclarationSpecifier t3] -> [(Maybe (CDeclarator t2), Maybe t1, Maybe t)] -> [HS.Decl ()] 200-- hsTransField :: [CDeclarationSpecifier t3] -> [(Maybe (CDeclarator t2), Maybe t1, Maybe t)] -> [HS.Decl ()]
201-- recursive for function signatures.
202hsTransField :: Show b =>
203 [CDeclarationSpecifier b] -- c structure name
204 -> [(Maybe (CDeclarator b), Maybe (CInitializer b), Maybe (CExpression b))] -- c variable declarations
205 -> [(String{-field name-}, HS.Type () {- haskell type -}) ]
185hsTransField ctyps vars 206hsTransField ctyps vars
186 = do 207 = do
187 typname <- hsMkName <$> (hsTypeSpec =<< ctyps) 208 typname <- hsMkName . either (capitalize . identToString) id <$> (hsTypeSpec =<< ctyps)
188 trace ("typname="++show typname) $ return () 209 trace ("typname="++show typname) $ return ()
189 (var,Nothing,Nothing) <- vars 210 (var,Nothing,Nothing) <- vars
190 trace ("var="++show var) $ return () 211 trace ("var="++show var) $ return ()
@@ -195,8 +216,12 @@ hsTransField ctyps vars
195 grok bs b = case bs of 216 grok bs b = case bs of
196 [] -> b 217 [] -> b
197 (CPtrDeclr [] _:cs) -> HS.TyApp () (HS.TyCon () (hsMkName "Ptr")) (grok cs b) 218 (CPtrDeclr [] _:cs) -> HS.TyApp () (HS.TyCon () (hsMkName "Ptr")) (grok cs b)
198 [CFunDeclr (Right (args,flg)) attrs _] -> let (as,ts) = unzip $ concatMap (\(CDecl rs as _) -> hsTransField rs as) args 219 CFunDeclr (Right (args,flg)) attrs _:p ->
199 in foldr (HS.TyFun ()) b ts 220 let (as,ts) = unzip $ concatMap (\(CDecl rs as _) -> hsTransField rs as) args
221 b0 = case p of
222 CPtrDeclr [] _:cs -> HS.TyApp () (HS.TyCon () (hsMkName "Ptr")) (grok cs b)
223 [] -> b
224 in foldr (HS.TyFun ()) b0 ts
200 _ -> HS.TyCon () (hsMkName $ show $ map (fmap (const ())) ptrdeclr) 225 _ -> HS.TyCon () (hsMkName $ show $ map (fmap (const ())) ptrdeclr)
201 ftyp = grok ptrdeclr btyp 226 ftyp = grok ptrdeclr btyp
202 fieldName = identToString fident 227 fieldName = identToString fident
@@ -215,11 +240,44 @@ transField (CDecl [CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)
215hsTransField _ _ = [] 240hsTransField _ _ = []
216-} 241-}
217 242
243extractType (HS.TypeDecl _ _ ftyp) = ftyp
244extractType (HS.TypeSig _ _ ftyp) = ftyp
245extractType _ = TyCon () (Special () (UnitCon ()))
246
247hsTransFieldExt :: Show b =>
248 [CDeclarationSpecifier b]
249 -> [(Maybe (CDeclarator b), Maybe (CInitializer b),
250 Maybe (CExpression b))]
251 -> [Decl ()]
218hsTransFieldExt rs as = concatMap (\(fieldName,ftyp)-> [ HS.TypeSig () [ HS.Ident () fieldName ] ftyp ]) 252hsTransFieldExt rs as = concatMap (\(fieldName,ftyp)-> [ HS.TypeSig () [ HS.Ident () fieldName ] ftyp ])
219 $ hsTransField rs as 253 $ hsTransField rs as
220 254
221sig (CDeclExt (CDecl rs as _)) = hsTransFieldExt rs as 255hsTransSig rs as = concatMap (\(fieldName,ftyp)-> [ HS.TypeDecl () (DHead () (HS.Ident () ("Sig_" ++ fieldName))) ftyp ])
222sig (CFDefExt (CFunDef rs cdeclr [] bdy _)) = hsTransFieldExt rs [(Just cdeclr, Nothing, Nothing)] 256 $ hsTransField rs as
257
258types (HS.TypeDecl _ _ typ) = primtypes typ
259
260primtypes (HS.TyFun _ a b) = primtypes a ++ primtypes b
261primtypes t = [t]
262
263tname (HS.TyCon () (HS.UnQual () (HS.Ident () str))) = str
264tname _ = "_unkonwn"
265
266getPtrType (HS.TyApp _ (HS.TyCon _ (HS.UnQual _ (HS.Ident _ "Ptr"))) x) = Just x
267getPtrType _ = Nothing
268
269-- pointers :: [HS.Decl ()] -> [String]
270pointers :: [HS.Type l] -> [HS.Type l]
271pointers decls = do
272 d <- decls
273 maybeToList $ getPtrType d
274
275
276sig :: Show t => CExternalDeclaration t -> [HS.Decl ()]
277sig = sigf hsTransFieldExt
278
279sigf f (CDeclExt (CDecl rs as _)) = f rs as
280sigf f (CFDefExt (CFunDef rs cdeclr [] bdy _)) = f rs [(Just cdeclr, Nothing, Nothing)]
223 281
224body0 (CFDefExt (CFunDef rs cdeclr [] bdy _)) = Just bdy 282body0 (CFDefExt (CFunDef rs cdeclr [] bdy _)) = Just bdy
225body0 _ = Nothing 283body0 _ = Nothing
@@ -278,17 +336,52 @@ parseOptions ("-v":args) opts = parseOptions args opts
278 { verbose = True 336 { verbose = True
279 } 337 }
280 338
339getsig (k,si) = do
340 d <- take 1 $ symbolSource si
341 let ts = filter notKnown $ map tname $ pointers $ concatMap types $ sigf hsTransSig d
342 s = sig d
343 [(ts,(k,s))]
344
345isAcceptableImport (HS.TyFun _ (TyCon _ (UnQual _ (HS.Ident _ x))) xs) | not (notKnown x) = isAcceptableImport xs
346isAcceptableImport (HS.TyFun _ (TyApp _ (TyCon _ (UnQual _ (HS.Ident _ "Ptr"))) x) xs) = isAcceptableImport xs
347isAcceptableImport (HS.TyFun _ (TyApp _ (TyCon _ (UnQual _ (HS.Ident _ "Ptr"))) x) xs) = isAcceptableImport xs
348isAcceptableImport (TyCon _ _) = True
349isAcceptableImport (TyApp _ _ _) = True
350isAcceptableImport _ = False
351
281c2haskell opts cs (CTranslUnit edecls _) = do 352c2haskell opts cs (CTranslUnit edecls _) = do
282 let db = foldr update initTranspile edecls 353 let db = foldr update initTranspile edecls
283 es = Map.filter (\d -> symbolLocal d && not (symbolStatic d)) (syms db) 354 es = Map.filter (\d -> symbolLocal d && not (symbolStatic d)) (syms db)
284 case selectFunction opts of 355 case selectFunction opts of
285 Nothing -> forM_ (Map.toList es) $ \(k,si) -> do 356 Nothing -> do
286 putStrLn "" 357 putStrLn $ "module T where"
287 putStrLn (commented k) 358 putStrLn $ "import Foreign.Ptr"
288 forM_ (symbolSource si) $ \d -> do 359 putStrLn $ "import Data.Word"
289 putStr $ commented (ppShow (fmap (const ()) d)) 360 let sigs = concatMap getsig (Map.toList es)
290 putStr $ commented (show $ pretty d) 361 ts = foldr (\t -> Map.insert t ()) Map.empty $ concatMap fst sigs
291 mapM_ (putStrLn . HS.prettyPrint) (sig d) 362 forM_ (Map.keys ts) $ \t -> do
363 putStrLn $ "data " ++ t
364 forM_ sigs $ \(_,(k,hs)) -> do
365 forM_ hs $ \hdecl -> do
366 {-
367 putStr (commented k)
368 putStr $ commented $ show $ length $ symbolSource si
369 forM_ (take 1 $ symbolSource si) $ \d -> do
370 let ts = filter notKnown $ map tname $ pointers $ concatMap types $ sigf hsTransSig d
371 -- putStr $ commented (ppShow (fmap (const ()) d))
372 -- putStr $ commented (show $ pretty d)
373 let typ = (TyCon () (Special () (UnitCon ())))
374 -- when (null $ sig d) $ putStr $ commented (ppShow (fmap (const ()) d))
375 forM_ (sig d) $ \hs -> case hs of
376 htyp -> -- putStr $ commented $ "Unsupported haskell type: " ++ HS.prettyPrint htyp
377 -}
378 let htyp = extractType hdecl
379 putStrLn $ (if isAcceptableImport htyp then id else commented)
380 $ HS.prettyPrint $ (HS.ForImp () (HS.CCall ()) Nothing (Just k)
381 (HS.Ident () k)
382 htyp)
383
384 -- mapM_ (putStrLn . HS.prettyPrint) (sig d)
292 {- 385 {-
293 forM_ (body d) $ \stmt -> do 386 forM_ (body d) $ \stmt -> do
294 putStr $ commented (take 130 $ show (fmap (const ()) stmt)) 387 putStr $ commented (take 130 $ show (fmap (const ()) stmt))
@@ -304,8 +397,39 @@ c2haskell opts cs (CTranslUnit edecls _) = do
304 forM_ (symbolSource $ syms db Map.! cfun) $ \d -> do 397 forM_ (symbolSource $ syms db Map.! cfun) $ \d -> do
305 -- putStr $ commented (ppShow (fmap (const ()) d)) 398 -- putStr $ commented (ppShow (fmap (const ()) d))
306 -- putStr $ commented (show $ pretty d) 399 -- putStr $ commented (show $ pretty d)
307 when (verbose opts) $ print (sig d) 400 -- when (verbose opts) $ print (sig d)
308 mapM_ (putStrLn . HS.prettyPrint) (sig d) 401 let ts = filter notKnown $ map tname $ pointers $ concatMap types $ sigf hsTransSig d
402 forM_ ts $ \t -> do
403 putStrLn $ "data " ++ t
404 forM_ (sigf hsTransSig d) $ \hs -> do
405 putStrLn . HS.prettyPrint $ hs
406 case hs of
407 HS.TypeDecl _ (DHead _ (HS.Ident _ signame)) ftyp -> do
408 let wrapname = "wrap" ++ drop 3 signame
409 settername = "setf" ++ drop 3 signame
410 funptr = (TyApp () (TyCon () (UnQual () (HS.Ident () "FunPtr")))
411 (TyCon () (UnQual () (HS.Ident () signame))))
412 -- putStrLn $ ppShow $ HS.parseDecl "foreign import ccall \"wrapper\" fname :: Spec -> IO (FunPtr Spec)"
413 -- mapM_ (putStrLn . HS.prettyPrint) (importWrapper $ sigf hsTransSig d)
414 putStrLn $ HS.prettyPrint $
415 (HS.ForImp () (HS.CCall ()) Nothing (Just "wrapper")
416 (HS.Ident () wrapname)
417 (TyFun ()
418 (TyCon () (UnQual () (HS.Ident () signame)))
419 (TyApp ()
420 (TyCon () (UnQual () (HS.Ident () "IO")))
421 (TyParen () funptr))))
422 putStrLn $ HS.prettyPrint $
423 (HS.ForImp () (HS.CCall ()) Nothing (Just settername)
424 (HS.Ident () settername)
425 (TyFun ()
426 funptr
427 (TyApp ()
428 (TyCon () (UnQual () (HS.Ident () "IO")))
429 (TyCon () (Special () (UnitCon ()))))))
430
431
432 htyp -> putStr $ commented $ "Unsupported haskell type: " ++ HS.prettyPrint htyp
309 433
310 434
311readComments fname = parseComments 1 1 <$> readFile fname 435readComments fname = parseComments 1 1 <$> readFile fname
@@ -319,6 +443,7 @@ findCloser !d (l,c,b) [] = (l,c,b)
319 443
320mkComment lin no str = (lin,no,str) 444mkComment lin no str = (lin,no,str)
321 445
446parseComments :: (Num col, Num lin) => lin -> col -> [Char] -> [(lin, col, [Char])]
322parseComments !lin !col = \case 447parseComments !lin !col = \case
323 ('/':'*':cs) -> let (lcnt,col',bcnt) = findCloser 1 (0,col,0) cs 448 ('/':'*':cs) -> let (lcnt,col',bcnt) = findCloser 1 (0,col,0) cs
324 (xs,cs') = splitAt bcnt cs 449 (xs,cs') = splitAt bcnt cs
@@ -348,6 +473,7 @@ usage args = do
348 return (hopts,cargs,fname) 473 return (hopts,cargs,fname)
349 _ -> Nothing 474 _ -> Nothing
350 475
476(<&>) :: Functor f => f a -> (a -> b) -> f b
351m <&> f = fmap f m 477m <&> f = fmap f m
352 478
353main :: IO () 479main :: IO ()