diff options
author | Joe Crayne <joe@jerkface.net> | 2019-03-23 01:11:05 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-03-23 01:11:05 -0400 |
commit | 56b8d9316dcb37aedf5a7727f05b6cd81f9f0f19 (patch) | |
tree | 8681e0a181013d504fbe7981791f0a10b41f911e | |
parent | 6cbcc42ef4ac75a9bccb4e9d0acc53116c7c68e8 (diff) |
Binary ops and global pointer refs.
-rw-r--r-- | monkeypatch.hs | 132 |
1 files changed, 117 insertions, 15 deletions
diff --git a/monkeypatch.hs b/monkeypatch.hs index bc55425..352a0f5 100644 --- a/monkeypatch.hs +++ b/monkeypatch.hs | |||
@@ -7,9 +7,12 @@ | |||
7 | {-# LANGUAGE QuasiQuotes #-} | 7 | {-# LANGUAGE QuasiQuotes #-} |
8 | {-# LANGUAGE TemplateHaskell #-} | 8 | {-# LANGUAGE TemplateHaskell #-} |
9 | {-# LANGUAGE TupleSections #-} | 9 | {-# LANGUAGE TupleSections #-} |
10 | {-# LANGUAGE ScopedTypeVariables #-} | ||
10 | module Main where | 11 | module Main where |
11 | 12 | ||
13 | import Debug.Trace | ||
12 | import Control.Arrow (left,first,second) | 14 | import Control.Arrow (left,first,second) |
15 | import Data.Bool | ||
13 | import Data.Either | 16 | import Data.Either |
14 | import Data.Generics.Aliases | 17 | import Data.Generics.Aliases |
15 | import Data.Generics.Schemes | 18 | import Data.Generics.Schemes |
@@ -52,8 +55,10 @@ import Text.Show.Pretty | |||
52 | import Sweeten | 55 | import Sweeten |
53 | import GrepNested | 56 | import GrepNested |
54 | 57 | ||
58 | {- | ||
55 | trace :: p -> a -> a | 59 | trace :: p -> a -> a |
56 | trace _ = id | 60 | trace _ = id |
61 | -} | ||
57 | 62 | ||
58 | -- | Pretty print the given tranlation unit, but replace declarations from header files with @#include@ directives. | 63 | -- | Pretty print the given tranlation unit, but replace declarations from header files with @#include@ directives. |
59 | -- | 64 | -- |
@@ -197,16 +202,105 @@ varmap vs = Map.fromList $ map (,()) vs | |||
197 | 202 | ||
198 | -} | 203 | -} |
199 | 204 | ||
205 | |||
206 | renameIntros :: forall v st. (Typeable st, Data st) => | ||
207 | [Computation (HS.Exp st)] | ||
208 | -> Computation (HS.Exp st) | ||
209 | -> Map String v | ||
210 | -> ([Computation (HS.Exp st)], Computation (HS.Exp st)) | ||
211 | renameIntros bs cb vs = (bs',cb') | ||
212 | where | ||
213 | (rs,bs') = unzip $ map go bs | ||
214 | |||
215 | cb' = foldr rename2 cb $ concat rs | ||
216 | |||
217 | rename2 (x,v) c = | ||
218 | let subst p@(Var la (UnQual lc (HS.Ident lb s))) | ||
219 | | s==x = Var (la::st) (UnQual lc (HS.Ident lb v)) | ||
220 | subst p = p | ||
221 | in c { comp = everywhere (mkT subst) (comp c) } | ||
222 | |||
223 | go c = | ||
224 | let xs = Map.keys (compIntro c) | ||
225 | in foldr rename1 ([],c) xs | ||
226 | |||
227 | rename1 x (rs,c) = | ||
228 | let v = uniqIdentifier x vs | ||
229 | subst p@(PVar la (HS.Ident lb s)) | ||
230 | | s==x = PVar (la::st) (HS.Ident lb v) | ||
231 | subst p = p | ||
232 | in if x/=v then (,) ((x,v):rs) c { compIntro = Map.insert v () $ Map.delete x (compIntro c) | ||
233 | , comp = everywhere (mkT subst) (comp c) | ||
234 | } | ||
235 | else (rs,c) | ||
236 | |||
237 | transpileBinOp :: CBinaryOp -> [Char] | ||
238 | transpileBinOp = \case | ||
239 | CMulOp -> "*" | ||
240 | CDivOp -> "/" | ||
241 | CRmdOp -> "rem" | ||
242 | CAddOp -> "+" | ||
243 | CSubOp -> "-" | ||
244 | CShlOp -> "shiftL" | ||
245 | CShrOp -> "shiftR" | ||
246 | CLeOp -> "<" | ||
247 | CGrOp -> ">" | ||
248 | CLeqOp -> "<=" | ||
249 | CGeqOp -> ">=" | ||
250 | CEqOp -> "==" | ||
251 | CNeqOp -> "/=" | ||
252 | CAndOp -> ".&." | ||
253 | CXorOp -> "xor" | ||
254 | COrOp -> ".|." | ||
255 | CLndOp -> "and" | ||
256 | CLorOp -> "or" | ||
257 | |||
258 | -- This function decides whether to treat an identifier as a constant or as a | ||
259 | -- pointer that must be peeked. | ||
260 | isGlobalRef :: FunctionEnvironment -> String -> Bool | ||
261 | isGlobalRef fe sym = fromMaybe False $ do | ||
262 | SymbolInformation{symbolSource = xs} <- Map.lookup sym (fnExternals fe) | ||
263 | forM_ xs $ \x -> do | ||
264 | -- Pattern fail for functions and pointers. | ||
265 | forM_ (sigf (\_ ds -> ds) x) $ \d -> do | ||
266 | CDeclr _ xs _ _ _ <- Just d | ||
267 | let func = filter (\case | ||
268 | CFunDeclr _ _ _ -> True | ||
269 | _ -> False) xs | ||
270 | guard $ null func -- Functions are not pointerized. | ||
271 | -- trace (sym ++ ": " ++ show xs) $ return () | ||
272 | -- ring: [CPtrDeclr [] (NodeInfo ("fetchers/about.c": line 64) (("fetchers/about.c": line 64),4) (Name {nameId = 14030}))] | ||
273 | return () | ||
274 | return True | ||
275 | |||
200 | -- Returns a list of statements bringing variables into scope and an | 276 | -- Returns a list of statements bringing variables into scope and an |
201 | -- expression. | 277 | -- expression. |
202 | grokExpression :: FunctionEnvironment | 278 | grokExpression :: FunctionEnvironment |
203 | -> CExpression a | 279 | -> CExpression a |
204 | -> Maybe ([Computation (HS.Exp ())], Computation (HS.Exp ())) | 280 | -> Maybe ([Computation (HS.Exp ())], Computation (HS.Exp ())) |
205 | grokExpression fe (CVar cv _) = Just $ (,) [] $ Computation | 281 | grokExpression fe (CVar cv _) = |
206 | { compFree = Map.singleton (identToString cv) () | 282 | let v = identToString cv |
207 | , compIntro = Map.empty | 283 | in Just $ |
208 | , comp = hsvar (identToString cv) | 284 | if isGlobalRef fe v |
209 | } | 285 | then let k = uniqIdentifier "go" (varmap [v,hv]) |
286 | s = Computation | ||
287 | { compFree = Map.singleton v () | ||
288 | , compIntro = Map.singleton hv () | ||
289 | , comp = Lambda () [hspvar k] | ||
290 | $ infixOp (App () (hsvar "peek") (hsvar v)) ">>=" | ||
291 | $ Lambda () [hspvar hv] (hsvar k) | ||
292 | } | ||
293 | hv = "v" ++ v | ||
294 | in (,) [s] Computation | ||
295 | { compFree = Map.singleton hv () | ||
296 | , compIntro = Map.empty | ||
297 | , comp = hsvar hv | ||
298 | } | ||
299 | else (,) [] $ Computation | ||
300 | { compFree = Map.singleton (identToString cv) () | ||
301 | , compIntro = Map.empty | ||
302 | , comp = hsvar v | ||
303 | } | ||
210 | grokExpression fe (CConst (CIntConst n _)) = Just $ (,) [] $ Computation | 304 | grokExpression fe (CConst (CIntConst n _)) = Just $ (,) [] $ Computation |
211 | { compFree = Map.empty | 305 | { compFree = Map.empty |
212 | , compIntro = Map.empty | 306 | , compIntro = Map.empty |
@@ -217,14 +311,20 @@ grokExpression fe (CConst (CStrConst s _)) = Just $ (,) [] $ Computation | |||
217 | , compIntro = Map.empty | 311 | , compIntro = Map.empty |
218 | , comp = Lit () (HS.String () (getCString s) (getCString s)) | 312 | , comp = Lit () (HS.String () (getCString s) (getCString s)) |
219 | } | 313 | } |
220 | grokExpression fe (CBinary CNeqOp a b _) = do | 314 | grokExpression fe (CBinary op a b _) = do |
221 | (as,ca) <- grokExpression fe a | 315 | (as,ca) <- grokExpression fe a |
222 | (bs,cb) <- grokExpression fe b | 316 | (bs0,cb0) <- grokExpression fe b |
223 | let ss = as ++ bs -- TODO: resolve variable name conflicts | 317 | let (bs,cb) = renameIntros bs0 cb0 (foldr Map.union Map.empty $ map compIntro as) |
318 | ss = as ++ bs | ||
319 | hop = transpileBinOp op | ||
320 | infx | isLower (head hop) = infixFn | ||
321 | | otherwise = infixOp | ||
322 | -- trace ("intros("++hop++"): "++show (foldr Map.union Map.empty $ map compIntro as)) $ return () | ||
323 | -- TODO: Short-circuit boolean evaluation side-effects. | ||
224 | return $ (,) ss $ Computation | 324 | return $ (,) ss $ Computation |
225 | { compFree = compFree ca `Map.union` compFree cb | 325 | { compFree = compFree ca `Map.union` compFree cb |
226 | , compIntro = Map.empty | 326 | , compIntro = Map.empty |
227 | , comp = infixOp (comp ca) "/=" (comp cb) | 327 | , comp = infx (comp ca) hop (comp cb) |
228 | } | 328 | } |
229 | grokExpression fe (CUnary CAdrOp (CVar cv0 _) _) = do | 329 | grokExpression fe (CUnary CAdrOp (CVar cv0 _) _) = do |
230 | let cv = identToString cv0 | 330 | let cv = identToString cv0 |
@@ -573,6 +673,8 @@ insertComment c stmts = everywhere (mkT go) stmts | |||
573 | mixComments :: [StyledComment] -> [CCompoundBlockItem NodeInfo] -> [CCompoundBlockItem NodeInfo] | 673 | mixComments :: [StyledComment] -> [CCompoundBlockItem NodeInfo] -> [CCompoundBlockItem NodeInfo] |
574 | mixComments cs stmts = foldr insertComment stmts cs | 674 | mixComments cs stmts = foldr insertComment stmts cs |
575 | 675 | ||
676 | applyDoSyntax' :: Data l => | ||
677 | C2HaskellOptions -> HS.Exp l -> HS.Exp l | ||
576 | applyDoSyntax' C2HaskellOptions{oSuppressDo=True} x = x | 678 | applyDoSyntax' C2HaskellOptions{oSuppressDo=True} x = x |
577 | applyDoSyntax' _ x = applyDoSyntax x | 679 | applyDoSyntax' _ x = applyDoSyntax x |
578 | 680 | ||
@@ -763,7 +865,7 @@ hsTypeSpec (CTypeSpec (CIntType _)) = [ R | |||
763 | hsTypeSpec (CTypeSpec (CCharType _)) = [ Right "Char"] | 865 | hsTypeSpec (CTypeSpec (CCharType _)) = [ Right "Char"] |
764 | hsTypeSpec (CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)) = maybeToList $ fmap Left mctyp | 866 | hsTypeSpec (CTypeSpec (CSUType (CStruct CStructTag mctyp Nothing [] _) _)) = maybeToList $ fmap Left mctyp |
765 | 867 | ||
766 | hsTypeSpec (CTypeSpec unhandled) = trace ("hsTypeSpec unhandled: "++ show (const () <$> unhandled)) $ [] | 868 | hsTypeSpec (CTypeSpec unhandled) = [] -- trace ("hsTypeSpec unhandled: "++ show (const () <$> unhandled)) $ [] |
767 | hsTypeSpec _ = [] | 869 | hsTypeSpec _ = [] |
768 | 870 | ||
769 | 871 | ||
@@ -786,15 +888,15 @@ hsTransField ctyps vars | |||
786 | (mcname,typname) <- second hsMkName . either ((\s -> (Just s,capitalize s)) . identToString) | 888 | (mcname,typname) <- second hsMkName . either ((\s -> (Just s,capitalize s)) . identToString) |
787 | (Nothing,) | 889 | (Nothing,) |
788 | <$> (hsTypeSpec =<< ctyps) | 890 | <$> (hsTypeSpec =<< ctyps) |
789 | trace ("typname="++show typname) $ return () | 891 | -- trace ("typname="++show typname) $ return () |
790 | -- (var,Nothing,Nothing) <- vars | 892 | -- (var,Nothing,Nothing) <- vars |
791 | var <- vars | 893 | var <- vars |
792 | trace ("var="++show var) $ return () | 894 | -- trace ("var="++show var) $ return () |
793 | -- CDeclr (Just fident) ptrdeclr Nothing [] _ <- maybeToList var | 895 | -- CDeclr (Just fident) ptrdeclr Nothing [] _ <- maybeToList var |
794 | let CDeclr mfident ptrdeclr Nothing ignored_attrs _ = var -- TODO: Look into: Irrefutable pattern failed (ctox/toxcore/DHT.c) | 896 | let CDeclr mfident ptrdeclr Nothing ignored_attrs _ = var -- TODO: Look into: Irrefutable pattern failed (ctox/toxcore/DHT.c) |
795 | -- let CDeclr mfident ptrdeclr _ _ _ = var | 897 | -- let CDeclr mfident ptrdeclr _ _ _ = var |
796 | trace ("fident="++show mfident) $ return () | 898 | -- trace ("fident="++show mfident) $ return () |
797 | trace ("ptrdeclr="++show ptrdeclr) $ return () | 899 | -- trace ("ptrdeclr="++show ptrdeclr) $ return () |
798 | let btyp = HS.TyCon () typname | 900 | let btyp = HS.TyCon () typname |
799 | grok :: Show a => [CDerivedDeclarator a] -> HS.Type () -> HS.Type () | 901 | grok :: Show a => [CDerivedDeclarator a] -> HS.Type () -> HS.Type () |
800 | grok bs b = case bs of | 902 | grok bs b = case bs of |
@@ -1306,7 +1408,7 @@ getArgList_ (CFDefExt (CFunDef xs ys zs c d)) = getArgList1 ys | |||
1306 | getArgList_ (CDeclExt (CDecl xs ys pos)) = getArgList2 ys | 1408 | getArgList_ (CDeclExt (CDecl xs ys pos)) = getArgList2 ys |
1307 | 1409 | ||
1308 | getArgList :: CExternalDeclaration a -> [CDerivedDeclarator a] | 1410 | getArgList :: CExternalDeclaration a -> [CDerivedDeclarator a] |
1309 | getArgList x = let v=getArgList_ x in trace ("getArgList ("++show (u x)++") = "++show (fmap u v)) v | 1411 | getArgList x = let v=getArgList_ x in {- trace ("getArgList ("++show (u x)++") = "++show (fmap u v)) -} v |
1310 | where | 1412 | where |
1311 | u :: Functor f => f a -> f () | 1413 | u :: Functor f => f a -> f () |
1312 | u = fmap (const ()) | 1414 | u = fmap (const ()) |