diff --git a/.github/hlint.json b/.github/hlint.json new file mode 100644 index 0000000..6730d3f --- /dev/null +++ b/.github/hlint.json @@ -0,0 +1,19 @@ +{ + "problemMatcher": [ + { + "owner": "hlint", + "pattern": [ + { + "regexp": "^hlint\\t(?[^\\t]*)\\t(?[^\\t]*)\\t(?[^\\t]*)\\t(?[^\\t]*)\\t(?[^\\t]*)\\t(?[^\\t]*)\\t(?[^\\t]*)$", + "file": 1, + "fromPath": 2, + "line": 3, + "column": 4, + "severity": 5, + "code": 6, + "message": 7 + } + ] + } + ] +} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0aaa6d..0d702f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,19 @@ jobs: MNIST_FNAME: /tmp/mnist/mnist.ts.pt MNIST_COMMIT: 94b288a631362aa44edc219eb8f54a7c39891169 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + + # Lint code with HLint + - name: Set up HLint + uses: haskell-actions/hlint-setup@v2 + with: + version: "3.8" + - name: Run HLint + uses: haskell-actions/hlint-run@v2 + with: + path: '["inferno-core/", "inferno-lsp/", "inferno-ml/", "inferno-ml-server-types/", "inferno-types/", "inferno-vc/"]' + fail-on: error + - uses: cachix/install-nix-action@v18 with: install_url: https://releases.nixos.org/nix/nix-2.13.3/install @@ -32,6 +44,8 @@ jobs: name: inferno authToken: "${{ secrets.CACHIX_TOKEN }}" - uses: DeterminateSystems/magic-nix-cache-action@main + + # Build inferno and run all tests - run: | nix build -L .# diff --git a/inferno-core/CHANGELOG.md b/inferno-core/CHANGELOG.md index 97b54ab..6265afa 100644 --- a/inferno-core/CHANGELOG.md +++ b/inferno-core/CHANGELOG.md @@ -1,6 +1,9 @@ # Revision History for inferno-core *Note*: we use https://pvp.haskell.org/ (MAJOR.MAJOR.MINOR.PATCH) +## 0.11.1.0 -- 2024-03-18 +* HLint everything + ## 0.11.0.0 -- 2024-03-12 * Add records to the Inferno language diff --git a/inferno-core/inferno-core.cabal b/inferno-core/inferno-core.cabal index 2148df7..523f698 100644 --- a/inferno-core/inferno-core.cabal +++ b/inferno-core/inferno-core.cabal @@ -1,6 +1,6 @@ cabal-version: 2.4 name: inferno-core -version: 0.11.0.0 +version: 0.11.1.0 synopsis: A statically-typed functional scripting language description: Parser, type inference, and interpreter for a statically-typed functional scripting language category: DSL,Scripting diff --git a/inferno-core/src/Inferno/Core.hs b/inferno-core/src/Inferno/Core.hs index 6345d25..1281810 100644 --- a/inferno-core/src/Inferno/Core.hs +++ b/inferno-core/src/Inferno/Core.hs @@ -1,14 +1,13 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} module Inferno.Core where import Control.Monad (foldM) import Control.Monad.Catch (MonadCatch, MonadThrow) import Control.Monad.Except (MonadFix) -import Data.Bifunctor (bimap) +import Data.Bifunctor (bimap, first) import Data.List.NonEmpty (NonEmpty) import qualified Data.Map as Map import qualified Data.Set as Set @@ -130,7 +129,7 @@ mkInferno prelude customTypes = do foldM ( \env (hash, obj) -> case obj of VCFunction expr _ -> do - let expr' = bimap pinnedToMaybe id expr + let expr' = first pinnedToMaybe expr pure $ Map.insert hash (Left expr') env _ -> pure env ) diff --git a/inferno-core/src/Inferno/Eval.hs b/inferno-core/src/Inferno/Eval.hs index 4d3cbf4..b4badfc 100644 --- a/inferno-core/src/Inferno/Eval.hs +++ b/inferno-core/src/Inferno/Eval.hs @@ -7,6 +7,7 @@ import Control.Monad.Catch (MonadCatch, MonadThrow (throwM), try) import Control.Monad.Except (forM) import Control.Monad.Reader (ask, local) import Data.Foldable (foldrM) +import Data.Functor ((<&>)) import Data.List.NonEmpty (NonEmpty (..), toList) import qualified Data.Map as Map import Data.Maybe (catMaybes) @@ -67,7 +68,7 @@ eval env@(localEnv, pinnedEnv) expr = case expr of toText (VText t) = t toText e = renderStrict $ layoutPretty (LayoutOptions Unbounded) $ pretty e Array_ es -> - foldrM (\(e, _) vs -> eval env e >>= return . (: vs)) [] es >>= return . VArray + foldrM (\(e, _) vs -> eval env e <&> (: vs)) [] es <&> VArray ArrayComp_ e srcs mCond -> do vals <- sequence' env srcs VArray <$> case mCond of @@ -76,19 +77,21 @@ eval env@(localEnv, pinnedEnv) expr = case expr of let nenv = foldr (uncurry Map.insert) localEnv vs in eval (nenv, pinnedEnv) e Just (_, cond) -> catMaybes - <$> ( forM vals $ \vs -> do - let nenv = foldr (uncurry Map.insert) localEnv vs - eval (nenv, pinnedEnv) cond >>= \case - VEnum hash "true" -> - if hash == enumBoolHash - then Just <$> (eval (nenv, pinnedEnv) e) - else throwM $ RuntimeError "failed to match with a bool" - VEnum hash "false" -> - if hash == enumBoolHash - then return Nothing - else throwM $ RuntimeError "failed to match with a bool" - _ -> throwM $ RuntimeError "failed to match with a bool" - ) + <$> forM + vals + ( \vs -> do + let nenv = foldr (uncurry Map.insert) localEnv vs + eval (nenv, pinnedEnv) cond >>= \case + VEnum hash "true" -> + if hash == enumBoolHash + then Just <$> eval (nenv, pinnedEnv) e + else throwM $ RuntimeError "failed to match with a bool" + VEnum hash "false" -> + if hash == enumBoolHash + then return Nothing + else throwM $ RuntimeError "failed to match with a bool" + _ -> throwM $ RuntimeError "failed to match with a bool" + ) where sequence' :: (MonadThrow m, Pretty c) => TermEnv VCObjectHash c (ImplEnvM m c) a -> NonEmpty (a, Ident, a, Expr (Maybe VCObjectHash) a, Maybe a) -> ImplEnvM m c [[(ExtIdent, Value c (ImplEnvM m c))]] sequence' env'@(localEnv', pinnedEnv') = \case @@ -100,10 +103,12 @@ eval env@(localEnv, pinnedEnv) expr = case expr of eval env' e_s >>= \case VArray vals -> concat - <$> ( forM vals $ \v -> do - res <- sequence' (Map.insert (ExtIdent $ Right x) v localEnv', pinnedEnv') (r :| rs) - return $ map ((ExtIdent $ Right x, v) :) res - ) + <$> forM + vals + ( \v -> do + res <- sequence' (Map.insert (ExtIdent $ Right x) v localEnv', pinnedEnv') (r :| rs) + return $ map ((ExtIdent $ Right x, v) :) res + ) _ -> throwM $ RuntimeError "failed to match with an array" Enum_ (Just hash) _ i -> return $ VEnum hash i Enum_ Nothing _ _ -> throwM $ RuntimeError "All enums must be pinned" @@ -162,7 +167,7 @@ eval env@(localEnv, pinnedEnv) expr = case expr of (_, Just x) : xs -> return $ VFun $ \arg -> go (Map.insert x arg nenv) xs (_, Nothing) : xs -> return $ VFun $ \_arg -> go nenv xs - App_ fun arg -> do + App_ fun arg -> eval env fun >>= \case VFun f -> do argv <- eval env arg @@ -178,7 +183,7 @@ eval env@(localEnv, pinnedEnv) expr = case expr of eval (nenv, pinnedEnv) body Let_ (Impl x) e body -> do e' <- eval env e - local (\impEnv -> Map.insert x e' impEnv) $ eval env body + local (Map.insert x e') $ eval env body If_ cond tr fl -> eval env cond >>= \case VEnum hash "true" -> @@ -191,7 +196,7 @@ eval env@(localEnv, pinnedEnv) expr = case expr of else throwM $ RuntimeError "failed to match with a bool" _ -> throwM $ RuntimeError "failed to match with a bool" Tuple_ es -> - foldrM (\(e, _) vs -> eval env e >>= return . (: vs)) [] (tListToList es) >>= return . VTuple + foldrM (\(e, _) vs -> eval env e <&> (: vs)) [] (tListToList es) <&> VTuple Record_ fs -> do valMap <- foldrM (\(f, e, _) vs -> eval env e >>= \v -> return ((f, v) : vs)) [] fs return $ VRecord $ Map.fromList valMap @@ -203,8 +208,8 @@ eval env@(localEnv, pinnedEnv) expr = case expr of Nothing -> throwM $ RuntimeError "record field not found" Just _ -> throwM $ RuntimeError "failed to match with a record" Nothing -> throwM $ RuntimeError $ show (ExtIdent $ Right r) <> " not found in the unpinned env" - One_ e -> eval env e >>= return . VOne - Empty_ -> return $ VEmpty + One_ e -> eval env e <&> VOne + Empty_ -> return VEmpty Assert_ cond e -> eval env cond >>= \case VEnum hash "false" -> @@ -224,13 +229,13 @@ eval env@(localEnv, pinnedEnv) expr = case expr of Just nenv -> -- (<>) is left biased so this will correctly override any shadowed vars from nenv onto env eval (nenv <> env) body - Nothing -> throwM $ RuntimeError $ "non-exhaustive patterns in case detected in " <> (Text.unpack $ renderPretty v) + Nothing -> throwM $ RuntimeError $ "non-exhaustive patterns in case detected in " <> Text.unpack (renderPretty v) matchAny v ((_, p, _, body) :| (r : rs)) = case match v p of Just nenv -> eval (nenv <> env) body Nothing -> matchAny v (r :| rs) match v p = case (v, p) of - (_, PVar _ (Just (Ident x))) -> Just $ (Map.singleton (ExtIdent $ Right x) v, mempty) + (_, PVar _ (Just (Ident x))) -> Just (Map.singleton (ExtIdent $ Right x) v, mempty) (_, PVar _ Nothing) -> Just mempty (VEnum h1 i1, PEnum _ (Just h2) _ i2) -> if h1 == h2 && i1 == i2 diff --git a/inferno-core/src/Inferno/Infer.hs b/inferno-core/src/Inferno/Infer.hs index 8c923d5..86f3e79 100644 --- a/inferno-core/src/Inferno/Infer.hs +++ b/inferno-core/src/Inferno/Infer.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeSynonymInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -38,9 +37,10 @@ import Control.Monad.State StateT (StateT, runStateT), evalStateT, execState, + gets, modify, ) -import Data.Bifunctor (bimap) +import Data.Bifunctor (Bifunctor (first, second), bimap) import qualified Data.Bimap as Bimap import Data.Either (partitionEithers, rights) import Data.Generics.Product (HasType, getTyped, setTyped) @@ -48,7 +48,7 @@ import Data.List (find, unzip4) import qualified Data.List.NonEmpty as NEList import qualified Data.Map as Map import qualified Data.Map.Merge.Lazy as Map -import Data.Maybe (catMaybes, fromJust) +import Data.Maybe (catMaybes, fromJust, mapMaybe) import qualified Data.Set as Set import qualified Data.Text as Text import Debug.Trace (trace) @@ -174,7 +174,7 @@ filterInstantiatedTypeClasses = Set.filter $ not . Set.null . ftv mkPattern :: Pat (Pinned VCObjectHash) SourcePos -> Pattern mkPattern = \case PVar _ _ -> W - PEnum _ Local _ns _ident -> error $ "internal error. cannot convert unpinned enum into a pattern" + PEnum _ Local _ns _ident -> error "internal error. cannot convert unpinned enum into a pattern" PEnum _ hash _ns ident@(Ident i) -> cEnum (vcHash (ident, fromJust $ pinnedToMaybe hash)) i PLit _ l -> case l of LInt v -> cInf v @@ -265,7 +265,7 @@ closeOverTypeReps implTys expr = -- if we have any type holes, we need to wrap the expression in a lambda and add a `requires rep on ...` typeclass -- capturing all the runtime reps that the expression needs _ : _ -> - let lamList = fmap (\merged -> let (v, _) = NEList.head merged in (pos, Just v)) $ NEList.fromList $ withTypeHoleGrouped + let lamList = ((\merged -> let (v, _) = NEList.head merged in (pos, Just v)) <$> NEList.fromList withTypeHoleGrouped) in ( Just $ TypeClass "rep" $ map @@ -316,14 +316,14 @@ inferExpr allModules expr = let cls = filterInstantiatedTypeClasses $ Set.map (apply subst . snd) $ Set.fromList $ rights $ Set.toList cs let substitutedTy@(ImplType implTys tyBody) = apply subst ty -- get current type variables - let tvs = ftv substitutedTy `Set.union` (Set.unions $ Set.elems $ Set.map ftv cls) + let tvs = ftv substitutedTy `Set.union` Set.unions (Set.elems $ Set.map ftv cls) let res substNew (mRepTyCls, implTys', expr'') = let finalTy = closeOver - ((filterInstantiatedTypeClasses $ Set.map (apply substNew) cls) `Set.union` (maybe mempty Set.singleton mRepTyCls)) + (filterInstantiatedTypeClasses (Set.map (apply substNew) cls) `Set.union` maybe mempty Set.singleton mRepTyCls) $ apply substNew $ ImplType implTys' tyBody - in Right $ + in Right ( expr'', finalTy, Map.map @@ -351,7 +351,7 @@ inferExpr allModules expr = ) -- start with the body of the type, i.e. in `forall a_1 ... a_n {requires ..., implicit ...} => t` get the type variables in `t` -- as well as any implicit arguments which aren't internal, since those are used for tracking type-reps - (ftv tyBody `Set.union` (Map.foldrWithKey (\(ExtIdent ident) t ftvs -> case ident of Left _ -> ftvs; Right _ -> ftv t `Set.union` ftvs) mempty implTys)) + (ftv tyBody `Set.union` Map.foldrWithKey (\(ExtIdent ident) t ftvs -> case ident of Left _ -> ftvs; Right _ -> ftv t `Set.union` ftvs) mempty implTys) cls subst' = Subst $ Set.foldr Map.delete s ftvsDependentOnOuterType in -- trace ("type ftvsDependentOnOuterType: " <> show ftvsDependentOnOuterType) $ @@ -369,7 +369,7 @@ inferExpr allModules expr = mempty $ Map.map ty $ Map.unions - $ pinnedModuleHashToTy builtinModule : (map pinnedModuleHashToTy $ Map.elems allModules) + $ pinnedModuleHashToTy builtinModule : map pinnedModuleHashToTy (Map.elems allModules) openBuiltinModuleAndAddPinnedTypes :: Map.Map ModuleName (PinnedModule m) -> (Env, Set.Set TypeClass) openBuiltinModuleAndAddPinnedTypes modules = let Module {moduleTypeClasses = tyCls, moduleObjects = (_, tys, _)} = builtinModule @@ -441,7 +441,7 @@ inferPossibleTypes allTypeClasses (ForallTC _ tyCls (ImplType _impl ty)) inputTy possibleInTysFromSig <- forM (zip inputTys inTysFromSig) findAllPossibleTypes (possibleInTysFromSig,) <$> findAllPossibleTypes (outputTy, outTyFromSig) where - gatherArgs (TArr t1 t2) = bimap (t1 :) id $ gatherArgs t2 + gatherArgs (TArr t1 t2) = first (t1 :) $ gatherArgs t2 gatherArgs x = ([], x) mkMaybeConstraints (TArr t1 t2) (Just x : xs) = Left (t1, x, []) : mkMaybeConstraints t2 xs mkMaybeConstraints (TArr _ t2) (Nothing : xs) = mkMaybeConstraints t2 xs @@ -454,14 +454,14 @@ inferPossibleTypes allTypeClasses (ForallTC _ tyCls (ImplType _impl ty)) inputTy -- | Extend type environment inEnv :: (ExtIdent, TypeMetadata TCScheme) -> Infer a -> Infer a inEnv (x, meta) m = do - let scope e = (Env.remove e x) `Env.extend` (x, meta) + let scope e = Env.remove e x `Env.extend` (x, meta) local scope m -- | Lookup type in the environment lookupEnv :: Location SourcePos -> Either VCObjectHash ExtIdent -> Infer (TypeMetadata (Set.Set TypeClass, ImplType)) lookupEnv loc x = do env <- ask - case either (flip Env.lookupPinned env) (flip Env.lookup env) x of + case either (`Env.lookupPinned` env) (`Env.lookup` env) x of Nothing -> throwError [ either @@ -511,7 +511,7 @@ instantiate :: TCScheme -> Infer (Set.Set TypeClass, ImplType) instantiate (ForallTC as tcs t) = do as' <- mapM (const fresh) as let s = Subst $ Map.fromList $ zip as as' - return $ (Set.map (apply s) tcs, apply s t) + return (Set.map (apply s) tcs, apply s t) opGetTyComponents :: ImplType -> (InfernoType, InfernoType, InfernoType) opGetTyComponents (ImplType _ (t1 `TArr` (t2 `TArr` t3))) = (t1, t2, t3) @@ -594,7 +594,7 @@ infer expr = Enum _ mHash _ _ -> do meta <- lookupEnv exprLoc (maybe (error "internal error, enums must always be pinned!!") Left $ pinnedToMaybe mHash) let (_, t) = ty meta - attachTypeToPosition exprLoc meta {identExpr = bimap (const ()) (const ()) $ expr} + attachTypeToPosition exprLoc meta {identExpr = bimap (const ()) (const ()) expr} return (expr, t, Set.empty) InterpolatedString p1 xs p2 -> do attachTypeToPosition @@ -606,10 +606,12 @@ infer expr = } (xs', is, css) <- unzip3 - <$> ( forM (toEitherList xs) $ \case - Left str -> return (Left str, Map.empty, Set.empty) - Right (p3, e, p4) -> (\(e', ImplType is _t, cs) -> (Right (p3, e', p4), is, cs)) <$> infer e - ) + <$> forM + (toEitherList xs) + ( \case + Left str -> return (Left str, Map.empty, Set.empty) + Right (p3, e, p4) -> (\(e', ImplType is _t, cs) -> (Right (p3, e', p4), is, cs)) <$> infer e + ) let (isMerged, ics) = mergeImplicitMaps (blockPosition expr) is return (InterpolatedString p1 (fromEitherList xs') p2, ImplType isMerged typeText, Set.unions css `Set.union` Set.fromList ics) Record p1 fes p2 -> do @@ -644,7 +646,7 @@ infer expr = fresh >>= \case (TVar x) -> pure x _ -> error "fresh returned something other than a TVar" - let tyCls = Set.fromList $ map snd $ rights $ Set.toList $ cs_r + let tyCls = Set.fromList $ map snd $ rights $ Set.toList cs_r let tyRec = TRecord (Map.singleton (Ident f) tv) (RowVar trv) return ( expr, @@ -843,14 +845,14 @@ infer expr = ) LetAnnot p1 loc x pT t p2 e1 p3 e2 -> do (e1', ImplType i1 t1, c1) <- infer e1 - (tcs, (ImplType iT tT)) <- instantiate t + (tcs, ImplType iT tT) <- instantiate t let tyCls = Set.fromList $ map snd $ rights $ Set.toList c1 attachTypeToPosition (elementPosition loc $ Expl x) TypeMetadata { identExpr = Var () () LocalScope $ Expl x, -- ty = (tyCls, ImplType i1 t1), - ty = (tcs, (ImplType iT tT)), + ty = (tcs, ImplType iT tT), docs = Nothing } let newEnv = @@ -906,9 +908,7 @@ infer expr = (e1', ImplType i1 t1, c1) <- infer e1 (e2', ImplType i2 t2, c2) <- infer e2 - v1 <- case Map.lookup x i2 of - Just t -> return t - Nothing -> fresh + v1 <- maybe fresh return (Map.lookup x i2) let (isMerged, ics) = mergeImplicitMaps (blockPosition expr) [i1, Map.withoutKeys i2 (Set.singleton x)] tyCls = Set.fromList $ map snd $ rights $ Set.toList $ c1 `Set.union` c2 @@ -948,7 +948,7 @@ infer expr = tyConstr u2 t2 [UnificationFail tyCls u2 t2 $ blockPosition e2], tyConstr u3 tv [UnificationFail tyCls u3 tv $ blockPosition expr] ] - `Set.union` (Set.map (Right . (opLoc,)) tcs) + `Set.union` Set.map (Right . (opLoc,)) tcs ) PreOp loc mHash opMeta modNm op e -> do let (sPos, ePos) = elementPosition loc op @@ -958,7 +958,7 @@ infer expr = meta <- lookupEnv opLoc (maybe (error "internal error, prefix ops must always be pinned!!") Left $ pinnedToMaybe mHash) let (tcs, (u1, u2)) = preOpGetTyComponents <$> ty meta - tyCls = Set.fromList $ map snd $ rights $ Set.toList $ c + tyCls = Set.fromList $ map snd $ rights $ Set.toList c tv <- fresh attachTypeToPosition opLoc meta {ty = (tcs, ImplType Map.empty $ t `TArr` tv)} @@ -971,7 +971,7 @@ infer expr = [ tyConstr u1 t [UnificationFail tyCls u1 t $ blockPosition e], tyConstr u2 tv [UnificationFail tyCls u2 tv $ blockPosition expr] ] - `Set.union` (Set.map (Right . (opLoc,)) tcs) + `Set.union` Set.map (Right . (opLoc,)) tcs ) If p1 cond p2 tr p3 fl -> do (cond', ImplType i1 t1, c1) <- infer cond @@ -1044,18 +1044,16 @@ infer expr = (e', ImplType i_e t_e, cs_e) <- infer e (patTys, patVars, patConstraints) <- unzip3 - <$> mapM - (\p -> checkVariableOverlap Map.empty p >> mkPatConstraint p) - (map (\(_, p, _, _) -> p) patExprs) + <$> mapM ((\p -> checkVariableOverlap Map.empty p >> mkPatConstraint p) . (\(_, p, _, _) -> p)) patExprs addCasePatterns exprLoc $ map (\(_, p, _, _) -> p) patExprs res <- forM (zip patVars $ map (\(_, _p, _, e'') -> e'') patExprs) $ - \(vars, e''') -> foldr inEnv (infer e''') $ map (\(Ident x, meta) -> (ExtIdent $ Right x, meta)) vars + \(vars, e''') -> foldr (inEnv . (\(Ident x, meta) -> (ExtIdent $ Right x, meta))) (infer e''') vars let (es'', is_res, ts_res, cs_res) = unzip4 $ map (\(e'', ImplType i_r t_r, cs_r) -> (e'', i_r, t_r, cs_r)) res (isMerged, ics) = mergeImplicitMaps (blockPosition expr) (i_e : is_res) - tyCls = Set.fromList $ map snd $ rights $ Set.toList $ cs_e `Set.union` (Set.unions cs_res) + tyCls = Set.fromList $ map snd $ rights $ Set.toList $ cs_e `Set.union` Set.unions cs_res patTysEqConstraints = Set.fromList [ tyConstr tPat4 tPat5 [PatternsMustBeEqType tyCls tPat4 tPat5 p4 p5 (blockPosition p4) (blockPosition p5)] @@ -1076,16 +1074,16 @@ infer expr = e1 /= e2 ] - return $ - ( Case p1 e' p2 (NEList.fromList $ map (\(e'', (p6, pat, p7, _)) -> (p6, pat, p7, e'')) $ zip es'' patExprs) p3, + return + ( Case p1 e' p2 (NEList.fromList $ zipWith (curry (\(e'', (p6, pat, p7, _)) -> (p6, pat, p7, e''))) es'' patExprs) p3, ImplType isMerged $ head ts_res, - (Set.fromList ics) + Set.fromList ics `Set.union` cs_e - `Set.union` (Set.unions patConstraints) + `Set.union` Set.unions patConstraints `Set.union` patTysEqConstraints `Set.union` patTysMustEqCaseExprTy t_e `Set.union` patExpTysEqConstraints (zip (map (\(_, ty, _) -> ty) res) (map (\(_, _p, _, e'') -> e'') patExprs)) - `Set.union` (Set.unions cs_res) + `Set.union` Set.unions cs_res ) where mkPatConstraint :: Pat (Pinned VCObjectHash) SourcePos -> Infer (InfernoType, [(Ident, TypeMetadata TCScheme)], Set.Set Constraint) @@ -1141,7 +1139,7 @@ infer expr = patLoc TypeMetadata { identExpr = patternToExpr $ bimap (const ()) (const ()) pat, - ty = (Set.empty, ImplType Map.empty $ t), + ty = (Set.empty, ImplType Map.empty t), docs = Nothing } return (t, [], Set.empty) @@ -1153,7 +1151,7 @@ infer expr = patLoc TypeMetadata { identExpr = patternToExpr $ bimap (const ()) (const ()) pat, - ty = (Set.empty, ImplType Map.empty $ inferredTy), + ty = (Set.empty, ImplType Map.empty inferredTy), docs = Nothing } return (inferredTy, vars1 ++ vars2, csP `Set.union` csPs) @@ -1174,7 +1172,7 @@ infer expr = patLoc TypeMetadata { identExpr = patternToExpr $ bimap (const ()) (const ()) pat, - ty = (Set.empty, ImplType Map.empty $ inferredTy), + ty = (Set.empty, ImplType Map.empty inferredTy), docs = Nothing } return (inferredTy, vars, cs) @@ -1394,8 +1392,8 @@ unifies err (TSeries t1) (TSeries t2) = unifies err t1 t2 unifies err (TOptional t1) (TOptional t2) = unifies err t1 t2 unifies err (TTuple ts1) (TTuple ts2) | length (tListToList ts1) == length (tListToList ts2) = unifyMany err (tListToList ts1) (tListToList ts2) - | otherwise = throwError [UnificationFail (getTypeClassFromErrs err) (TTuple ts1) (TTuple ts2) loc | loc <- (getLocFromErrs err)] -unifies err (TRecord ts1 trv1) (TRecord ts2 trv2) = do + | otherwise = throwError [UnificationFail (getTypeClassFromErrs err) (TTuple ts1) (TTuple ts2) loc | loc <- getLocFromErrs err] +unifies err (TRecord ts1 trv1) (TRecord ts2 trv2) = unifyRecords err (Map.toAscList ts1, trv1) (Map.toAscList ts2, trv2) [] [] [] unifies err _ _ = -- trace "throwing in unifies " $ @@ -1410,7 +1408,7 @@ solver varCount (su, cs) = let (tyConstrs, typeCls) = partitionEithers cs su1 <- flip evalSolveState varCount $ solverTyCs su tyConstrs -- trace ("After solverTyCs, final su1\n" <> show su1) $ pure () - let partResolvedTyCls = map (\(loc, tc) -> (loc, apply su1 tc)) typeCls + let partResolvedTyCls = map (second (apply su1)) typeCls -- trace ("partResolvedTyCls: " <> (intercalate "\n" $ map (unpack . renderPretty . pretty . snd) partResolvedTyCls)) $ evalSolveState (solverTypeClasses $ su1 `compose` su) (Set.fromList partResolvedTyCls, mempty) @@ -1451,7 +1449,7 @@ applySubsts su = state $ \(current, marked) -> then (current', Set.insert (loc, a') marked') else (Set.insert (loc, a') current', marked') ) - (Set.map (\(loc, a) -> (loc, apply su a)) current, mempty) + (Set.map (Data.Bifunctor.second (apply su)) current, mempty) marked where filterFullyInstantiated = @@ -1477,7 +1475,7 @@ solverTypeClasses su = (Subst s : xs) -> do -- even if we have multiple matching substitutions, we can still make progress if they all agree -- on some parameter - let su' = (Subst $ foldr intersection s [x | Subst x <- xs]) `compose` su + let su' = Subst (foldr intersection s [x | Subst x <- xs]) `compose` su -- trace ("applying su': "<> show su' <> "\nprevious was su: " <> show su) $ applySubsts su' solverTypeClasses su' @@ -1555,8 +1553,8 @@ findTypeClassWitnesses allClasses iters tyCls tvs = filteredSubs = filteredTypeClassSubstitutions allClasses $ Set.toList tyCls (_, litMap, clauses) = flip execState (Counter 1, Bimap.empty, []) $ do encodeTypeClasses allClasses filteredSubs $ Set.toList tyCls - lm :: Bimap.Bimap Int (TV, InfernoType) <- getTyped <$> get - let ls_grouped = foldr (\(l, (tv, _)) m' -> Map.alter (Just . maybe [l] (l :)) tv m') mempty $ Bimap.toList $ lm + lm :: Bimap.Bimap Int (TV, InfernoType) <- gets getTyped + let ls_grouped = foldr (\(l, (tv, _)) m' -> Map.alter (Just . maybe [l] (l :)) tv m') mempty $ Bimap.toList lm forM_ (Map.elems ls_grouped) $ \ls -> xor ls getSolutions = \case @@ -1564,7 +1562,7 @@ findTypeClassWitnesses allClasses iters tyCls tvs = i -> do Picosat.scopedSolutionWithAssumptions [] >>= \case Picosat.Solution ls -> do - let found = catMaybes $ map (\l -> (l,) <$> Bimap.lookup l litMap) ls + let found = mapMaybe (\l -> (l,) <$> Bimap.lookup l litMap) ls Picosat.addBaseClauses [[-l | (l, (tv, _)) <- found, tv `Set.member` tvs]] ((Subst $ Map.fromList $ map snd found) :) <$> getSolutions ((\x -> x - 1) <$> i) _ -> pure [] @@ -1594,7 +1592,7 @@ filteredTypeClassSubstitutions allClasses = \case [] -> mempty TypeClass nm tys : tcs -> do let possibleMatchingInstances = Set.toList $ Set.filter (\(TypeClass nm' _) -> nm == nm') allClasses - case runIdentity $ runExceptT $ flip runReaderT allClasses $ (catMaybes <$> forM possibleMatchingInstances (tryMatchPartial tys)) of + case runIdentity $ runExceptT $ flip runReaderT allClasses $ catMaybes <$> forM possibleMatchingInstances (tryMatchPartial tys) of Left _ -> filteredTypeClassSubstitutions allClasses tcs Right subs' -> let subs = [su | Subst su <- subs'] @@ -1612,22 +1610,23 @@ encodeTypeClasses allClasses filteredSubs = \case [] -> pure () TypeClass nm tys : tcs -> do let possibleMatchingInstances = Set.toList $ Set.filter (\(TypeClass nm' _) -> nm == nm') allClasses - case runIdentity $ runExceptT $ flip runReaderT allClasses $ (catMaybes <$> forM possibleMatchingInstances (tryMatchPartial tys)) of + case runIdentity $ runExceptT $ flip runReaderT allClasses $ catMaybes <$> forM possibleMatchingInstances (tryMatchPartial tys) of Left _err -> encodeTypeClasses allClasses filteredSubs tcs Right subs -> do insts <- forM (filterSubs subs) $ \(Subst su) -> do ls <- concat - <$> ( forM tys $ \t -> - case t of - TVar tv -> do - let t' = su Map.! tv - tvLit <- getLit (tv, t') - freshLit <- newLit - [tvLit] `iff` freshLit - pure [freshLit] - _ -> pure [] - ) + <$> forM + tys + ( \case + TVar tv -> do + let t' = su Map.! tv + tvLit <- getLit (tv, t') + freshLit <- newLit + [tvLit] `iff` freshLit + pure [freshLit] + _ -> pure [] + ) freshLit <- newLit ls `iff` freshLit pure freshLit @@ -1666,7 +1665,7 @@ xor ls = bind :: [TypeError SourcePos] -> TV -> InfernoType -> SolveState Int Subst bind err a t | t == TVar a = return emptySubst - | occursCheck a t = throwError [InfiniteType a t loc | loc <- (getLocFromErrs err)] + | occursCheck a t = throwError [InfiniteType a t loc | loc <- getLocFromErrs err] | otherwise = return (Subst $ Map.singleton a t) occursCheck :: Substitutable a => TV -> a -> Bool diff --git a/inferno-core/src/Inferno/Infer/Env.hs b/inferno-core/src/Inferno/Infer/Env.hs index fe4ca0b..4753d8b 100644 --- a/inferno-core/src/Inferno/Infer/Env.hs +++ b/inferno-core/src/Inferno/Infer/Env.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE GeneralizedNewtypeDeriving #-} - module Inferno.Infer.Env ( Env (..), Namespace (..), @@ -130,7 +128,7 @@ fv (TBase _) = [] fv (TArray t) = fv t fv (TSeries t) = fv t fv (TOptional t) = fv t -fv (TTuple ts) = foldr ((++) . fv) [] ts +fv (TTuple ts) = concatMap fv ts fv (TRecord ts RowAbsent) = concatMap fv ts fv (TRecord ts (RowVar a)) = foldr ((++) . fv) [a] ts fv (TRep t) = fv t @@ -169,7 +167,7 @@ normalize (ForallTC _ tcs (ImplType impl body)) = generalize :: Set.Set TypeClass -> ImplType -> TCScheme generalize tcs t = ForallTC as tcs t where - as = Set.toList $ ((ftv t) `Set.union` (Set.unions $ Set.elems $ Set.map ftv tcs)) + as = Set.toList (ftv t `Set.union` Set.unions (Set.elems $ Set.map ftv tcs)) -- | Canonicalize and return the polymorphic toplevel type. closeOver :: Set.Set TypeClass -> ImplType -> TCScheme diff --git a/inferno-core/src/Inferno/Infer/Error.hs b/inferno-core/src/Inferno/Infer/Error.hs index 49c82d7..2e106af 100644 --- a/inferno-core/src/Inferno/Infer/Error.hs +++ b/inferno-core/src/Inferno/Infer/Error.hs @@ -1,6 +1,4 @@ -{-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveTraversable #-} -{-# LANGUAGE KindSignatures #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} @@ -92,4 +90,4 @@ getTypeClassFromErr = \case _ -> mempty getTypeClassFromErrs :: [TypeError a] -> Set.Set TypeClass -getTypeClassFromErrs = foldr Set.union mempty . map getTypeClassFromErr +getTypeClassFromErrs = foldr (Set.union . getTypeClassFromErr) mempty diff --git a/inferno-core/src/Inferno/Infer/Exhaustiveness.hs b/inferno-core/src/Inferno/Infer/Exhaustiveness.hs index 765a2b9..566c086 100644 --- a/inferno-core/src/Inferno/Infer/Exhaustiveness.hs +++ b/inferno-core/src/Inferno/Infer/Exhaustiveness.hs @@ -38,7 +38,7 @@ instance Eq Con where CEmpty == CEmpty = True (CTuple i) == (CTuple j) = i == j (CEnum e _) == (CEnum f _) = e == f - (CInf a) == (CInf b) = (show a) == (show b) + (CInf a) == (CInf b) = show a == show b _ == _ = False -- we don't really care about the ord instance here @@ -208,10 +208,10 @@ exhaustive sigs pm = i sigs pm 1 Nothing -> go rest Just pat -> Just $ - [C ck $ take (cSize ck) pat] ++ drop (cSize ck) pat + C ck (take (cSize ck) pat) : drop (cSize ck) pat checkUsefullness :: Map VCObjectHash (Set (VCObjectHash, Text)) -> PMatrix -> [(Int, Int)] -checkUsefullness enum_sigs p = go 0 [] p +checkUsefullness enum_sigs = go 0 [] where go _ _ [] = [] go n preceding (p_i : rest) = @@ -262,7 +262,7 @@ mkEnumArrayPat = EnumArrayPat . length instance Pretty EnumArrayPat where pretty (EnumArrayPat n) = -- Since SourcePos is ignored when pretty printing, we use an undefined SourcePos - pretty $ PArray undefined (replicate n $ (PVar (initialPos "") Nothing, Nothing)) undefined + pretty $ PArray undefined (replicate n (PVar (initialPos "") Nothing, Nothing)) undefined instance Enum EnumArrayPat where toEnum = EnumArrayPat diff --git a/inferno-core/src/Inferno/Infer/Pinned.hs b/inferno-core/src/Inferno/Infer/Pinned.hs index 02b686e..bdcecd8 100644 --- a/inferno-core/src/Inferno/Infer/Pinned.hs +++ b/inferno-core/src/Inferno/Infer/Pinned.hs @@ -8,7 +8,7 @@ module Inferno.Infer.Pinned ) where -import Control.Monad (foldM, forM, when) +import Control.Monad (foldM, forM, unless, when) import Control.Monad.Except (MonadError (throwError)) import Control.Monad.State (get, put, runStateT) import Data.Functor.Foldable (cata) @@ -27,8 +27,7 @@ insertIntoLocalScope :: Map Namespace (Pinned a) -> Map (Scoped ModuleName) (Map Namespace (Pinned a)) -> Map (Scoped ModuleName) (Map Namespace (Pinned a)) -insertIntoLocalScope m moduleMap = - Map.alter (Just . addModuleToLocalScope) LocalScope moduleMap +insertIntoLocalScope m = Map.alter (Just . addModuleToLocalScope) LocalScope where addModuleToLocalScope maybeMap = case maybeMap of Nothing -> m @@ -99,8 +98,8 @@ pinPat m pat = es' <- mapM (\(e, p3) -> (,p3) <$> pinPat m e) es pure $ PTuple p1 es' p2 PCommentAbove c e -> PCommentAbove c <$> pinPat m e - PCommentAfter e c -> (\e' -> PCommentAfter e' c) <$> pinPat m e - PCommentBelow e c -> (\e' -> PCommentBelow e' c) <$> pinPat m e + PCommentAfter e c -> (`PCommentAfter` c) <$> pinPat m e + PCommentBelow e c -> (`PCommentBelow` c) <$> pinPat m e -- pinExpr :: -- (MonadError [TypeError SourcePos] m, Eq a) => @@ -121,7 +120,7 @@ patVars p = flip cata p $ \case PVarF _ (Just v) -> [v] - rest -> foldr (++) [] rest + rest -> concat rest isModNs :: Namespace -> p -> Bool isModNs k _v = case k of @@ -131,10 +130,10 @@ isModNs k _v = case k of pinExpr :: (MonadError [TypeError SourcePos] m, Eq a) => Map (Scoped ModuleName) (Map Namespace (Pinned a)) -> Expr h SourcePos -> m (Expr (Pinned a) SourcePos) pinExpr m expr = let exprPos = blockPosition expr - insertLocal k m' = Map.alter (alterFun (FunNamespace k) Local) LocalScope m' alterFun k v = \case Just m' -> Just $ Map.insert k v m' Nothing -> Just $ Map.singleton k v + insertLocal k = Map.alter (alterFun (FunNamespace k) Local) LocalScope in case expr of Lit p l -> pure $ Lit p l Var p _hash modNm (Impl x) -> pure $ Var p Local modNm (Impl x) @@ -163,7 +162,7 @@ pinExpr m expr = hash <- lookupName exprPos modNm (EnumNamespace x) m pure $ Enum p hash modNm x InterpolatedString p1 xs p2 -> do - xs' <- mapM (\(p3, e, p4) -> (\e' -> (p3, e', p4)) <$> pinExpr m e) xs + xs' <- mapM (\(p3, e, p4) -> (p3,,p4) <$> pinExpr m e) xs pure $ InterpolatedString p1 xs' p2 Record p1 es p2 -> do es' <- mapM (\(f, e, p3) -> (f,,p3) <$> pinExpr m e) es @@ -179,7 +178,7 @@ pinExpr m expr = currentM <- get e1' <- pinExpr currentM e1 put $ insertLocal i currentM - pure $ (p4, i, p5, e1', p6) + pure (p4, i, p5, e1', p6) cond' <- mapM (\(p4, e1) -> (p4,) <$> pinExpr m' e1) cond e' <- pinExpr m' e @@ -242,13 +241,13 @@ pinExpr m expr = pat' <- pinPat m pat let m' = foldr insertLocal m $ patVars pat e1' <- pinExpr m' e1 - pure $ (p4, pat', p5, e1') + pure (p4, pat', p5, e1') ) patExprs pure $ Case p1 e' p2 patExprs' p3 CommentAbove c e -> CommentAbove c <$> pinExpr m e - CommentAfter e c -> (\e' -> CommentAfter e' c) <$> pinExpr m e - CommentBelow e c -> (\e' -> CommentBelow e' c) <$> pinExpr m e + CommentAfter e c -> (`CommentAfter` c) <$> pinExpr m e + CommentBelow e c -> (`CommentBelow` c) <$> pinExpr m e Bracketed p1 e p2 -> (\e' -> Bracketed p1 e' p2) <$> pinExpr m e RenameModule l1 newNm l2 oldNm l3 e -> do hash <- lookupName exprPos LocalScope (ModuleNamespace oldNm) m @@ -268,29 +267,29 @@ pinExpr m expr = let localM = fromMaybe mempty $ Map.lookup LocalScope m checkedImports <- case imports of - [] -> pure $ openMod - _ -> Map.fromList <$> (foldM (collectImports openMod modPos) [] $ map fst imports) + [] -> pure openMod + _ -> Map.fromList <$> foldM (collectImports openMod modPos) [] (map fst imports) let intersectionWithLocal = localM `Map.intersection` checkedImports - when (not $ Map.null intersectionWithLocal) $ throwError [AmbiguousName modNm i modPos | i <- Map.keys checkedImports] + unless (Map.null intersectionWithLocal) $ throwError [AmbiguousName modNm i modPos | i <- Map.keys checkedImports] OpenModule p1 hash modNm imports p2 <$> pinExpr (Map.insertWith Map.union LocalScope checkedImports m) e where collectImports openMod pos xs = \case IVar _ i -> do let k = FunNamespace i - when (not $ k `Map.member` openMod) $ throwError [NameInModuleDoesNotExist modNm i pos] + unless (k `Map.member` openMod) $ throwError [NameInModuleDoesNotExist modNm i pos] return $ (k, openMod Map.! k) : xs IOpVar _ i -> do let k = FunNamespace i - when (not $ k `Map.member` openMod) $ throwError [NameInModuleDoesNotExist modNm i pos] + unless (k `Map.member` openMod) $ throwError [NameInModuleDoesNotExist modNm i pos] return $ (k, openMod Map.! k) : xs IEnum _ _ i -> do let k = TypeNamespace i - when (not $ k `Map.member` openMod) $ throwError [NameInModuleDoesNotExist modNm i pos] + unless (k `Map.member` openMod) $ throwError [NameInModuleDoesNotExist modNm i pos] let enumHash = openMod Map.! k return $ - (Map.toList $ Map.filter (\h -> h == enumHash) openMod) ++ xs + Map.toList (Map.filter (== enumHash) openMod) ++ xs ICommentAbove _ x' -> collectImports openMod pos xs x' ICommentAfter x' _ -> collectImports openMod pos xs x' ICommentBelow x' _ -> collectImports openMod pos xs x' diff --git a/inferno-core/src/Inferno/Instances/Arbitrary.hs b/inferno-core/src/Inferno/Instances/Arbitrary.hs index 7533f4c..eb20a38 100644 --- a/inferno-core/src/Inferno/Instances/Arbitrary.hs +++ b/inferno-core/src/Inferno/Instances/Arbitrary.hs @@ -1,6 +1,5 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE GADTs #-} @@ -124,19 +123,18 @@ instance Arbitrary BaseType where (TEnum <$> arbitraryTypeName <*> (Set.fromList <$> suchThat (listOf (Ident <$> arbitraryName)) (not . null))) -- NOTE: we don't generate custom types because these need to be known when constructing the parser -- : (TCustom . Text.unpack <$> arbitraryName) - : ( map - pure - [ TInt, - TDouble, - TWord16, - TWord32, - TWord64, - TText, - TTime, - TTimeDiff, - TResolution - ] - ) + : map + pure + [ TInt, + TDouble, + TWord16, + TWord32, + TWord64, + TText, + TTime, + TTimeDiff, + TResolution + ] deriving instance ToADTArbitrary RestOfRecord @@ -153,8 +151,8 @@ instance Arbitrary InfernoType where arbitraryArr = TArr - <$> (scale (`div` 3) arbitraryType) - <*> (scale (`div` 3) arbitraryType) + <$> scale (`div` 3) arbitraryType + <*> scale (`div` 3) arbitraryType arbitraryTTuple = do let arbitrarySmaller = scale (`div` 3) arbitraryType @@ -165,15 +163,14 @@ instance Arbitrary InfernoType where arbitraryBase = TBase <$> arbitrary - arbitraryRecord = do - TRecord <$> scale (`div` 3) arbitrary <*> arbitrary + arbitraryRecord = TRecord <$> scale (`div` 3) arbitrary <*> arbitrary arbitraryRest = do -- NOTE: we omit TRep because it is an internal type that the parser does not support constr <- elements [TArray, TSeries, TOptional] constr <$> scale (`div` 3) arbitraryType - arbitraryType = do + arbitraryType = getSize >>= \case 0 -> oneof [arbitraryVar, arbitraryBase] @@ -191,19 +188,19 @@ instance Arbitrary InfernoType where arbitraryName :: Gen Text.Text arbitraryName = ( (\a as -> Text.pack $ a : as) - <$> (elements ['a' .. 'z']) - <*> (listOf $ elements $ ['0' .. '9'] ++ ['a' .. 'z'] ++ ['_']) + <$> elements ['a' .. 'z'] + <*> listOf (elements $ ['0' .. '9'] ++ ['a' .. 'z'] ++ ['_']) ) - `suchThat` (\i -> not $ i `elem` rws) + `suchThat` (`notElem` rws) -- | An arbitrary valid type variable name arbitraryTypeName :: Gen Text.Text arbitraryTypeName = ( (\a as -> Text.pack $ a : as) - <$> (elements ['a' .. 'z']) - <*> (listOf $ elements $ ['0' .. '9'] ++ ['a' .. 'z']) + <$> elements ['a' .. 'z'] + <*> listOf (elements $ ['0' .. '9'] ++ ['a' .. 'z']) ) - `suchThat` (not . (flip elem rws)) + `suchThat` (not . (`elem` rws)) deriving instance ToADTArbitrary Ident @@ -222,7 +219,7 @@ deriving instance ToADTArbitrary ExtIdent instance Arbitrary ExtIdent where shrink = shrinkNothing arbitrary = - ExtIdent <$> oneof [Left <$> (arbitrary `suchThat` ((<) 0)), Right <$> arbitraryName] + ExtIdent <$> oneof [Left <$> (arbitrary `suchThat` (0 <)), Right <$> arbitraryName] deriving instance ToADTArbitrary ImplExpl @@ -242,11 +239,11 @@ instance Arbitrary pos => Arbitrary (Comment pos) where oneof [ LineComment <$> arbitrary - <*> (Text.pack . getPrintableString <$> arbitrary) `suchThat` (Text.all $ \c -> c /= '\n' && c /= '\r') + <*> (Text.pack . getPrintableString <$> arbitrary) `suchThat` Text.all (\c -> c /= '\n' && c /= '\r') <*> arbitrary, BlockComment <$> arbitrary - <*> (Text.pack . getPrintableString <$> arbitrary) `suchThat` (Text.all $ \c -> c /= '*') -- prevent having a '*/' + <*> (Text.pack . getPrintableString <$> arbitrary) `suchThat` Text.all (/= '*') -- prevent having a '*/' <*> arbitrary ] @@ -257,7 +254,7 @@ instance Arbitrary Lit where oneof [ LInt <$> arbitrary, LDouble <$> arbitrary, - (LText . Text.pack . getPrintableString) <$> arbitrary, + LText . Text.pack . getPrintableString <$> arbitrary, LHex <$> arbitrary ] @@ -288,8 +285,8 @@ instance Arbitrary a => Arbitrary (SomeIStr a) where shrink (SomeIStr ISEmpty) = [] shrink (SomeIStr (ISStr s xs)) = -- shrink to subterms - [SomeIStr xs] - ++ + SomeIStr xs + : -- recursively shrink subterms [ case xs' of SomeIStr (ISStr _ _) -> xs' @@ -331,7 +328,7 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where arbitrary = sized arbitrarySized where -- Don't generate implicit variables, because parser does not support them - arbitraryExtIdent = ExtIdent <$> Right <$> arbitraryName + arbitraryExtIdent = ExtIdent . Right <$> arbitraryName arbitraryImplExpl = oneof [Impl <$> arbitraryExtIdent, Expl <$> arbitraryExtIdent] arbitraryVar :: (Arbitrary hash, Arbitrary pos) => Gen (Expr hash pos) arbitraryVar = @@ -342,15 +339,15 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where <*> arbitrary <*> pure LocalScope <*> ( Ident - <$> ( oneof - $ concatMap - ( \case - (InfixOp _, _, op) -> [pure op] - _ -> [] - ) - $ concat - $ IntMap.elems baseOpsTable - ) + <$> oneof + ( concatMap + ( \case + (InfixOp _, _, op) -> [pure op] + _ -> [] + ) + $ concat + $ IntMap.elems baseOpsTable + ) ) ] arbitraryEnum :: (Arbitrary hash, Arbitrary pos) => Gen (Expr hash pos) @@ -360,19 +357,19 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where arbitraryApp n = App - <$> (arbitrarySized $ n `div` 3) - <*> (arbitrarySized $ n `div` 3) + <$> arbitrarySized (n `div` 3) + <*> arbitrarySized (n `div` 3) arbitraryLam n = Lam <$> arbitrary <*> arbitraryLamVars <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) where -- Don't generate implicit vars. Sorry, there must be a nicer way to do this arbitraryLamVars :: Arbitrary pos => Gen (NonEmpty (pos, Maybe ExtIdent)) - arbitraryLamVars = arbitrary `suchThat` (all isSomeRight . snd . NonEmpty.unzip) + arbitraryLamVars = arbitrary `suchThat` all (isSomeRight . snd) isSomeRight (Just (ExtIdent (Right _))) = True isSomeRight _ = False @@ -382,9 +379,9 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where <*> arbitrary <*> arbitraryImplExpl <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) arbitraryLetAnnot n = LetAnnot @@ -394,9 +391,9 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where <*> arbitrary <*> resize (n `div` 3) arbitrary <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) arbitraryIString n = InterpolatedString @@ -411,8 +408,8 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where 0 -> pure ISEmpty m -> oneof - [ ISExpr <$> ((,,) <$> arbitrary <*> (arbitrarySized $ n `div` 3) <*> arbitrary) <*> goT (m - 1), - ISExpr <$> ((,,) <$> arbitrary <*> (arbitrarySized $ n `div` 3) <*> arbitrary) <*> goF (m - 1) + [ ISExpr <$> ((,,) <$> arbitrary <*> arbitrarySized (n `div` 3) <*> arbitrary) <*> goT (m - 1), + ISExpr <$> ((,,) <$> arbitrary <*> arbitrarySized (n `div` 3) <*> arbitrary) <*> goF (m - 1) ] goF :: (Arbitrary hash, Arbitrary pos) => Int -> Gen (IStr 'False (pos, Expr hash pos, pos)) @@ -433,55 +430,55 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where arbitraryIf n = If <$> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) arbitraryAssert n = Assert <$> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) <*> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) arbitraryOp n = (\(prec, fix, op) e1 e2 p h -> Op e1 p h (prec, fix) LocalScope (Ident op) e2) - <$> ( oneof - $ map pure - $ concatMap - ( \(prec, xs) -> - concatMap - ( \case - (InfixOp fix, _, op) -> [(prec, fix, op)] - _ -> [] - ) - xs - ) - $ IntMap.toList baseOpsTable - ) - <*> (arbitrarySized $ n `div` 3) - <*> (arbitrarySized $ n `div` 3) + <$> oneof + ( map pure + $ concatMap + ( \(prec, xs) -> + concatMap + ( \case + (InfixOp fix, _, op) -> [(prec, fix, op)] + _ -> [] + ) + xs + ) + $ IntMap.toList baseOpsTable + ) + <*> arbitrarySized (n `div` 3) + <*> arbitrarySized (n `div` 3) <*> arbitrary <*> arbitrary arbitraryPreOp n = (\(prec, op) e p h -> PreOp p h prec LocalScope (Ident op) e) - <$> ( oneof - $ map pure - $ concatMap - ( \(prec, xs) -> - concatMap - ( \case - (PrefixOp, _, op) -> [(prec, op)] - _ -> [] - ) - xs - ) - $ IntMap.toList baseOpsTable - ) - <*> (arbitrarySized $ n `div` 3) + <$> oneof + ( map pure + $ concatMap + ( \(prec, xs) -> + concatMap + ( \case + (PrefixOp, _, op) -> [(prec, op)] + _ -> [] + ) + xs + ) + $ IntMap.toList baseOpsTable + ) + <*> arbitrarySized (n `div` 3) <*> arbitrary <*> arbitrary @@ -489,7 +486,7 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where arbitraryCase 0 = undefined arbitraryCase n = (\e cs p1 p2 p3 -> Case p1 e p2 (NonEmpty.fromList cs) p3) - <$> (arbitrarySized $ n `div` 3) + <$> arbitrarySized (n `div` 3) <*> ( do k <- choose (1, n) sequence @@ -513,14 +510,14 @@ instance (Arbitrary hash, Arbitrary pos) => Arbitrary (Expr hash pos) where arbitraryArrayComp n = ArrayComp <$> arbitrary - <*> (arbitrarySized $ n `div` 3) + <*> arbitrarySized (n `div` 3) <*> arbitrary <*> ( NonEmpty.fromList <$> do k <- choose (1, n) sequence [(,,,,) <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrarySized (n `div` (3 * k)) <*> pure Nothing | _ <- [1 .. k]] ) - <*> oneof [(\p e -> Just (p, e)) <$> arbitrary <*> (arbitrarySized $ n `div` 3), pure Nothing] + <*> oneof [curry Just <$> arbitrary <*> arbitrarySized (n `div` 3), pure Nothing] <*> arbitrary arbitraryRecord n = do @@ -619,7 +616,7 @@ instance Arbitrary Type.TCScheme where arbitraryImplType = ImplType <$> arbitraryImpls <*> arbitrary arbitraryImpls = - Map.fromList <$> listOf ((,) <$> (ExtIdent <$> Right <$> arbitraryName) <*> arbitrary) + Map.fromList <$> listOf (((,) . ExtIdent . Right <$> arbitraryName) <*> arbitrary) deriving instance ToADTArbitrary Type.Namespace diff --git a/inferno-core/src/Inferno/Module.hs b/inferno-core/src/Inferno/Module.hs index f92da2f..d59c3de 100644 --- a/inferno-core/src/Inferno/Module.hs +++ b/inferno-core/src/Inferno/Module.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE NamedFieldPuns #-} @@ -19,7 +18,7 @@ where import Control.Monad (foldM) import Control.Monad.Catch (MonadThrow (..)) -import Data.Bifunctor (bimap) +import Data.Bifunctor (bimap, second) import Data.Foldable (foldl') import qualified Data.IntMap as IntMap import qualified Data.Map as Map @@ -109,7 +108,7 @@ buildPinnedQQModules modules = Left (sig', val) -> let ns' = sigVarToNamespace name hsh' = vcHash $ BuiltinFunHash (sigVarToExpr LocalScope name, sig) - in (sig', ns', hsh', (\(local, pinned) -> (local, Map.insert hsh (Right val) pinned)) mTrmEnv) + in (sig', ns', hsh', second (Map.insert hsh (Right val)) mTrmEnv) Right (mSig, expr) -> let pinMap = Pinned.openModule moduleName $ @@ -118,20 +117,19 @@ buildPinnedQQModules modules = (Map.map Builtin nsMap) alreadyPinnedModulesMap pinnedExpr = either (error . show) id $ pinExpr pinMap expr - inferEnv = Map.insert moduleName m $ alreadyBuiltModules + inferEnv = Map.insert moduleName m alreadyBuiltModules (pinnedExpr', sig') = either (\err -> error $ "Could not infer the type of this expression: " <> show err) (\(e, typ, _) -> (e, typ)) $ - inferExpr inferEnv $ - pinnedExpr + inferExpr inferEnv pinnedExpr ns' = sigVarToNamespace name hsh' = vcHash $ BuiltinFunHash (sigVarToExpr LocalScope name, sig) - finalExpr = (bimap pinnedToMaybe (const ()) pinnedExpr') + finalExpr = bimap pinnedToMaybe (const ()) pinnedExpr' in case mSig of Just sig'' | sig' /= sig'' -> error $ "Type of " <> show name <> " does not matched inferred type " <> show sig' _ -> - (sig', ns', hsh', (\(local, pinned) -> (local, Map.insert hsh (Left finalExpr) pinned)) mTrmEnv) + (sig', ns', hsh', second (Map.insert hsh (Left finalExpr)) mTrmEnv) in buildModule alreadyPinnedModulesMap alreadyBuiltModules xs $ m { moduleObjects = diff --git a/inferno-core/src/Inferno/Module/Builtin.hs b/inferno-core/src/Inferno/Module/Builtin.hs index c47940c..94673d4 100644 --- a/inferno-core/src/Inferno/Module/Builtin.hs +++ b/inferno-core/src/Inferno/Module/Builtin.hs @@ -53,7 +53,7 @@ builtinModule = [ ( enumBoolHash, TypeMetadata { identExpr = Var () () LocalScope (Expl $ ExtIdent $ Right "_"), - ty = ForallTC [] Set.empty $ ImplType Map.empty $ typeBool, + ty = ForallTC [] Set.empty $ ImplType Map.empty typeBool, docs = Just "Boolean type" } ), @@ -84,12 +84,12 @@ builtinModule = emptyTy, oneTy, boolTy :: TCScheme emptyTy = ForallTC [TV 0] Set.empty $ ImplType Map.empty $ TOptional (TVar $ TV 0) oneTy = ForallTC [TV 0] Set.empty $ ImplType Map.empty $ TVar (TV 0) .-> TOptional (TVar $ TV 0) -boolTy = ForallTC [] Set.empty $ ImplType Map.empty $ typeBool +boolTy = ForallTC [] Set.empty $ ImplType Map.empty typeBool emptyHash, oneHash, enumBoolHash :: VCObjectHash emptyHash = builtinFunHash "empty" emptyTy oneHash = builtinFunHash "one" oneTy -enumBoolHash = vcHash $ BuiltinEnumHash $ boolTy +enumBoolHash = vcHash $ BuiltinEnumHash boolTy builtinFunHash :: Text -> TCScheme -> VCObjectHash builtinFunHash n ty = vcHash $ BuiltinFunHash (Var () () LocalScope $ Expl $ ExtIdent $ Right n, ty) diff --git a/inferno-core/src/Inferno/Module/Cast.hs b/inferno-core/src/Inferno/Module/Cast.hs index 4ffb35b..39af698 100644 --- a/inferno-core/src/Inferno/Module/Cast.hs +++ b/inferno-core/src/Inferno/Module/Cast.hs @@ -1,6 +1,4 @@ -{-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -- TODO export only needed? -- module Inferno.Module.Cast (FromValue, ToValue) where @@ -41,7 +39,7 @@ class ToValue c m a where -- | Class of types that can be converted from script values, allowing IO in the process. class FromValue c m a where - fromValue :: MonadThrow m => (Value c m) -> m a + fromValue :: MonadThrow m => Value c m -> m a -- | Haskell types that can be casted to mask script types. class Kind0 a where @@ -54,9 +52,9 @@ couldNotCast v = throwM $ CastError $ "Could not cast value " - <> (unpack $ renderPretty v) + <> unpack (renderPretty v) <> " to " - <> (show $ typeRep (Proxy :: Proxy a)) + <> show (typeRep (Proxy :: Proxy a)) instance ToValue c m (Value c m) where toValue = id @@ -82,7 +80,7 @@ instance Pretty c => FromValue c m Bool where if ident == "true" then pure True else pure False - else couldNotCast $ (VEnum hash ident :: Value c m) + else couldNotCast (VEnum hash ident :: Value c m) fromValue v = couldNotCast v instance ToValue c m Double where @@ -163,37 +161,37 @@ instance Kind0 Bool where toType _ = TBase $ TEnum "bool" $ Set.fromList ["true", "false"] instance Kind0 Float where - toType _ = TBase $ TDouble + toType _ = TBase TDouble instance Kind0 Double where - toType _ = TBase $ TDouble + toType _ = TBase TDouble instance Kind0 Int where - toType _ = TBase $ TInt + toType _ = TBase TInt instance Kind0 Int64 where - toType _ = TBase $ TInt + toType _ = TBase TInt instance Kind0 Integer where - toType _ = TBase $ TInt + toType _ = TBase TInt instance Kind0 Word16 where - toType _ = TBase $ TWord16 + toType _ = TBase TWord16 instance Kind0 Word32 where - toType _ = TBase $ TWord32 + toType _ = TBase TWord32 instance Kind0 Word64 where - toType _ = TBase $ TWord64 + toType _ = TBase TWord64 instance Kind0 () where toType _ = TTuple TNil instance Kind0 CTime where - toType _ = TBase $ TTime + toType _ = TBase TTime instance Kind0 Text where - toType _ = TBase $ TText + toType _ = TBase TText instance (Kind0 a, Kind0 b) => Kind0 (a -> b) where toType _ = TArr (toType (Proxy :: Proxy a)) (toType (Proxy :: Proxy b)) diff --git a/inferno-core/src/Inferno/Module/Prelude/Defs.hs b/inferno-core/src/Inferno/Module/Prelude/Defs.hs index fe49987..1b93300 100644 --- a/inferno-core/src/Inferno/Module/Prelude/Defs.hs +++ b/inferno-core/src/Inferno/Module/Prelude/Defs.hs @@ -91,11 +91,11 @@ truncateYear day = in fromGregorian y 1 1 secondsBeforeFun, minutesBeforeFun, hoursBeforeFun, daysBeforeFun, weeksBeforeFun :: CTime -> Int64 -> CTime -secondsBeforeFun t i = t - (secondsFun i) -minutesBeforeFun t i = t - (minutesFun i) -hoursBeforeFun t i = t - (hoursFun i) -daysBeforeFun t i = t - (daysFun i) -weeksBeforeFun t i = t - (weeksFun i) +secondsBeforeFun t i = t - secondsFun i +minutesBeforeFun t i = t - minutesFun i +hoursBeforeFun t i = t - hoursFun i +daysBeforeFun t i = t - daysFun i +weeksBeforeFun t i = t - weeksFun i monthsBeforeFun, yearsBeforeFun :: CTime -> Integer -> CTime monthsBeforeFun t m = advanceMonths (negate m) t @@ -202,8 +202,8 @@ sumFun :: (Word32 -> Word32) (Word64 -> Word64) sumFun = - bimap (\x -> either ((+) x) ((+) x . fromIntegral)) $ - bimap (\i -> bimap ((+) $ fromIntegral i) ((+) i)) $ + bimap (\x -> either (x +) ((+) x . fromIntegral)) $ + bimap (\i -> bimap ((+) $ fromIntegral i) (i +)) $ bimap (+) $ bimap (+) $ bimap (+) (+) @@ -214,8 +214,7 @@ divFun :: (Either Double Int64 -> Double) (Either Double Int64 -> Either Double Int64) divFun = - bimap (\x -> either ((/) x) ((/) x . fromIntegral)) $ - (\i -> bimap ((/) $ fromIntegral i) ((div) i)) + bimap (\x -> either (x /) ((/) x . fromIntegral)) (\i -> bimap ((/) $ fromIntegral i) (div i)) modFun :: Int64 -> Int64 -> Int64 modFun = mod @@ -227,10 +226,10 @@ mulFun :: (Either3 Double Int64 EpochTime -> Either3 Double Int64 EpochTime) (Int64 -> EpochTime) mulFun = - bimap (\x -> either ((*) x) ((*) x . fromIntegral)) $ + bimap (\x -> either (x *) ((*) x . fromIntegral)) $ bimap - (\i -> bimap ((*) $ fromIntegral i) (bimap ((*) i) ((*) $ secondsFun i))) - (\x -> ((*) x . secondsFun)) + (\i -> bimap ((*) $ fromIntegral i) (bimap (i *) ((*) $ secondsFun i))) + (\x -> (*) x . secondsFun) subFun :: Either6 Double Int64 EpochTime Word16 Word32 Word64 -> @@ -242,8 +241,8 @@ subFun :: (Word32 -> Word32) (Word64 -> Word64) subFun = - bimap (\x -> either ((-) x) ((-) x . fromIntegral)) $ - bimap (\i -> bimap ((-) $ fromIntegral i) ((-) i)) $ + bimap (\x -> either (x -) ((-) x . fromIntegral)) $ + bimap (\i -> bimap ((-) $ fromIntegral i) (i -)) $ bimap (-) $ bimap (-) $ bimap (-) (-) @@ -298,7 +297,7 @@ truncateToFun n x = in fromIntegral (truncate (x * q) :: Int64) / q limitFun :: Double -> Double -> Double -> Double -limitFun = (\l u -> min u . max l) +limitFun l u = min u . max l piFun :: Double piFun = pi @@ -352,10 +351,10 @@ leqFun :: Either3 Int64 Double EpochTime -> Either3 (Int64 -> Bool) (Double -> B leqFun = bimap (<=) (bimap (<=) (<=)) minFun :: Either3 Int64 Double EpochTime -> Either3 (Int64 -> Int64) (Double -> Double) (EpochTime -> EpochTime) -minFun = bimap (min) (bimap (min) (min)) +minFun = bimap min (bimap min min) maxFun :: Either3 Int64 Double EpochTime -> Either3 (Int64 -> Int64) (Double -> Double) (EpochTime -> EpochTime) -maxFun = bimap (max) (bimap (max) (max)) +maxFun = bimap max (bimap max max) arrayIndexOptFun :: (MonadIO m, MonadThrow m, Pretty c) => Value c m arrayIndexOptFun = @@ -407,7 +406,7 @@ orFun :: Either4 Bool Word16 Word32 Word64 -> Either4 (Bool -> Bool) (Word16 -> orFun = bimap (||) (bimap (.|.) (bimap (.|.) (.|.))) xorFun :: Either4 Bool Word16 Word32 Word64 -> Either4 (Bool -> Bool) (Word16 -> Word16) (Word32 -> Word32) (Word64 -> Word64) -xorFun = bimap (xor) (bimap (xor) (bimap (xor) (xor))) +xorFun = bimap xor (bimap xor (bimap xor xor)) shiftFun :: Either3 Word16 Word32 Word64 -> Either3 (Int -> Word16) (Int -> Word32) (Int -> Word64) shiftFun = bimap shift (bimap shift shift) @@ -440,7 +439,7 @@ zipFun = VFun $ \case VArray xs -> return $ VFun $ \case VArray ys -> - return $ VArray $ map (\(v1, v2) -> VTuple [v1, v2]) $ zip xs ys + return $ VArray $ zipWith (\v1 v2 -> VTuple [v1, v2]) xs ys _ -> throwM $ RuntimeError "zip: expecting an array" _ -> throwM $ RuntimeError "zip: expecting an array" @@ -562,7 +561,7 @@ magnitudeFun = VArray _ -> throwM $ RuntimeError "magnitude: unsupported array type" _ -> throwM $ RuntimeError "magnitude: expecting a number" where - magnitude = sqrt . sum . map (\x -> x ** 2) + magnitude = sqrt . sum . map (** 2) normFun :: (MonadThrow m) => Value c m normFun = magnitudeFun diff --git a/inferno-core/src/Inferno/Parse.hs b/inferno-core/src/Inferno/Parse.hs index 710acc9..de8d68c 100644 --- a/inferno-core/src/Inferno/Parse.hs +++ b/inferno-core/src/Inferno/Parse.hs @@ -1,6 +1,5 @@ {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE ExplicitForAll #-} -{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} module Inferno.Parse @@ -28,10 +27,11 @@ import Control.Monad.Combinators.Expr ) import Control.Monad.Reader (ReaderT (..), ask, withReaderT) import Control.Monad.Writer (WriterT (..), tell) -import Data.Bifunctor (bimap) +import Data.Bifunctor (Bifunctor (first)) import Data.Char (isAlphaNum, isSpace) import Data.Data (Data) import Data.Either (partitionEithers) +import Data.Functor (($>)) import qualified Data.IntMap as IntMap import qualified Data.List as List import Data.List.NonEmpty (NonEmpty) @@ -189,7 +189,7 @@ variable = do where p = pack <$> (((:) <$> letterChar <*> hidden (many alphaNumCharOrSeparator)) "a variable") check oT x = - if x `elem` rws ++ (map (\(_, _, i) -> i) $ concat oT) + if x `elem` rws ++ map (\(_, _, i) -> i) (concat oT) then fail $ "Keyword " <> show x <> " cannot be a variable/function name" else return x @@ -197,14 +197,14 @@ mIdent :: Parser (SourcePos, Maybe Ident) mIdent = lexeme $ do startPos <- getSourcePos (startPos,) . Just . Ident <$> variable - <|> (char '_' *> takeWhileP Nothing isAlphaNumOrSeparator *> pure (startPos, Nothing)) + <|> (char '_' *> takeWhileP Nothing isAlphaNumOrSeparator $> (startPos, Nothing)) "a wildcard parameter '_'" mExtIdent :: Parser (SourcePos, Maybe ExtIdent) mExtIdent = lexeme $ do startPos <- getSourcePos (startPos,) . Just . ExtIdent . Right <$> variable - <|> (char '_' *> takeWhileP Nothing isAlphaNumOrSeparator *> pure (startPos, Nothing)) + <|> (char '_' *> takeWhileP Nothing isAlphaNumOrSeparator $> (startPos, Nothing)) "a wildcard parameter '_'" implicitVariable :: Parser Text @@ -218,11 +218,11 @@ enumConstructor = -- | 'signedInteger' parses an integer with an optional sign (with no space) signedInteger :: Num a => Parser a -signedInteger = Lexer.signed (takeWhileP Nothing isHSpace *> pure ()) Lexer.decimal +signedInteger = Lexer.signed (takeWhileP Nothing isHSpace $> ()) Lexer.decimal -- | 'signedInteger' parses a float/double with an optional sign (with no space) signedFloat :: Parser Double -signedFloat = Lexer.signed (takeWhileP Nothing isHSpace *> pure ()) Lexer.float +signedFloat = Lexer.signed (takeWhileP Nothing isHSpace $> ()) Lexer.float enumE :: (SourcePos -> () -> Scoped ModuleName -> Ident -> f) -> Parser f enumE f = do @@ -261,12 +261,12 @@ signedDoubleE f = label "a number\nfor example: 42, 3.1415, (-6)" $ do noneE :: (SourcePos -> a) -> Parser a noneE e = label "an optional\nfor example: Some x, None" $ do startPos <- getSourcePos - lexeme $ (const $ e startPos) <$> (hidden $ string "None") + lexeme (e startPos <$ hidden (string "None")) someE :: (SourcePos -> t -> a) -> Parser t -> Parser a someE f p = label "an optional\nfor example: Some x, None" $ do startPos <- getSourcePos - lexeme $ (hidden $ string "Some") + lexeme (hidden $ string "Some") f startPos <$> p stringE :: (SourcePos -> Lit -> f SourcePos) -> Parser (f SourcePos) @@ -281,27 +281,26 @@ interpolatedStringE = label "an interpolated string\nfor example: `hello ${1 + 2 lexeme $ do startPos@(SourcePos _ _ col) <- getSourcePos es <- mkInterpolatedString <$> (char '`' *> go) - endPos <- getSourcePos - return $ InterpolatedString startPos (fromEitherList $ fixSpacing (unPos col) es) endPos + InterpolatedString startPos (fromEitherList $ fixSpacing (unPos col) es) <$> getSourcePos where go = - ([] <$ char '`') - <|> try (((:) . Left . singleton) <$> (hidden $ char '\\' *> char '\\') <*> go) - <|> try (((:) . Left . singleton) <$> (hidden $ char '\\' *> char '`') <*> go) - <|> try (((:) . Left . singleton) <$> (hidden $ char '\\' *> char '$') <*> go) - <|> ( ((:) . Right) - <$> ( hidden $ do - startPos <- getSourcePos - e <- char '$' *> char '{' *> sc *> expr <* char '}' - endPos <- getSourcePos - pure $ (startPos, e, endPos) - ) - <*> go + [] <$ char '`' + <|> try ((:) . Left . singleton <$> hidden (char '\\' *> char '\\') <*> go) + <|> try ((:) . Left . singleton <$> hidden (char '\\' *> char '`') <*> go) + <|> try ((:) . Left . singleton <$> hidden (char '\\' *> char '$') <*> go) + <|> (:) . Right + <$> hidden + ( do + startPos <- getSourcePos + e <- char '$' *> char '{' *> sc *> expr <* char '}' + endPos <- getSourcePos + pure (startPos, e, endPos) ) - <|> (((:) . Left . singleton) <$> Lexer.charLiteral <*> go) + <*> go + <|> (:) . Left . singleton <$> Lexer.charLiteral <*> go fixSpacing newlineSpaceLength = - map (bimap (Text.replace (pack $ '\n' : List.replicate (newlineSpaceLength - 1) ' ') "\n") id) + map (first (Text.replace (pack $ '\n' : List.replicate (newlineSpaceLength - 1) ' ') "\n")) arrayComprE = label "array builder\nfor example: [n * 2 + 1 | n <- range 0 10, if n % 2 == 0]" $ lexeme $ do startPos <- getSourcePos @@ -331,7 +330,7 @@ arrayComprE = label "array builder\nfor example: [n * 2 + 1 | n <- range 0 10, i (xs, mcond) <- try rhsE <|> (\c -> ([], Just c)) <$> condE pure ((startPos, var, arrPos, e, Just pos) : xs, mcond) ) - <|> ((\(startPos, var, arrPos, e) -> ([(startPos, var, arrPos, e, Nothing)], Nothing)) <$> selectE) + <|> (\(startPos, var, arrPos, e) -> ([(startPos, var, arrPos, e, Nothing)], Nothing)) <$> selectE condE :: Parser (SourcePos, Expr () SourcePos) condE = do @@ -406,8 +405,7 @@ funE = label "a function\nfor example: fun x y -> x + y" $ do args <- some mExtIdent arrPos <- getSourcePos symbol "->" "'->'" - body <- expr - return $ Lam startPos (NEList.fromList args) arrPos body + Lam startPos (NEList.fromList args) arrPos <$> expr renameModE :: Parser (Expr () SourcePos) renameModE = label "a 'let module' expression\nfor example: let module A = Base in A.#true" $ @@ -415,10 +413,10 @@ renameModE = label "a 'let module' expression\nfor example: let module A = Base hidden $ rword "let" hidden $ rword "module" newNmPos <- getSourcePos - newNm <- lexeme $ (ModuleName <$> variable "module name") + newNm <- lexeme (ModuleName <$> variable "module name") symbol "=" "'='" oldNmPos <- getSourcePos - oldNm <- lexeme $ (ModuleName <$> variable "name of an existing module") + oldNm <- lexeme (ModuleName <$> variable "name of an existing module") inPos <- getSourcePos (opsTable, modOpsTables, customTypes) <- ask case Map.lookup oldNm modOpsTables of @@ -479,21 +477,21 @@ openModArgs modNm = do Nothing -> customFailure $ ModuleNotFound modNm go = try - ((:) <$> ((,) <$> parseImport <*> lexeme ((Just <$> getSourcePos) <* symbol ",")) <*> go) - <|> ((\i -> [(i, Nothing)]) <$> parseImport) + ((:) <$> ((,) <$> parseImport <*> lexeme (Just <$> getSourcePos <* symbol ",")) <*> go) + <|> (\i -> [(i, Nothing)]) <$> parseImport parseImport = try (IOpVar <$> getSourcePos <*> lexeme (char '(' *> (Ident <$> takeWhile1P Nothing isAlphaNum) <* char ')')) <|> try (IEnum <$> lexeme (getSourcePos <* string "enum") <*> getSourcePos <*> lexeme (Ident <$> variable)) - <|> (IVar <$> getSourcePos <*> lexeme (Ident <$> variable)) + <|> IVar <$> getSourcePos <*> lexeme (Ident <$> variable) openModE :: Parser (Expr () SourcePos) openModE = label "an 'open' module expression\nfor example: open A in ..." $ do hidden $ rword "open" nmPos <- getSourcePos - nm <- lexeme $ (ModuleName <$> variable "module name") - (uncurry3 (OpenModule nmPos () nm) <$> (try (openModArgs nm) <|> ((\inPos e -> ([], inPos, e)) <$> getSourcePos <*> openAll nm))) + nm <- lexeme (ModuleName <$> variable "module name") + uncurry3 (OpenModule nmPos () nm) <$> (try (openModArgs nm) <|> (\inPos e -> ([], inPos, e)) <$> getSourcePos <*> openAll nm) where openAll modNm = do (opsTable, modOpsTables, customTypes) <- ask @@ -509,7 +507,7 @@ letE = label ("a 'let' expression" ++ example "x") $ startPos <- getSourcePos hidden $ rword "let" varPos <- getSourcePos - x <- lexeme $ (((Expl . ExtIdent . Right <$> variable) <|> (Impl . ExtIdent . Right <$> implicitVariable)) "a variable") + x <- lexeme ((Expl . ExtIdent . Right <$> variable <|> Impl . ExtIdent . Right <$> implicitVariable) "a variable") let xStr = unpack $ renderPretty x tPos <- getSourcePos maybeTy <- @@ -530,14 +528,14 @@ letE = label ("a 'let' expression" ++ example "x") $ pat :: Parser (Pat () SourcePos) pat = - (uncurry3 PArray <$> array pat) + uncurry3 PArray <$> array pat <|> try (uncurry3 PTuple <$> tuple pat) <|> parens pat <|> try (hexadecimal PLit) <|> try (signedDoubleE PLit) <|> signedIntE PLit <|> enumE PEnum - <|> (uncurry PVar <$> mIdent) + <|> uncurry PVar <$> mIdent <|> noneE PEmpty <|> someE POne pat <|> stringE PLit @@ -594,7 +592,7 @@ tuple p = label "a tuple\nfor example: (2, #true, 4.4)" $ lexeme $ do startPos <- getSourcePos symbol "(" - r <- tListFromList <$> tupleArgs p <|> ((takeWhileP Nothing isHSpace) *> pure TNil) + r <- tListFromList <$> tupleArgs p <|> takeWhileP Nothing isHSpace $> TNil endPos <- getSourcePos char ')' return (startPos, r, endPos) @@ -612,7 +610,7 @@ ifE :: Parser (Expr () SourcePos) ifE = do ifPos <- getSourcePos hidden $ rword "if" - cond <- (hidden $ expr) "_a conditional expression\nfor example: x > 2" + cond <- hidden expr "_a conditional expression\nfor example: x > 2" thenPos <- getSourcePos tr <- (rword "then" *> expr) "_the 'then' branch\nfor example: if x > 2 then 1 else 0" elsePos <- getSourcePos @@ -622,7 +620,7 @@ ifE = do -- | Parses an op in prefix syntax WITHOUT opening paren @(@ but with closing paren @)@ -- E.g. @+)@ prefixOpsWithoutModule :: SourcePos -> Parser (Expr () SourcePos) -prefixOpsWithoutModule startPos = do +prefixOpsWithoutModule startPos = hidden (ask >>= choiceOf (prefixOp startPos) . opsInLocalScope) where opsInLocalScope (ops, _, _) = [s | (_, modNm, s) <- concat ops, modNm == LocalScope] @@ -633,7 +631,7 @@ prefixOpsWithoutModule startPos = do -- | Parses a op in prefix syntax of the form @Mod.(+)@ prefixOpsWithModule :: SourcePos -> Parser (Expr () SourcePos) -prefixOpsWithModule startPos = do +prefixOpsWithModule startPos = hidden (ask >>= tryMany prefixOp . opsNotInLocal) where opsNotInLocal (ops, _, _) = [(modNm, s) | (_, modNm, s) <- concat ops, modNm /= LocalScope] @@ -720,7 +718,7 @@ term = <|> try implVarE <|> stringE Lit <|> interpolatedStringE - <|> (try (uncurry3 Array <$> array expr)) + <|> try (uncurry3 Array <$> array expr) <|> try (uncurry3 Record <$> record expr) <|> arrayComprE @@ -750,19 +748,19 @@ mkOperators opsTable = mkOperatorP prec (InfixOp NoFix) ns o = InfixN $ infixLabel $ - (\pos e1 e2 -> Op e1 pos () (prec, NoFix) ns (Ident o) e2) <$> (lexeme $ getSourcePos <* string (opString ns o)) + (\pos e1 e2 -> Op e1 pos () (prec, NoFix) ns (Ident o) e2) <$> lexeme (getSourcePos <* string (opString ns o)) mkOperatorP prec (InfixOp LeftFix) ns o = InfixL $ infixLabel $ - (\pos e1 e2 -> Op e1 pos () (prec, LeftFix) ns (Ident o) e2) <$> (lexeme $ getSourcePos <* string (opString ns o)) + (\pos e1 e2 -> Op e1 pos () (prec, LeftFix) ns (Ident o) e2) <$> lexeme (getSourcePos <* string (opString ns o)) mkOperatorP prec (InfixOp RightFix) ns o = InfixR $ infixLabel $ - (\pos e1 e2 -> Op e1 pos () (prec, RightFix) ns (Ident o) e2) <$> (lexeme $ getSourcePos <* string (opString ns o)) + (\pos e1 e2 -> Op e1 pos () (prec, RightFix) ns (Ident o) e2) <$> lexeme (getSourcePos <* string (opString ns o)) mkOperatorP prec PrefixOp ns o = Prefix $ prefixLabel $ - (\pos e -> PreOp pos () prec ns (Ident o) e) <$> (lexeme $ getSourcePos <* string (opString ns o)) + (\pos e -> PreOp pos () prec ns (Ident o) e) <$> lexeme (getSourcePos <* string (opString ns o)) parseExpr :: OpsTable -> @@ -797,20 +795,20 @@ baseType :: TyParser InfernoType baseType = do (_, _, _, customTypes) <- ask TBase - <$> ( (symbol "int" *> pure TInt) - <|> (symbol "double" *> pure TDouble) - <|> (symbol "word16" *> pure TWord16) - <|> (symbol "word32" *> pure TWord32) - <|> (symbol "word64" *> pure TWord64) - <|> (symbol "text" *> pure TText) - <|> try (symbol "timeDiff" *> pure TTimeDiff) - <|> (symbol "time" *> pure TTime) - <|> (symbol "resolution" *> pure TResolution) - <|> choice (map (\t -> symbol (pack t) *> pure (TCustom t)) customTypes) + <$> ( symbol "int" $> TInt + <|> symbol "double" $> TDouble + <|> symbol "word16" $> TWord16 + <|> symbol "word32" $> TWord32 + <|> symbol "word64" $> TWord64 + <|> symbol "text" $> TText + <|> try (symbol "timeDiff" $> TTimeDiff) + <|> symbol "time" $> TTime + <|> symbol "resolution" $> TResolution + <|> choice (map (\t -> symbol (pack t) $> TCustom t) customTypes) ) type_variable_raw :: TyParser Text -type_variable_raw = (char '\'' *> takeWhile1P Nothing isAlphaNum) +type_variable_raw = char '\'' *> takeWhile1P Nothing isAlphaNum type_variable :: TyParser Int type_variable = do @@ -875,7 +873,7 @@ typeParserBase = enumList = try ((:) <$> enumConstructor <* symbol "," <*> enumList) - <|> ((: []) <$> enumConstructor) + <|> (: []) <$> enumConstructor typeParser :: TyParser InfernoType typeParser = @@ -923,25 +921,25 @@ tyContext = lexeme $ do _ <- symbol "{" res <- listParser tyContextSingle _ <- symbol "}" - _ <- (symbol "=>" <|> symbol "⇒") + _ <- symbol "=>" <|> symbol "⇒" return res typeClass :: TyParser TypeClass -typeClass = TypeClass <$> (lexeme typeIdent <* symbol "on") <*> (many typeParser) +typeClass = TypeClass <$> (lexeme typeIdent <* symbol "on") <*> many typeParser tyContextSingle :: TyParser (Either TypeClass (Text, InfernoType)) -tyContextSingle = (Left <$> (symbol "requires" *> typeClass)) <|> (Right <$> ((,) <$> (symbol "implicit" *> lexeme (withReaderT (\(_, ops, m, customTypes) -> (ops, m, customTypes)) variable)) <*> (symbol ":" *> typeParser))) +tyContextSingle = Left <$> (symbol "requires" *> typeClass) <|> Right <$> ((,) <$> (symbol "implicit" *> lexeme (withReaderT (\(_, ops, m, customTypes) -> (ops, m, customTypes)) variable)) <*> (symbol ":" *> typeParser)) schemeParser :: TyParser TCScheme schemeParser = do - vars <- try (rword "forall" *> (many $ lexeme $ type_variable_raw) <* rword ".") <|> pure mempty + vars <- try (rword "forall" *> many (lexeme type_variable_raw) <* rword ".") <|> pure mempty withReaderT (\(_, ops, m, ts) -> (Map.fromList $ zip vars [0 ..], ops, m, ts)) $ constructScheme <$> (try tyContext <|> pure []) <*> typeParser where constructScheme :: [Either TypeClass (Text, InfernoType)] -> InfernoType -> TCScheme constructScheme cs t = let (tcs, impls) = partitionEithers cs - in closeOver (Set.fromList tcs) $ ImplType (Map.fromList $ map (bimap (ExtIdent . Right) id) impls) t + in closeOver (Set.fromList tcs) $ ImplType (Map.fromList $ map (first (ExtIdent . Right)) impls) t doc :: Parser Text doc = do @@ -984,24 +982,24 @@ sigVariable = $ concat $ IntMap.elems opsTable in lexeme $ - (tryMany (\op -> char '(' *> (SigOpVar <$> string op) <* char ')') opList) - <|> (tryMany (\op -> (SigVar <$> string op)) preOpList) - <|> (SigVar <$> variable) + tryMany (\op -> char '(' *> (SigOpVar <$> string op) <* char ')') opList + <|> tryMany (fmap SigVar . string) preOpList + <|> SigVar <$> variable data QQDefinition = QQRawDef String | QQToValueDef String | InlineDef (Expr () SourcePos) deriving (Data) exprOrBuiltin :: Parser QQDefinition exprOrBuiltin = - try ((QQToValueDef . unpack) <$> lexeme (string "###" *> withReaderT (const (mempty, mempty, [])) variable <* string "###")) - <|> try ((QQRawDef . unpack) <$> lexeme (string "###!" *> withReaderT (const (mempty, mempty, [])) variable <* string "###")) - <|> (InlineDef <$> expr) + try (QQToValueDef . unpack <$> lexeme (string "###" *> withReaderT (const (mempty, mempty, [])) variable <* string "###")) + <|> try (QQRawDef . unpack <$> lexeme (string "###!" *> withReaderT (const (mempty, mempty, [])) variable <* string "###")) + <|> InlineDef <$> expr sigParser :: Parser (TopLevelDefn (Maybe TCScheme, QQDefinition)) sigParser = - ( try (Signature <$> (try (Just <$> doc) <|> pure Nothing) <*> sigVariable <*> ((,) <$> (try (Just <$> (symbol ":" *> (withReaderT (\(ops, m, customTypes) -> (mempty, ops, m, customTypes)) schemeParser))) <|> pure Nothing) <*> (symbol ":=" *> exprOrBuiltin))) - <|> try (EnumDef <$> (Just <$> doc) <*> (symbol "enum" *> lexeme variable <* symbol ":=") <*> enumConstructors) - <|> (EnumDef Nothing <$> (symbol "enum" *> lexeme variable <* symbol ":=") <*> enumConstructors) - <|> TypeClassInstance <$> (symbol "define" *> (withReaderT (\(ops, m, customTypes) -> (mempty, ops, m, customTypes)) typeClass)) + ( try (Signature <$> (try (Just <$> doc) <|> pure Nothing) <*> sigVariable <*> ((,) <$> (try (Just <$> (symbol ":" *> withReaderT (\(ops, m, customTypes) -> (mempty, ops, m, customTypes)) schemeParser)) <|> pure Nothing) <*> (symbol ":=" *> exprOrBuiltin))) + <|> try ((EnumDef . Just <$> doc) <*> (symbol "enum" *> lexeme variable <* symbol ":=") <*> enumConstructors) + <|> EnumDef Nothing <$> (symbol "enum" *> lexeme variable <* symbol ":=") <*> enumConstructors + <|> TypeClassInstance <$> (symbol "define" *> withReaderT (\(ops, m, customTypes) -> (mempty, ops, m, customTypes)) typeClass) <|> Export <$> (symbol "export" *> (ModuleName <$> lexeme variable)) ) <* symbol ";" @@ -1009,10 +1007,10 @@ sigParser = fixityP :: Parser Fixity fixityP = lexeme $ - try (rword "infixr" *> pure (InfixOp RightFix)) - <|> try (rword "infixl" *> pure (InfixOp LeftFix)) - <|> try (rword "infix" *> pure (InfixOp NoFix)) - <|> try (rword "prefix" *> pure PrefixOp) + try (rword "infixr" $> InfixOp RightFix) + <|> try (rword "infixl" $> InfixOp LeftFix) + <|> try (rword "infix" $> InfixOp NoFix) + <|> try (rword "prefix" $> PrefixOp) type OpsTable = IntMap.IntMap [(Fixity, Scoped ModuleName, Text)] @@ -1022,7 +1020,7 @@ fixityLvl = try (lexeme Lexer.decimal >>= check) check x = if x >= 0 && x < 20 then return x - else fail $ "Fixity level annotation must be between 0 and 19 (inclusive)" + else fail "Fixity level annotation must be between 0 and 19 (inclusive)" sigsParser :: Parser (OpsTable, [TopLevelDefn (Maybe TCScheme, QQDefinition)]) sigsParser = diff --git a/inferno-core/src/Inferno/Parse/Commented.hs b/inferno-core/src/Inferno/Parse/Commented.hs index af578cb..93438dd 100644 --- a/inferno-core/src/Inferno/Parse/Commented.hs +++ b/inferno-core/src/Inferno/Parse/Commented.hs @@ -1,9 +1,3 @@ -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveFoldable #-} -{-# LANGUAGE DeriveTraversable #-} -{-# LANGUAGE KindSignatures #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} module Inferno.Parse.Commented where @@ -72,7 +66,7 @@ insertCommentIntoPat comment e = x : xs -> x : insertTuple xs insertCommentIntoExpr :: Comment SourcePos -> Expr hash SourcePos -> Expr hash SourcePos -insertCommentIntoExpr comment expr = go' expr +insertCommentIntoExpr comment = go' where (startC, endC) = blockPosition comment commentIsWithin s e = s <= startC && endC <= e @@ -203,7 +197,7 @@ insertCommentIntoExpr comment expr = go' expr then ArrayComp p1 (go' e1) posOfBar args mcond p2 else let (args', mcond') = arrayCompGo' mcond $ toList args - in ArrayComp p1 e1 posOfBar (fromList $ args') mcond' p2 + in ArrayComp p1 e1 posOfBar (fromList args') mcond' p2 CommentAfter e1 c -> CommentAfter (go' e1) c CommentBelow e1 c -> CommentBelow (go' e1) c Bracketed p1 e1 p2 -> Bracketed p1 (go' e1) p2 diff --git a/inferno-core/src/Inferno/Utils/QQ/Common.hs b/inferno-core/src/Inferno/Utils/QQ/Common.hs index 7545d3b..219da68 100644 --- a/inferno-core/src/Inferno/Utils/QQ/Common.hs +++ b/inferno-core/src/Inferno/Utils/QQ/Common.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TemplateHaskellQuotes #-} module Inferno.Utils.QQ.Common where @@ -18,7 +18,7 @@ location' :: Q SourcePos location' = aux <$> location where aux :: Loc -> SourcePos - aux loc = let (l, c) = (loc_start loc) in SourcePos (loc_filename loc) (mkPos l) (mkPos c) + aux loc = let (l, c) = loc_start loc in SourcePos (loc_filename loc) (mkPos l) (mkPos c) -- fix for https://stackoverflow.com/questions/38143464/cant-find-inerface-file-declaration-for-variable liftText :: Text -> Q Exp @@ -27,8 +27,8 @@ liftText txt = AppE (VarE 'Text.pack) <$> lift (Text.unpack txt) mkParseErrorStr :: ShowErrorComponent e => (ParseError Text e, SourcePos) -> String mkParseErrorStr (err, SourcePos {..}) = "Error at line " - <> (show $ unPos sourceLine) + <> show (unPos sourceLine) <> " column " - <> (show $ unPos sourceColumn) + <> show (unPos sourceColumn) <> "\n " - <> (Text.unpack $ Text.replace "\n" "\n " $ Text.pack $ prettyError err) + <> Text.unpack (Text.replace "\n" "\n " $ Text.pack $ prettyError err) diff --git a/inferno-core/src/Inferno/Utils/QQ/Module.hs b/inferno-core/src/Inferno/Utils/QQ/Module.hs index b8f0bdc..fbcbe31 100644 --- a/inferno-core/src/Inferno/Utils/QQ/Module.hs +++ b/inferno-core/src/Inferno/Utils/QQ/Module.hs @@ -41,13 +41,13 @@ mkProxy _ = Proxy metaToValue :: (Maybe Type.TCScheme, QQDefinition) -> Maybe TH.ExpQ metaToValue = \case - (Just sch, QQToValueDef x) -> Just [|Left ($(dataToExpQ (\a -> liftText <$> cast a) sch), toValue $(TH.varE (mkName x)))|] + (Just sch, QQToValueDef x) -> Just [|Left ($(dataToExpQ (fmap liftText . cast) sch), toValue $(TH.varE (mkName x)))|] (Nothing, QQToValueDef x) -> Just [|Left (closeOverType (toType (mkProxy $(TH.varE (mkName x)))), toValue $(TH.varE (mkName x)))|] - (Just sch, QQRawDef x) -> Just [|Left ($(dataToExpQ (\a -> liftText <$> cast a) sch), $(TH.varE (mkName x)))|] + (Just sch, QQRawDef x) -> Just [|Left ($(dataToExpQ (fmap liftText . cast) sch), $(TH.varE (mkName x)))|] (Nothing, QQRawDef _) -> error "QQRawDef must have an explicit type" (sch, InlineDef e) -> - Just [|Right ($(dataToExpQ (\a -> liftText <$> cast a) sch), $(dataToExpQ (\a -> liftText <$> cast a) e))|] + Just [|Right ($(dataToExpQ (fmap liftText . cast) sch), $(dataToExpQ (fmap liftText . cast) e))|] -- | QuasiQuoter for builtin Inferno modules. TH dictates that QQs have to be imported, -- not defined locally, so this instantiation is done in this module. @@ -71,7 +71,7 @@ moduleQuoter customTypes = let errs' = map mkParseErrorStr $ NEList.toList $ fst $ attachSourcePos errorOffset errs pos in fail $ intercalate "\n\n" errs' Right (modules, _comments) -> - [|buildPinnedQQModules $(dataToExpQ ((\a -> liftText <$> cast a) `extQ` metaToValue) modules)|], + [|buildPinnedQQModules $(dataToExpQ ((fmap liftText . cast) `extQ` metaToValue) modules)|], quotePat = error "moduleQuoter: Invalid use of this quasi-quoter in pattern context.", quoteType = error "moduleQuoter: Invalid use of this quasi-quoter in type context.", quoteDec = error "moduleQuoter: Invalid use of this quasi-quoter in top-level declaration context." diff --git a/inferno-core/src/Inferno/Utils/QQ/Script.hs b/inferno-core/src/Inferno/Utils/QQ/Script.hs index b951823..7f668d9 100644 --- a/inferno-core/src/Inferno/Utils/QQ/Script.hs +++ b/inferno-core/src/Inferno/Utils/QQ/Script.hs @@ -1,6 +1,6 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE TypeApplications #-} module Inferno.Utils.QQ.Script where @@ -48,7 +48,7 @@ inferno = { quoteExp = \str -> do l <- location' let (_, res) = - runParser' (runWriterT $ flip runReaderT (baseOpsTable @_ @c builtins, builtinModulesOpsTable @_ @c builtins, []) $ topLevel $ expr) $ + runParser' (runWriterT $ flip runReaderT (baseOpsTable @_ @c builtins, builtinModulesOpsTable @_ @c builtins, []) $ topLevel expr) $ State (pack str) 0 @@ -66,7 +66,7 @@ inferno = Left err -> fail $ "Inference failed:\n" <> show err Right (pinnedAST', t, _tyMap) -> do let final = insertCommentsIntoExpr (appEndo comments []) pinnedAST' - dataToExpQ ((\a -> liftText <$> cast a) `extQ` vcObjectHashToValue) (final, t), + dataToExpQ ((fmap liftText . cast) `extQ` vcObjectHashToValue) (final, t), quotePat = error "inferno: Invalid use of this quasi-quoter in pattern context.", quoteType = error "inferno: Invalid use of this quasi-quoter in type context.", quoteDec = error "inferno: Invalid use of this quasi-quoter in top-level declaration context." @@ -75,8 +75,8 @@ inferno = builtins = builtinModules @m @c vcObjectHashToValue :: Crypto.Digest Crypto.SHA256 -> Maybe TH.ExpQ vcObjectHashToValue h = - let str = (convert h) :: ByteString - in Just $ + let str = convert h :: ByteString + in Just ( AppE (VarE 'Maybe.fromJust) <$> (AppE (VarE 'Crypto.digestFromByteString) <$> lift (unpack str)) ) diff --git a/inferno-core/test/Eval/Spec.hs b/inferno-core/test/Eval/Spec.hs index fe1ac0c..1242ac4 100644 --- a/inferno-core/test/Eval/Spec.hs +++ b/inferno-core/test/Eval/Spec.hs @@ -8,6 +8,7 @@ module Eval.Spec where import Control.Monad.Catch (MonadThrow (..)) import Control.Monad.Reader (MonadReader (ask), ReaderT (runReaderT)) import Data.Bifunctor (bimap) +import Data.Foldable (for_) import Data.Int (Int64) import qualified Data.Map as Map import Data.Text (unpack) @@ -47,21 +48,21 @@ runtimeTypeRepsTests Interpreter {evalExpr, defaultEnv, parseAndInfer} = describ shouldEvaluateTo expr (v :: Value TestCustomValue IO) = do evalExpr defaultEnv Map.empty expr >>= \case Left err -> expectationFailure $ "Failed eval with: " <> show err - Right v' -> (renderPretty v') `shouldBe` (renderPretty v) + Right v' -> renderPretty v' `shouldBe` renderPretty v evalTests :: Spec evalTests = describe "evaluate" $ do inferno@(Interpreter {evalExpr, defaultEnv, parseAndInferTypeReps}) <- - runIO $ (mkInferno Prelude.builtinModules [] :: IO (Interpreter IO TestCustomValue)) + runIO (mkInferno Prelude.builtinModules [] :: IO (Interpreter IO TestCustomValue)) let shouldEvaluateInEnvTo implEnv str (v :: Value TestCustomValue IO) = - it ("\"" <> unpack str <> "\" should evaluate to " <> (unpack $ renderPretty v)) $ do + it ("\"" <> unpack str <> "\" should evaluate to " <> unpack (renderPretty v)) $ do case parseAndInferTypeReps str of Left err -> expectationFailure $ show err Right ast -> evalExpr defaultEnv implEnv ast >>= \case Left err -> expectationFailure $ "Failed eval with: " <> show err - Right v' -> (renderPretty v') `shouldBe` (renderPretty v) + Right v' -> renderPretty v' `shouldBe` renderPretty v let shouldEvaluateTo = shouldEvaluateInEnvTo Map.empty let shouldThrowRuntimeError str merr = it ("\"" <> unpack str <> "\" should throw a runtime error") $ do @@ -69,10 +70,8 @@ evalTests = describe "evaluate" $ Left err -> expectationFailure $ show err Right ast -> evalExpr defaultEnv Map.empty ast >>= \case - Left err' -> case merr of - Nothing -> pure () - Just err -> err' `shouldBe` err - Right _ -> expectationFailure $ "Should not evaluate." + Left err' -> (for_ merr (shouldBe err')) + Right _ -> expectationFailure "Should not evaluate." shouldEvaluateTo "3" $ VDouble 3 shouldEvaluateTo "-3" $ VDouble (-3) @@ -152,9 +151,9 @@ evalTests = describe "evaluate" $ shouldEvaluateTo "tanh 1.87" $ VDouble (sinh 1.87 / cosh 1.87) shouldEvaluateTo "truncateTo 4 ((sin 1.87 / (cos 1.87)) - tan 1.87)" $ VDouble 0.0 shouldEvaluateTo "truncateTo 4 (sin (2 * pi))" $ VDouble 0.0 - shouldEvaluateTo "arcSin (sin 1.02) - 1.02 < 1e-9" $ vTrue - shouldEvaluateTo "arcCos (cos 1.02) - 1.02 < 1e-9" $ vTrue - shouldEvaluateTo "arcTan (tan 1.02) - 1.02 < 1e-9" $ vTrue + shouldEvaluateTo "arcSin (sin 1.02) - 1.02 < 1e-9" vTrue + shouldEvaluateTo "arcCos (cos 1.02) - 1.02 < 1e-9" vTrue + shouldEvaluateTo "arcTan (tan 1.02) - 1.02 < 1e-9" vTrue -- Booleans shouldEvaluateTo "#true" vTrue shouldEvaluateTo "!#true" vFalse @@ -254,7 +253,7 @@ evalTests = describe "evaluate" $ shouldEvaluateTo "Array.argmin [3.0, 4.0] ? 1" $ VInt 0 shouldEvaluateTo "Array.argmax [3.0, 4.0] ? 0" $ VInt 1 shouldEvaluateTo "Array.argsort [3.0, 1.0, 2.0]" $ VArray [VInt 1, VInt 2, VInt 0] - shouldEvaluateTo "Array.magnitude []" $ VEmpty + shouldEvaluateTo "Array.magnitude []" VEmpty shouldEvaluateTo "Array.magnitude [1.0, 2.0, 3.0]" $ VOne $ VDouble (sqrt (1.0 + 4.0 + 9.0)) shouldEvaluateTo "Array.norm [1.0, -2.0, 3.0]" $ VOne $ VDouble (sqrt (1.0 + 4.0 + 9.0)) @@ -294,8 +293,8 @@ evalTests = describe "evaluate" $ shouldEvaluateTo "Option.reduce (fun d -> d + 2) 0.0 (Some 4.0)" $ VDouble 6 shouldEvaluateTo "Option.reduce (fun d -> d + 2) 0 (Some 4.0)" $ VDouble 6 shouldEvaluateTo "Option.reduce (fun d -> d + 2) 0.0 None" $ VDouble 0 - shouldEvaluateTo "Option.join None" $ VEmpty - shouldEvaluateTo "Option.join (Some None)" $ VEmpty + shouldEvaluateTo "Option.join None" VEmpty + shouldEvaluateTo "Option.join (Some None)" VEmpty shouldEvaluateTo "Option.join (Some (Some 2.3))" $ VOne $ VDouble 2.3 -- Time shouldEvaluateTo "Time.seconds 5" $ VEpochTime 5 @@ -382,13 +381,13 @@ evalTests = describe "evaluate" $ shouldEvaluateTo "match [1.2, 3, 3] with { | [x, y, z] -> 2*x+3*y+z | _ -> 3 }" $ VDouble 14.4 shouldEvaluateTo "(fun a -> match a with { | [x, y, z] -> truncateTo x 1.1 | _ -> 3 }) [1, 2, 3]" $ VDouble 1.1 -- Tuple - shouldEvaluateTo "fst (1, 0) == snd (0, 1)" $ vTrue - shouldEvaluateTo "zip [1, 2, 3] [4, 5] == [(1, 4), (2, 5)]" $ vTrue - shouldEvaluateTo "zip [1, 2] [\"a\", \"b\"] == [(1,\"a\"),(2,\"b\")]" $ vTrue - shouldEvaluateTo "zip [1] [\"a\", \"b\"] == [(1,\"a\")]" $ vTrue - shouldEvaluateTo "zip [1, 2] [\"a\"] == [(1,\"a\")]" $ vTrue - shouldEvaluateTo "zip [] [1, 2] == []" $ vTrue - shouldEvaluateTo "zip [1, 2] [] == []" $ vTrue + shouldEvaluateTo "fst (1, 0) == snd (0, 1)" vTrue + shouldEvaluateTo "zip [1, 2, 3] [4, 5] == [(1, 4), (2, 5)]" vTrue + shouldEvaluateTo "zip [1, 2] [\"a\", \"b\"] == [(1,\"a\"),(2,\"b\")]" vTrue + shouldEvaluateTo "zip [1] [\"a\", \"b\"] == [(1,\"a\")]" vTrue + shouldEvaluateTo "zip [1, 2] [\"a\"] == [(1,\"a\")]" vTrue + shouldEvaluateTo "zip [] [1, 2] == []" vTrue + shouldEvaluateTo "zip [1, 2] [] == []" vTrue -- Records shouldEvaluateTo "let r = {x = 2; y = 3} in r.x" $ VDouble 2 shouldEvaluateTo "let r = {x = 2; y = 3} in r.y" $ VDouble 3 @@ -398,8 +397,8 @@ evalTests = describe "evaluate" $ shouldEvaluateTo "let x : int = 2 in x" $ VInt 2 shouldEvaluateTo "let x : double = 2 in x" $ VDouble 2 -- Miscellaneous - shouldEvaluateTo "Array.map ((Text.append \"a\") << (Text.append \"b\")) [\"0\", \"1\"] == [\"ab0\", \"ab1\"]" $ vTrue - shouldEvaluateTo "\"0\" |> Text.append \"a\" |> Text.append \"b\" == \"ba0\"" $ vTrue + shouldEvaluateTo "Array.map ((Text.append \"a\") << (Text.append \"b\")) [\"0\", \"1\"] == [\"ab0\", \"ab1\"]" vTrue + shouldEvaluateTo "\"0\" |> Text.append \"a\" |> Text.append \"b\" == \"ba0\"" vTrue shouldEvaluateTo "\"hello world\"" $ VText "hello world" shouldEvaluateInEnvTo (Map.fromList [(ExtIdent $ Right "x", VInt 5)]) @@ -435,12 +434,12 @@ evalTests = describe "evaluate" $ -- Test running interpreter in a custom (reader) monad: ------------------------------------------------------------------------------- -data TestEnv = TestEnv {cache :: Int64} +newtype TestEnv = TestEnv {cache :: Int64} cachedGet :: (MonadReader TestEnv m, MonadThrow m) => Value TestCustomValue (ImplEnvM m TestCustomValue) cachedGet = VFun $ \_ -> do - TestEnv {cache} <- liftImplEnvM $ ask + TestEnv {cache} <- liftImplEnvM ask pure $ VInt cache evalInMonadPrelude :: ModuleMap (ReaderT TestEnv IO) TestCustomValue @@ -461,18 +460,18 @@ evalInMonadTest = do (Prelude.builtinModules @(ReaderT TestEnv IO) @TestCustomValue) evalInMonadPrelude Interpreter {evalExpr, defaultEnv, parseAndInferTypeReps} <- - runIO $ flip runReaderT testEnv $ (mkInferno modules [] :: ReaderT TestEnv IO (Interpreter (ReaderT TestEnv IO) TestCustomValue)) + runIO $ runReaderT (mkInferno modules []) testEnv let shouldEvaluateInEnvTo implEnv str (v :: Value TestCustomValue IO) = - it ("\"" <> unpack str <> "\" should evaluate to " <> (unpack $ renderPretty v)) $ do + it ("\"" <> unpack str <> "\" should evaluate to " <> unpack (renderPretty v)) $ do case parseAndInferTypeReps str of Left err -> expectationFailure $ show err Right ast -> do res <- flip runReaderT testEnv $ evalExpr defaultEnv implEnv ast case res of Left err -> expectationFailure $ "Failed eval with: " <> show err - Right v' -> (renderPretty v') `shouldBe` (renderPretty v) + Right v' -> renderPretty v' `shouldBe` renderPretty v let shouldEvaluateTo = shouldEvaluateInEnvTo Map.empty - describe "TODO" $ do + describe "evalInMonad" $ do shouldEvaluateTo "EvalInMonad.cachedGet ()" $ VInt 4 diff --git a/inferno-core/test/Infer/Spec.hs b/inferno-core/test/Infer/Spec.hs index 52960ec..8a274e1 100644 --- a/inferno-core/test/Infer/Spec.hs +++ b/inferno-core/test/Infer/Spec.hs @@ -41,15 +41,15 @@ inferTests = describe "infer" $ let tv i = TVar (TV {unTV = i}) let makeTCs name params = TypeClass {className = name, params = params} - let addTC ts = makeTCs "addition" ts - let mulTC ts = makeTCs "multiplication" ts - let negTC ts = makeTCs "negate" ts - let numTC ts = makeTCs "numeric" ts - let ordTC ts = makeTCs "order" ts - let repTC ts = makeTCs "rep" ts + let addTC = makeTCs "addition" + let mulTC = makeTCs "multiplication" + let negTC = makeTCs "negate" + let numTC = makeTCs "numeric" + let ordTC = makeTCs "order" + let repTC = makeTCs "rep" let makeType numTypeVars typeClassList t = ForallTC (map (\i -> TV {unTV = i}) [0 .. numTypeVars]) (Set.fromList typeClassList) (ImplType mempty t) - inferno <- runIO $ (mkInferno Prelude.builtinModules [] :: IO (Interpreter IO ())) + inferno <- runIO (mkInferno Prelude.builtinModules [] :: IO (Interpreter IO ())) let shouldInferTypeFor str t = it ("should infer type of \"" <> unpack str <> "\"") $ case parseAndInfer inferno str of @@ -62,7 +62,7 @@ inferTests = describe "infer" $ Left (ParseError err) -> expectationFailure $ prettyError $ fst $ NEList.head err Left (PinError _err) -> pure () Left (InferenceError _err) -> pure () - Right _ -> expectationFailure $ "Should fail to infer a type" + Right _ -> expectationFailure "Should fail to infer a type" shouldInferTypeFor "3" $ makeType 0 [numTC [tv 0], repTC [tv 0]] (TVar $ TV {unTV = 0}) @@ -340,13 +340,13 @@ inferTests = describe "infer" $ shouldBeExhaustive patts = it ("patterns\n " <> printPatts patts <> "\n should be exhaustive") $ case exhaustive enum_sigs $ map (: []) patts of - Just _ps -> expectationFailure $ "These patterns should be exhaustive" + Just _ps -> expectationFailure "These patterns should be exhaustive" Nothing -> pure () shouldBeInexhaustive patts = it ("patterns\n " <> printPatts patts <> "\n should be inexhaustive") $ case exhaustive enum_sigs $ map (: []) patts of Just _ps -> pure () - Nothing -> expectationFailure $ "These patterns should be inexhaustive" + Nothing -> expectationFailure "These patterns should be inexhaustive" shouldBeUseful patts = it ("patterns\n " <> printPatts patts <> "\n should be useful") $ checkUsefullness enum_sigs (map (: []) patts) `shouldBe` [] diff --git a/inferno-core/test/Parse/Spec.hs b/inferno-core/test/Parse/Spec.hs index c2dce4b..e027db6 100644 --- a/inferno-core/test/Parse/Spec.hs +++ b/inferno-core/test/Parse/Spec.hs @@ -1,11 +1,12 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Parse.Spec where +import Control.Monad (void) +import Data.Bifunctor (second) import Data.Functor.Foldable (ana, project) import qualified Data.List.NonEmpty as NonEmpty import Data.Text (Text, pack, unpack) @@ -53,7 +54,7 @@ normalizeExpr = ana $ \case PreOp pos hsh prec LocalScope (Ident "-") e -> case normalizeExpr e of Lit l' (LInt x) -> project $ Lit l' $ LInt $ -x Lit l' (LDouble x) -> project $ Lit l' $ LDouble $ -x - PreOp _ _ _ LocalScope (Ident "-") e' -> project $ e' + PreOp _ _ _ LocalScope (Ident "-") e' -> project e' e' -> project $ PreOp pos hsh prec LocalScope (Ident "-") e' Tuple p1 xs p2 -> project $ Tuple p1 (fmap (\(e, _) -> (normalizeExpr e, Nothing)) xs) p2 Record p1 xs p2 -> project $ Record p1 (fmap (\(f, e, _) -> (f, normalizeExpr e, Nothing)) xs) p2 @@ -67,7 +68,7 @@ normalizeExpr = ana $ \case (normalizeExpr e_body) p2 (fmap (\(p4, x, p5, e, _) -> (p4, x, p5, normalizeExpr e, Nothing)) args) - (fmap (\(p4, e) -> (p4, normalizeExpr e)) e_cond) + (fmap (second normalizeExpr) e_cond) p3 Bracketed _ e _ -> project $ normalizeExpr e Op e1 p1 h (_, fix) modNm i e2 -> project $ Op (normalizeExpr e1) p1 h (0, fix) modNm i (normalizeExpr e2) @@ -88,18 +89,18 @@ parsingTests = describe "pretty printing/parsing" $ do Left err -> property False ( "Pretty: \n" - <> (renderPretty x) + <> renderPretty x <> "\nParse error:\n" - <> (pack $ prettyError $ fst $ NonEmpty.head err) + <> pack (prettyError $ fst $ NonEmpty.head err) ) Right (res, _comments) -> - (normalizeExpr (removeComments x) === normalizeExpr (fmap (const ()) res)) + (normalizeExpr (removeComments x) === normalizeExpr (void res)) ( "Pretty: \n" - <> (renderPretty x) + <> renderPretty x <> "\nParsed: \n" - <> (toStrict $ pShow res) + <> toStrict (pShow res) <> "\nParsed pretty: \n" - <> (renderPretty res) + <> renderPretty res ) describe "parsing literals" $ do @@ -119,7 +120,7 @@ parsingTests = describe "pretty printing/parsing" $ do shouldFailFor "\"0X\nFF\"" describe "parsing interpolated strings" $ do - shouldSucceedFor "``" $ InterpolatedString () (SomeIStr $ ISEmpty) () + shouldSucceedFor "``" $ InterpolatedString () (SomeIStr ISEmpty) () shouldSucceedFor "`hello\nworld`" $ InterpolatedString () (SomeIStr (ISStr "hello\nworld" ISEmpty)) () shouldSucceedFor "`${1}`" $ InterpolatedString () (SomeIStr (ISExpr ((), Lit () (LInt 1), ()) ISEmpty)) () shouldSucceedFor "`hello\nworld${1}`" $ InterpolatedString () (SomeIStr (ISStr "hello\nworld" (ISExpr ((), Lit () (LInt 1), ()) ISEmpty))) () @@ -171,7 +172,7 @@ parsingTests = describe "pretty printing/parsing" $ do describe "parsing records" $ do let r = Record () [(Ident "name", Lit () (LText "Zaphod"), Just ()), (Ident "age", Lit () (LInt 391), Nothing)] () shouldSucceedFor "{}" $ Record () [] () - shouldSucceedFor "{name = \"Zaphod\"; age = 391}" $ r + shouldSucceedFor "{name = \"Zaphod\"; age = 391}" r -- Records are parsed as Var, converted to RecordField later in pinExpr: let varRecordAccess = Var () () (Scope (ModuleName "r")) (Expl (ExtIdent (Right "age"))) shouldSucceedFor "let r = {name = \"Zaphod\"; age = 391} in r.age" $ @@ -267,10 +268,10 @@ parsingTests = describe "pretty printing/parsing" $ do shouldSucceedFor str ast = it ("should succeed for \"" <> unpack str <> "\"") $ case parseExpr (baseOpsTable prelude) (builtinModulesOpsTable prelude) [] str of - Left err -> expectationFailure $ "Failed with: " <> (prettyError $ fst $ NonEmpty.head err) - Right (res, _) -> fmap (const ()) res `shouldBe` ast + Left err -> expectationFailure $ "Failed with: " <> prettyError (fst $ NonEmpty.head err) + Right (res, _) -> void res `shouldBe` ast shouldFailFor str = it ("should fail for \"" <> unpack str <> "\"") $ case parseExpr (baseOpsTable prelude) (builtinModulesOpsTable prelude) [] str of Left _err -> pure () - Right _res -> expectationFailure $ "This should not parse" + Right _res -> expectationFailure "This should not parse" diff --git a/inferno-lsp/CHANGELOG.md b/inferno-lsp/CHANGELOG.md index a8012be..ae142ce 100644 --- a/inferno-lsp/CHANGELOG.md +++ b/inferno-lsp/CHANGELOG.md @@ -1,6 +1,9 @@ # Revision History for inferno-lsp *Note*: we use https://pvp.haskell.org/ (MAJOR.MAJOR.MINOR.PATCH) +## 0.2.4.0 -- 2024-03-18 +* HLint everything + ## 0.2.3.0 -- 2024-03-12 * Update inferno-types and inferno-core version; fix `parseAndInferTypeReps` diff --git a/inferno-lsp/inferno-lsp.cabal b/inferno-lsp/inferno-lsp.cabal index d60d8c5..fa64092 100644 --- a/inferno-lsp/inferno-lsp.cabal +++ b/inferno-lsp/inferno-lsp.cabal @@ -1,6 +1,6 @@ cabal-version: >=1.10 name: inferno-lsp -version: 0.2.3.0 +version: 0.2.4.0 synopsis: LSP for Inferno description: A language server protocol implementation for the Inferno language category: IDE,DSL,Scripting diff --git a/inferno-lsp/src/Inferno/LSP/Completion.hs b/inferno-lsp/src/Inferno/LSP/Completion.hs index 7b1ecbd..23f93b8 100644 --- a/inferno-lsp/src/Inferno/LSP/Completion.hs +++ b/inferno-lsp/src/Inferno/LSP/Completion.hs @@ -5,10 +5,11 @@ module Inferno.LSP.Completion where +import Data.Bifunctor (bimap) import Data.List (delete, nub) import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map as Map -import qualified Data.Maybe as Maybe +import Data.Maybe (mapMaybe) import Data.Set (Set) import Data.Text (Text) import qualified Data.Text as Text @@ -36,7 +37,7 @@ completionQueryAt text pos = (completionLeadup, completionPrefix) text' = Text.take off text breakEnd :: (Char -> Bool) -> Text -> (Text, Text) breakEnd p = - (\(l, r) -> (Text.reverse l, Text.reverse r)) . Text.break p . Text.reverse + bimap Text.reverse Text.reverse . Text.break p . Text.reverse (completionPrefix, completionLeadup) = breakEnd (`elem` (" \t\n[(,=+*&|}?>" :: String)) text' @@ -142,7 +143,7 @@ mkCompletionItem typeClasses txt (modNm, ns) tm@TypeMetadata {ty} = identifierCompletionItems :: [Text] -> Text -> [CompletionItem] identifierCompletionItems idents prefix | "." `Text.isSuffixOf` prefix = [] -- For case like "Module.", returned empty because identifier has no namespace/module prefix - | otherwise = fmap makeIdentifierCompletion $ filter (\identifier -> prefix `Text.isPrefixOf` identifier) idents + | otherwise = makeIdentifierCompletion <$> filter (\identifier -> prefix `Text.isPrefixOf` identifier) idents where makeIdentifierCompletion identifier = CompletionItem @@ -200,7 +201,7 @@ rwsCompletionItems prefix moduleNameCompletionItems :: forall c. (Pretty c, Eq c) => Map.Map (Maybe ModuleName, Namespace) (TypeMetadata TCScheme) -> [CompletionItem] moduleNameCompletionItems preludeNameToTypeMap = fmap mkModuleCompletionItem modules where - modules = nub . fmap unModuleName . Maybe.catMaybes . fmap fst $ Map.keys preludeNameToTypeMap + modules = nub . fmap unModuleName . mapMaybe fst $ Map.keys preludeNameToTypeMap mkModuleCompletionItem m = CompletionItem { _label = m, diff --git a/inferno-lsp/src/Inferno/LSP/ParseInfer.hs b/inferno-lsp/src/Inferno/LSP/ParseInfer.hs index 350f15e..4643eb7 100644 --- a/inferno-lsp/src/Inferno/LSP/ParseInfer.hs +++ b/inferno-lsp/src/Inferno/LSP/ParseInfer.hs @@ -5,7 +5,7 @@ module Inferno.LSP.ParseInfer where -import Control.Monad (forM_) +import Control.Monad (forM_, void) import Control.Monad.IO.Class (MonadIO (..)) import Data.Either (isLeft) import Data.List (find, findIndices, foldl', nub, sort) @@ -135,7 +135,7 @@ inferErrorDiagnostic = \case (unPos $ sourceLine e) (unPos $ sourceColumn e) $ renderDoc - $ "Could not unify" <+> pretty tv <+> "~" <+> (pretty $ closeOverType t) + $ "Could not unify" <+> pretty tv <+> "~" <+> pretty (closeOverType t) ] UnboundExtIdent modNm v (s, e) -> [ errorDiagnosticInfer @@ -223,9 +223,9 @@ inferErrorDiagnostic = \case $ renderDoc $ vsep [ "The implicit variable '" <> case ident of { Left i -> "var$" <> pretty i; Right i -> pretty i } <> "' has multiple types:", - indent 2 (pretty $ closeOverType $ t1), + indent 2 (pretty $ closeOverType t1), "and", - indent 2 (pretty $ closeOverType $ t2) + indent 2 (pretty $ closeOverType t2) ] ] VarMultipleOccurrence (Ident x) (s2, e2) (s1, e1) -> @@ -241,13 +241,13 @@ inferErrorDiagnostic = \case (unPos $ sourceColumn s1) (unPos $ sourceLine e1) (unPos $ sourceColumn e1) - $ message, + message, errorDiagnosticInfer (unPos $ sourceLine s2) (unPos $ sourceColumn s2) (unPos $ sourceLine e2) (unPos $ sourceColumn e2) - $ message + message ] IfConditionMustBeBool _ t (s, e) -> [ errorDiagnosticInfer @@ -287,13 +287,13 @@ inferErrorDiagnostic = \case (unPos $ sourceColumn s1) (unPos $ sourceLine e1) (unPos $ sourceColumn e1) - $ message, + message, errorDiagnosticInfer (unPos $ sourceLine s2) (unPos $ sourceColumn s2) (unPos $ sourceLine e2) (unPos $ sourceColumn e2) - $ message + message ] CaseBranchesMustBeEqType _ t1 t2 (s1, e1) (s2, e2) -> let message = @@ -309,13 +309,13 @@ inferErrorDiagnostic = \case (unPos $ sourceColumn s1) (unPos $ sourceLine e1) (unPos $ sourceColumn e1) - $ message, + message, errorDiagnosticInfer (unPos $ sourceLine s2) (unPos $ sourceColumn s2) (unPos $ sourceLine e2) (unPos $ sourceColumn e2) - $ message + message ] PatternUnificationFail tPat tE p (s, e) -> [ errorDiagnosticInfer @@ -346,13 +346,13 @@ inferErrorDiagnostic = \case (unPos $ sourceColumn s1) (unPos $ sourceLine e1) (unPos $ sourceColumn e1) - $ message, + message, errorDiagnosticInfer (unPos $ sourceLine s2) (unPos $ sourceColumn s2) (unPos $ sourceLine e2) (unPos $ sourceColumn e2) - $ message + message ] NonExhaustivePatternMatch pat (s, e) -> [ errorDiagnosticInfer @@ -364,7 +364,7 @@ inferErrorDiagnostic = \case $ vsep [ "The patterns in this case expression are non-exhaustive.", "For example, the following pattern is missing:", - indent 2 (pretty $ pat) + indent 2 (pretty pat) ] ] UselessPattern (Just pat) (s, e) -> @@ -376,7 +376,7 @@ inferErrorDiagnostic = \case $ renderDoc $ vsep [ "This case is unreachable, since it is subsumed by the previous pattern", - indent 2 (pretty $ pat) + indent 2 (pretty pat) ] ] UselessPattern Nothing (s, e) -> @@ -385,8 +385,7 @@ inferErrorDiagnostic = \case (unPos $ sourceColumn s) (unPos $ sourceLine e) (unPos $ sourceColumn e) - $ renderDoc - $ "This case is unreachable, since it is subsumed by the previous patterns" + $ renderDoc "This case is unreachable, since it is subsumed by the previous patterns" ] -- TypeClassUnificationError t1 t2 tcs (s, e) -> -- [ errorDiagnosticInfer @@ -480,7 +479,7 @@ inferErrorDiagnostic = \case "you are trying to import from", indent 2 (pretty m), "already exists in local scope and would be overshadowed. Consider using:", - indent 2 $ (pretty m) <> "." <> (pretty i) + indent 2 $ pretty m <> "." <> pretty i ] ] CouldNotFindTypeclassWitness tyCls (s, e) -> @@ -507,16 +506,13 @@ parseAndInferDiagnostics :: parseAndInferDiagnostics Interpreter {parseAndInfer, typeClasses} idents txt validateInput = do let input = case idents of [] -> "\n" <> txt - ids -> "fun " <> (Text.intercalate " " $ map (maybe "_" (\(Ident i) -> i)) ids) <> " -> \n" <> txt + ids -> "fun " <> Text.intercalate " " (map (maybe "_" (\(Ident i) -> i)) ids) <> " -> \n" <> txt -- AppConfig _ _ tracer <- ask -- let trace = const $ pure () --traceWith tracer case parseAndInfer input of - Left (ParseError err) -> do - return $ Left $ fmap parseErrorDiagnostic $ NEList.toList err - Left (PinError err) -> do - return $ Left $ concatMap inferErrorDiagnostic $ Set.toList $ Set.fromList err - Left (InferenceError err) -> do - return $ Left $ concatMap inferErrorDiagnostic $ Set.toList $ Set.fromList err + Left (ParseError err) -> return $ Left (parseErrorDiagnostic <$> NEList.toList err) + Left (PinError err) -> return $ Left $ concatMap inferErrorDiagnostic $ Set.toList $ Set.fromList err + Left (InferenceError err) -> return $ Left $ concatMap inferErrorDiagnostic $ Set.toList $ Set.fromList err Right (pinnedAST', tcSch@(ForallTC _ currentClasses (ImplType _ typSig)), tyMap, comments) -> do let signature = collectArrs typSig -- Validate input types @@ -529,12 +525,12 @@ parseAndInferDiagnostics Interpreter {parseAndInfer, typeClasses} idents txt val Left errors -> return $ Left errors Right () -> do -- Insert comments into Lam body - let final = putBackLams lams $ fmap (const ()) $ insertCommentsIntoExpr comments lamBody + let final = putBackLams lams (void (insertCommentsIntoExpr comments lamBody)) return $ Right ( final, tcSch, - Map.foldrWithKey (\k v xs -> (mkHover typeClasses currentClasses k v) : xs) mempty tyMap + Map.foldrWithKey (\k v xs -> mkHover typeClasses currentClasses k v : xs) mempty tyMap ) where -- Extract and replace outermost Lams so that comments can be inserted into script body. @@ -542,11 +538,11 @@ parseAndInferDiagnostics Interpreter {parseAndInfer, typeClasses} idents txt val extractLams lams = \case Lam _ xs _ e -> extractLams (fmap snd xs : lams) e e -> (lams, e) - putBackLams = flip $ foldl' (\e xs -> Lam () (fmap (\x -> ((), x)) xs) () e) + putBackLams = flip $ foldl' (\e xs -> Lam () (fmap ((),) xs) () e) checkScriptIsNotAFunction signature parameters = -- A function with N parameters should have a signature a_1 -> a_2 -> ... -> a_{N+1} - if length signature > (length parameters + 1) + if length signature > length parameters + 1 then Left [errorDiagnosticInfer 0 0 0 2 $ renderDoc $ vsep ["This script evaluates to a function. Did you mean to add input parameters instead?"]] else Right () @@ -570,7 +566,7 @@ parseAndInferDiagnostics Interpreter {parseAndInfer, typeClasses} idents txt val parseAndInferPretty :: forall c. (Pretty c, Eq c) => ModuleMap IO c -> Text -> IO () parseAndInferPretty prelude txt = do interpreter@(Interpreter {typeClasses}) <- mkInferno prelude [] - (parseAndInferDiagnostics @IO @c interpreter) [] txt (const $ Right ()) >>= \case + parseAndInferDiagnostics @IO @c interpreter [] txt (const $ Right ()) >>= \case Left err -> print err Right (expr, typ, _hovers) -> do putStrLn $ Text.unpack $ "internal: " <> renderPretty expr @@ -579,16 +575,16 @@ parseAndInferPretty prelude txt = do putStrLn $ Text.unpack $ "\ntype: " <> renderPretty typ - putStrLn $ "\ntype (pretty)" <> (Text.unpack $ renderDoc $ mkPrettyTy typeClasses mempty typ) + putStrLn $ "\ntype (pretty)" <> Text.unpack (renderDoc $ mkPrettyTy typeClasses mempty typ) parseAndInferTypeReps :: forall c. (Pretty c, Eq c) => ModuleMap IO c -> Text -> [Text] -> Text -> IO () parseAndInferTypeReps prelude expr inTys outTy = do interpreter@(Interpreter {typeClasses}) <- mkInferno prelude [] - (parseAndInferDiagnostics @IO @c interpreter) [] expr (const $ Right ()) >>= \case + parseAndInferDiagnostics @IO @c interpreter [] expr (const $ Right ()) >>= \case Left err -> print err Right (_expr, typ, _hovers) -> do putStrLn $ Text.unpack $ "\ntype: " <> renderPretty typ - putStrLn $ "\ntype (pretty)" <> (Text.unpack $ renderDoc $ mkPrettyTy typeClasses mempty typ) + putStrLn $ "\ntype (pretty)" <> Text.unpack (renderDoc $ mkPrettyTy typeClasses mempty typ) case traverse parseType inTys of Left errs -> print errs @@ -607,15 +603,15 @@ parseAndInferPossibleTypes :: forall c. (Pretty c, Eq c) => ModuleMap IO c -> Te parseAndInferPossibleTypes prelude expr args inTys outTy = do let argIdents = map (Just . Ident) args interpreter@(Interpreter {typeClasses}) <- mkInferno prelude [] - (parseAndInferDiagnostics @IO @c interpreter) argIdents expr (const $ Right ()) >>= \case + parseAndInferDiagnostics @IO @c interpreter argIdents expr (const $ Right ()) >>= \case Left err -> print err Right (_expr, typ, _hovers) -> do putStrLn $ Text.unpack $ "\ntype: " <> renderPretty typ - putStrLn $ "\ntype (pretty)" <> (Text.unpack $ renderDoc $ mkPrettyTy typeClasses mempty typ) + putStrLn $ "\ntype (pretty)" <> Text.unpack (renderDoc $ mkPrettyTy typeClasses mempty typ) case traverse (maybe (pure Nothing) ((Just <$>) . parseType)) inTys of Left errs -> print errs - Right inTysParsed -> case (maybe (pure Nothing) ((Just <$>) . parseType)) outTy of + Right inTysParsed -> case maybe (pure Nothing) ((Just <$>) . parseType) outTy of Left errTy -> print errTy Right outTyParsed -> case inferPossibleTypes typeClasses typ inTysParsed outTyParsed of @@ -631,13 +627,13 @@ parseAndInferPossibleTypes prelude expr args inTys outTy = do mkHover :: Set.Set TypeClass -> Set.Set TypeClass -> (SourcePos, SourcePos) -> TypeMetadata TCScheme -> (Range, MarkupContent) mkHover allClasses currentClasses (s, e) meta@TypeMetadata {identExpr = expr, ty = tcSchTy} = let prettyTy = mkPrettyTy allClasses currentClasses tcSchTy - in ( mkRange ((fromIntegral $ unPos $ sourceLine s) - 2) ((fromIntegral $ unPos $ sourceColumn s) - 1) ((fromIntegral $ unPos $ sourceLine e) - 2) ((fromIntegral $ unPos $ sourceColumn e) - 1), + in ( mkRange (fromIntegral (unPos $ sourceLine s) - 2) (fromIntegral (unPos $ sourceColumn s) - 1) (fromIntegral (unPos $ sourceLine e) - 2) (fromIntegral (unPos $ sourceColumn e) - 1), MarkupContent MkMarkdown $ "**Type**\n" <> "~~~inferno\n" - <> (renderDoc $ pretty expr <+> align prettyTy) + <> renderDoc (pretty expr <+> align prettyTy) <> "\n~~~" - <> (maybe "" ("\n" <>) (getTypeMetadataText meta)) + <> maybe "" ("\n" <>) (getTypeMetadataText meta) ) mkPrettyTy :: forall ann. Set.Set TypeClass -> Set.Set TypeClass -> TCScheme -> Doc ann @@ -656,8 +652,8 @@ mkPrettyTy allClasses currentClasses (ForallTC _tvs cls typ) = let prettyList = map pretty $ nub $ sort $ map (flip apply $ filterOutImplicitTypeReps typ) subs prettyListMax10 = take 10 prettyList in if length prettyListMax10 == length prettyList - then (sep $ unionTySig prettyList) - else (sep $ unionTySig $ prettyList <> ["..."]) + then sep $ unionTySig prettyList + else sep $ unionTySig $ prettyList <> ["..."] where unionTySig [] = [] unionTySig (t : ts) = (":" <+> t) : go ts @@ -680,7 +676,7 @@ getTypeMetadataText TypeMetadata {docs = tcsDocs, ty = ForallTC _ _ (ImplType _ <> hardline <> "enum" <+> pretty nm - <+> align (sep $ "=" : (punctuate' "|" $ map (("#" <>) . pretty . unIdent) $ Set.toList cs)) + <+> align (sep $ "=" : punctuate' "|" (map (("#" <>) . pretty . unIdent) $ Set.toList cs)) <> hardline <> "~~~" _ -> Just $ pretty (fromMaybe "" tcsDocs) diff --git a/inferno-lsp/src/Inferno/LSP/Server.hs b/inferno-lsp/src/Inferno/LSP/Server.hs index d02b83d..d376c12 100644 --- a/inferno-lsp/src/Inferno/LSP/Server.hs +++ b/inferno-lsp/src/Inferno/LSP/Server.hs @@ -14,7 +14,7 @@ module Inferno.LSP.Server where import Colog.Core.Action (LogAction (..)) import Control.Concurrent (forkIO) import Control.Concurrent.STM.TChan (TChan, newTChan, readTChan, writeTChan) -import Control.Concurrent.STM.TVar (TVar, modifyTVar, newTVar, readTVar) +import Control.Concurrent.STM.TVar (TVar, modifyTVar, newTVarIO, readTVarIO) import qualified Control.Exception as E import Control.Monad (forever) import Control.Monad.IO.Class (MonadIO (..)) @@ -91,7 +91,7 @@ runInfernoLspServerWith :: IO Int runInfernoLspServerWith tracer clientIn clientOut prelude customTypes getIdents validateInput before after = flip E.catches handlers $ do rin <- atomically newTChan :: IO (TChan ReactorInput) - docMap <- atomically $ newTVar mempty + docMap <- newTVarIO mempty interpreter <- mkInferno prelude customTypes let infernoEnv = InfernoEnv docMap tracer getIdents before after validateInput @@ -195,7 +195,7 @@ reactor tracer inp = do act getInfernoEnv :: InfernoLspM InfernoEnv -getInfernoEnv = LspT $ ReaderT $ \_ -> ask +getInfernoEnv = LspT $ ReaderT $ const ask trace :: String -> InfernoLspM () trace s = LspT $ @@ -227,7 +227,7 @@ parseAndInferWithTimeout beforeParse afterParse interpreter idents doc_txt valid let timeLimit = 10 mResult <- liftIO $ timeout (timeLimit * 1_000_000) $ parseAndInferDiagnostics @_ @c interpreter idents doc_txt validateInput case mResult of - Nothing -> pure $ Left $ [errorDiagnostic 1 1 1 1 (Just "inferno.lsp") $ "Inferno timed out in " <> T.pack (show timeLimit) <> "s"] + Nothing -> pure $ Left [errorDiagnostic 1 1 1 1 (Just "inferno.lsp") $ "Inferno timed out in " <> T.pack (show timeLimit) <> "s"] Just res -> pure res liftIO $ afterParse (uuid, ts) result @@ -237,13 +237,12 @@ lspHandlers :: forall c. (Pretty c, Eq c) => Interpreter IO c -> TChan ReactorIn lspHandlers interpreter rin = mapHandlers goReq goNot (handle @c interpreter) where goReq :: forall (a :: J.Method 'J.FromClient 'J.Request). Handler InfernoLspM a -> Handler InfernoLspM a - goReq f = \msg k -> do + goReq f msg k = do env <- getLspEnv infernoEnv <- getInfernoEnv liftIO $ atomically $ writeTChan rin $ ReactorAction (flip runReaderT infernoEnv $ runLspT env $ f msg k) - goNot :: forall (a :: J.Method 'J.FromClient 'J.Notification). Handler InfernoLspM a -> Handler InfernoLspM a - goNot f = \msg -> do + goNot f msg = do env <- getLspEnv infernoEnv <- getInfernoEnv liftIO $ atomically $ writeTChan rin $ ReactorAction (flip runReaderT infernoEnv $ runLspT env $ f msg) @@ -314,18 +313,18 @@ handle interpreter@(Interpreter {nameToTypeMap, typeClasses}) = pure $ Just completionPrefix Nothing -> pure Nothing trace $ "Completion prefix: " <> show completionPrefix - mIdents <- liftIO $ getIdents - let completions = maybe [] id $ findInPrelude @c nameToTypeMap <$> completionPrefix + mIdents <- liftIO getIdents + let completions = maybe [] (findInPrelude @c nameToTypeMap) completionPrefix idents = unIdent <$> catMaybes mIdents - identCompletions = maybe [] id $ identifierCompletionItems idents <$> completionPrefix - rwsCompletions = maybe [] id $ rwsCompletionItems <$> completionPrefix - moduleCompletions = maybe [] id $ filterModuleNameCompletionItems @c nameToTypeMap <$> completionPrefix + identCompletions = maybe [] (identifierCompletionItems idents) completionPrefix + rwsCompletions = maybe [] rwsCompletionItems completionPrefix + moduleCompletions = maybe [] (filterModuleNameCompletionItems @c nameToTypeMap) completionPrefix allCompletions = rwsCompletions ++ moduleCompletions ++ identCompletions ++ map (uncurry $ mkCompletionItem typeClasses $ fromMaybe "" completionPrefix) completions trace $ "Ident completions: " <> show identCompletions trace $ "Found completions: " <> show (map fst completions) - responder $ Right $ J.InL $ J.List $ allCompletions, + responder $ Right $ J.InL $ J.List allCompletions, requestHandler J.STextDocumentHover $ \req responder -> do InfernoEnv {hovers = hoversTV} <- getInfernoEnv trace "Processing a textDocument/hover request" @@ -342,25 +341,17 @@ handle interpreter@(Interpreter {nameToTypeMap, typeClasses}) = Just (VirtualFile doc_version _ _) -> pure $ Just doc_version Nothing -> pure Nothing - hoversMap <- liftIO $ atomically $ readTVar hoversTV + hoversMap <- liftIO $ readTVarIO hoversTV responder $ Right $ case mDoc_version of Just doc_version -> case Map.lookup (doc_uri, doc_version) hoversMap of Just hovers -> (\(r, t) -> J.Hover (J.HoverContents t) (Just r)) - <$> ( findSmallestRange $ - flip filter hovers $ - \(J.Range (J.Position lStart cStart) (J.Position lEnd cEnd), _) -> - if l < lStart || l > lEnd - then False - else - if l == lStart && c < cStart - then False - else - if l == lEnd && c > cEnd - then False - else True - ) + <$> findSmallestRange + ( flip filter hovers $ + \(J.Range (J.Position lStart cStart) (J.Position lEnd cEnd), _) -> + not (((l < lStart || l > lEnd) || (l == lStart && c < cStart)) || (l == lEnd && c > cEnd)) + ) Nothing -> Nothing Nothing -> Nothing ] @@ -370,18 +361,9 @@ findSmallestRange = \case [] -> Nothing (r : rs) -> Just $ foldr (\x@(a, _) y@(b, _) -> if a `containsRange` b then y else x) r rs where - containsRange - (J.Range (J.Position aStartLine aStartColumn) (J.Position aEndLine aEndColumn)) - (J.Range (J.Position bStartLine bStartColumn) (J.Position bEndLine bEndColumn)) = - if bStartLine < aStartLine || bEndLine < aStartLine - then False - else - if bStartLine > aEndLine || bEndLine > aEndLine - then False - else - if bStartLine == aStartLine && bStartColumn < aStartColumn - then False - else - if bEndLine == aEndLine && bEndColumn > aEndColumn - then False - else True + containsRange (J.Range (J.Position aStartLine aStartColumn) (J.Position aEndLine aEndColumn)) (J.Range (J.Position bStartLine bStartColumn) (J.Position bEndLine bEndColumn)) + | bStartLine < aStartLine || bEndLine < aStartLine = False + | bStartLine > aEndLine || bEndLine > aEndLine = False + | bStartLine == aStartLine && bStartColumn < aStartColumn = False + | bEndLine == aEndLine && bEndColumn > aEndColumn = False + | otherwise = True diff --git a/inferno-ml/CHANGELOG.md b/inferno-ml/CHANGELOG.md index 96e80d3..b218d85 100644 --- a/inferno-ml/CHANGELOG.md +++ b/inferno-ml/CHANGELOG.md @@ -1,6 +1,9 @@ # Revision History for inferno-ml *Note*: we use https://pvp.haskell.org/ (MAJOR.MAJOR.MINOR.PATCH) +## 0.3.3.0 -- 2024-03-18 +* HLint everything + ## 0.3.0.0 -- 2024-02-26 * Breaking change: add `VExtended` constructor to `MlValue` * Add `toType` primitive diff --git a/inferno-ml/inferno-ml.cabal b/inferno-ml/inferno-ml.cabal index 1c61e73..a48e048 100644 --- a/inferno-ml/inferno-ml.cabal +++ b/inferno-ml/inferno-ml.cabal @@ -1,6 +1,6 @@ cabal-version: >=1.10 name: inferno-ml -version: 0.3.0.0 +version: 0.3.1.0 synopsis: Machine Learning primitives for Inferno description: Machine Learning primitives for Inferno homepage: https://github.com/plow-technologies/inferno.git#readme diff --git a/inferno-ml/src/Inferno/ML/Module/Prelude.hs b/inferno-ml/src/Inferno/ML/Module/Prelude.hs index 4740115..804bbea 100644 --- a/inferno-ml/src/Inferno/ML/Module/Prelude.hs +++ b/inferno-ml/src/Inferno/ML/Module/Prelude.hs @@ -111,19 +111,19 @@ asArray4Fun :: Tensor -> [[[[Double]]]] asArray4Fun t = asValue $ toType TD.Double t argmaxFun :: Int -> Bool -> Tensor -> Tensor -argmaxFun i keepDim t = argmax (Dim i) (if keepDim then KeepDim else RemoveDim) t +argmaxFun i keepDim = argmax (Dim i) (if keepDim then KeepDim else RemoveDim) softmaxFun :: Int -> Tensor -> Tensor -softmaxFun i t = softmax (Dim i) t +softmaxFun i = softmax (Dim i) stackFun :: Int -> [Tensor] -> Tensor -stackFun i t = Torch.stack (Dim i) t +stackFun i = Torch.stack (Dim i) tanHTFun :: Tensor -> Tensor tanHTFun = Torch.Functional.tanh powTFun :: Int -> Tensor -> Tensor -powTFun i t = pow i t +powTFun = pow loadModelFun :: Text -> ScriptModule loadModelFun f = unsafePerformIO $ TS.loadScript TS.WithoutRequiredGrad $ unpack f diff --git a/inferno-ml/test/Spec.hs b/inferno-ml/test/Spec.hs index e401eb6..38c5d27 100644 --- a/inferno-ml/test/Spec.hs +++ b/inferno-ml/test/Spec.hs @@ -51,7 +51,7 @@ evalTests = describe "evaluate" $ Interpreter {evalExpr, defaultEnv, parseAndInfer, parseAndInferTypeReps} <- runIO $ mkInferno @_ @(MlValue ()) mlPrelude customTypes let shouldEvaluateInEnvTo implEnv str (v :: Value (MlValue ()) IO) = - it ("\"" <> unpack str <> "\" should evaluate to " <> (unpack $ renderPretty v)) $ do + it ("\"" <> unpack str <> "\" should evaluate to " <> unpack (renderPretty v)) $ do case parseAndInferTypeReps str of Left err -> expectationFailure $ show err Right ast -> diff --git a/inferno-types/CHANGELOG.md b/inferno-types/CHANGELOG.md index d4aa2a7..5930ef8 100644 --- a/inferno-types/CHANGELOG.md +++ b/inferno-types/CHANGELOG.md @@ -1,6 +1,9 @@ # Revision History for inferno-types *Note*: we use https://pvp.haskell.org/ (MAJOR.MAJOR.MINOR.PATCH) +## 0.4.1.0 -- 2024-03-18 +* HLint everything + ## 0.4.0.0 -- 2024-03-12 * Add record types to InfernoType, Value, and Expr diff --git a/inferno-types/inferno-types.cabal b/inferno-types/inferno-types.cabal index 3b4235b..fdae2ae 100644 --- a/inferno-types/inferno-types.cabal +++ b/inferno-types/inferno-types.cabal @@ -1,6 +1,6 @@ cabal-version: >=1.10 name: inferno-types -version: 0.4.0.0 +version: 0.4.1.0 synopsis: Core types for Inferno description: Core types for the Inferno language category: DSL,Scripting diff --git a/inferno-types/src/Inferno/Types/Syntax.hs b/inferno-types/src/Inferno/Types/Syntax.hs index fe33eee..59e4738 100644 --- a/inferno-types/src/Inferno/Types/Syntax.hs +++ b/inferno-types/src/Inferno/Types/Syntax.hs @@ -1,15 +1,11 @@ {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveFoldable #-} -{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-} -{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} -{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RankNTypes #-} @@ -120,12 +116,12 @@ module Inferno.Types.Syntax ) where -import Control.Applicative (liftA, liftA2, liftA3) +import Control.Applicative (liftA2, liftA3) import Control.DeepSeq (NFData (..)) import Control.Monad (replicateM) import Data.Aeson (FromJSON (..), FromJSONKey (..), FromJSONKeyFunction (FromJSONKeyTextParser), ToJSON (..), ToJSONKey (..)) import Data.Aeson.Types (toJSONKeyText) -import Data.Bifunctor (bimap) +import Data.Bifunctor (bimap, first) import Data.Bifunctor.TH (deriveBifunctor) import Data.Data (Constr, Data (..), Typeable, gcast1, mkConstr, mkDataType) import qualified Data.Data as Data @@ -138,7 +134,7 @@ import Data.List (intercalate) import Data.List.NonEmpty (NonEmpty ((:|)), toList) import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map as Map -import Data.Maybe (fromMaybe, mapMaybe) +import Data.Maybe (mapMaybe) import Data.Serialize (Serialize (..)) import qualified Data.Serialize as Serialize import qualified Data.Set as Set @@ -218,11 +214,9 @@ instance Serialize BaseType where 8 -> pure TResolution 9 -> do nm <- Serialize.get - ids <- Serialize.get - pure $ TEnum (Text.decodeUtf8 nm) $ Set.fromList $ map (Ident . Text.decodeUtf8) ids + TEnum (Text.decodeUtf8 nm) . Set.fromList . map (Ident . Text.decodeUtf8) <$> Serialize.get 10 -> do - t <- Serialize.get - pure $ TCustom t + TCustom <$> Serialize.get _ -> error "Unknown serialization of BaseType" put = \case @@ -323,7 +317,7 @@ instance Pretty BaseType where TTime -> "time" TTimeDiff -> "timeDiff" TResolution -> "resolution" - TEnum t cs -> pretty t <> encloseSep lbrace rbrace comma (map (((<>) "#") . pretty . unIdent) $ Set.toList cs) + TEnum t cs -> pretty t <> encloseSep lbrace rbrace comma (map (("#" <>) . pretty . unIdent) $ Set.toList cs) TCustom t -> pretty t instance Pretty InfernoType where @@ -423,7 +417,7 @@ instance Pretty Scheme where instance Pretty TypeClass where pretty = \case - TypeClass nm tys -> pretty nm <+> "on" <+> (hsep $ map bracketPretty tys) + TypeClass nm tys -> pretty nm <+> "on" <+> hsep (map bracketPretty tys) where bracketPretty ty = case ty of TVar _ -> pretty ty @@ -434,7 +428,7 @@ newtype TypeClassShape = TypeClassShape TypeClass instance Pretty TypeClassShape where pretty = \case - TypeClassShape (TypeClass nm tys) -> pretty nm <+> "on" <+> (hsep $ map bracketPretty tys) + TypeClassShape (TypeClass nm tys) -> pretty nm <+> "on" <+> hsep (map bracketPretty tys) where bracketPretty ty = case ty of TVar _ -> "_" @@ -512,7 +506,7 @@ instance Substitutable InfernoType where instance Substitutable ImplType where apply s (ImplType impl t) = ImplType (Map.map (apply s) impl) $ apply s t - ftv (ImplType impl t) = (foldr Set.union Set.empty $ map (ftv . snd) $ Map.toList impl) `Set.union` ftv t + ftv (ImplType impl t) = foldr (Set.union . ftv . snd) Set.empty (Map.toList impl) `Set.union` ftv t instance Substitutable TypeClass where apply s (TypeClass n tys) = TypeClass n $ map (apply s) tys @@ -522,7 +516,7 @@ instance Substitutable TCScheme where apply (Subst s) (ForallTC as tcs t) = ForallTC as (Set.map (apply s') tcs) (apply s' t) where s' = Subst $ foldr Map.delete s as - ftv (ForallTC as tcs t) = ((ftv t) `Set.union` (Set.unions $ Set.elems $ Set.map ftv tcs)) `Set.difference` Set.fromList as + ftv (ForallTC as tcs t) = (ftv t `Set.union` Set.unions (Set.elems $ Set.map ftv tcs)) `Set.difference` Set.fromList as instance Substitutable a => Substitutable [a] where apply = map . apply @@ -592,7 +586,7 @@ newtype ExtIdent = ExtIdent (Either Int Text) instance ToJSONKey ExtIdent where toJSONKey = toJSONKeyText $ \case - ExtIdent (Left i) -> "var$" <> (Text.pack $ show i) + ExtIdent (Left i) -> "var$" <> Text.pack (show i) ExtIdent (Right k) -> "reg$" <> k instance FromJSONKey ExtIdent where @@ -670,7 +664,7 @@ instance Pretty Lit where LInt i -> if i < 0 then "(" <> pretty i <> ")" else pretty i LDouble d -> if d < 0 then "(" <> pretty d <> ")" else pretty d LText t -> pretty $ show t - LHex w -> "0x" <> (pretty $ showHex w "") + LHex w -> "0x" <> pretty (showHex w "") instance ElementPosition Lit where elementPosition pos l = (pos, incSourceCol pos $ length $ show $ pretty l) @@ -723,7 +717,7 @@ instance (Typeable f, Data e) => Data (IStr f e) where toConstr (ISExpr _ _) = con_ISExpr dataTypeOf _ = ty_IStr - dataCast1 f = gcast1 f + dataCast1 = gcast1 con_ISEmpty, con_ISStr, con_ISExpr :: Constr con_ISEmpty = mkConstr ty_IStr "ISEmpty" [] Data.Prefix @@ -743,7 +737,7 @@ instance Traversable (IStr f) where {-# INLINE traverse #-} -- so that traverse can fuse traverse f = \case ISEmpty -> pure ISEmpty - ISStr s xs -> liftA (ISStr s) (traverse f xs) + ISStr s xs -> fmap (ISStr s) (traverse f xs) ISExpr e xs -> liftA2 ISExpr (f e) (traverse f xs) data SomeIStr e = forall f. (Typeable f) => SomeIStr (IStr f e) @@ -762,7 +756,7 @@ instance Data e => Data (SomeIStr e) where toConstr _ = con_SomeIStr dataTypeOf _ = ty_SomeIStr - dataCast1 f = gcast1 f + dataCast1 = gcast1 con_SomeIStr :: Constr con_SomeIStr = mkConstr ty_SomeIStr "SomeIStr" [] Data.Prefix @@ -775,9 +769,9 @@ deriving instance Show e => Show (SomeIStr e) instance Eq e => Eq (SomeIStr e) where (SomeIStr ISEmpty) == (SomeIStr ISEmpty) = True (SomeIStr (ISStr s1 xs)) == (SomeIStr (ISStr s2 ys)) = - (s1 == s2) && (SomeIStr xs) == (SomeIStr ys) + s1 == s2 && SomeIStr xs == SomeIStr ys (SomeIStr (ISExpr e1 xs)) == (SomeIStr (ISExpr e2 ys)) = - (e1 == e2) && (SomeIStr xs) == (SomeIStr ys) + e1 == e2 && SomeIStr xs == SomeIStr ys _ == _ = False instance Ord e => Ord (SomeIStr e) where @@ -1152,8 +1146,8 @@ patternToExpr = \case PLit _ l -> Lit () l POne _ p -> One () $ patternToExpr p PEmpty _ -> Empty () - PArray _ ps _ -> Array () (fmap (\(pat, pos) -> (patternToExpr pat, pos)) ps) () - PTuple _ ps _ -> Tuple () (fmap (\(pat, pos) -> (patternToExpr pat, pos)) ps) () + PArray _ ps _ -> Array () (fmap (first patternToExpr) ps) () + PTuple _ ps _ -> Tuple () (fmap (first patternToExpr) ps) () PCommentAbove c p -> CommentAbove c $ patternToExpr p PCommentAfter p c -> CommentAfter (patternToExpr p) c PCommentBelow p c -> CommentBelow (patternToExpr p) c @@ -1164,7 +1158,7 @@ getIdentifierPositions (Ident i) = cata go go :: ExprF a SourcePos [(SourcePos, SourcePos)] -> [(SourcePos, SourcePos)] go = \case VarF pos _ _ v@(Expl (ExtIdent (Right a))) -> if i == a then let (sPos, ePos) = elementPosition pos v in [(sPos, ePos)] else [] - rest -> foldr (++) [] rest + rest -> concat rest class BlockUtils f where blockPosition :: f SourcePos -> (SourcePos, SourcePos) @@ -1184,7 +1178,7 @@ instance BlockUtils Comment where renameModule _ = id instance BlockUtils Import where - blockPosition p = cata go p + blockPosition = cata go where go = \case IVarF pos v -> elementPosition pos v @@ -1215,12 +1209,12 @@ instance BlockUtils Import where rest -> foldl (++) [False] rest instance BlockUtils (Pat hash) where - blockPosition p = cata go p + blockPosition = cata go where go :: PatF hash SourcePos (SourcePos, SourcePos) -> (SourcePos, SourcePos) go = \case PVarF pos v -> elementPosition pos v - PEnumF pos _ ns (Ident i) -> (pos, incSourceCol pos $ Text.length i + 1 + (fromScoped 0 $ (+ 1) . Text.length . unModuleName <$> ns)) + PEnumF pos _ ns (Ident i) -> (pos, incSourceCol pos $ Text.length i + 1 + fromScoped 0 ((+ 1) . Text.length . unModuleName <$> ns)) PLitF pos l -> elementPosition pos l PEmptyF pos -> (pos, incSourceCol pos 5) POneF pos1 (_, pos2) -> (pos1, pos2) @@ -1256,13 +1250,13 @@ instance BlockUtils (Pat hash) where rest -> foldl (++) [False] rest instance BlockUtils (Expr hash) where - blockPosition e = cata go e + blockPosition = cata go where go :: ExprF hash SourcePos (SourcePos, SourcePos) -> (SourcePos, SourcePos) go = \case VarF pos _ ns v -> let (sPos, ePos) = elementPosition pos v in (sPos, incSourceCol ePos $ fromScoped 0 $ (+ 1) . Text.length . unModuleName <$> ns) OpVarF pos _ ns v -> let (sPos, ePos) = elementPosition pos v in (sPos, incSourceCol ePos $ fromScoped 2 $ (+ 3) . Text.length . unModuleName <$> ns) - EnumF pos _ ns (Ident i) -> (pos, incSourceCol pos $ Text.length i + 1 + (fromScoped 0 $ (+ 1) . Text.length . unModuleName <$> ns)) + EnumF pos _ ns (Ident i) -> (pos, incSourceCol pos $ Text.length i + 1 + fromScoped 0 ((+ 1) . Text.length . unModuleName <$> ns)) AppF (pos1, _) (_, pos2) -> (pos1, pos2) LamF pos1 _ _ (_, pos2) -> (pos1, pos2) LetF pos1 _ _ _ _ _ (_, pos2) -> (pos1, pos2) @@ -1401,12 +1395,12 @@ instance Pretty (Pat hash a) where pretty = \case PVar _ (Just (Ident x)) -> pretty x PVar _ Nothing -> "_" - PEnum _ _ ns (Ident n) -> (fromScoped mempty $ (<> ".") . pretty . unModuleName <$> ns) <> "#" <> pretty n + PEnum _ _ ns (Ident n) -> fromScoped mempty ((<> ".") . pretty . unModuleName <$> ns) <> "#" <> pretty n PLit _ l -> pretty l PArray _ [] _ -> "[]" - PArray _ ps _ -> group $ (flatAlt "[ " "[") <> prettyElems True "]" ps + PArray _ ps _ -> group $ flatAlt "[ " "[" <> prettyElems True "]" ps PTuple _ TNil _ -> "()" - PTuple _ ps _ -> group $ (flatAlt "( " "(") <> prettyElems True ")" (tListToList ps) + PTuple _ ps _ -> group $ flatAlt "( " "(" <> prettyElems True ")" (tListToList ps) POne _ e -> "Some" <+> align (pretty e) PEmpty _ -> "None" PCommentAbove c e -> pretty c <> hardline <> pretty e @@ -1434,34 +1428,34 @@ instance Pretty (Expr hash pos) where prettyPrec :: Bool -> Int -> Expr hash pos -> Doc ann prettyPrec isBracketed prec expr = case expr of - Var _ _ ns x -> (fromScoped mempty $ (<> ".") . pretty . unModuleName <$> ns) <> pretty x + Var _ _ ns x -> fromScoped mempty ((<> ".") . pretty . unModuleName <$> ns) <> pretty x TypeRep _ ty -> "@" <> pretty ty - OpVar _ _ ns (Ident x) -> (fromScoped mempty $ (<> ".") . pretty . unModuleName <$> ns) <> "(" <> pretty x <> ")" - Enum _ _ ns (Ident n) -> (fromScoped mempty $ (<> ".") . pretty . unModuleName <$> ns) <> "#" <> pretty n + OpVar _ _ ns (Ident x) -> fromScoped mempty ((<> ".") . pretty . unModuleName <$> ns) <> "(" <> pretty x <> ")" + Enum _ _ ns (Ident n) -> fromScoped mempty ((<> ".") . pretty . unModuleName <$> ns) <> "#" <> pretty n App _ _ -> group $ nest 2 $ prettyApp $ collectApps expr where prettyAppAux m p = case m of - Var _ _ _ _ -> p - OpVar _ _ _ _ -> p - Enum _ _ _ _ -> p + Var {} -> p + OpVar {} -> p + Enum {} -> p Lit _ _ -> p - InterpolatedString _ _ _ -> p - Tuple _ _ _ -> p + InterpolatedString {} -> p + Tuple {} -> p Empty _ -> p -- TODO test that these do the right thing! - Record _ _ _ -> p - RecordField _ _ _ -> p - Array _ _ _ -> p - ArrayComp _ _ _ _ _ _ -> p - Bracketed _ _ _ -> p + Record {} -> p + RecordField {} -> p + Array {} -> p + ArrayComp {} -> p + Bracketed {} -> p _ -> enclose lparen rparen $ if hasTrailingComment m then p <> hardline else p prettyApp = \case [] -> mempty [x] -> prettyAppAux x $ prettyPrec True 0 x - (x : xs) -> (prettyAppAux x $ prettyPrec True 0 x) <> (if hasTrailingComment x then hardline else line) <> prettyApp xs + (x : xs) -> prettyAppAux x (prettyPrec True 0 x) <> (if hasTrailingComment x then hardline else line) <> prettyApp xs Lam _ xs _ e -> - let fun = "fun" <+> align (sep $ map (fromMaybe "_" . fmap pretty . snd) $ toList xs) <+> "->" + let fun = "fun" <+> align (sep $ map (maybe "_" pretty . snd) $ toList xs) <+> "->" body = align $ prettyPrec False 0 e in group $ nest 2 $ vsep [fun, body] Let _ _ x _ e1 _ e2 -> @@ -1484,15 +1478,15 @@ prettyPrec isBracketed prec expr = prettyISExpr :: IStr 'True (a, Expr hash a, a) -> [Doc ann] prettyISExpr = \case ISEmpty -> [] - ISExpr (_, e, _) ISEmpty -> (indentE $ prettyPrec False 0 e) : if hasTrailingComment e then [hardline, "}"] else ["}"] + ISExpr (_, e, _) ISEmpty -> indentE (prettyPrec False 0 e) : if hasTrailingComment e then [hardline, "}"] else ["}"] ISExpr (_, e, _) xs@(ISExpr _ _) -> - ((indentE $ prettyPrec False 0 e) : if hasTrailingComment e then [hardline, "}${"] else ["}${"]) ++ prettyISExpr xs + (indentE (prettyPrec False 0 e) : if hasTrailingComment e then [hardline, "}${"] else ["}${"]) ++ prettyISExpr xs ISExpr (_, e, _) (ISStr str xs@(ISExpr _ _)) -> let str' = vsepHard $ addToLast $ addToFirst $ map pretty $ Text.splitOn "\n" str - in ((indentE $ prettyPrec False 0 e) : if hasTrailingComment e then [hardline, str'] else [str']) ++ prettyISExpr xs + in (indentE (prettyPrec False 0 e) : if hasTrailingComment e then [hardline, str'] else [str']) ++ prettyISExpr xs ISExpr (_, e, _) (ISStr str xs) -> let str' = vsepHard $ addToFirst $ map pretty $ Text.splitOn "\n" str - in ((indentE $ prettyPrec False 0 e) : if hasTrailingComment e then [hardline, str'] else [str']) ++ prettyISExpr xs + in (indentE (prettyPrec False 0 e) : if hasTrailingComment e then [hardline, str'] else [str']) ++ prettyISExpr xs prettyISStr :: IStr 'False (a, Expr hash a, a) -> [Doc ann] prettyISStr = \case @@ -1546,7 +1540,7 @@ prettyPrec isBracketed prec expr = <+> (if hasLeadingComment e then line else mempty) <> prettyOpAux (n + 1) e Tuple _ TNil _ -> "()" - Tuple _ xs _ -> group $ (flatAlt "( " "(") <> prettyTuple True (tListToList xs) + Tuple _ xs _ -> group $ flatAlt "( " "(" <> prettyTuple True (tListToList xs) where prettyTuple firstElement = \case [] -> mempty @@ -1563,14 +1557,14 @@ prettyPrec isBracketed prec expr = Empty _ -> "None" Assert _ c _ e -> let assertPretty = "assert" <+> align (prettyPrec False 0 c) - body = (flatAlt " in" "in") <+> align (prettyPrec False 0 e) + body = flatAlt " in" "in" <+> align (prettyPrec False 0 e) in assertPretty <> (if hasTrailingComment c then hardline else line) <> body Case _ e_case _ patExprs _ -> group $ nest 2 $ vsep [ "match" <+> align (prettyPrec False 0 e_case <> if hasTrailingComment e_case then hardline else mempty) <+> "with" <+> "{", - (align $ prettyCase True $ toList patExprs) <> flatAlt " }" "}" + align (prettyCase True $ toList patExprs) <> flatAlt " }" "}" ] where prettyCase :: Bool -> [(a, Pat hash a, a, Expr hash a)] -> Doc ann @@ -1584,13 +1578,13 @@ prettyPrec isBracketed prec expr = <> (if hasTrailingComment pat then hardline else mempty) <+> "->" <> line - <> (prettyPrec False 0 e) + <> prettyPrec False 0 e ) ) <> (if hasTrailingComment e then hardline else mempty) (_, pat, _, e) : es -> (if not firstElement && hasLeadingComment pat then hardline else mempty) - <> group ("|" <+> align (pretty pat <> (if hasTrailingComment pat then hardline else mempty) <+> "->" <> line <> (prettyPrec False 0 e))) + <> group ("|" <+> align (pretty pat <> (if hasTrailingComment pat then hardline else mempty) <+> "->" <> line <> prettyPrec False 0 e)) <> (if hasTrailingComment e then hardline else line) <> prettyCase False es Record _ [] _ -> "{}" @@ -1614,7 +1608,7 @@ prettyPrec isBracketed prec expr = RecordField _ (Ident r) (Ident f) -> pretty r <> "." <> pretty f Array _ [] _ -> "[]" - Array _ xs _ -> group $ (flatAlt "[ " "[") <> prettyArray True xs + Array _ xs _ -> group $ flatAlt "[ " "[" <> prettyArray True xs where prettyArray firstElement = \case [] -> mempty @@ -1630,7 +1624,7 @@ prettyPrec isBracketed prec expr = ArrayComp _ e_body _ args e_cond _ -> enclose lbracket rbracket $ align $ - (align $ prettyPrec False 0 e_body <> if hasTrailingComment e_body then hardline else mempty) <+> align ("|" <+> (argsPretty $ toList args)) + align (prettyPrec False 0 e_body <> if hasTrailingComment e_body then hardline else mempty) <+> align ("|" <+> argsPretty (toList args)) where argsPretty = \case [] -> mempty @@ -1654,16 +1648,16 @@ prettyPrec isBracketed prec expr = Bracketed _ e _ -> enclose lparen rparen $ if hasTrailingComment e then prettyPrec True prec e <> hardline else prettyPrec True prec e RenameModule _ (ModuleName nNew) _ (ModuleName nOld) _ e -> let letPretty = "let" <+> align ("module" <+> pretty nNew <+> "=" <+> pretty nOld) - body = (flatAlt " in" "in") <+> align (prettyPrec False 0 e) + body = flatAlt " in" "in" <+> align (prettyPrec False 0 e) in letPretty <> line <> body OpenModule _ _ (ModuleName n) ns _ e -> "open" <+> pretty n <> ( case ns of [] -> line - _ -> (align $ group $ (flatAlt "( " "(") <> prettyImports True (map fst ns)) <> (if hasTrailingComment $ fst (last ns) then hardline else line) + _ -> align (group $ flatAlt "( " "(" <> prettyImports True (map fst ns)) <> (if hasTrailingComment $ fst (last ns) then hardline else line) ) - <> (flatAlt " in" "in") + <> flatAlt " in" "in" <+> align (prettyPrec False 0 e) where prettyImports firstElement = \case @@ -1689,29 +1683,26 @@ prettyPrec isBracketed prec expr = cat' (x : Pretty.Line : xs) = x <> hardline <> cat' xs cat' (x : xs) = x <> line' <> cat' xs - bracketWhen e b = - if isBracketed - then id - else - if b - then (\x -> enclose lparen rparen $ x <> if hasTrailingComment e then hardline else mempty) - else id + bracketWhen e b + | isBracketed = id + | b = \x -> enclose lparen rparen $ x <> if hasTrailingComment e then hardline else mempty + | otherwise = id - prettyOp ns op = (fromScoped mempty $ (<> ".") . pretty . unModuleName <$> ns) <> pretty op + prettyOp ns op = fromScoped mempty ((<> ".") . pretty . unModuleName <$> ns) <> pretty op prettyOpAux n e = case e of - Var _ _ _ _ -> prettyPrec False n e - OpVar _ _ _ _ -> prettyPrec False n e - Enum _ _ _ _ -> prettyPrec False n e + Var {} -> prettyPrec False n e + OpVar {} -> prettyPrec False n e + Enum {} -> prettyPrec False n e Lit _ _ -> prettyPrec False n e - InterpolatedString _ _ _ -> prettyPrec False n e - Tuple _ _ _ -> prettyPrec False n e + InterpolatedString {} -> prettyPrec False n e + Tuple {} -> prettyPrec False n e Empty _ -> prettyPrec False n e - Array _ _ _ -> prettyPrec False n e - ArrayComp _ _ _ _ _ _ -> prettyPrec False n e - Bracketed _ _ _ -> prettyPrec False n e - Op _ _ _ _ _ _ _ -> prettyPrec False n e - PreOp _ _ _ _ _ _ -> prettyPrec False n e + Array {} -> prettyPrec False n e + ArrayComp {} -> prettyPrec False n e + Bracketed {} -> prettyPrec False n e + Op {} -> prettyPrec False n e + PreOp {} -> prettyPrec False n e _ -> enclose lparen rparen $ if hasTrailingComment e then prettyPrec False n e <> hardline else prettyPrec False n e data TypeMetadata ty = TypeMetadata diff --git a/inferno-types/src/Inferno/Types/Type.hs b/inferno-types/src/Inferno/Types/Type.hs index e1d5534..630f265 100644 --- a/inferno-types/src/Inferno/Types/Type.hs +++ b/inferno-types/src/Inferno/Types/Type.hs @@ -1,7 +1,4 @@ -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingVia #-} -{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Inferno.Types.Type ( BaseType (..), diff --git a/inferno-types/src/Inferno/Types/Value.hs b/inferno-types/src/Inferno/Types/Value.hs index 01f5d63..829eaa8 100644 --- a/inferno-types/src/Inferno/Types/Value.hs +++ b/inferno-types/src/Inferno/Types/Value.hs @@ -59,7 +59,7 @@ instance NFData custom => NFData (Value custom m) where rnf (VWord64 x) = x `seq` () rnf (VEpochTime x) = x `seq` () rnf (VText x) = rnf x - rnf (VEnum hash i) = rnf hash `seq` rnf i `seq` () + rnf (VEnum hash i) = rnf hash `seq` rnf i rnf (VArray xs) = rnf xs rnf (VTuple xs) = rnf xs rnf (VRecord xs) = rnf xs @@ -80,8 +80,8 @@ instance Eq c => Eq (Value c m) where (VEnum h1 e1) == (VEnum h2 e2) = h1 == h2 && e1 == e2 (VOne v1) == (VOne v2) = v1 == v2 VEmpty == VEmpty = True - (VArray a1) == (VArray a2) = length a1 == length a2 && (foldr ((&&) . (uncurry (==))) True $ zip a1 a2) - (VTuple a1) == (VTuple a2) = length a1 == length a2 && (foldr ((&&) . (uncurry (==))) True $ zip a1 a2) + (VArray a1) == (VArray a2) = length a1 == length a2 && foldr ((&&) . uncurry (==)) True (zip a1 a2) + (VTuple a1) == (VTuple a2) = length a1 == length a2 && foldr ((&&) . uncurry (==)) True (zip a1 a2) (VRecord fs1) == (VRecord fs2) = Map.size fs1 == Map.size fs2 && Map.toAscList fs1 == Map.toAscList fs2 (VTypeRep t1) == (VTypeRep t2) = t1 == t2 @@ -92,9 +92,9 @@ instance Pretty c => Pretty (Value c m) where pretty = \case VInt n -> pretty n VDouble n -> pretty n - VWord16 w -> "0x" <> (pretty $ showHex w "") - VWord32 w -> "0x" <> (pretty $ showHex w "") - VWord64 w -> "0x" <> (pretty $ showHex w "") + VWord16 w -> "0x" <> pretty (showHex w "") + VWord32 w -> "0x" <> pretty (showHex w "") + VWord64 w -> "0x" <> pretty (showHex w "") VText t -> pretty $ Text.pack $ show t VEnum _ (Ident s) -> "#" <> pretty s VArray vs -> encloseSep lbracket rbracket comma $ map pretty vs diff --git a/inferno-types/src/Inferno/Types/VersionControl.hs b/inferno-types/src/Inferno/Types/VersionControl.hs index eefe9c4..0b59ca8 100644 --- a/inferno-types/src/Inferno/Types/VersionControl.hs +++ b/inferno-types/src/Inferno/Types/VersionControl.hs @@ -1,6 +1,5 @@ {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -95,7 +94,7 @@ instance Hashable VCObjectHash where instance Serialize VCObjectHash where get = - (getByteString 44) + getByteString 44 >>= ( \b -> do b64 <- either fail pure $ Base64.decode b digest <- maybe (fail "VCObjectHash: Unable to digest from Base64 ByteString") pure $ digestFromByteString b64 @@ -110,7 +109,7 @@ class VCHashUpdate obj where ctxt &< o = genHashUpdate ctxt $ from o hashUpdateVia :: ByteArrayAccess ba => (obj -> ba) -> Context SHA256 -> obj -> Context SHA256 -hashUpdateVia toBAA ctxt obj = ctxt `hashUpdate` (toBAA obj) +hashUpdateVia toBAA ctxt obj = ctxt `hashUpdate` toBAA obj {-# INLINE hashUpdateVia #-} newtype VCHashUpdateViaShow a = VCHashUpdateViaShow {unVCHashUpdateViaShow :: a} @@ -162,16 +161,16 @@ instance VCHashUpdate ExtIdent where ctxt &< (ExtIdent (Right b)) = ctxt &< ("reg$" :: ByteString) &< b instance VCHashUpdate a => VCHashUpdate (NonEmpty.NonEmpty a) where - ctxt &< xs = ctxt &< (NonEmpty.toList xs) + ctxt &< xs = ctxt &< NonEmpty.toList xs instance VCHashUpdate a => VCHashUpdate (Set.Set a) where - ctxt &< xs = ctxt &< (Set.toList xs) + ctxt &< xs = ctxt &< Set.toList xs instance (VCHashUpdate k, VCHashUpdate a) => VCHashUpdate (Map.Map k a) where - ctxt &< m = ctxt &< (Map.toList m) + ctxt &< m = ctxt &< Map.toList m instance VCHashUpdate a => VCHashUpdate (IntMap.IntMap a) where - ctxt &< m = ctxt &< (IntMap.toList m) + ctxt &< m = ctxt &< IntMap.toList m class GenericVCHashUpdate f where genHashUpdate :: Context SHA256 -> f p -> Context SHA256 @@ -186,7 +185,7 @@ instance GenericVCHashUpdate f => GenericVCHashUpdate (D1 c f) where genHashUpdate ctxt (M1 x) = genHashUpdate ctxt x instance (Constructor c, GenericVCHashUpdate f) => GenericVCHashUpdate (C1 c f) where - genHashUpdate ctxt x@(M1 y) = ctxt &< (Char8.pack $ conName x) `genHashUpdate` y + genHashUpdate ctxt x@(M1 y) = ctxt &< Char8.pack (conName x) `genHashUpdate` y instance GenericVCHashUpdate f => GenericVCHashUpdate (S1 c f) where genHashUpdate ctxt (M1 x) = genHashUpdate ctxt x @@ -213,28 +212,23 @@ deriving instance VCHashUpdate ImplExpl instance VCHashUpdate Int64 where (&<) = - hashUpdateVia $ - (\i64 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf i64) $ putStorable i64) + hashUpdateVia (\i64 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf i64) $ putStorable i64) instance VCHashUpdate Int32 where (&<) = - hashUpdateVia $ - (\i32 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf i32) $ putStorable i32) + hashUpdateVia (\i32 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf i32) $ putStorable i32) instance VCHashUpdate Double where (&<) = - hashUpdateVia $ - (\d -> either error (id :: ByteString -> ByteString) $ fill (sizeOf d) $ putStorable d) + hashUpdateVia (\d -> either error (id :: ByteString -> ByteString) $ fill (sizeOf d) $ putStorable d) instance VCHashUpdate Word32 where (&<) = - hashUpdateVia $ - (\w32 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf w32) $ putStorable w32) + hashUpdateVia (\w32 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf w32) $ putStorable w32) instance VCHashUpdate Word64 where (&<) = - hashUpdateVia $ - (\w64 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf w64) $ putStorable w64) + hashUpdateVia (\w64 -> either error (id :: ByteString -> ByteString) $ fill (sizeOf w64) $ putStorable w64) deriving instance VCHashUpdate Lit @@ -250,7 +244,7 @@ instance VCHashUpdate e => VCHashUpdate (IStr f e) where deriving instance VCHashUpdate a => VCHashUpdate (Comment a) instance VCHashUpdate a => VCHashUpdate (TList a) where - ctxt &< ts = ctxt &< (tListToList ts) + ctxt &< ts = ctxt &< tListToList ts deriving instance VCHashUpdate a => VCHashUpdate (Import a) diff --git a/inferno-vc/CHANGELOG.md b/inferno-vc/CHANGELOG.md index d837033..dc98625 100644 --- a/inferno-vc/CHANGELOG.md +++ b/inferno-vc/CHANGELOG.md @@ -1,6 +1,9 @@ # Revision History for inferno-vc *Note*: we use https://pvp.haskell.org/ (MAJOR.MAJOR.MINOR.PATCH) +## 0.3.6.0 -- 2024-03-18 +* HLint everything + ## 0.3.5.0 -- 2024-03-12 * Update inferno-types version diff --git a/inferno-vc/inferno-vc.cabal b/inferno-vc/inferno-vc.cabal index bd5725c..174922a 100644 --- a/inferno-vc/inferno-vc.cabal +++ b/inferno-vc/inferno-vc.cabal @@ -1,6 +1,6 @@ cabal-version: >=1.10 name: inferno-vc -version: 0.3.5.0 +version: 0.3.6.0 synopsis: Version control server for Inferno description: A version control server for Inferno scripts category: DSL,Scripting diff --git a/inferno-vc/src/Inferno/VersionControl/Client/Cached.hs b/inferno-vc/src/Inferno/VersionControl/Client/Cached.hs index be65069..429013b 100644 --- a/inferno-vc/src/Inferno/VersionControl/Client/Cached.hs +++ b/inferno-vc/src/Inferno/VersionControl/Client/Cached.hs @@ -68,9 +68,9 @@ fetchVCObjectClosure :: VCObjectHash -> m (Map.Map VCObjectHash (VCMeta a g VCObject)) fetchVCObjectClosure fetchVCObjects remoteFetchVCObjectClosureHashes objHash = do - VCCachePath storePath <- getTyped <$> ask + VCCachePath storePath <- asks getTyped deps <- - (liftIO $ doesFileExist $ storePath "deps" show objHash) >>= \case + liftIO (doesFileExist $ storePath "deps" show objHash) >>= \case False -> do deps <- liftServantClient $ remoteFetchVCObjectClosureHashes objHash liftIO @@ -81,16 +81,20 @@ fetchVCObjectClosure fetchVCObjects remoteFetchVCObjectClosureHashes objHash = d True -> fetchVCObjectClosureHashes objHash (nonLocalHashes, localHashes) <- partitionEithers - <$> ( forM (objHash : deps) $ \depHash -> do - (liftIO $ doesFileExist $ storePath show depHash) >>= \case - True -> pure $ Right depHash - False -> pure $ Left depHash - ) + <$> forM + (objHash : deps) + ( \depHash -> do + liftIO (doesFileExist $ storePath show depHash) >>= \case + True -> pure $ Right depHash + False -> pure $ Left depHash + ) localObjs <- Map.fromList - <$> ( forM localHashes $ \h -> - (h,) <$> fetchVCObjectUnsafe h - ) + <$> forM + localHashes + ( \h -> + (h,) <$> fetchVCObjectUnsafe h + ) nonLocalObjs <- liftServantClient $ fetchVCObjects nonLocalHashes forM_ (Map.toList nonLocalObjs) $ \(h, o) -> @@ -119,7 +123,7 @@ readVCObjectHashTxt :: FilePath -> m [VCObjectHash] readVCObjectHashTxt fp = do - deps <- filter (not . B.null) . Char8.lines <$> (liftIO $ B.readFile fp) + deps <- filter (not . B.null) . Char8.lines <$> liftIO (B.readFile fp) forM deps $ \dep -> do decoded <- either (const $ throwing _Typed $ InvalidHash $ Char8.unpack dep) pure $ Base64.decode dep maybe (throwing _Typed $ InvalidHash $ Char8.unpack dep) (pure . VCObjectHash) $ digestFromByteString decoded @@ -150,8 +154,8 @@ liftServantClient :: TypedClientM a b -> m b liftServantClient m = do - client <- getTyped <$> ask - (liftIO $ runTypedClientM m client) >>= \case + client <- asks getTyped + liftIO (runTypedClientM m client) >>= \case Left (Left clientErr) -> throwing _Typed clientErr Left (Right serverErr) -> throwing _Typed serverErr Right res -> pure res diff --git a/inferno-vc/src/Inferno/VersionControl/Operations/Filesystem.hs b/inferno-vc/src/Inferno/VersionControl/Operations/Filesystem.hs index 09f7ae8..ff60a35 100644 --- a/inferno-vc/src/Inferno/VersionControl/Operations/Filesystem.hs +++ b/inferno-vc/src/Inferno/VersionControl/Operations/Filesystem.hs @@ -31,7 +31,7 @@ import Control.Concurrent.FairRWLock (RWLock) import qualified Control.Concurrent.FairRWLock as RWL import Control.Exception (throwIO) import Control.Lens ((^.)) -import Control.Monad (foldM, forM, forM_) +import Control.Monad (foldM, forM, forM_, when) import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow, bracket_) import Control.Monad.Error.Lens (catching, throwing) import Control.Monad.Except (ExceptT, MonadError) @@ -219,16 +219,15 @@ instance withWrite lock $ do metas <- fetchVCObjectHistory obj_hash - forM_ (takeUpUntilClone metas) $ \VCMeta {obj = hash} -> do - forM_ - [ show hash, - "heads" show hash, - "to_head" show hash, - "deps" show hash - ] - $ \source_fp -> safeRenameFile (storePath source_fp) (storePath "removed" source_fp) + forM_ (takeUpUntilClone metas) $ \VCMeta {obj = hash} -> forM_ + [ show hash, + "heads" show hash, + "to_head" show hash, + "deps" show hash + ] + $ \source_fp -> safeRenameFile (storePath source_fp) (storePath "removed" source_fp) where - safeRenameFile source target = do + safeRenameFile source target = liftIO (doesFileExist source) >>= \case False -> pure () True -> liftIO $ renameFile source target @@ -289,7 +288,7 @@ instance getHistory history where -- Recurse through history, newest to oldest, and stop when we find a clone - getHistory (hsh : history) = do + getHistory (hsh : history) = getObj hsh >>= \case Nothing -> getHistory history Just eObj -> do @@ -352,27 +351,27 @@ instance ( \h -> do -- fetch object, check name and timestamp (VCMeta {name, timestamp} :: VCMeta a g VCObject) <- fetchVCObject h - if name == "" && timestamp < CTime (truncate t) - then -- delete the stale ones (> t old) - deleteAutosavedVCObject h - else pure () + when (name == "" && timestamp < CTime (truncate t)) $ -- delete the stale ones (> t old) + deleteAutosavedVCObject h ) getAllHeads :: VCStoreEnvM err m => m [VCObjectHash] getAllHeads = do - VCStorePath storePath <- getTyped <$> ask + VCStorePath storePath <- asks getTyped -- We don't need a lock here because this only lists the heads/ directory, it doesn't -- read any file contents (and I assume the `ls` is atomic) headsRaw <- liftIO $ getDirectoryContents $ storePath "heads" pure $ foldr - ( \hd xs -> - case (either (const Nothing) Just $ Base64.decode $ Char8.pack hd) >>= digestFromByteString of - Just hsh -> (VCObjectHash hsh) : xs - Nothing -> xs + ( ( \hd xs -> + case either (const Nothing) Just (Base64.decode $ Char8.pack hd) >>= digestFromByteString of + Just hsh -> VCObjectHash hsh : xs + Nothing -> xs + ) + . takeFileName ) [] - (map takeFileName headsRaw) + headsRaw fetchCurrentHead :: ( MonadError err m, @@ -417,7 +416,7 @@ withRead lock = bracket_ (liftIO $ RWL.acquireRead lock) (liftIO $ RWL.releaseRe trace :: VCStoreLogM env m => VCServerTrace -> m () trace t = do - tracer <- getTyped <$> ask + tracer <- asks getTyped traceWith @IOTracer tracer t throwError :: (VCStoreLogM env m, VCStoreErrM err m) => VCStoreError -> m a @@ -462,7 +461,7 @@ readVCObjectHashTxt :: (VCStoreLogM env m, VCStoreErrM err m) => FilePath -> m [ readVCObjectHashTxt fp = do checkPathExists fp trace $ ReadTxt fp - deps <- filter (not . B.null) . Char8.lines <$> (liftIO $ B.readFile fp) + deps <- filter (not . B.null) . Char8.lines <$> liftIO (B.readFile fp) forM deps $ \dep -> do decoded <- either (const $ throwError $ InvalidHash $ Char8.unpack dep) pure $ Base64.decode dep maybe (throwError $ InvalidHash $ Char8.unpack dep) (pure . VCObjectHash) $ digestFromByteString decoded diff --git a/inferno-vc/src/Inferno/VersionControl/Server/UnzipRequest.hs b/inferno-vc/src/Inferno/VersionControl/Server/UnzipRequest.hs index 0d3c68d..7a5c851 100644 --- a/inferno-vc/src/Inferno/VersionControl/Server/UnzipRequest.hs +++ b/inferno-vc/src/Inferno/VersionControl/Server/UnzipRequest.hs @@ -19,6 +19,6 @@ ungzipRequest app req = app req' req' | Just "gzip" <- lookup "Content-encoding" (requestHeaders req) = go req | otherwise = req - go r = r {requestBody = decompressNonEmpty <$> (strictRequestBody r)} + go r = r {requestBody = decompressNonEmpty <$> strictRequestBody r} decompressNonEmpty "" = "" -- Necessary 'cause the IO gets pulled until requestBody gives "" decompressNonEmpty x = BL.toStrict . decompress $ x diff --git a/inferno-vc/src/Inferno/VersionControl/Testing.hs b/inferno-vc/src/Inferno/VersionControl/Testing.hs index 7ca84c8..eb018e1 100644 --- a/inferno-vc/src/Inferno/VersionControl/Testing.hs +++ b/inferno-vc/src/Inferno/VersionControl/Testing.hs @@ -36,7 +36,7 @@ import Test.QuickCheck (Arbitrary, arbitrary, generate) runOperation :: ClientEnv -> ClientMWithVCStoreError a -> IO a runOperation vcClientEnv op = - (flip runTypedClientM vcClientEnv op) >>= \case + runTypedClientM op vcClientEnv >>= \case Left err -> do expectationFailure $ show err pure $ error "i shouldn't be evaluated" @@ -45,7 +45,7 @@ runOperation vcClientEnv op = runOperationFail :: (Show a) => ClientEnv -> ClientMWithVCStoreError a -> IO VCServerError runOperationFail vcClientEnv op = - (flip runTypedClientM vcClientEnv op) >>= \case + runTypedClientM op vcClientEnv >>= \case Left (Right err) -> pure err Left (Left err) -> do @@ -127,7 +127,7 @@ vcServerSpec url = do case obj o' of VCFunction e t -> do timestamp o' `shouldBe` timestamp o - (e, t) `shouldBe` (obj o) + (e, t) `shouldBe` obj o _ -> expectationFailure "Expected to get a VCFunction" -- Test fetchVCObjects: @@ -214,7 +214,7 @@ vcServerSpec url = do o4 <- createObj $ MarkedBreakingWithPred h3 h4 <- runOperation vcClientEnv (pushFunction o4) metas <- runOperation vcClientEnv (fetchVCObjectHistory h4) - (map obj metas) `shouldBe` [h4, h3, h2, h1] + map obj metas `shouldBe` [h4, h3, h2, h1] it "history of clone" $ do o1 <- createObj Init @@ -226,7 +226,7 @@ vcServerSpec url = do o4 <- createObj $ MarkedBreakingWithPred h3 h4 <- runOperation vcClientEnv (pushFunction o4) metas <- runOperation vcClientEnv (fetchVCObjectHistory h4) - (map obj metas) `shouldBe` [h4, h3, h2] + map obj metas `shouldBe` [h4, h3, h2] it "history of clone of clone" $ do o1 <- createObj Init @@ -238,7 +238,7 @@ vcServerSpec url = do o4 <- createObj $ MarkedBreakingWithPred h3 h4 <- runOperation vcClientEnv (pushFunction o4) metas <- runOperation vcClientEnv (fetchVCObjectHistory h4) - (map obj metas) `shouldBe` [h4, h3, h2] + map obj metas `shouldBe` [h4, h3, h2] it "history of clone of deleted" $ do o1 <- createObj Init @@ -258,7 +258,7 @@ vcServerSpec url = do o4 <- createObj $ MarkedBreakingWithPred h3 h4 <- runOperation vcClientEnv (pushFunction o4) metas <- runOperation vcClientEnv (fetchVCObjectHistory h4) - (map obj metas) `shouldBe` [h4, h3, h2] + map obj metas `shouldBe` [h4, h3, h2] let o3' = metas !! 1 Inferno.VersionControl.Types.pred o3' `shouldBe` CloneOfRemoved h2 @@ -273,8 +273,8 @@ vcServerSpec url = do h3 <- runOperation vcClientEnv (pushFunction o3) runOperation vcClientEnv (deleteVCObject h2) metas <- runOperation vcClientEnv (fetchVCObjectHistory h3) - (map obj metas) `shouldBe` [h3, h2] - Inferno.VersionControl.Types.pred (metas !! 0) `shouldBe` CloneOfRemoved h2 + map obj metas `shouldBe` [h3, h2] + Inferno.VersionControl.Types.pred (head metas) `shouldBe` CloneOfRemoved h2 it "cannot branch" $ do o1 <- createObj Init diff --git a/inferno-vc/src/Inferno/VersionControl/Types.hs b/inferno-vc/src/Inferno/VersionControl/Types.hs index edcfa80..d006228 100644 --- a/inferno-vc/src/Inferno/VersionControl/Types.hs +++ b/inferno-vc/src/Inferno/VersionControl/Types.hs @@ -1,12 +1,7 @@ -{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TypeOperators #-} module Inferno.VersionControl.Types ( VCObjectHash (..), @@ -27,7 +22,7 @@ where import Data.Aeson (FromJSON, ToJSON) import Data.Map (Map) import qualified Data.Map as Map -import Data.Maybe (catMaybes) +import Data.Maybe (mapMaybe) import Data.Set (Set) import qualified Data.Set as Set import Data.Text (Text) @@ -35,7 +30,7 @@ import Foreign.C.Types (CTime) import GHC.Generics (Generic) import Inferno.Types.Module (Module (..)) import Inferno.Types.Syntax (Dependencies (..), Expr (..), Ident (..)) -import Inferno.Types.Type (Namespace, TCScheme (..)) -- TypeMetadata(..), +import Inferno.Types.Type (Namespace, TCScheme (..)) import Inferno.Types.VersionControl (Pinned (..), VCHashUpdate (..), VCObjectHash (..), pinnedUnderVCToMaybe, vcHash, vcObjectHashToByteString) data VCObject @@ -55,8 +50,8 @@ showVCObjectType = \case instance Dependencies VCObject VCObjectHash where getDependencies = \case VCModule Module {moduleObjects = os} -> Set.fromList $ Map.elems os - VCFunction expr _ -> Set.fromList $ catMaybes $ map pinnedUnderVCToMaybe $ Set.toList $ getDependencies expr - VCTestFunction expr -> Set.fromList $ catMaybes $ map pinnedUnderVCToMaybe $ Set.toList $ getDependencies expr + VCFunction expr _ -> Set.fromList $ mapMaybe pinnedUnderVCToMaybe (Set.toList $ getDependencies expr) + VCTestFunction expr -> Set.fromList $ mapMaybe pinnedUnderVCToMaybe (Set.toList $ getDependencies expr) VCEnum _ _ -> mempty data VCObjectVisibility = VCObjectPublic | VCObjectPrivate deriving (Show, Eq, Generic, ToJSON, FromJSON, VCHashUpdate)