diff --git a/cabal.project b/cabal.project index 2d76ffa..90be4c1 100644 --- a/cabal.project +++ b/cabal.project @@ -1,5 +1,3 @@ packages: ./fdep - ./coresyn2chart - ./sheriff ./fieldInspector diff --git a/coresyn2chart/coresyn2chart.cabal b/coresyn2chart/coresyn2chart.cabal index 4b2b1f9..f6a917f 100644 --- a/coresyn2chart/coresyn2chart.cabal +++ b/coresyn2chart/coresyn2chart.cabal @@ -38,13 +38,13 @@ common common-options bytestring , containers , filepath - , ghc ^>= 8.10.7 + , ghc , unordered-containers , aeson , directory , extra , aeson-pretty - , base ^>=4.14.3.0 + , base , text , base64-bytestring , optparse-applicative @@ -55,7 +55,6 @@ common common-options , hasbolt , universum , data-default - , streamly library import: common-options diff --git a/fdep/fdep.cabal b/fdep/fdep.cabal index 7f1f5ba..79f1fda 100644 --- a/fdep/fdep.cabal +++ b/fdep/fdep.cabal @@ -12,7 +12,7 @@ build-type: Simple extra-doc-files: CHANGELOG.md common common-options - build-depends: base ^>=4.14.3.0 + build-depends: base ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates @@ -39,17 +39,17 @@ library bytestring , containers , filepath - , ghc ^>= 8.10.7 + , ghc , ghc-exactprint , unordered-containers - , uniplate >= 1.6 && < 1.7 + , uniplate , references , classyplate , aeson , directory , extra , aeson-pretty - , streamly + , streamly-core , async , time , text @@ -58,6 +58,7 @@ library , deepseq , websockets , network + , primitive hs-source-dirs: src default-language: Haskell2010 diff --git a/fdep/src/Fdep/Plugin.hs b/fdep/src/Fdep/Plugin.hs index 590e62a..3e23c86 100644 --- a/fdep/src/Fdep/Plugin.hs +++ b/fdep/src/Fdep/Plugin.hs @@ -1,10 +1,10 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE CPP #-} module Fdep.Plugin (plugin) where -import Bag (bagToList) import Control.Concurrent ( forkIO ) import Control.DeepSeq (force) import Control.Exception (SomeException, evaluate, try) @@ -19,7 +19,6 @@ import Data.ByteString.Lazy (toStrict, writeFile) import qualified Data.ByteString.Lazy as BL import Data.Data (toConstr) import Data.Generics.Uniplate.Data () -import qualified Data.HashMap.Strict as HM import Data.List.Extra (splitOn) import qualified Data.Map as Map import Data.Maybe (fromJust, fromMaybe, isJust) @@ -27,26 +26,36 @@ import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8, encodeUtf8) import Data.Time ( diffUTCTime, getCurrentTime ) -import DynFlags () -import Text.Read (readMaybe) import Fdep.Types ( PFunction(PFunction), FunctionInfo(FunctionInfo) ) -import GHC ( - GRHS (..), - GRHSs (..), - GhcTc, - HsExpr (..), - LGRHS, - LHsExpr, - LMatch, - Match (m_grhss), - MatchGroup (..), - Module (moduleName), - getName, - hsmodDecls, - moduleNameString, GhcPs - ) +import Text.Read (readMaybe) +import Prelude hiding (id, mapM, mapM_, writeFile) +import qualified Prelude as P +import qualified Data.List.Extra as Data.List +import Network.Socket (withSocketsDo) +import qualified Network.WebSockets as WS +import System.Directory ( createDirectoryIfMissing ) +import System.Environment (lookupEnv) +import GHC.IO (unsafePerformIO) +#if __GLASGOW_HASKELL__ >= 900 +import Streamly.Internal.Data.Stream (fromList,mapM_,mapM,toList) +import GHC +import GHC.Driver.Plugins (Plugin(..),CommandLineOption,defaultPlugin,PluginRecompile(..)) +import GHC.Driver.Env +import GHC.Tc.Types +import GHC.Unit.Module.ModSummary +import GHC.Utils.Outputable (showSDocUnsafe,ppr) +import GHC.Data.Bag (bagToList) +import GHC.Types.Name hiding (varName) +import GHC.Types.Var +import qualified Data.Aeson.KeyMap as HM +#else +import Streamly.Internal.Data.Stream (fromList, mapM, mapM_, toList,parallely) +import qualified Data.HashMap.Strict as HM +import Bag (bagToList) +import DynFlags () +import GHC import GHC.Hs.Binds ( HsBindLR(PatBind, FunBind, AbsBinds, VarBind, PatSynBind, XHsBindsLR, fun_id, abs_binds, var_rhs), @@ -57,36 +66,24 @@ import GHC.Hs.Binds PatSynBind(XPatSynBind, PSB, psb_def) ) import GHC.Hs.Decls ( HsDecl(SigD, TyClD, InstD, DerivD, ValD), LHsDecl ) -import GHC.IO (unsafePerformIO) import GhcPlugins (HsParsedModule, Hsc, Plugin (..), PluginRecompile (..), Var (..), getOccString, hpm_module, ppr, showSDocUnsafe) import HscTypes (ModSummary (..),msHsFilePath) import Name (nameStableString) -import Network.Socket (withSocketsDo) -import qualified Network.WebSockets as WS import Outputable () import Plugins (CommandLineOption, defaultPlugin) import SrcLoc ( GenLocated(L), getLoc, noLoc, unLoc ) -import Streamly ( parallely ) -import Streamly.Prelude (fromList, mapM, mapM_, toList) -import System.Directory ( createDirectoryIfMissing ) -import System.Environment (lookupEnv) import TcRnTypes (TcGblEnv (..), TcM) -import Prelude hiding (id, mapM, mapM_, writeFile) -import qualified Prelude as P -import qualified Data.List.Extra as Data.List import StringBuffer +#endif plugin :: Plugin plugin = defaultPlugin { typeCheckResultAction = fDep - , pluginRecompile = purePlugin + , pluginRecompile = (\_ -> return NoForceRecompile) , parsedResultAction = collectDecls } -purePlugin :: [CommandLineOption] -> IO PluginRecompile -purePlugin _ = return NoForceRecompile - filterList :: [Text] filterList = [ "show" @@ -157,7 +154,7 @@ collectDecls opts modSummary hsParsedModule = do path = (Data.List.intercalate "/" . reverse . tail . reverse . splitOn "/") modulePath declsList = hsmodDecls $ unLoc $ hpm_module hsParsedModule createDirectoryIfMissing True path - functionsVsCodeString <- toList $ parallely $ mapM getDecls $ fromList declsList + functionsVsCodeString <- toList $ mapM getDecls $ fromList declsList writeFile (modulePath <> ".function_code.json") (encodePretty $ Map.fromList $ concat functionsVsCodeString) pure hsParsedModule @@ -171,7 +168,7 @@ getDecls x = do (L _ (SigD _ _)) -> pure mempty _ -> pure mempty where - getFunBind f@FunBind{fun_id = funId} = [((T.pack $ showSDocUnsafe $ ppr $ unLoc funId) <> "**" <> (T.pack $ showSDocUnsafe $ ppr $ getLoc funId), PFunction ((T.pack $ showSDocUnsafe $ ppr $ unLoc funId) <> "**" <> (T.pack $ showSDocUnsafe $ ppr $ getLoc funId)) (T.pack $ showSDocUnsafe $ ppr f) (T.pack $ showSDocUnsafe $ ppr $ getLoc funId))] + getFunBind f@FunBind{fun_id = funId} = [((T.pack $ showSDocUnsafe $ ppr $ unLoc funId) <> "**" <> (T.pack $ getLoc' funId), PFunction ((T.pack $ showSDocUnsafe $ ppr $ unLoc funId) <> "**" <> (T.pack $ getLoc' funId)) (T.pack $ showSDocUnsafe $ ppr f) (T.pack $ getLoc' funId))] getFunBind _ = mempty shouldForkPerFile :: Bool @@ -187,7 +184,7 @@ shouldForkPerFile = readBool $ unsafePerformIO $ lookupEnv "SHOULD_FORK" readBool _ = True shouldGenerateFdep :: Bool -shouldGenerateFdep = True--readBool $ unsafePerformIO $ lookupEnv "GENERATE_FDEP" +shouldGenerateFdep = readBool $ unsafePerformIO $ lookupEnv "GENERATE_FDEP" where readBool :: (Maybe String) -> Bool readBool (Just "true") = True @@ -242,7 +239,7 @@ fDep opts modSummary tcEnv = do eres <- try $ WS.runClient websocketHost websocketPort ("/" <> modulePath <> ".json") (\conn -> do mapM_ (loopOverLHsBindLR (Just conn) Nothing (T.pack ("/" <> modulePath <> ".json"))) (fromList binds)) case eres of Left (err :: SomeException) -> when shouldLog $ print err - Right val -> pure () + Right _ -> pure () t2 <- getCurrentTime when shouldLog $ print ("generated dependancy for module: " <> moduleName' <> " at path: " <> path <> " total-timetaken: " <> show (diffUTCTime t2 t1)) return tcEnv @@ -268,7 +265,11 @@ sendTextData' conn path data_ = do when (shouldLog) $ print ("websocket call timetaken: " <> (T.pack $ show $ diffUTCTime t2 t1)) loopOverLHsBindLR :: Maybe WS.Connection -> (Maybe Text) -> Text -> LHsBindLR GhcTc GhcTc -> IO () +#if __GLASGOW_HASKELL__ >= 900 +loopOverLHsBindLR mConn mParentName path (L _ x@(FunBind fun_ext id matches _)) = do +#else loopOverLHsBindLR mConn mParentName path (L _ x@(FunBind fun_ext id matches _ _)) = do +#endif funName <- evaluate $ force $ T.pack $ getOccString $ unLoc id fName <- evaluate $ force $ T.pack $ nameStableString $ getName id let matchList = mg_alts matches @@ -276,7 +277,11 @@ loopOverLHsBindLR mConn mParentName path (L _ x@(FunBind fun_ext id matches _ _) then pure mempty else do when (shouldLog) $ print ("processing function: " <> fName) - name <- evaluate $ force (fName <> "**" <> (T.pack $ showSDocUnsafe (ppr (getLoc id)))) +#if __GLASGOW_HASKELL__ >= 900 + name <- evaluate $ force (fName <> "**" <> (T.pack (getLoc' id))) +#else + name <- evaluate $ force (fName <> "**" <> (T.pack ((showSDocUnsafe . ppr . getLoc) id))) +#endif typeSignature <- evaluate $ force $ (T.pack $ showSDocUnsafe (ppr (varType (unLoc id)))) nestedNameWithParent <- evaluate $ force $ (maybe (name) (\x -> x <> "::" <> name) mParentName) data_ <- evaluate $ force $ (decodeUtf8 $ toStrict $ Data.Aeson.encode $ Object $ HM.fromList [("key", String nestedNameWithParent), ("typeSignature", String typeSignature)]) @@ -303,7 +308,11 @@ loopOverLHsBindLR _ _ _ (L _ (PatBind _ _ pat_rhs _)) = pure mempty processMatch :: WS.Connection -> Text -> Text -> LMatch GhcTc (LHsExpr GhcTc) -> IO () processMatch con keyFunction path (L _ match) = do +#if __GLASGOW_HASKELL__ >= 900 + whereClause <- (evaluate . force) =<< (processHsLocalBinds con keyFunction path $ grhssLocalBinds (m_grhss match)) +#else whereClause <- (evaluate . force) =<< (processHsLocalBinds con keyFunction path $ unLoc $ grhssLocalBinds (m_grhss match)) +#endif mapM_ (processGRHS con keyFunction path) $ fromList $ grhssGRHSs (m_grhss match) pure mempty @@ -318,11 +327,42 @@ processHsLocalBinds con keyFunction path (HsValBinds _ (XValBindsLR (NValBinds x mapM_ (\(recFlag, binds) -> mapM_ (loopOverLHsBindLR (Just con) (Just keyFunction) path) $ fromList $ bagToList binds) (fromList x) processHsLocalBinds _ _ _ _ = pure mempty +grhsExpr :: LGRHS GhcTc (LHsExpr GhcTc) -> LHsExpr GhcTc +grhsExpr (L _ (GRHS _ _ body)) = body + +hsStmtsExpr :: WS.Connection -> Text -> Text -> [LStmt GhcTc (LHsExpr GhcTc)] -> IO () +hsStmtsExpr con keyFunction path stmts = mapM_ (stmtExpr con keyFunction path) $ fromList stmts + +stmtExpr :: WS.Connection -> Text -> Text -> LStmt GhcTc (LHsExpr GhcTc) -> IO () +stmtExpr con keyFunction path (L _ stmt) = case stmt of + BindStmt _ pat expr -> processExpr con keyFunction path expr + BodyStmt _ expr _ _ -> processExpr con keyFunction path expr + LastStmt _ expr _ _ -> processExpr con keyFunction path expr + ParStmt _ stmtBlocks _ _ -> mapM_ blockExprs (fromList stmtBlocks) + TransStmt{..} -> do + hsStmtsExpr con keyFunction path $ trS_stmts + processExpr con keyFunction path trS_using + maybe (pure ()) (processExpr con keyFunction path) trS_by + ApplicativeStmt _ args _ -> mapM_ (extractApplicativeArg con keyFunction path . snd) (fromList args) + LetStmt _ binds -> processHsLocalBinds con keyFunction path binds + RecStmt{..} -> mapM_ (stmtExpr con keyFunction path) (fromList $ unXRec @(GhcTc) recS_stmts) + XStmtLR{} -> pure () + where + blockExprs :: ParStmtBlock GhcTc GhcTc -> IO () + blockExprs (ParStmtBlock _ stmts _ _) = mapM_ (stmtExpr con keyFunction path) (fromList stmts) + + extractApplicativeArg con keyFunction path (ApplicativeArgOne _ _ arg_expr _) = processExpr con keyFunction path arg_expr + extractApplicativeArg con keyFunction path (ApplicativeArgMany _ app_stmts final_expr _ _) = do + hsStmtsExpr con keyFunction path app_stmts + processExpr con keyFunction path $ wrapXRec @(GhcTc) final_expr + extractApplicativeArg _ _ _ _ = pure () + processExpr :: WS.Connection -> Text -> Text -> LHsExpr GhcTc -> IO () processExpr con keyFunction path x@(L _ (HsVar _ (L _ var))) = do let name = T.pack $ nameStableString $ varName var _type = T.pack $ showSDocUnsafe $ ppr $ varType var - expr <- evaluate $ force $ transformFromNameStableString (Just name, Just $ T.pack $ showSDocUnsafe $ ppr $ getLoc $ x, Just _type, mempty) + print (Just $ T.pack $ getLocTC' $ x) + expr <- evaluate $ force $ transformFromNameStableString (Just name, Just $ T.pack $ getLocTC' $ x, Just _type, mempty) sendTextData' con path (decodeUtf8 $ toStrict $ Data.Aeson.encode $ Object $ HM.fromList [("key", String keyFunction), ("expr", toJSON expr)]) processExpr _ _ _ (L _ (HsUnboundVar _ _)) = pure mempty processExpr con keyFunction path (L _ (HsApp _ funl funr)) = do @@ -338,10 +378,9 @@ processExpr con keyFunction path (L _ (HsTick _ _ fun)) = processExpr con keyFunction path fun processExpr con keyFunction path (L _ (HsStatic _ fun)) = processExpr con keyFunction path fun -processExpr con keyFunction path (L _ x@(HsWrap _ _ fun)) = - processExpr con keyFunction path (noLoc fun) processExpr con keyFunction path (L _ (HsBinTick _ _ _ fun)) = processExpr con keyFunction path fun +#if __GLASGOW_HASKELL__ < 900 processExpr con keyFunction path (L _ (ExplicitList _ _ funList)) = mapM_ (processExpr con keyFunction path) (fromList funList) processExpr con keyFunction path (L _ (HsTickPragma _ _ _ _ fun)) = @@ -350,50 +389,71 @@ processExpr con keyFunction path (L _ (HsSCC _ _ _ fun)) = processExpr con keyFunction path fun processExpr con keyFunction path (L _ (HsCoreAnn _ _ _ fun)) = processExpr con keyFunction path fun +processExpr con keyFunction path (L _ x@(HsWrap _ _ fun)) = + processExpr con keyFunction path (noLoc fun) +processExpr con keyFunction path (L _ (HsIf _ exprLStmt funl funm funr)) = + mapM_ (processExpr con keyFunction path) $ fromList $ [funl, funm, funr] +processExpr con keyFunction path (L _ (HsTcBracketOut b exprLStmtL exprLStmtR)) = do + let stmtsL = (exprLStmtL ^? biplateRef :: [LHsExpr GhcTc]) + stmtsR = (exprLStmtR ^? biplateRef :: [LHsExpr GhcTc]) + mapM_ (processExpr con keyFunction path) (fromList $ stmtsL <> stmtsR) +#else +processExpr con keyFunction path (L _ (HsGetField _ exprLStmt _)) = + let stmts = exprLStmt ^? biplateRef :: [LHsExpr GhcTc] + in mapM_ (processExpr con keyFunction path) (fromList stmts) +processExpr con keyFunction path (L _ (ExplicitList _ funList)) = + mapM_ (processExpr con keyFunction path) (fromList funList) +processExpr con keyFunction path (L _ (HsPragE _ _ fun)) = + processExpr con keyFunction path fun +processExpr con keyFunction path (L _ (HsProc _ lPat fun)) = do + let stmts = lPat ^? biplateRef :: [LHsExpr GhcTc] + stmts' = fun ^? biplateRef :: [LHsExpr GhcTc] + mapM_ (processExpr con keyFunction path) (fromList (stmts <> stmts')) +processExpr con keyFunction path (L _ (HsIf _ funl funm funr)) = mapM_ (processExpr con keyFunction path) $ fromList $ [funl, funm, funr] +processExpr con keyFunction path (L _ (HsTcBracketOut b mQW exprLStmtL exprLStmtR)) = + let stmtsL = (exprLStmtL ^? biplateRef :: [LHsExpr GhcTc]) + stmtsR = (exprLStmtR ^? biplateRef :: [LHsExpr GhcTc]) + in mapM_ (processExpr con keyFunction path) (fromList $ stmtsL <> stmtsR) +#endif processExpr con keyFunction path (L _ (ExprWithTySig _ fun _)) = processExpr con keyFunction path fun processExpr con keyFunction path (L _ (HsDo _ _ exprLStmt)) = - let stmts = exprLStmt ^? biplateRef :: [LHsExpr GhcTc] - in mapM_ (processExpr con keyFunction path) (fromList stmts) -processExpr con keyFunction path (L _ (HsLet _ exprLStmt func)) = - let stmts = exprLStmt ^? biplateRef :: [LHsExpr GhcTc] - in mapM_ (processExpr con keyFunction path) (fromList $ [func] <> stmts) -processExpr con keyFunction path (L _ (HsMultiIf _ exprLStmt)) = - let stmts = exprLStmt ^? biplateRef :: [LHsExpr GhcTc] - in mapM_ (processExpr con keyFunction path) (fromList stmts) -processExpr con keyFunction path (L _ (HsIf _ exprLStmt funl funm funr)) = - let stmts = (exprLStmt ^? biplateRef :: [LHsExpr GhcTc]) - in mapM_ (processExpr con keyFunction path) $ fromList $ [funl, funm, funr] <> stmts -processExpr con keyFunction path (L _ (HsCase _ funl exprLStmt)) = - let stmts = (exprLStmt ^? biplateRef :: [LHsExpr GhcTc]) - in mapM_ (processExpr con keyFunction path) $ fromList $ [funl] <> stmts + hsStmtsExpr con keyFunction path $ unLoc exprLStmt +processExpr con keyFunction path (L _ (HsLet _ exprLStmt func)) = do + processHsLocalBinds con keyFunction path exprLStmt + processExpr con keyFunction path func +processExpr con keyFunction path (L _ (HsMultiIf _ exprLStmt)) = do + mapM_ (processExpr con keyFunction path . grhsExpr) (fromList exprLStmt) +processExpr con keyFunction path (L _ (HsCase _ funl exprLStmt)) = do + processExpr con keyFunction path funl + mapM_ (processMatch con keyFunction path) (fromList $ unLoc $ mg_alts exprLStmt) processExpr con keyFunction path (L _ (ExplicitSum _ _ _ fun)) = processExpr con keyFunction path fun processExpr con keyFunction path (L _ (SectionR _ funl funr)) = processExpr con keyFunction path funl <> processExpr con keyFunction path funr processExpr con keyFunction path (L _ (ExplicitTuple _ exprLStmt _)) = - let stmts = (exprLStmt ^? biplateRef :: [LHsExpr GhcTc]) - in mapM_ (processExpr con keyFunction path) (fromList stmts) + mapM_ (\x -> + case x of + (Present _ exprs) -> processExpr con keyFunction path exprs + _ -> pure ()) (fromList exprLStmt) processExpr con keyFunction path (L _ (HsPar _ fun)) = processExpr con keyFunction path fun processExpr con keyFunction path (L _ (HsAppType _ fun _)) = processExpr con keyFunction path fun processExpr con keyFunction path (L _ x@(HsLamCase _ exprLStmt)) = - let stmts = (exprLStmt ^? biplateRef :: [LHsExpr GhcTc]) - in mapM_ (processExpr con keyFunction path) (fromList stmts) + mapM_ (processMatch con keyFunction path) (fromList $ unLoc $ mg_alts exprLStmt) processExpr con keyFunction path (L _ x@(HsLam _ exprLStmt)) = - let stmts = (exprLStmt ^? biplateRef :: [LHsExpr GhcTc]) - in mapM_ (processExpr con keyFunction path) (fromList stmts) + mapM_ (processMatch con keyFunction path) (fromList $ unLoc $ mg_alts exprLStmt) processExpr con keyFunction path y@(L _ x@(HsLit _ hsLit)) = do - expr <- evaluate $ force $ transformFromNameStableString (Just $ ("$_lit$" <> (T.pack $ showSDocUnsafe $ ppr hsLit)), (Just $ T.pack $ showSDocUnsafe $ ppr $ getLoc $ y), (Just $ T.pack $ show $ toConstr hsLit), mempty) + expr <- evaluate $ force $ transformFromNameStableString (Just $ ("$_lit$" <> (T.pack $ showSDocUnsafe $ ppr hsLit)), (Just $ T.pack $ getLocTC' $ y), (Just $ T.pack $ show $ toConstr hsLit), mempty) sendTextData' con path (decodeUtf8 $ toStrict $ Data.Aeson.encode $ Object $ HM.fromList [("key", String keyFunction), ("expr", toJSON expr)]) processExpr con keyFunction path y@(L _ x@(HsOverLit _ overLitVal)) = do - expr <- evaluate $ force $ transformFromNameStableString (Just $ ("$_lit$" <> (T.pack $ showSDocUnsafe $ ppr overLitVal)), (Just $ T.pack $ showSDocUnsafe $ ppr $ getLoc $ y), (Just $ T.pack $ show $ toConstr overLitVal), mempty) + expr <- evaluate $ force $ transformFromNameStableString (Just $ ("$_lit$" <> (T.pack $ showSDocUnsafe $ ppr overLitVal)), (Just $ T.pack $ getLocTC' $ y), (Just $ T.pack $ show $ toConstr overLitVal), mempty) sendTextData' con path (decodeUtf8 $ toStrict $ Data.Aeson.encode $ Object $ HM.fromList [("key", String keyFunction), ("expr", toJSON expr)]) processExpr con keyFunction path (L _ (HsRecFld _ exprLStmt)) = let stmts = (exprLStmt ^? biplateRef :: [LHsExpr GhcTc]) in mapM_ (processExpr con keyFunction path) (fromList stmts) -processExpr con keyFunction path (L _ (HsSpliceE exprLStmtL exprLStmtR)) = +processExpr con keyFunction path (L _ (HsSpliceE exprLStmtL exprLStmtR)) = do let stmtsL = (exprLStmtL ^? biplateRef :: [LHsExpr GhcTc]) stmtsR = (exprLStmtR ^? biplateRef :: [LHsExpr GhcTc]) - in mapM_ (processExpr con keyFunction path) (fromList $ stmtsL <> stmtsR) + mapM_ (processExpr con keyFunction path) (fromList $ stmtsL <> stmtsR) processExpr con keyFunction path (L _ (ArithSeq _ (Just exprLStmtL) exprLStmtR)) = let stmtsL = (exprLStmtL ^? biplateRef :: [LHsExpr GhcTc]) stmtsR = (exprLStmtR ^? biplateRef :: [LHsExpr GhcTc]) @@ -405,14 +465,33 @@ processExpr con keyFunction path (L _ (HsRnBracketOut _ exprLStmtL exprLStmtR)) let stmtsL = (exprLStmtL ^? biplateRef :: [LHsExpr GhcTc]) stmtsR = (exprLStmtR ^? biplateRef :: [LHsExpr GhcTc]) in mapM_ (processExpr con keyFunction path) (fromList $ stmtsL <> stmtsR) -processExpr con keyFunction path (L _ (HsTcBracketOut _ exprLStmtL exprLStmtR)) = - let stmtsL = (exprLStmtL ^? biplateRef :: [LHsExpr GhcTc]) - stmtsR = (exprLStmtR ^? biplateRef :: [LHsExpr GhcTc]) - in mapM_ (processExpr con keyFunction path) (fromList $ stmtsL <> stmtsR) + processExpr con keyFunction path (L _ (RecordCon _ (L _ (iD)) rcon_flds)) = let stmts = (rcon_flds ^? biplateRef :: [LHsExpr GhcTc]) in mapM_ (processExpr con keyFunction path) (fromList stmts) + processExpr con keyFunction path (L _ (RecordUpd _ rupd_expr rupd_flds)) = let stmts = (rupd_flds ^? biplateRef :: [LHsExpr GhcTc]) in mapM_ (processExpr con keyFunction path) (fromList stmts) -processExpr _ _ _ _ = pure mempty \ No newline at end of file + +processExpr con keyFunction path (L _ x) = + let stmts = (x ^? biplateRef :: [LHsExpr GhcTc]) + in mapM_ (processExpr con keyFunction path) (fromList stmts) + + +-- processExpr _ _ _ (L _ (HsConLikeOut _ _)) = pure mempty +-- processExpr _ _ _ (L _ (HsOverLabel _ _)) = pure mempty +-- processExpr _ _ _ (L _ (HsIPVar _ _)) = pure mempty +-- processExpr _ _ _ (L _ (SectionL _ _ _)) = pure mempty +-- processExpr _ _ _ (L _ (HsProjection _ _)) = pure mempty +-- processExpr _ _ _ (L _ (HsBracket _ _)) = pure mempty +-- processExpr _ _ _ (L _ (XExpr _)) = pure mempty + + +#if __GLASGOW_HASKELL__ > 900 +getLocTC' = (showSDocUnsafe . ppr . la2r . getLoc) +getLoc' = (showSDocUnsafe . ppr . la2r . getLoc) +#else +getLocTC' = (showSDocUnsafe . ppr . getLoc) +getLoc' = (showSDocUnsafe . ppr . getLoc) +#endif \ No newline at end of file diff --git a/fieldInspector/fieldInspector.cabal b/fieldInspector/fieldInspector.cabal index 1d2f724..e33baec 100644 --- a/fieldInspector/fieldInspector.cabal +++ b/fieldInspector/fieldInspector.cabal @@ -79,14 +79,14 @@ common common-options bytestring , containers , filepath - , ghc ^>= 8.10.7 + , ghc , unordered-containers , aeson , directory , extra , aeson-pretty , aeson - , base ^>=4.14.3.0 + , base , text , base64-bytestring , optparse-applicative @@ -96,13 +96,13 @@ common common-options , cryptonite , hasbolt , universum + , streamly-core , data-default - , streamly , large-records , large-generics , large-anon , ghc-hasfield-plugin - , record-dot-preprocessor ==0.2.14 + , record-dot-preprocessor , ghc-tcplugin-api , typelet , record-hasfield @@ -177,8 +177,8 @@ test-suite fieldInspector-test , large-records , large-generics , large-anon - , ghc-hasfield-plugin - , record-dot-preprocessor ==0.2.14 + , record-dot-preprocessor , ghc-tcplugin-api , typelet , record-hasfield + , scientific diff --git a/fieldInspector/src/FieldInspector/PluginFields.hs b/fieldInspector/src/FieldInspector/PluginFields.hs index a53860e..ec713fb 100644 --- a/fieldInspector/src/FieldInspector/PluginFields.hs +++ b/fieldInspector/src/FieldInspector/PluginFields.hs @@ -2,41 +2,96 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE CPP #-} module FieldInspector.PluginFields (plugin) where -import Bag (bagToList) -import Control.Exception (evaluate) -import Control.Reference (biplateRef, (^?)) -import CoreMonad (CoreM, CoreToDo (CoreDoPluginPass)) + +#if __GLASGOW_HASKELL__ >= 900 +import qualified Data.IntMap.Internal as IntMap +import Streamly.Internal.Data.Stream (fromList,mapM_,mapM,toList) +import GHC +import GHC.Driver.Plugins (Plugin(..),CommandLineOption,defaultPlugin,PluginRecompile(..)) +import GHC as GhcPlugins +import GHC.Core.DataCon as GhcPlugins +import GHC.Core.TyCo.Rep +import GHC.Core.TyCon as GhcPlugins +import GHC.Driver.Env +import GHC.Tc.Types +import GHC.Unit.Module.ModSummary +import GHC.Utils.Outputable (showSDocUnsafe,ppr,SDoc) +import GHC.Data.Bag (bagToList) +import GHC.Types.Name hiding (varName) +import GHC.Types.Var +import qualified Data.Aeson.KeyMap as HM +import GHC.Core.Opt.Monad +import GHC.Core +import GHC.Unit.Module.ModGuts +import GHC.Types.Name.Reader +import GHC.Types.Id +import GHC.Data.FastString + +#else +import CoreMonad (CoreM, CoreToDo (CoreDoPluginPass), liftIO) import CoreSyn ( AltCon (..), Bind (NonRec, Rec), CoreBind, CoreExpr, Expr (..), + mkStringLit ) -import Data.Aeson.Encode.Pretty (encodePretty) -import Data.Bool (bool) -import qualified Data.ByteString as DBS -import Data.ByteString.Lazy (toStrict) -import Data.Data (Data (toConstr)) -import Data.Generics.Uniplate.Data () -import Data.List (sortBy) -import Data.List.Extra (groupBy, intercalate, splitOn) -import Data.Map (Map) -import qualified Data.Map as Map -import Data.Maybe (mapMaybe) -import Data.Text (Text, pack) -import qualified Data.Text as T -import FieldInspector.Types ( - DataConInfo (..), - DataTypeUC (DataTypeUC), - FieldRep (FieldRep), - FieldUsage (FieldUsage), - TypeInfo (..), - TypeVsFields (TypeVsFields), +import TyCoRep +import GHC.IO (unsafePerformIO) +import GHC.Hs +import GHC.Hs.Decls +import GhcPlugins ( + CommandLineOption,Arg (..), + HsParsedModule(..), + Hsc, + Name,SDoc,DataCon,DynFlags,ModSummary(..),TyCon, + Literal (..),typeEnvElts, + ModGuts (mg_binds, mg_loc, mg_module),showSDoc, + Module (moduleName),tyConKind, + NamedThing (getName),getDynFlags,tyConDataCons,dataConOrigArgTys,dataConName, + Outputable (..),dataConFieldLabels, + Plugin (..), + Var,flLabel,dataConRepType, + coVarDetails, + defaultPlugin, + idName, + mkInternalName, + mkLitString, + mkLocalVar, + mkVarOcc, + moduleNameString, + nameStableString, + noCafIdInfo, + purePlugin, + showSDocUnsafe, + tyVarKind, + unpackFS, + tyConName, + msHsFilePath ) +import Id (isExportedId,idType) +import Name (getSrcSpan) +import SrcLoc +import Unique (mkUnique) +import Var (isLocalId,varType) +import FieldInspector.Types +import TcRnTypes +import TcRnMonad +import DataCon +import CoreMonad (CoreM, CoreToDo (CoreDoPluginPass)) +import CoreSyn ( + AltCon (..), + Bind (NonRec, Rec), + CoreBind, + CoreExpr, + Expr (..), + ) +import Bag (bagToList) import GHC.Hs ( ConDecl ( ConDeclGADT, @@ -85,6 +140,7 @@ import GHC.Hs ( import GhcPlugins ( CommandLineOption, HsParsedModule (..), + PluginRecompile(..), Hsc, ModGuts (mg_binds, mg_loc), ModSummary (..), @@ -118,8 +174,61 @@ import SrcLoc ( getLoc, unLoc, ) -import Streamly (parallely) -import Streamly.Prelude (fromList, mapM, toList) +import TcRnMonad (MonadIO (liftIO)) +import TcRnTypes (TcGblEnv (tcg_binds), TcM) +import TyCoRep (Type (AppTy, FunTy, TyConApp, TyVarTy)) +import Var (varName, varType) +#endif + +import FieldInspector.Types +import Control.Concurrent (MVar, modifyMVar, newMVar) +import Data.Aeson +import Data.Aeson.Encode.Pretty (encodePretty) +import qualified Data.ByteString as DBS +import Data.ByteString.Lazy (toStrict) +import Data.Int (Int64) +import Data.List.Extra (intercalate, isSuffixOf, replace, splitOn,groupBy) +import Data.List ( sortBy, intercalate ,foldl') +import qualified Data.Map as Map +import Data.Text (Text, concat, isInfixOf, pack, unpack) +import qualified Data.Text as T +import Data.Text.Encoding (decodeUtf8, encodeUtf8) +import Data.Time +import Data.Map (Map) +import Data.Data +import Data.Maybe (catMaybes) +import Control.Monad.IO.Class (liftIO) +import System.IO (writeFile) +import Control.Monad (forM) +import Streamly.Internal.Data.Stream hiding (concatMap, init, length, map, splitOn,foldl',intercalate) +import System.Directory (createDirectoryIfMissing, removeFile) +import System.Directory.Internal.Prelude hiding (mapM, mapM_) +import Prelude hiding (id, mapM, mapM_) +import Control.Exception (evaluate) +import Control.Exception (evaluate) +import Control.Reference (biplateRef, (^?)) +import Data.Aeson.Encode.Pretty (encodePretty) +import Data.Bool (bool) +import qualified Data.ByteString as DBS +import Data.ByteString.Lazy (toStrict) +import Data.Data (Data (toConstr)) +import Data.Generics.Uniplate.Data () +import Data.List (sortBy) +import Data.List.Extra (groupBy, intercalate, splitOn) +import Data.Map (Map) +import qualified Data.Map as Map +import Data.Maybe (mapMaybe) +import Data.Text (Text, pack) +import qualified Data.Text as T +import FieldInspector.Types ( + DataConInfo (..), + DataTypeUC (DataTypeUC), + FieldRep (FieldRep), + FieldUsage (FieldUsage), + TypeInfo (..), + TypeVsFields (TypeVsFields), + ) +import Streamly.Internal.Data.Stream (fromList, mapM, toList) import System.Directory (createDirectoryIfMissing, removeFile) import System.Directory.Internal.Prelude ( catMaybes, @@ -129,17 +238,13 @@ import System.Directory.Internal.Prelude ( on, throwIO, ) -import TcRnMonad (MonadIO (liftIO)) -import TcRnTypes (TcGblEnv (tcg_binds), TcM) -import TyCoRep (Type (AppTy, FunTy, TyConApp, TyVarTy)) -import Var (varName, varType) import Prelude hiding (id, mapM, mapM_) plugin :: Plugin plugin = defaultPlugin { installCoreToDos = install - , pluginRecompile = GhcPlugins.purePlugin + , pluginRecompile = (\_ -> return NoForceRecompile) , typeCheckResultAction = collectTypesTC } install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo] @@ -155,17 +260,17 @@ removeIfExists fileName = removeFile fileName `catch` handleExists collectTypesTC :: [CommandLineOption] -> ModSummary -> TcGblEnv -> TcM TcGblEnv collectTypesTC opts modSummary tcEnv = do _ <- liftIO $ - forkIO $ - do - let prefixPath = case opts of - [] -> "/tmp/fieldInspector/" - local : _ -> local - modulePath = prefixPath <> msHsFilePath modSummary - path = (intercalate "/" . init . splitOn "/") modulePath - binds = bagToList $ tcg_binds tcEnv - createDirectoryIfMissing True path - functionVsUpdates <- getAllTypeManipulations binds - DBS.writeFile ((modulePath) <> ".typeUpdates.json") (toStrict $ encodePretty functionVsUpdates) + forkIO $ + do + let prefixPath = case opts of + [] -> "/tmp/fieldInspector/" + local : _ -> local + modulePath = prefixPath <> msHsFilePath modSummary + path = (intercalate "/" . init . splitOn "/") modulePath + binds = bagToList $ tcg_binds tcEnv + createDirectoryIfMissing True path + functionVsUpdates <- getAllTypeManipulations binds + DBS.writeFile ((modulePath) <> ".typeUpdates.json") (toStrict $ encodePretty functionVsUpdates) return tcEnv buildCfgPass :: [CommandLineOption] -> ModGuts -> CoreM ModGuts @@ -179,7 +284,7 @@ buildCfgPass opts guts = do moduleLoc = prefixPath Prelude.<> getFilePath (mg_loc guts) createDirectoryIfMissing True ((intercalate "/" . init . splitOn "/") moduleLoc) removeIfExists (moduleLoc Prelude.<> ".fieldUsage.json") - l <- toList $ parallely $ mapM (liftIO . toLBind) (fromList binds) + l <- toList $ mapM (liftIO . toLBind) (fromList binds) DBS.writeFile (moduleLoc Prelude.<> ".fieldUsage.json") =<< (evaluate $ toStrict $ encodePretty $ Map.fromList $ groupByFunction $ Prelude.concat l) return guts @@ -187,18 +292,22 @@ getAllTypeManipulations :: [LHsBindLR GhcTc GhcTc] -> IO [DataTypeUC] getAllTypeManipulations binds = do bindWiseUpdates <- toList $ - parallely $ mapM ( \x -> do let functionName = getFunctionName x - filterRecordUpdateAndCon = Prelude.filter (\x -> ((show $ toConstr x) `Prelude.elem` ["RecordCon", "RecordUpd"])) (x ^? biplateRef :: [HsExpr GhcTc]) + filterRecordUpdateAndCon = Prelude.filter (\x -> ((show $ toConstr x) `Prelude.elem` ["HsGetField","RecordCon", "RecordUpd"])) (x ^? biplateRef :: [HsExpr GhcTc]) + print functionName pure $ bool (Nothing) (Just (DataTypeUC functionName (Data.Maybe.mapMaybe getDataTypeDetails filterRecordUpdateAndCon))) (not (Prelude.null filterRecordUpdateAndCon)) ) (fromList binds) - pure $ catMaybes bindWiseUpdates + pure $ System.Directory.Internal.Prelude.catMaybes bindWiseUpdates where getDataTypeDetails :: HsExpr GhcTc -> Maybe TypeVsFields - getDataTypeDetails (RecordCon _ (L _ (iD)) rcon_flds) = Just (TypeVsFields (T.pack $ nameStableString $ getName $ idName iD) (extractRecordBinds (rcon_flds))) +#if __GLASGOW_HASKELL__ >= 900 + getDataTypeDetails (RecordCon _ (iD) rcon_flds) = Just (TypeVsFields (T.pack $ nameStableString $ getName (GHC.unXRec @(GhcTc) iD)) (extractRecordBinds (rcon_flds))) +#else + getDataTypeDetails (RecordCon _ (iD) rcon_flds) = Just (TypeVsFields (T.pack $ nameStableString $ getName $ idName $ unLoc $ iD) (extractRecordBinds (rcon_flds))) +#endif getDataTypeDetails (RecordUpd _ rupd_expr rupd_flds) = Just (TypeVsFields (T.pack $ showSDocUnsafe $ ppr rupd_expr) (getFieldUpdates rupd_flds)) -- inferFieldType :: Name -> String @@ -213,18 +322,32 @@ getAllTypeManipulations binds = do Orig module' occName -> ((moduleNameString $ moduleName module') <> "$" <> (showSDocUnsafe $ pprNameSpaceBrief $ occNameSpace occName) <> "$" <> (occNameString occName) <> "$" <> (unpackFS $ occNameFS occName)) Exact name -> nameStableString name - getFieldUpdates :: [LHsRecUpdField GhcTc] -> [FieldRep] - getFieldUpdates fields = map extractField fields +#if __GLASGOW_HASKELL__ >= 900 + getFieldUpdates :: Either [LHsRecUpdField GhcTc] [LHsRecUpdProj GhcTc] -> Either [FieldRep] [Text] + getFieldUpdates fields = + case fields of + Left x -> (Left . map (extractField . unLoc)) x + Right x -> (Right . map (T.pack . showSDocUnsafe . ppr)) x + where + extractField :: HsRecUpdField GhcTc -> FieldRep + extractField (HsRecField{hsRecFieldLbl = lbl, hsRecFieldArg = expr, hsRecPun = pun}) = + if pun + then (FieldRep (T.pack $ showSDocUnsafe $ ppr lbl) (T.pack $ showSDocUnsafe $ ppr lbl) (T.pack $ inferFieldTypeAFieldOcc lbl)) + else (FieldRep (T.pack $ showSDocUnsafe $ ppr lbl) (T.pack $ showSDocUnsafe $ ppr (unLoc expr)) (T.pack $ inferFieldTypeAFieldOcc lbl)) +#else + getFieldUpdates :: [LHsRecUpdField GhcTc]-> Either [FieldRep] [Text] + getFieldUpdates fields = Left $ map extractField fields where extractField :: LHsRecUpdField GhcTc -> FieldRep extractField (L _ (HsRecField{hsRecFieldLbl = lbl, hsRecFieldArg = expr, hsRecPun = pun})) = if pun then (FieldRep (T.pack $ showSDocUnsafe $ ppr lbl) (T.pack $ showSDocUnsafe $ ppr lbl) (T.pack $ inferFieldTypeAFieldOcc lbl)) else (FieldRep (T.pack $ showSDocUnsafe $ ppr lbl) (T.pack $ showSDocUnsafe $ ppr (unLoc expr)) (T.pack $ inferFieldTypeAFieldOcc lbl)) +#endif - extractRecordBinds :: HsRecFields GhcTc (LHsExpr GhcTc) -> [FieldRep] + extractRecordBinds :: HsRecFields GhcTc (LHsExpr GhcTc) -> Either [FieldRep] [Text] extractRecordBinds (HsRecFields{rec_flds = fields}) = - map extractField fields + Left $ map extractField fields where extractField :: LHsRecField GhcTc (LHsExpr GhcTc) -> FieldRep extractField (L _ (HsRecField{hsRecFieldLbl = lbl, hsRecFieldArg = expr, hsRecPun = pun})) = @@ -233,29 +356,47 @@ getAllTypeManipulations binds = do else (FieldRep (T.pack $ showSDocUnsafe $ ppr lbl) (T.pack $ showSDocUnsafe $ ppr $ unLoc expr) (T.pack $ inferFieldTypeFieldOcc lbl)) getFunctionName :: LHsBindLR GhcTc GhcTc -> [Text] +#if __GLASGOW_HASKELL__ >= 900 + getFunctionName (L _ x@(FunBind fun_ext id matches _)) = [T.pack $ nameStableString $ getName id] +#else getFunctionName (L _ x@(FunBind fun_ext id matches _ _)) = [T.pack $ nameStableString $ getName id] - getFunctionName (L _ (VarBind{var_id = var, var_rhs = expr, var_inline = inline})) = [T.pack $ nameStableString $ getName var] +#endif + getFunctionName (L _ (VarBind{var_id = var, var_rhs = expr})) = [T.pack $ nameStableString $ getName var] getFunctionName (L _ (PatBind{pat_lhs = pat, pat_rhs = expr})) = [""] getFunctionName (L _ (AbsBinds{abs_binds = binds})) = Prelude.concatMap getFunctionName $ bagToList binds processPat :: LPat GhcTc -> [(Name, Maybe Text)] processPat (L _ pat) = case pat of +#if __GLASGOW_HASKELL__ >= 900 + ConPat _ _ details -> processDetails details +#else ConPatIn _ details -> processDetails details +#endif VarPat _ x@(L _ var) -> [(varName var, Just $ T.pack $ showSDocUnsafe $ ppr $ getLoc $ x)] ParPat _ pat' -> processPat pat' _ -> [] processDetails :: HsConPatDetails GhcTc -> [(Name, Maybe Text)] +#if __GLASGOW_HASKELL__ >= 900 +processDetails (PrefixCon _ args) = Prelude.concatMap processPat args +#else processDetails (PrefixCon args) = Prelude.concatMap processPat args +#endif processDetails (InfixCon arg1 arg2) = processPat arg1 <> processPat arg2 processDetails (RecCon rec) = Prelude.concatMap processPatField (rec_flds rec) processPatField :: LHsRecField GhcTc (LPat GhcTc) -> [(Name, Maybe Text)] processPatField (L _ HsRecField{hsRecFieldArg = arg}) = processPat arg +#if __GLASGOW_HASKELL__ >= 900 +getFilePath :: SrcSpan -> String +getFilePath (RealSrcSpan rSSpan _) = unpackFS $ srcSpanFile rSSpan +getFilePath (UnhelpfulSpan fs) = showSDocUnsafe $ ppr $ fs +#else getFilePath :: SrcSpan -> String getFilePath (RealSrcSpan rSSpan) = unpackFS $ srcSpanFile rSSpan getFilePath (UnhelpfulSpan fs) = unpackFS fs +#endif -- 1. `HasField _ r _` where r is a variable @@ -318,7 +459,11 @@ processHasField functionName (Var x) (Var hasField) = do else do print y pure res +#if __GLASGOW_HASKELL__ >= 900 + (FunTy _ _ a _) -> do +#else (FunTy _ a _) -> do +#endif let fieldType = T.strip $ Prelude.last $ T.splitOn "->" $ pack $ showSDocUnsafe $ ppr $ varType hasField pure $ res @@ -481,7 +626,6 @@ toLBind (NonRec binder expr) = do toLBind (Rec binds) = do r <- toList $ - parallely $ mapM ( \(b, e) -> do toLexpr (pack $ nameStableString (idName b)) e @@ -492,7 +636,11 @@ toLBind (Rec binds) = do processFieldExtraction :: Text -> Var -> Var -> Text -> IO [(Text, [FieldUsage])] processFieldExtraction functionName _field _type b = do res <- case (varType _field) of +#if __GLASGOW_HASKELL__ >= 900 + (FunTy _ _ a _) -> do +#else (FunTy _ a _) -> do +#endif let fieldType = T.strip $ Prelude.last $ T.splitOn "->" $ pack $ showSDocUnsafe $ ppr $ varType _field pure [ @@ -560,7 +708,7 @@ toLexpr functionName (Var x) = pure mempty toLexpr functionName (Lit x) = pure mempty toLexpr functionName (Type _id) = pure mempty toLexpr functionName x@(App func@(App _ _) args@(Var isHasField)) - | "$_sys$$dHasField" == pack (nameStableString $ idName isHasField) = + | "$_sys$$dHasField" == pack (nameStableString $ idName isHasField) = do processHasField functionName func args | otherwise = do processApp functionName x @@ -575,7 +723,7 @@ toLexpr functionName (Let func args) = do pure $ map (\(x, y) -> (functionName, y)) f <> a toLexpr functionName (Case condition bind _type alts) = do c <- toLexpr functionName condition - a <- toList $ parallely $ mapM (toLAlt functionName) (fromList alts) + a <- toList $ mapM (toLAlt functionName) (fromList alts) pure $ c <> Prelude.concat a toLexpr functionName (Tick _ expr) = toLexpr functionName expr toLexpr functionName (Cast expr _) = toLexpr functionName expr @@ -586,6 +734,22 @@ processApp functionName x@(App func args) = do a <- toLexpr functionName args pure $ f <> a +#if __GLASGOW_HASKELL__ >= 900 +toLAlt :: Text -> Alt Var -> IO [(Text, [FieldUsage])] +toLAlt x (Alt a b c) = toLAlt' x (a,b,c) + where + toLAlt' :: Text -> (AltCon, [Var], CoreExpr) -> IO [(Text, [FieldUsage])] + toLAlt' functionName (DataAlt dataCon, val, e) = do + let typeName = GhcPlugins.tyConName $ GhcPlugins.dataConTyCon dataCon + extractingConstruct = showSDocUnsafe $ ppr $ GhcPlugins.dataConName dataCon + kindStr = showSDocUnsafe $ ppr $ tyConKind $ GhcPlugins.dataConTyCon dataCon + res <- toLexpr functionName e + pure $ ((map (\x -> (functionName, [FieldUsage (pack $ showSDocUnsafe $ ppr $ typeName) (pack $ extractingConstruct) (pack $ showSDocUnsafe $ ppr $ varType x) (pack $ nameStableString $ typeName) (pack $ showSDocUnsafe $ ppr x)])) val)) <> res + toLAlt' functionName (LitAlt lit, val, e) = + toLexpr functionName e + toLAlt' functionName (DEFAULT, val, e) = + toLexpr functionName e +#else toLAlt :: Text -> (AltCon, [Var], CoreExpr) -> IO [(Text, [FieldUsage])] toLAlt functionName (DataAlt dataCon, val, e) = do let typeName = GhcPlugins.tyConName $ GhcPlugins.dataConTyCon dataCon @@ -597,71 +761,10 @@ toLAlt functionName (LitAlt lit, val, e) = toLexpr functionName e toLAlt functionName (DEFAULT, val, e) = toLexpr functionName e +#endif pprTyCon :: Name -> SDoc pprTyCon = ppr pprDataCon :: Name -> SDoc -pprDataCon = ppr - -collectTypeInfoParser :: [CommandLineOption] -> ModSummary -> HsParsedModule -> Hsc HsParsedModule -collectTypeInfoParser opts modSummary hpm = do - _ <- liftIO $ - do - let prefixPath = case opts of - [] -> "/tmp/fieldInspector/" - local : _ -> local - moduleName' = moduleNameString $ GhcPlugins.moduleName $ ms_mod modSummary - modulePath = prefixPath <> msHsFilePath modSummary - hm_module = unLoc $ hpm_module hpm - path = (intercalate "/" . init . splitOn "/") modulePath - -- print ("generating types data for module: " <> moduleName' <> " at path: " <> path) - types <- toList $ parallely $ mapM (pure . getTypeInfo) (fromList $ hsmodDecls hm_module) - createDirectoryIfMissing True path - DBS.writeFile (modulePath <> ".types.parser.json") (toStrict $ encodePretty $ Map.fromList $ Prelude.concat types) - -- print ("generated types data for module: " <> moduleName' <> " at path: " <> path) - return hpm - -getTypeInfo :: LHsDecl GhcPs -> [(String, TypeInfo)] -getTypeInfo (L _ (TyClD _ (DataDecl _ lname _ _ defn))) = - [ - ( showSDocUnsafe (ppr lname) - , TypeInfo - { name = showSDocUnsafe (ppr lname) - , typeKind = "data" - , dataConstructors = map getDataConInfo (dd_cons defn) - } - ) - ] -getTypeInfo (L _ (TyClD _ (SynDecl _ lname _ _ rhs))) = - [ - ( showSDocUnsafe (ppr lname) - , TypeInfo - { name = showSDocUnsafe (ppr lname) - , typeKind = "type" - , dataConstructors = [DataConInfo (showSDocUnsafe (ppr lname)) (Map.singleton "synonym" (showSDocUnsafe (ppr rhs))) []] - } - ) - ] -getTypeInfo _ = [] - -getDataConInfo :: LConDecl GhcPs -> DataConInfo -getDataConInfo (L _ ConDeclH98{con_name = lname, con_args = args}) = - DataConInfo - { dataConNames = showSDocUnsafe (ppr lname) - , fields = getFieldMap args - , sumTypes = [] -- For H98-style data constructors, sum types are not applicable - } -getDataConInfo (L _ ConDeclGADT{con_names = lnames, con_res_ty = ty}) = - DataConInfo - { dataConNames = intercalate ", " (map (showSDocUnsafe . ppr) lnames) - , fields = Map.singleton "gadt" (showSDocUnsafe (ppr ty)) - , sumTypes = [] -- For GADT-style data constructors, sum types can be represented by the type itself - } - -getFieldMap :: HsConDeclDetails GhcPs -> Map String String -getFieldMap (PrefixCon args) = Map.fromList $ Prelude.zipWith (\i t -> (show i, showSDocUnsafe (ppr t))) [1 ..] args -getFieldMap (RecCon (L _ fields)) = Map.fromList $ concatMap getRecField fields - where - getRecField (L _ (ConDeclField _ fnames t _)) = [(showSDocUnsafe (ppr fname), showSDocUnsafe (ppr t)) | L _ fname <- fnames] -getFieldMap (InfixCon t1 t2) = Map.fromList [("field1", showSDocUnsafe (ppr t1)), ("field2", showSDocUnsafe (ppr t2))] +pprDataCon = ppr \ No newline at end of file diff --git a/fieldInspector/src/FieldInspector/PluginTypes.hs b/fieldInspector/src/FieldInspector/PluginTypes.hs index 4530eef..5add1ca 100644 --- a/fieldInspector/src/FieldInspector/PluginTypes.hs +++ b/fieldInspector/src/FieldInspector/PluginTypes.hs @@ -7,7 +7,30 @@ module FieldInspector.PluginTypes (plugin) where -import Control.Concurrent (MVar, modifyMVar, newMVar) +#if __GLASGOW_HASKELL__ >= 900 +import Language.Haskell.Syntax.Type +import GHC.Hs.Extension () +import GHC.Parser.Annotation () +import GHC.Utils.Outputable () +import qualified Data.IntMap.Internal as IntMap +import Streamly.Internal.Data.Stream (fromList,mapM_,mapM,toList) +import GHC +import GHC.Driver.Plugins (Plugin(..),CommandLineOption,defaultPlugin,PluginRecompile(..)) +import GHC.Driver.Env +import GHC.Tc.Types +import GHC.Unit.Module.ModSummary +import GHC.Utils.Outputable (showSDocUnsafe,ppr,SDoc,Outputable) +import GHC.Data.Bag (bagToList) +import GHC.Types.Name hiding (varName) +import GHC.Types.Var +import qualified Data.Aeson.KeyMap as HM +import GHC.Core.Opt.Monad +import GHC.Rename.HsType +-- import GHC.HsToCore.Docs +import GHC.Types.Name.Reader + + +#else import CoreMonad (CoreM, CoreToDo (CoreDoPluginPass), liftIO) import CoreSyn ( AltCon (..), @@ -17,26 +40,9 @@ import CoreSyn ( Expr (..), mkStringLit ) -import Data.Aeson -import Data.Aeson.Encode.Pretty (encodePretty) -import qualified Data.ByteString as DBS -import Data.ByteString.Lazy (toStrict) -import Data.Int (Int64) -import Data.List.Extra (intercalate, isSuffixOf, replace, splitOn,groupBy) -import Data.List ( sortBy, intercalate ,foldl') -import qualified Data.Map as Map -import Data.Text (Text, concat, isInfixOf, pack, unpack) -import qualified Data.Text as T -import Data.Text.Encoding (decodeUtf8, encodeUtf8) -import Data.Time import TyCoRep import GHC.IO (unsafePerformIO) import GHC.Hs -import Data.Map (Map) -import Data.Data -import Data.Maybe (catMaybes) -import Control.Monad.IO.Class (liftIO) -import System.IO (writeFile) import GHC.Hs.Decls import GhcPlugins ( CommandLineOption,Arg (..), @@ -47,7 +53,7 @@ import GhcPlugins ( ModGuts (mg_binds, mg_loc, mg_module),showSDoc, Module (moduleName),tyConKind, NamedThing (getName),getDynFlags,tyConDataCons,dataConOrigArgTys,dataConName, - Outputable (..),dataConFieldLabels, + Outputable (..),dataConFieldLabels,PluginRecompile(..), Plugin (..), Var,flLabel,dataConRepType, coVarDetails, @@ -69,29 +75,50 @@ import GhcPlugins ( ) import Id (isExportedId,idType) import Name (getSrcSpan) -import Control.Monad (forM) import SrcLoc -import Streamly (parallely, serially) -import Streamly.Prelude hiding (concatMap, init, length, map, splitOn,foldl') -import System.Directory (createDirectoryIfMissing, removeFile) -import System.Directory.Internal.Prelude hiding (mapM, mapM_) import Unique (mkUnique) import Var (isLocalId,varType) -import Prelude hiding (id, mapM, mapM_) import FieldInspector.Types import TcRnTypes import TcRnMonad import DataCon +#endif +import Debug.Trace + +import FieldInspector.Types +import Control.Concurrent (MVar, modifyMVar, newMVar) +import Data.Aeson +import Data.Aeson.Encode.Pretty (encodePretty) +import qualified Data.ByteString as DBS +import Data.ByteString.Lazy (toStrict) +import Data.Int (Int64) +import Data.List.Extra (intercalate, isSuffixOf, replace, splitOn,groupBy) +import Data.List ( sortBy, intercalate ,foldl') +import qualified Data.Map as Map +import Data.Text (Text, concat, isInfixOf, pack, unpack) +import qualified Data.Text as T +import Data.Text.Encoding (decodeUtf8, encodeUtf8) +import Data.Time +import Data.Map (Map) +import Data.Data +import Data.Maybe (catMaybes) +import Control.Monad.IO.Class (liftIO) +import System.IO (writeFile) +import Control.Monad (forM) +import Streamly.Internal.Data.Stream hiding (concatMap, init, length, map, splitOn,foldl',intercalate) +import System.Directory (createDirectoryIfMissing, removeFile) +import System.Directory.Internal.Prelude hiding (mapM, mapM_) +import Prelude hiding (id, mapM, mapM_) +import Control.Exception (evaluate) import qualified Data.Record.Plugin as DRP import qualified Data.Record.Anon.Plugin as DRAP import qualified Data.Record.Plugin.HasFieldPattern as DRPH import qualified RecordDotPreprocessor as RDP -import Control.Exception (evaluate) plugin :: Plugin plugin = (defaultPlugin{ -- installCoreToDos = install - pluginRecompile = GhcPlugins.purePlugin + pluginRecompile = (\_ -> return NoForceRecompile) , parsedResultAction = collectTypeInfoParser }) #if defined(ENABLE_LR_PLUGINS) @@ -162,12 +189,12 @@ collectTypeInfoParser opts modSummary hpm = do let prefixPath = case opts of [] -> "/tmp/fieldInspector/" local : _ -> local - moduleName' = moduleNameString $ GhcPlugins.moduleName $ ms_mod modSummary + moduleName' = moduleNameString $ moduleName $ ms_mod modSummary modulePath = prefixPath <> msHsFilePath modSummary hm_module = unLoc $ hpm_module hpm path = (intercalate "/" . init . splitOn "/") modulePath -- print ("generating types data for module: " <> moduleName' <> " at path: " <> path) - types <- toList $ parallely $ mapM (pure . getTypeInfo) (fromList $ hsmodDecls hm_module) + types <- toList $ mapM (pure . getTypeInfo) (fromList $ hsmodDecls hm_module) createDirectoryIfMissing True path DBS.writeFile (modulePath <> ".types.parser.json") =<< (evaluate $ toStrict $ encodePretty $ Map.fromList $ Prelude.concat types) -- print ("generated types data for module: " <> moduleName' <> " at path: " <> path) @@ -175,36 +202,91 @@ collectTypeInfoParser opts modSummary hpm = do getTypeInfo :: LHsDecl GhcPs -> [(String,TypeInfo)] getTypeInfo (L _ (TyClD _ (DataDecl _ lname _ _ defn))) = - [(showSDocUnsafe (ppr lname) ,TypeInfo - { name = showSDocUnsafe (ppr lname) + [((showSDocUnsafe' lname) ,TypeInfo + { name = showSDocUnsafe' lname , typeKind = "data" , dataConstructors = map getDataConInfo (dd_cons defn) })] getTypeInfo (L _ (TyClD _ (SynDecl _ lname _ _ rhs))) = - [(showSDocUnsafe (ppr lname),TypeInfo - { name = showSDocUnsafe (ppr lname) + [((showSDocUnsafe' lname),TypeInfo + { name = showSDocUnsafe' lname , typeKind = "type" - , dataConstructors = [DataConInfo (showSDocUnsafe (ppr lname)) (Map.singleton "synonym" (showSDocUnsafe (ppr rhs))) []] +#if __GLASGOW_HASKELL__ >= 900 + , dataConstructors = [DataConInfo (showSDocUnsafe' lname) (maybe mempty (Map.singleton "synonym" . unpackHDS) (hsTypeToString $ unLoc rhs)) []] +#else + , dataConstructors = [DataConInfo (showSDocUnsafe' lname) (Map.singleton "synonym" ((showSDocUnsafe . ppr . unLoc) rhs)) []] +#endif })] getTypeInfo _ = [] +instance Outputable Void where + getDataConInfo :: LConDecl GhcPs -> DataConInfo -getDataConInfo (L _ ConDeclH98{ con_name = lname, con_args = args }) = - DataConInfo - { dataConNames = showSDocUnsafe (ppr lname) - , fields = getFieldMap args - , sumTypes = [] -- For H98-style data constructors, sum types are not applicable - } +getDataConInfo (L _ x@ConDeclH98{ con_name = lname, con_args = args }) = + Debug.Trace.trace (showSDocUnsafe $ ppr args) $ + DataConInfo + { dataConNames = showSDocUnsafe' lname + , fields = getFieldMap args + , sumTypes = [] -- For H98-style data constructors, sum types are not applicable + } getDataConInfo (L _ ConDeclGADT{ con_names = lnames, con_res_ty = ty }) = DataConInfo - { dataConNames = intercalate ", " (map (showSDocUnsafe . ppr) lnames) - , fields = Map.singleton "gadt" (showSDocUnsafe (ppr ty)) + { dataConNames = intercalate ", " (map (showSDocUnsafe') lnames) +#if __GLASGOW_HASKELL__ >= 900 + , fields = maybe (mempty) (\x -> Map.singleton "gadt" $ unpackHDS x) (hsTypeToString $ unLoc ty) +#else + , fields = Map.singleton "gadt" (showSDocUnsafe $ ppr ty) +#endif , sumTypes = [] -- For GADT-style data constructors, sum types can be represented by the type itself } +#if __GLASGOW_HASKELL__ >= 900 +hsTypeToString :: HsType GhcPs -> Maybe HsDocString +hsTypeToString = f + where + f :: HsType GhcPs -> Maybe HsDocString + f (HsDocTy _ _ lds) = Just (unLoc lds) + f (HsBangTy _ _ (L _ (HsDocTy _ _ lds))) = Just (unLoc lds) + f x = Just (mkHsDocString $ showSDocUnsafe $ ppr x) + +extractInfixCon :: [HsType GhcPs] -> Map.Map String String +extractInfixCon x = + let l = length x + in Map.fromList $ map (\(a,b) -> (show a , b)) $ Prelude.zip [0..l] (map f x) + where + f :: HsType GhcPs -> (String) + f (HsDocTy _ _ lds) = showSDocUnsafe $ ppr $ (unLoc lds) + f (HsBangTy _ _ (L _ (HsDocTy _ _ lds))) = showSDocUnsafe $ ppr $ (unLoc lds) + f x = (showSDocUnsafe $ ppr x) + +extractConDeclField :: [ConDeclField GhcPs] -> Map.Map String String +extractConDeclField x = Map.fromList (go x) + where + go :: [ConDeclField GhcPs] -> [(String,String)] + go [] = [] + go ((ConDeclField _ cd_fld_names cd_fld_type _):xs) = + [((intercalate "," $ convertRdrNameToString cd_fld_names),(showSDocUnsafe $ ppr cd_fld_type))] <> (go xs) + + convertRdrNameToString x = map (showSDocUnsafe . ppr . rdrNameOcc . unLoc . reLocN . rdrNameFieldOcc . unXRec @(GhcPs)) x + +getFieldMap :: HsConDeclH98Details GhcPs -> Map.Map String String +getFieldMap con_args = + case con_args of + PrefixCon _ args -> extractInfixCon $ map (unLoc . hsScaledThing) args + InfixCon arg1 arg2 -> extractInfixCon $ map (unLoc . hsScaledThing) [arg1,arg2] + RecCon (fields) -> extractConDeclField $ map unLoc $ (unXRec @(GhcPs)) fields + +#else getFieldMap :: HsConDeclDetails GhcPs -> Map String String getFieldMap (PrefixCon args) = Map.fromList $ Prelude.zipWith (\i t -> (show i, showSDocUnsafe (ppr t))) [1..] args getFieldMap (RecCon (L _ fields)) = Map.fromList $ concatMap getRecField fields where getRecField (L _ (ConDeclField _ fnames t _)) = [(showSDocUnsafe (ppr fname), showSDocUnsafe (ppr t)) | L _ fname <- fnames] getFieldMap (InfixCon t1 t2) = Map.fromList [("field1", showSDocUnsafe (ppr t1)), ("field2", showSDocUnsafe (ppr t2))] +#endif + +#if __GLASGOW_HASKELL__ >= 900 +showSDocUnsafe' = showSDocUnsafe . ppr . GHC.unXRec @(GhcPs) +#else +showSDocUnsafe' = showSDocUnsafe . ppr +#endif \ No newline at end of file diff --git a/fieldInspector/src/FieldInspector/Types.hs b/fieldInspector/src/FieldInspector/Types.hs index d504144..2b88b62 100644 --- a/fieldInspector/src/FieldInspector/Types.hs +++ b/fieldInspector/src/FieldInspector/Types.hs @@ -43,7 +43,7 @@ data DataTypeUC = DataTypeUC { data TypeVsFields = TypeVsFields { type_name :: Text - , fieldsVsExprs :: [(FieldRep)] + , fieldsVsExprs :: Either [(FieldRep)] [Text] } deriving (Show, Eq, Ord,Binary,Generic,NFData,ToJSON,FromJSON) data FieldRep = FieldRep { diff --git a/fieldInspector/test/Main.hs b/fieldInspector/test/Main.hs index a164cbe..1e91562 100644 --- a/fieldInspector/test/Main.hs +++ b/fieldInspector/test/Main.hs @@ -10,11 +10,10 @@ main = do print $ demo $ (A "Test suite not yet implemented." 0) pure () - data A = A {name :: String,age :: Int} deriving (Generic,Show) demo :: A -> String demo a = case a of - (A {name}) -> name \ No newline at end of file + (A {name}) -> name \ No newline at end of file diff --git a/flake.lock b/flake.lock index 3fa8b73..cb7eda3 100644 --- a/flake.lock +++ b/flake.lock @@ -1,19 +1,41 @@ { "nodes": { - "classyplate": { + "beam": { "flake": false, "locked": { - "lastModified": 1678370822, - "narHash": "sha256-8AJ/55ShKCe49MEcyMqzJ3ADjs5dvtuTIhuTTq2q5nQ=", - "owner": "Chaitanya-nair", + "lastModified": 1716967568, + "narHash": "sha256-8K7EPhhS6cUz0Qrmrwj8lJYftq8u749tD3/uTcC5nHU=", + "owner": "well-typed", + "repo": "beam", + "rev": "57a12e68727c027f0f1c25752f8c5704ddbe1516", + "type": "github" + }, + "original": { + "owner": "well-typed", + "repo": "beam", + "rev": "57a12e68727c027f0f1c25752f8c5704ddbe1516", + "type": "github" + } + }, + "classyplate": { + "inputs": { + "flake-parts": "flake-parts", + "haskell-flake": "haskell-flake", + "nixpkgs": "nixpkgs", + "systems": "systems" + }, + "locked": { + "lastModified": 1721385699, + "narHash": "sha256-Gof2hSQSX581LA8GGnHGjXWu5F899Cot+Id1SYxlUMY=", + "owner": "eswar2001", "repo": "classyplate", - "rev": "46f5e0e7073e1d047f70473bf3c75366a613bfeb", + "rev": "a360f56820df6ca5284091f318bcddcd3e065243", "type": "github" }, "original": { - "owner": "Chaitanya-nair", + "owner": "eswar2001", "repo": "classyplate", - "rev": "46f5e0e7073e1d047f70473bf3c75366a613bfeb", + "rev": "a360f56820df6ca5284091f318bcddcd3e065243", "type": "github" } }, @@ -21,6 +43,24 @@ "inputs": { "nixpkgs-lib": "nixpkgs-lib" }, + "locked": { + "lastModified": 1719994518, + "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, "locked": { "lastModified": 1717285511, "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", @@ -35,9 +75,45 @@ "type": "github" } }, - "flake-parts_2": { + "flake-parts_3": { "inputs": { - "nixpkgs-lib": "nixpkgs-lib_2" + "nixpkgs-lib": "nixpkgs-lib_3" + }, + "locked": { + "lastModified": 1719994518, + "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_4" + }, + "locked": { + "lastModified": 1719994518, + "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_5": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_5" }, "locked": { "lastModified": 1685662779, @@ -54,23 +130,43 @@ } }, "ghc-hasfield-plugin": { - "flake": false, + "inputs": { + "flake-parts": "flake-parts_4", + "haskell-flake": "haskell-flake_3", + "nixpkgs": "nixpkgs_2", + "systems": "systems_2" + }, "locked": { - "lastModified": 1658487566, - "narHash": "sha256-pZ6kFNfRtBWWqJ3zZSJhZQz7hcdgTdpkqUbzRCuRSl8=", - "owner": "juspay", + "lastModified": 1721371073, + "narHash": "sha256-1xTFZRE/vAHV/mLMW5rNyZH1SkkbyFqDxXZvw7JwOHo=", + "owner": "eswar2001", "repo": "ghc-hasfield-plugin", - "rev": "d82ac5a6c0ad643eebe2b9b32c91f6523d3f30dc", + "rev": "c932ebc0d7e824129bb70c8a078f3c68feed85c9", "type": "github" }, "original": { - "owner": "juspay", + "owner": "eswar2001", "repo": "ghc-hasfield-plugin", - "rev": "d82ac5a6c0ad643eebe2b9b32c91f6523d3f30dc", + "rev": "c932ebc0d7e824129bb70c8a078f3c68feed85c9", "type": "github" } }, "haskell-flake": { + "locked": { + "lastModified": 1721530802, + "narHash": "sha256-eUMmQKXjt4WQq+IBscftg/Y9bXWiOYhasfeH5Yb9Psc=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "f8f38ecd259338167cc0c85fd541479297a315af", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "haskell-flake", + "type": "github" + } + }, + "haskell-flake_2": { "locked": { "lastModified": 1719249394, "narHash": "sha256-ytIvs6dq1dD3eicwhmqMyhIDH52DfqhOiCpmJbjBYVI=", @@ -85,7 +181,37 @@ "type": "github" } }, - "haskell-flake_2": { + "haskell-flake_3": { + "locked": { + "lastModified": 1720977934, + "narHash": "sha256-k9kwz2lpUqafRUpuCMgkv4AWtHEoJPCds1ZPRkyW2XE=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "cd449f1c04175efdf5b553302d22916640090066", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "haskell-flake", + "type": "github" + } + }, + "haskell-flake_4": { + "locked": { + "lastModified": 1721530802, + "narHash": "sha256-eUMmQKXjt4WQq+IBscftg/Y9bXWiOYhasfeH5Yb9Psc=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "f8f38ecd259338167cc0c85fd541479297a315af", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "haskell-flake", + "type": "github" + } + }, + "haskell-flake_5": { "locked": { "lastModified": 1686160859, "narHash": "sha256-UE+0TQHyPxF8jhbLEeqvNQAy7B79bBix/rpFrf5nsn0=", @@ -101,39 +227,58 @@ } }, "large-records": { - "flake": false, + "inputs": { + "beam": "beam", + "flake-parts": "flake-parts_3", + "ghc-hasfield-plugin": "ghc-hasfield-plugin", + "haskell-flake": "haskell-flake_4", + "nixpkgs": "nixpkgs_3", + "systems": "systems_3" + }, "locked": { - "lastModified": 1719312727, - "narHash": "sha256-NLs4yiUh4vNf4sqOQUUTCr0Fpld1y6ZyZJNhqSTzAI0=", + "lastModified": 1721562622, + "narHash": "sha256-4XivoIvlVl7UyVCyZneeLIvyKBbRIvDEOEnJBxnZp+c=", "owner": "eswar2001", "repo": "large-records", - "rev": "e393f4501d76a98b4482b0a5b35d120ae70e5dd3", + "rev": "b60bcb312c7d55f1d638aa1a5143696e6586e76d", "type": "github" }, "original": { "owner": "eswar2001", "repo": "large-records", - "rev": "e393f4501d76a98b4482b0a5b35d120ae70e5dd3", + "rev": "b60bcb312c7d55f1d638aa1a5143696e6586e76d", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1643795778, - "narHash": "sha256-sBxYgXu+4JTpXPu3c1QGl2a2zzzDJj4VNsVatF1sEIY=", + "lastModified": 1698266953, + "narHash": "sha256-jf72t7pC8+8h8fUslUYbWTX5rKsRwOzRMX8jJsGqDXA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "43e3b6af08f29c4447a6073e3d5b86a4f45dd420", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", "type": "github" }, "original": { "owner": "nixos", "repo": "nixpkgs", - "rev": "43e3b6af08f29c4447a6073e3d5b86a4f45dd420", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", "type": "github" } }, "nixpkgs-lib": { + "locked": { + "lastModified": 1719876945, + "narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + } + }, + "nixpkgs-lib_2": { "locked": { "lastModified": 1717284937, "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", @@ -145,7 +290,31 @@ "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" } }, - "nixpkgs-lib_2": { + "nixpkgs-lib_3": { + "locked": { + "lastModified": 1719876945, + "narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + } + }, + "nixpkgs-lib_4": { + "locked": { + "lastModified": 1719876945, + "narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + } + }, + "nixpkgs-lib_5": { "locked": { "dir": "lib", "lastModified": 1685564631, @@ -165,69 +334,116 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1686582075, - "narHash": "sha256-vtflsfKkHtF8IduxDNtbme4cojiqvlvjp5QNYhvoHXc=", + "lastModified": 1698266953, + "narHash": "sha256-jf72t7pC8+8h8fUslUYbWTX5rKsRwOzRMX8jJsGqDXA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "7e63eed145566cca98158613f3700515b4009ce3", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", "type": "github" } }, - "record-dot-preprocessor": { - "flake": false, + "nixpkgs_3": { "locked": { - "lastModified": 1644582826, - "narHash": "sha256-BXprRyjI4ZTG+Orz858xmttiC8O0yuubaaKmeRAL/UY=", - "owner": "ndmitchell", - "repo": "record-dot-preprocessor", - "rev": "99452d27f35ea1ff677be9af570d834e8fab4caf", + "lastModified": 1698266953, + "narHash": "sha256-jf72t7pC8+8h8fUslUYbWTX5rKsRwOzRMX8jJsGqDXA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", "type": "github" }, "original": { - "owner": "ndmitchell", - "repo": "record-dot-preprocessor", - "rev": "99452d27f35ea1ff677be9af570d834e8fab4caf", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1698266953, + "narHash": "sha256-jf72t7pC8+8h8fUslUYbWTX5rKsRwOzRMX8jJsGqDXA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1698266953, + "narHash": "sha256-jf72t7pC8+8h8fUslUYbWTX5rKsRwOzRMX8jJsGqDXA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c", "type": "github" } }, "references": { "inputs": { - "flake-parts": "flake-parts_2", - "haskell-flake": "haskell-flake_2", - "nixpkgs": "nixpkgs_2" + "flake-parts": "flake-parts_5", + "haskell-flake": "haskell-flake_5", + "nixpkgs": "nixpkgs_5" }, "locked": { - "lastModified": 1686714318, - "narHash": "sha256-Ogy9S6cF/8WNfpcQ1k65rPjjTfWlH15Jp5JeraYaAQQ=", + "lastModified": 1721735703, + "narHash": "sha256-0F/xsz64sUwKQvKL5yuU+7+QPiyvlQFUb8zZI1ZTbrI=", "owner": "eswar2001", "repo": "references", - "rev": "35912f3cc72b67fa63a8d59d634401b79796469e", + "rev": "120ae7826a7af01a527817952ad0c3f5ef08efd0", "type": "github" }, "original": { "owner": "eswar2001", "repo": "references", - "rev": "35912f3cc72b67fa63a8d59d634401b79796469e", + "rev": "120ae7826a7af01a527817952ad0c3f5ef08efd0", "type": "github" } }, "root": { "inputs": { "classyplate": "classyplate", - "flake-parts": "flake-parts", - "ghc-hasfield-plugin": "ghc-hasfield-plugin", - "haskell-flake": "haskell-flake", + "flake-parts": "flake-parts_2", + "haskell-flake": "haskell-flake_2", "large-records": "large-records", - "nixpkgs": "nixpkgs", - "record-dot-preprocessor": "record-dot-preprocessor", + "nixpkgs": "nixpkgs_4", "references": "references", - "systems": "systems" + "streamly": "streamly", + "systems": "systems_4" + } + }, + "streamly": { + "flake": false, + "locked": { + "lastModified": 1701516357, + "narHash": "sha256-Ap7kdurs4NZyMUeMUIF5qU5eHKifO9YmnO5eSEvdtA8=", + "owner": "composewell", + "repo": "streamly", + "rev": "12d85026291d9305f93f573d284d0d35abf40968", + "type": "github" + }, + "original": { + "owner": "composewell", + "repo": "streamly", + "rev": "12d85026291d9305f93f573d284d0d35abf40968", + "type": "github" } }, "systems": { @@ -244,6 +460,51 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 837e139..b7d0a10 100644 --- a/flake.nix +++ b/flake.nix @@ -1,19 +1,18 @@ { inputs = { - nixpkgs.url = "github:nixos/nixpkgs/43e3b6af08f29c4447a6073e3d5b86a4f45dd420"; + nixpkgs.url = "github:nixos/nixpkgs/75a52265bda7fd25e06e3a67dee3f0354e73243c"; systems.url = "github:nix-systems/default"; flake-parts.url = "github:hercules-ci/flake-parts"; haskell-flake.url = "github:srid/haskell-flake"; - classyplate.flake = false; - classyplate.url = "github:Chaitanya-nair/classyplate/46f5e0e7073e1d047f70473bf3c75366a613bfeb"; - references.flake = true; - references.url = "github:eswar2001/references/35912f3cc72b67fa63a8d59d634401b79796469e"; - ghc-hasfield-plugin.flake = false; - large-records.flake = false; - ghc-hasfield-plugin.url = "github:juspay/ghc-hasfield-plugin/d82ac5a6c0ad643eebe2b9b32c91f6523d3f30dc"; - large-records.url = "github:eswar2001/large-records/e393f4501d76a98b4482b0a5b35d120ae70e5dd3"; - record-dot-preprocessor.url = "github:ndmitchell/record-dot-preprocessor/99452d27f35ea1ff677be9af570d834e8fab4caf"; - record-dot-preprocessor.flake = false; + classyplate.url = "github:eswar2001/classyplate/a360f56820df6ca5284091f318bcddcd3e065243"; + references.url = "github:eswar2001/references/120ae7826a7af01a527817952ad0c3f5ef08efd0"; + large-records = { + url = "github:eswar2001/large-records/b60bcb312c7d55f1d638aa1a5143696e6586e76d"; + }; + streamly = { + url = "github:composewell/streamly/12d85026291d9305f93f573d284d0d35abf40968"; + flake = false; + }; }; outputs = inputs@{ self, nixpkgs, flake-parts, ... }: flake-parts.lib.mkFlake { inherit inputs; } { @@ -21,7 +20,6 @@ imports = [ inputs.haskell-flake.flakeModule ]; perSystem = { self', pkgs, ... }: { - # Typically, you just want a single project named "default". But # multiple projects are also possible, each using different GHC version. haskellProjects.default = { @@ -35,20 +33,21 @@ # Note that local packages are automatically included in `packages` # (defined by `defaults.packages` option). # + # defaults.enable = false; + # devShell.tools = hp: with hp; { + # inherit cabal-install; + # inherit hp; + # }; projectFlakeName = "spider"; - basePackages = pkgs.haskell.packages.ghc8107; + # basePackages = pkgs.haskell.packages.ghc8107; + basePackages = pkgs.haskell.packages.ghc92; imports = [ inputs.references.haskellFlakeProjectModules.output + inputs.classyplate.haskellFlakeProjectModules.output + inputs.large-records.haskellFlakeProjectModules.output ]; packages = { - classyplate.source = inputs.classyplate; - ghc-hasfield-plugin.source = inputs.ghc-hasfield-plugin; - large-records.source = inputs.large-records + /large-records; - large-generics.source = inputs.large-records + /large-generics; - large-anon.source = inputs.large-records + /large-anon; - ghc-tcplugin-api.source = "0.7.1.0"; - typelet.source = inputs.large-records + /typelet; - record-dot-preprocessor.source = inputs.record-dot-preprocessor; + streamly-core.source = inputs.streamly + /core; }; settings = { # aeson = { @@ -58,7 +57,11 @@ # haddock = false; # broken = false; # }; - sheriff.check = false; + # primitive-checked = { + # broken = false; + # jailbreak = true; + # }; + sheriff.check = false; }; devShell = { @@ -67,7 +70,7 @@ # Programs you want to make available in the shell. # Default programs can be disabled by setting to 'null' - # tools = hp: { fourmolu = hp.fourmolu; ghcid = null; }; + # tools = hp: { fourmolu = null; ghcid = null; }; hlsCheck.enable = pkgs.stdenv.isDarwin; # On darwin, sandbox is disabled, so HLS can use the network. };