From 18d0b2d1038a289a10b65bc13b53c682222c8d9e Mon Sep 17 00:00:00 2001 From: Jan Mas Rovira Date: Wed, 19 Jan 2022 13:26:21 +0100 Subject: [PATCH 1/6] [pretty] fix postfix operator printing for patterns --- src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs index 26f7a79b4..dce5375ed 100644 --- a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs +++ b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs @@ -432,7 +432,7 @@ ppPattern = goAtom ppPatternPostfixApp PatternPostfixApp {..} = do patPostfixConstructor' <- ppSName patPostfixConstructor patPostfixParameter' <- goAtom patPostfixParameter - return $ patPostfixConstructor' <+> patPostfixParameter' + return $ patPostfixParameter' <+> patPostfixConstructor' ppExpressionAtom :: forall r. Members '[Reader Options] r => Expression -> Sem r (Doc Ann) ppExpressionAtom e = do From 8b864ec31c9cf34ecc851dbf1a062458a317e4aa Mon Sep 17 00:00:00 2001 From: Jan Mas Rovira Date: Wed, 19 Jan 2022 14:05:39 +0100 Subject: [PATCH 2/6] [pretty] improve pretty printing --- app/Main.hs | 1 - src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs | 4 ++-- src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs | 8 +++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 269a0da89..27cb5c9e3 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -8,7 +8,6 @@ import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Ansi as M import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base as M import Options.Applicative import Options.Applicative.Help.Pretty -import Data.Aeson (defaultOptions) import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base (Options(_optShowNameId)) data Command = diff --git a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs index 0fd7a4157..f276de752 100644 --- a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs +++ b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs @@ -25,7 +25,7 @@ stylize a = case a of KNameInductive -> colorDull Green KNameAxiom -> colorDull Red KNameLocalModule -> mempty - KNameFunction -> mempty + KNameFunction -> colorDull Yellow KNameLocal -> mempty - AnnDelimiter -> mempty + AnnDelimiter -> colorDull White AnnKeyword -> colorDull Blue diff --git a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs index dce5375ed..3683e3062 100644 --- a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs +++ b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs @@ -348,10 +348,12 @@ ppLambda Lambda {..} = do ppFunctionClause :: forall r. Members '[Reader Options] r => FunctionClause 'Scoped -> Sem r (Doc Ann) ppFunctionClause FunctionClause {..} = do clauseOwnerFunction' <- ppSSymbol clauseOwnerFunction - clausePatterns' <- hsep <$> mapM ppPattern clausePatterns + clausePatterns' <- case nonEmpty clausePatterns of + Nothing -> return Nothing + Just ne -> Just . hsep . toList <$> mapM ppPattern ne clauseBody' <- ppExpression clauseBody clauseWhere' <- sequence $ ppWhereBlock <$> clauseWhere - return $ clauseOwnerFunction' <+> clausePatterns' <+> kwAssignment <+> clauseBody' + return $ clauseOwnerFunction' <+?> clausePatterns' <+> kwAssignment <+> clauseBody' <+?> (((line <> kwWhere) <+>) <$> clauseWhere') where ppWhereBlock :: WhereBlock 'Scoped -> Sem r (Doc Ann) @@ -432,7 +434,7 @@ ppPattern = goAtom ppPatternPostfixApp PatternPostfixApp {..} = do patPostfixConstructor' <- ppSName patPostfixConstructor patPostfixParameter' <- goAtom patPostfixParameter - return $ patPostfixParameter' <+> patPostfixConstructor' + return $ patPostfixParameter' <+> patPostfixConstructor' ppExpressionAtom :: forall r. Members '[Reader Options] r => Expression -> Sem r (Doc Ann) ppExpressionAtom e = do From b808a037603f516baa43bb7e0059e96249231766 Mon Sep 17 00:00:00 2001 From: Jan Mas Rovira Date: Thu, 20 Jan 2022 12:50:01 +0100 Subject: [PATCH 3/6] [app] pretty print parsed Haskell AST --- app/Main.hs | 78 ++++++++++++++----- package.yaml | 1 + .../Syntax/Concrete/Scoped/Scoper.hs | 32 +++----- 3 files changed, 70 insertions(+), 41 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 27cb5c9e3..d8be6f3cc 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -3,12 +3,17 @@ module Main (main) where import MiniJuvix.Utils.Prelude import qualified MiniJuvix.Syntax.Concrete.Parser as M +import qualified MiniJuvix.Syntax.Concrete.Language as M import qualified MiniJuvix.Syntax.Concrete.Scoped.Scoper as M import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Ansi as M import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base as M import Options.Applicative +import System.IO.Error import Options.Applicative.Help.Pretty import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base (Options(_optShowNameId)) +import Data.Text (unpack) +import Text.Show.Pretty +import Control.Monad.Extra data Command = Scope ScopeOptions @@ -20,7 +25,23 @@ data ScopeOptions = ScopeOptions { , _scopeShowIds :: Bool } -data ParseOptions = ParseOptions +data ParseOptions = ParseOptions { + _parseInputFile :: FilePath, + _parseNoPrettyShow :: Bool + } + +parseParse :: Parser ParseOptions +parseParse = do + _parseInputFile <- argument str + (metavar "MINIJUVIX_FILE" + <> help "Path to a .mjuvix file" + ) + _parseNoPrettyShow <- switch + ( long "no-pretty-show" + <> help "Disable formatting of the Haskell AST" + ) + pure ParseOptions {..} + parseScope :: Parser ScopeOptions parseScope = do @@ -42,46 +63,61 @@ parseScope = do pure ScopeOptions {..} -parseParse :: Parser ParseOptions -parseParse = pure ParseOptions - descr :: ParserInfo Command descr = info (parseCommand <**> helper) (fullDesc <> progDesc "The MiniJuvix compiler." - <> headerDoc (Just $ dullblue $ bold $ underline "MiniJuvix help") + <> headerDoc (Just headDoc) <> footerDoc (Just foot) ) where + headDoc :: Doc + headDoc = dullblue $ bold $ underline "MiniJuvix help" foot :: Doc foot = bold "maintainers: " <> "jan@heliax.dev; jonathan@heliax.dev" parseCommand :: Parser Command -parseCommand = subparser ( - command "parse" (info (Parse <$> parseParse) (progDesc "Parse some .mjuvix files")) - <> command "scope" (info (Scope <$> parseScope) (progDesc "Parse and scope some .mjuvix files")) - ) +parseCommand = hsubparser $ mconcat [ + commandParse, + commandScope + ] + where + commandParse :: Mod CommandFields Command + commandParse = command "parse" minfo + where + minfo :: ParserInfo Command + minfo = info (Parse <$> parseParse) + (progDesc "Parse a .mjuvix file") + + commandScope :: Mod CommandFields Command + commandScope = command "scope" minfo + where + minfo :: ParserInfo Command + minfo = info (Scope <$> parseScope) + (progDesc "Parse and scope a .mjuvix file") + mkPrettyOptions :: ScopeOptions -> M.Options mkPrettyOptions ScopeOptions {..} = M.defaultOptions { _optShowNameId = _scopeShowIds } +parseModuleIO :: FilePath -> IO (M.Module 'M.Parsed 'M.ModuleTop) +parseModuleIO = fromRightIO id . M.runModuleParserIO + +fromRightIO :: (e -> Text) -> IO (Either e r) -> IO r +fromRightIO pp = eitherM (ioError . userError . unpack . pp) return + go :: Command -> IO () go c = case c of Scope opts@ScopeOptions {..} -> do - res <- M.runModuleParserIO _scopeInputFile - case res of - Left err -> print err - Right m -> do - print m - putStrLn "\n\n" - s <- M.scopeCheck _scopeInputFile [m] - case s of - Left err -> print err - Right [r] -> M.printTopModule (mkPrettyOptions opts) r - Right _ -> error "impossible" - Parse _ -> putStrLn "not implemented" + m <- parseModuleIO _scopeInputFile + s <- fromRightIO show $ M.scopeCheck1 _scopeInputFile m + M.printTopModule (mkPrettyOptions opts) s + Parse ParseOptions {..} -> do + m <- parseModuleIO _parseInputFile + if _parseNoPrettyShow then print m else pPrint m + main :: IO () main = execParser descr >>= go diff --git a/package.yaml b/package.yaml index f5cc18861..64f5388cc 100644 --- a/package.yaml +++ b/package.yaml @@ -78,6 +78,7 @@ executables: dependencies: - MiniJuvix - optparse-applicative == 0.16.* + - pretty-show == 1.10.* tests: MiniJuvix-test: diff --git a/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs b/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs index 0c9e00d8d..30f954929 100644 --- a/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs +++ b/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs @@ -68,7 +68,6 @@ data SymbolEntry = SymbolEntry data Scope = Scope { _scopePath :: S.AbsModulePath, _scopeFixities :: HashMap Symbol Fixity, - _scopeUsedFixities :: HashSet Symbol, _scopeSymbols :: HashMap Symbol SymbolInfo, _scopeModules :: HashMap QualifiedName ModuleScopeInfo, _scopeBindGroup :: HashMap Symbol LocalVariable @@ -92,8 +91,7 @@ data ScopeError = ErrParser Text | Err | ErrInfixParser String - | ErrPattern String - | ErrPatternUnfold + | ErrInfixPattern String | ErrAlreadyDefined Symbol | ErrLacksTypeSig Symbol | ErrImportCycle TopModulePath @@ -122,7 +120,10 @@ data ScopeState = ScopeState makeLenses ''ScopeState -scopeCheck :: FilePath -> [Module 'Parsed 'ModuleTop] -> IO (Either ScopeError [Module 'Scoped 'ModuleTop]) +scopeCheck1 :: FilePath -> Module 'Parsed 'ModuleTop -> IO (Either ScopeError (Module 'Scoped 'ModuleTop)) +scopeCheck1 root m = fmap head <$> scopeCheck root (pure m) + +scopeCheck :: FilePath -> NonEmpty (Module 'Parsed 'ModuleTop) -> IO (Either ScopeError (NonEmpty (Module 'Scoped 'ModuleTop))) scopeCheck root modules = runM $ runError $ @@ -170,14 +171,7 @@ freshSymbol _nameKind _nameConcrete = do getFixity :: Sem r S.NameFixity getFixity | S.canHaveFixity _nameKind = do - mfix <- HashMap.lookup _nameConcrete <$> gets _scopeFixities - case mfix of - Nothing -> return S.NoFixity - Just fixity -> do - -- deleting the fixity so we know it has been used - modify (over scopeFixities (HashMap.delete _nameConcrete)) - modify (over scopeUsedFixities (HashSet.insert _nameConcrete)) - return (S.SomeFixity fixity) + maybe S.NoFixity S.SomeFixity . HashMap.lookup _nameConcrete <$> gets _scopeFixities | otherwise = return S.NoFixity reserveSymbolOf :: @@ -354,12 +348,7 @@ checkOperatorSyntaxDef OperatorSyntaxDef {..} = do where checkNotDefined :: Sem r () checkNotDefined = - whenM - ( orM - [ HashSet.member opSymbol <$> gets _scopeUsedFixities, - HashMap.member opSymbol <$> gets _scopeFixities - ] - ) + whenM (HashMap.member opSymbol <$> gets _scopeFixities) (throw (ErrDuplicateFixity opSymbol)) checkTypeSignature :: @@ -453,7 +442,6 @@ checkTopModule m@(Module path stmts) = do Scope { _scopePath = getTopModulePath m, _scopeFixities = mempty, - _scopeUsedFixities = mempty, _scopeSymbols = mempty, _scopeModules = mempty, _scopeBindGroup = mempty @@ -485,6 +473,10 @@ checkLocalModule Module {..} = do moduleBody = moduleBody' } +-- | checks if there is an infix declaration without a binding. +checkOrphanFixities :: Members '[Error ScopeError, State Scope] r => Sem r () +checkOrphanFixities = undefined + checkOpenModule :: forall r. Members '[Error ScopeError, State Scope] r => @@ -1270,7 +1262,7 @@ parsePatternSection sec = do parser = runM (mkPatternParser tbl) <* P.eof res = P.parse parser filePath [sec] case res of - Left err -> throw (ErrPattern (show err)) + Left err -> throw (ErrInfixPattern (show err)) Right r -> return r where filePath = "tmp" From 0d14e62a4ff0fd3496182872e4d4741cb23a2005 Mon Sep 17 00:00:00 2001 From: Jan Mas Rovira Date: Fri, 21 Jan 2022 09:20:27 +0100 Subject: [PATCH 4/6] [test] remove qualified-by-type constructors --- test/Parsing/Test.hs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/test/Parsing/Test.hs b/test/Parsing/Test.hs index ae580f948..27cd5c832 100644 --- a/test/Parsing/Test.hs +++ b/test/Parsing/Test.hs @@ -54,11 +54,6 @@ inductive Empty {}; -- An inductive type named Unit with only one constructor. inductive Unit { tt : Unit; }; -inductive Nat' : Type -{ zero : Nat' ; - suc : Nat' -> Nat' ; -}; - -- The use of the type `Type` below is optional. -- The following declaration is equivalent to Nat'. @@ -86,8 +81,8 @@ inductive Fin (n : Nat) { -- The type of sized vectors. inductive Vec (n : Nat) (A : Type) { - zero : Vec Nat.zero A; - succ : A -> Vec n A -> Vec (Nat.succ n) A; + zero : Vec zero A; + succ : A -> Vec n A -> Vec (succ n) A; }; -- * Indexed inductive type declarations. @@ -151,8 +146,8 @@ f' := \ {zero ↦ a ; -- We can use lambda abstractions to pattern match -- signature is missing. g : Nat -> A; -g Nat.zero := a; -g (Nat.suc t) := a'; +g zero := a; +g (suc t) := a'; -- For pattern-matching, the symbol `_` is the wildcard pattern as in -- Haskell or Agda. The following function definition is equivalent to @@ -176,8 +171,8 @@ neg := A -> Empty; -- An equivalent type for sized vectors. Vec' : Nat -> Type -> Type; -Vec' Nat.zero A := Unit; -Vec' (Nat.suc n) A := A -> Vec' n A; +Vec' zero A := Unit; +Vec' (suc n) A := A -> Vec' n A; -------------------------------------------------------------------------------- -- Fixity notation similarly as in Agda or Haskell. @@ -185,8 +180,8 @@ Vec' (Nat.suc n) A := A -> Vec' n A; infixl 10 + ; + : Nat → Nat → Nat ; -+ Nat.zero m := m; -+ (Nat.suc n) m := Nat.suc (n + m) ; ++ zero m := m; ++ (suc n) m := suc (n + m) ; -------------------------------------------------------------------------------- -- Quantities for variables. From 7cbbdf5a1334c4401c19603fa9de765b60ff8e7c Mon Sep 17 00:00:00 2001 From: Jan Mas Rovira Date: Fri, 21 Jan 2022 09:50:24 +0100 Subject: [PATCH 5/6] [clean] purge old code --- src/MiniJuvix/Desugaring/Error.hs | 10 - src/MiniJuvix/Error.hs | 67 ------ src/MiniJuvix/Main.hs | 6 - src/MiniJuvix/Monad.hs | 48 ----- src/MiniJuvix/Pipeline.hs | 54 ----- src/MiniJuvix/Pretty.hs | 93 -------- src/MiniJuvix/Typing.hs | 3 - src/MiniJuvix/Typing/Coverage.hs | 3 - src/MiniJuvix/Typing/Erasure.hs | 3 - src/MiniJuvix/Typing/Error.hs | 40 ---- src/MiniJuvix/Typing/Scopechecking.hs | 6 - src/MiniJuvix/Typing/Termination.hs | 3 - src/MiniJuvix/Typing/Typechecking.hs | 61 ------ src/MiniJuvix/Typing/Utils.hs | 62 ------ src/MiniJuvix/Utils/File.hs | 1 - src/MiniJuvix/Utils/Monad.hs | 1 - src/MiniJuvix/Utils/Parser.hs | 295 -------------------------- src/MiniJuvix/Utils/Pretty.hs | 116 ---------- 18 files changed, 872 deletions(-) delete mode 100644 src/MiniJuvix/Desugaring/Error.hs delete mode 100644 src/MiniJuvix/Error.hs delete mode 100644 src/MiniJuvix/Main.hs delete mode 100644 src/MiniJuvix/Monad.hs delete mode 100644 src/MiniJuvix/Pipeline.hs delete mode 100644 src/MiniJuvix/Pretty.hs delete mode 100644 src/MiniJuvix/Typing.hs delete mode 100644 src/MiniJuvix/Typing/Coverage.hs delete mode 100644 src/MiniJuvix/Typing/Erasure.hs delete mode 100644 src/MiniJuvix/Typing/Error.hs delete mode 100644 src/MiniJuvix/Typing/Scopechecking.hs delete mode 100644 src/MiniJuvix/Typing/Termination.hs delete mode 100644 src/MiniJuvix/Typing/Typechecking.hs delete mode 100644 src/MiniJuvix/Typing/Utils.hs delete mode 100644 src/MiniJuvix/Utils/File.hs delete mode 100644 src/MiniJuvix/Utils/Monad.hs delete mode 100644 src/MiniJuvix/Utils/Parser.hs delete mode 100644 src/MiniJuvix/Utils/Pretty.hs diff --git a/src/MiniJuvix/Desugaring/Error.hs b/src/MiniJuvix/Desugaring/Error.hs deleted file mode 100644 index a74868415..000000000 --- a/src/MiniJuvix/Desugaring/Error.hs +++ /dev/null @@ -1,10 +0,0 @@ -module MiniJuvix.Desugaring.Error where - --------------------------------------------------------------------------------- - -import MiniJuvix.Utils.Prelude - --------------------------------------------------------------------------------- - -data DesugaringError = DesugaringError - deriving stock (Show) diff --git a/src/MiniJuvix/Error.hs b/src/MiniJuvix/Error.hs deleted file mode 100644 index c695a6fd6..000000000 --- a/src/MiniJuvix/Error.hs +++ /dev/null @@ -1,67 +0,0 @@ -module MiniJuvix.Error - ( ErrorType (..), - ErrorLocation (..), - ErrorReport (..), - printErrors, - ) -where - --------------------------------------------------------------------------------- - -import qualified Data.List as List -import qualified Data.Set as Set -import MiniJuvix.Desugaring.Error (DesugaringError) -import MiniJuvix.Pretty -import MiniJuvix.Typing.Error -import MiniJuvix.Utils.Prelude -import qualified Text.Show - --------------------------------------------------------------------------------- - -data ErrorType - = DError DesugaringError - | CError CheckingError - | UnknownError - -instance Show ErrorType where - show e = case e of - DError de -> show de - CError te -> show te - UnknownError -> show ("UnknownError" :: String) - --------------------------------------------------------------------------------- - -type Row = Int - -type Col = Int - -type Loc = (String, Row, Col) - -newtype ErrorLocation = ErrorLocation (Maybe (Loc, Loc)) - deriving stock (Eq, Ord, Show) - -{- TODO: I don't know yet how to deal with scope. But the errors -should be printed with some information about the enviroment. --} -data Scope - --------------------------------------------------------------------------------- - -type ErrorDescription = Text - -type ErrorScope = Maybe Scope - -data ErrorReport = ErrorReport - { _errorType :: ErrorType, - _errorLoc :: ErrorLocation, - _errorText :: ErrorDescription, - _errorParentScopes :: [ErrorScope] - } - -instance Show ErrorReport where - show _ = undefined - --------------------------------------------------------------------------------- - -printErrors :: Set ErrorReport -> IO () -printErrors = printList . Set.toList diff --git a/src/MiniJuvix/Main.hs b/src/MiniJuvix/Main.hs deleted file mode 100644 index c97fb46a6..000000000 --- a/src/MiniJuvix/Main.hs +++ /dev/null @@ -1,6 +0,0 @@ -module MiniJuvix.Main where - -import MiniJuvix.Utils.Prelude - -main :: IO () -main = putStrLn "hello" diff --git a/src/MiniJuvix/Monad.hs b/src/MiniJuvix/Monad.hs deleted file mode 100644 index 75db66377..000000000 --- a/src/MiniJuvix/Monad.hs +++ /dev/null @@ -1,48 +0,0 @@ -module MiniJuvix.Monad () where - --------------------------------------------------------------------------------- - --- import MiniJuvix.Utils.Prelude - --------------------------------------------------------------------------------- - --- newtype MiniJuvixT e r s m a --- = MiniJuvixT {unMgT :: ExceptT e (ReaderT r (StateT s m)) a} --- deriving anyclass (Functor, Applicative, Monad) - --- instance MonadIO m => MonadIO (MiniJuvixT e r s m) where --- liftIO = MiniJuvixT . liftIO --- -- type MiniJuvix = MiniJuvixT () [Name] (S.Set Err) IO - --- type MiniJuvix = MiniJuvixT () [Name] (Set Error) IO - --- runMiniJuvixT :: MiniJuvixT e r s m a -> r -> s -> m (Either e a, s) --- runMiniJuvixT mgm r s = --- (`St.runStateT` s) . (`R.runReaderT` r) . E.runExceptT $ unMgT mgm - --- runMiniJuvix :: MiniJuvix a -> IO (Either () a, S.Set Err) --- runMiniJuvix m = runMiniJuvixT m [] S.empty - --- -- | Retrieves the state within a MiniJuvixT. --- get :: Monad m => MiniJuvixT e r s m s --- get = MiniJuvixT (lift (lift St.get)) - --- -- | Modifies the state within a MiniJuvixT using the provided function. --- modify :: Monad m => (s -> s) -> MiniJuvixT e r s m () --- modify f = MiniJuvixT (lift (lift (St.modify f))) - --- -- | Throws an exception within a MiniJuvixT. --- throwE :: Monad m => e -> MiniJuvixT e s r m a --- throwE = MiniJuvixT . E.throwE - --- -- | Catches an exception within a MiniJuvixT. --- catchE :: --- Monad m => --- MiniJuvixT e r s m a -> --- (e -> MiniJuvixT e r s m a) -> --- MiniJuvixT e r s m a --- catchE me f = MiniJuvixT (unMgT me `E.catchE` (unMgT . f)) - --- -- | Retrieves the environment within a MiniJuvixT. --- ask :: Monad m => MiniJuvixT e r s m r --- ask = MiniJuvixT (lift R.ask) diff --git a/src/MiniJuvix/Pipeline.hs b/src/MiniJuvix/Pipeline.hs deleted file mode 100644 index 63d750b79..000000000 --- a/src/MiniJuvix/Pipeline.hs +++ /dev/null @@ -1,54 +0,0 @@ -module MiniJuvix.Pipeline - ( -- * Compiler configuration-related data structures - Config (..), - WriteToFsBehavior (..), - Pass (..), - Backend (..), - Mode (..), - ) -where - --------------------------------------------------------------------------------- - -import MiniJuvix.Error -import MiniJuvix.Utils.Prelude (Eq, FilePath, Maybe, Ord, Show, Text) - --------------------------------------------------------------------------------- - -data Mode - = ReplMode - | CheckMode Config FilePath - | CompileMode Config FilePath - | TestMode Config FilePath - -data Config = Config - { _configPass :: Pass, - _configBackend :: Backend, - _configOutputDirectory :: Maybe FilePath, - _configWriteToFsBehavior :: WriteToFsBehavior - } - -data Pass - = Parsing - | Desugaring - | Checking - | Compiling - deriving stock (Show) - -data Backend = LLVM - deriving stock (Eq, Ord, Show) - -data WriteToFsBehavior = OverwriteTargetFiles | WriteIfDoesNotExist - --- run' :: MiniJuvix a -> IO () --- run' m = runMiniJuvix m >>= \(_, errs) -> logErrors errs - --- runTestWith :: FilePath -> Config -> IO () --- runTestWith filePath config = case _configPass config of --- Parsing -> undefined --- Desugaring -> undefined --- Checking -> run' $ filePath >>= parsingPass >>= checkingPass --- Compiling -> undefined - --- runMiniJuvix :: MiniJuvix a -> IO () --- runMiniJuvix = undefined diff --git a/src/MiniJuvix/Pretty.hs b/src/MiniJuvix/Pretty.hs deleted file mode 100644 index cddcf9e18..000000000 --- a/src/MiniJuvix/Pretty.hs +++ /dev/null @@ -1,93 +0,0 @@ -{-# OPTIONS_GHC -Wno-orphans -Wno-unused-matches #-} - -module MiniJuvix.Pretty - ( module MiniJuvix.Utils.Pretty, - ) -where - --------------------------------------------------------------------------------- - -import MiniJuvix.Syntax.Core -import MiniJuvix.Syntax.Eval -import MiniJuvix.Typing.Utils -import MiniJuvix.Utils.Prelude -import MiniJuvix.Utils.Pretty - ( Doc, - Pretty (..), - ascii, - color, - hardlines, - printList, - render, - unicode, - ) - --- import qualified MiniJuvix.Utils.Pretty as PP --- import qualified Prettyprinter.Render.Terminal as Term - --------------------------------------------------------------------------------- - -instance Pretty Text where - pretty = undefined -- const PP.pretty - -instance Pretty Int where - pretty = undefined -- const PP.pretty - -instance Pretty Quantity where - pretty _ Zero = undefined - pretty _ One = undefined - pretty b Many = undefined - -instance Pretty Relevance where - pretty _ Relevant = undefined -- PP.pretty "!" - pretty _ Irrelevant = undefined -- PP.pretty "-" - -instance Pretty Name where - pretty _ (Global n) = undefined -- PP.pretty n - pretty _ (Local n _) = undefined -- PP.pretty n - -instance Pretty Variable where - pretty _ (Bound idx) = undefined -- PP.pretty idx - pretty b (Free name) = undefined -- pretty b name - -instance Pretty CheckableTerm where - pretty _ = prettyCheckable - -prettyCheckable :: CheckableTerm -> Doc -prettyCheckable UniverseType = undefined -prettyCheckable (PiType q x s t) = undefined -prettyCheckable (Lam x t) = undefined -prettyCheckable (TensorType q x s t) = undefined -prettyCheckable (TensorIntro s t) = undefined -prettyCheckable UnitType = undefined -prettyCheckable Unit = undefined -prettyCheckable (SumType s t) = undefined -prettyCheckable (Inl x) = undefined -prettyCheckable (Inr x) = undefined -prettyCheckable (Inferred x) = undefined - -instance Pretty InferableTerm where - pretty _ = prettyInferrable - -prettyInferrable :: InferableTerm -> Doc -prettyInferrable (Var x) = undefined -prettyInferrable (Ann x t) = undefined -prettyInferrable (App m n) = undefined -prettyInferrable (TensorTypeElim q x _ _ t _ _) = undefined -prettyInferrable (SumTypeElim q b x y c z s t) = undefined - -instance Pretty Term where - pretty b (Checkable t) = pretty b t - pretty b (Inferable t) = pretty b t - -instance Pretty Value where - pretty _ = undefined - -instance Pretty Neutral where - pretty _ = undefined - -instance Pretty Binding where - pretty _ = undefined - -instance Pretty TypingContext where - pretty _ = undefined diff --git a/src/MiniJuvix/Typing.hs b/src/MiniJuvix/Typing.hs deleted file mode 100644 index e01d77692..000000000 --- a/src/MiniJuvix/Typing.hs +++ /dev/null @@ -1,3 +0,0 @@ -module MiniJuvix.Typing where - --------------------------------------------------------------------------------- diff --git a/src/MiniJuvix/Typing/Coverage.hs b/src/MiniJuvix/Typing/Coverage.hs deleted file mode 100644 index 56a178bc6..000000000 --- a/src/MiniJuvix/Typing/Coverage.hs +++ /dev/null @@ -1,3 +0,0 @@ -module MiniJuvix.Typing.Coverage () where - --------------------------------------------------------------------------------- diff --git a/src/MiniJuvix/Typing/Erasure.hs b/src/MiniJuvix/Typing/Erasure.hs deleted file mode 100644 index c85bdd29e..000000000 --- a/src/MiniJuvix/Typing/Erasure.hs +++ /dev/null @@ -1,3 +0,0 @@ -module MiniJuvix.Typing.Erasure () where - --------------------------------------------------------------------------------- diff --git a/src/MiniJuvix/Typing/Error.hs b/src/MiniJuvix/Typing/Error.hs deleted file mode 100644 index e7bb295c5..000000000 --- a/src/MiniJuvix/Typing/Error.hs +++ /dev/null @@ -1,40 +0,0 @@ -module MiniJuvix.Typing.Error - ( Error (..), - CheckingError (..), - CommonError (..), - ) -where - --------------------------------------------------------------------------------- - -import MiniJuvix.Utils.Prelude -import qualified Text.Show - --------------------------------------------------------------------------------- - -data CommonError - = MissingVariable - | QuantityError - deriving stock (Show) - -data CheckingError - = ExpectUniverseType - | ExpectPiType - | ExpectTensorType - | ExpectSumType - deriving stock (Show) - --- ! TODO add the other possible cases.. - -data InferingError = InferingError - deriving stock (Show) - -data ErasingError = ErasingError - deriving stock (Show) - -data Error - = CheckError CheckingError - | InferError InferingError - | ErasureError ErasingError - | CommonError - deriving stock (Show) diff --git a/src/MiniJuvix/Typing/Scopechecking.hs b/src/MiniJuvix/Typing/Scopechecking.hs deleted file mode 100644 index c2ee14cf3..000000000 --- a/src/MiniJuvix/Typing/Scopechecking.hs +++ /dev/null @@ -1,6 +0,0 @@ -module MiniJuvix.Typing.Scopechecking - ( - ) -where - --------------------------------------------------------------------------------- diff --git a/src/MiniJuvix/Typing/Termination.hs b/src/MiniJuvix/Typing/Termination.hs deleted file mode 100644 index 017e6c2c1..000000000 --- a/src/MiniJuvix/Typing/Termination.hs +++ /dev/null @@ -1,3 +0,0 @@ -module MiniJuvix.Typing.Termination where - --------------------------------------------------------------------------------- diff --git a/src/MiniJuvix/Typing/Typechecking.hs b/src/MiniJuvix/Typing/Typechecking.hs deleted file mode 100644 index 73d8030d3..000000000 --- a/src/MiniJuvix/Typing/Typechecking.hs +++ /dev/null @@ -1,61 +0,0 @@ -module MiniJuvix.Typing.Typechecking () where - --------------------------------------------------------------------------------- - -import MiniJuvix.Syntax.Core -import MiniJuvix.Syntax.Eval -import MiniJuvix.Typing.Error -import MiniJuvix.Typing.Utils - ( Binding, - Quantities, - TypingContext, - TypingContextM, - ) -import MiniJuvix.Utils.Prelude - --------------------------------------------------------------------------------- - -type TypingResult = Either Error - -{- Let's try to have support Andy's notation. Γ |- (x :q M) -| Δ - where Γ is the given context, x is a variable of quantity q of type - M, and Δ is the leftovers of quantities for each variable in Γ. --} - -type LeftOvers = Quantities - -type Judgment = TypingContextM TypingResult LeftOvers - --- This should be equivalent to have 0Γ. -type ZeroJudgment = TypingContextM TypingResult () - -extendLocalContext :: String -> Binding -> Judgment -> Judgment -extendLocalContext = undefined - -type Type = Value - --------------------------------------------------------------------------------- --- Type checking --------------------------------------------------------------------------------- - -check :: Relevance -> Term -> Type -> TypingResult (Type, LeftOvers) -check = undefined - -check' :: Relevance -> CheckableTerm -> Type -> TypingResult (Type, LeftOvers) -check' = undefined - --------------------------------------------------------------------------------- --- Type inference --------------------------------------------------------------------------------- - --- | infer the type of a term and check that context has appropriate --- resources available for the term. -infer :: TypingContext -> Quantity -> Term -> TypingResult (Type, LeftOvers) -infer = undefined - -infer' :: - TypingContext -> - Quantity -> - InferableTerm -> - TypingResult (Type, LeftOvers) -infer' = undefined diff --git a/src/MiniJuvix/Typing/Utils.hs b/src/MiniJuvix/Typing/Utils.hs deleted file mode 100644 index 946eaf44b..000000000 --- a/src/MiniJuvix/Typing/Utils.hs +++ /dev/null @@ -1,62 +0,0 @@ -module MiniJuvix.Typing.Utils - ( Binding (..), - Context, - TypingContextM, - weakenGlobal, - weakenLocal, - Quantities, - checkResources, - TypingContext (..), - ) -where - --------------------------------------------------------------------------------- - -import MiniJuvix.Syntax.Core (Name, Quantity) -import MiniJuvix.Syntax.Eval (Value) -import MiniJuvix.Utils.Prelude -import qualified MiniJuvix.Utils.Prelude as Map - --------------------------------------------------------------------------------- - -{- - Γ ⊢ let Δ in (x :^q M) - - On the left side of the turnstile, we have the global context (Γ). - On the right side of the turnstile, we have the local context (Δ). A - context, regardless its kind, consists of triples, each consisting - of a variable, its quantity, and its type. --} - -data Binding = Binding - { varName :: Name, - varQuantity :: Quantity, - varType :: Value - } - -type Context = [Binding] - -data TypingContext = TypingContext - { globalEnv :: Context, - localEnv :: Context - } - -type TypingContextM = ReaderT TypingContext - -weakenGlobal :: Binding -> TypingContext -> TypingContext -weakenGlobal var ctxt = ctxt {globalEnv = var : globalEnv ctxt} - -weakenLocal :: Binding -> TypingContext -> TypingContext -weakenLocal var ctxt = ctxt {localEnv = var : localEnv ctxt} - --- a.k.a. Resources -type Quantities = Map.Map Name Quantity - -checkResources :: - Context -> - Quantity -> - Maybe [(Binding, Quantity)] -checkResources = undefined - -mergeResources :: Quantities -> Quantities -> Quantities -mergeResources = undefined diff --git a/src/MiniJuvix/Utils/File.hs b/src/MiniJuvix/Utils/File.hs deleted file mode 100644 index 4ca31949a..000000000 --- a/src/MiniJuvix/Utils/File.hs +++ /dev/null @@ -1 +0,0 @@ -module MiniJuvix.Utils.File where diff --git a/src/MiniJuvix/Utils/Monad.hs b/src/MiniJuvix/Utils/Monad.hs deleted file mode 100644 index 2cedcf959..000000000 --- a/src/MiniJuvix/Utils/Monad.hs +++ /dev/null @@ -1 +0,0 @@ -module MiniJuvix.Utils.Monad where diff --git a/src/MiniJuvix/Utils/Parser.hs b/src/MiniJuvix/Utils/Parser.hs deleted file mode 100644 index 5aa90865d..000000000 --- a/src/MiniJuvix/Utils/Parser.hs +++ /dev/null @@ -1,295 +0,0 @@ --- | Adapted from heliaxdev/Juvix/library/StandardLibrary/src/Juvix/Parser* -module MiniJuvix.Utils.Parser - ( Parser, - ParserError, - - -- * Tokens - charToWord8, - toChar, - validUpperSymbol, - validStartSymbol', - dash, - percent, - slash, - newLine, - backtick, - hat, - asterisk, - amper, - bang, - question, - dot, - at, - equals, - pipe, - doubleQuote, - quote, - backSlash, - closeBracket, - openBracket, - closeCurly, - openCurly, - closeParen, - openParen, - hash, - comma, - semi, - colon, - space, - under, - validStartSymbol, - validMiddleSymbol, - validInfixSymbol, - endOfLine, - - -- * Lexing - emptyCheck, - spacer, - spaceLiner, - skipLiner, - eatSpaces, - between, - parens, - brackets, - curly, - many1H, - sepBy1HFinal, - sepBy1, - sepBy1H, - maybeParend, - integer, - - -- * Misc - symbolEndGen, - symbolEnd, - reserved, - ) -where - --------------------------------------------------------------------------------- - --- import qualified Data.ByteString as ByteString -import qualified Data.ByteString.Char8 as Char8 --- import qualified Data.Set as Set -import qualified Data.Word8 as Word8 -import qualified GHC.Unicode as Unicode -import MiniJuvix.Utils.Prelude --- import qualified MiniJuvix.Utils.Prelude as Encoding --- import qualified MiniJuvix.Utils.Prelude as Set -import qualified Text.Megaparsec as P -import qualified Text.Megaparsec.Byte as P - --------------------------------------------------------------------------------- - -type Parser = P.Parsec Void ByteString - --- ^ ^ --- | | --- Custom error component Type of input stream - -type ParserError = P.ParseErrorBundle ByteString Void - --------------------------------------------------------------------------------- --- Tokens --------------------------------------------------------------------------------- - -charToWord8 :: Char -> Word8 -charToWord8 = fromIntegral . ord -{-# INLINE charToWord8 #-} - -toChar :: Integral a => a -> Char -toChar = chr . fromIntegral - --- Hopefully this is fast! -validStartSymbol' :: Integral a => a -> Bool -validStartSymbol' = Unicode.isAlpha . toChar - --- Unicode.isUpper 'İ' = True! -validUpperSymbol :: Integral a => a -> Bool -validUpperSymbol = Unicode.isUpper . toChar - -dash :: Word8 -dash = charToWord8 '-' - -under :: Word8 -under = charToWord8 '_' - -space :: Word8 -space = charToWord8 ' ' - -colon :: Word8 -colon = charToWord8 ':' - -semi :: Word8 -semi = charToWord8 ';' - -comma :: Word8 -comma = charToWord8 ',' - -hash :: Word8 -hash = charToWord8 '#' - -openParen :: Word8 -openParen = charToWord8 '(' - -closeParen :: Word8 -closeParen = charToWord8 ')' - -openCurly :: Word8 -openCurly = charToWord8 '{' - -closeCurly :: Word8 -closeCurly = charToWord8 '}' - -openBracket :: Word8 -openBracket = charToWord8 '[' - -closeBracket :: Word8 -closeBracket = charToWord8 ']' - -backSlash :: Word8 -backSlash = charToWord8 '\\' - -quote :: Word8 -quote = charToWord8 '\'' - -doubleQuote :: Word8 -doubleQuote = charToWord8 '\"' - -pipe :: Word8 -pipe = charToWord8 '|' - -equals :: Word8 -equals = charToWord8 '=' - -at :: Word8 -at = charToWord8 '@' - -dot :: Word8 -dot = charToWord8 '.' - -question :: Word8 -question = charToWord8 '?' - -bang :: Word8 -bang = charToWord8 '!' - -amper :: Word8 -amper = charToWord8 '&' - -asterisk :: Word8 -asterisk = charToWord8 '*' - -hat :: Word8 -hat = charToWord8 '^' - -backtick :: Word8 -backtick = charToWord8 '`' - -newLine :: Word8 -newLine = charToWord8 '\n' - -slash :: Word8 -slash = charToWord8 '/' - -percent :: Word8 -percent = charToWord8 '%' - -validStartSymbol :: Word8 -> Bool -validStartSymbol w = - validStartSymbol' w || w == under - -validInfixSymbol :: Word8 -> Bool -validInfixSymbol w = - Unicode.isSymbol (toChar w) - || w == asterisk - || w == hat - || w == dash - || w == amper - || w == colon - || w == slash - || w == percent - || w == dot - -validMiddleSymbol :: Word8 -> Bool -validMiddleSymbol w = - validStartSymbol w - || Word8.isDigit w - || w == dash - || w == bang - || w == question - || w == percent - --- check for \r or \n -endOfLine :: (Eq a, Num a) => a -> Bool -endOfLine w = w == 13 || w == 10 - --------------------------------------------------------------------------------- --- Lexing --------------------------------------------------------------------------------- - -emptyCheck :: Word8 -> Bool -emptyCheck x = Word8.isSpace x || x == newLine - -spacer :: Parser p -> Parser p -spacer p = P.takeWhileP (Just "spacer") Word8.isSpace *> p - -spaceLiner :: Parser p -> Parser p -spaceLiner p = do - p <* P.takeWhileP (Just "space liner") emptyCheck - -skipLiner :: Word8 -> Parser () -skipLiner p = spaceLiner (P.skipCount 1 (P.char p)) - -eatSpaces :: Parser p -> Parser p -eatSpaces p = P.takeWhileP (Just "eat spaces") emptyCheck *> p - -between :: Word8 -> Parser p -> Word8 -> Parser p -between x p end = skipLiner x *> spaceLiner p <* P.satisfy (== end) - -parens :: Parser p -> Parser p -parens p = between openParen p closeParen - -brackets :: Parser p -> Parser p -brackets p = between openBracket p closeBracket - -curly :: Parser p -> Parser p -curly p = between openCurly p closeCurly - -many1H :: Parser a -> Parser (NonEmpty a) -many1H = fmap fromList . P.some - --- | 'sepBy1HFinal' is like 'sepBy1H' but also tries to --- parse a last separator -sepBy1HFinal :: Parser a -> Parser s -> Parser (NonEmpty a) -sepBy1HFinal parse sep = sepBy1H parse sep <* P.optional sep - -sepBy1 :: Parser a -> Parser s -> Parser [a] -sepBy1 p sep = liftA2 (:) p (many (P.try $ sep *> p)) - -sepBy1H :: Parser a -> Parser s -> Parser (NonEmpty a) -sepBy1H parse sep = fromList <$> sepBy1 parse sep - -maybeParend :: Parser a -> Parser a -maybeParend p = p <|> parens p - -integer :: Parser Integer -integer = do - digits <- P.takeWhileP (Just "digits") Word8.isDigit - case Char8.readInteger digits of - Just (x, _) -> pure x - Nothing -> fail "didn't parse an int" - -symbolEndGen :: ByteString -> Parser () -symbolEndGen _s = do - P.notFollowedBy (P.satisfy validMiddleSymbol) - _ <- P.takeWhileP (Just "Empty Check") emptyCheck - return () - -symbolEnd :: Parser () -symbolEnd = symbolEndGen "current symbol is not over" - -reserved :: ByteString -> Parser () -reserved w = do - _ <- P.string w - symbolEndGen "symbol is not the reserved symbol" diff --git a/src/MiniJuvix/Utils/Pretty.hs b/src/MiniJuvix/Utils/Pretty.hs deleted file mode 100644 index d2056d743..000000000 --- a/src/MiniJuvix/Utils/Pretty.hs +++ /dev/null @@ -1,116 +0,0 @@ -module MiniJuvix.Utils.Pretty - ( Doc, - Pretty (..), - unicode, - ascii, - color, - render, - hardlines, - format, - annotateSpecialSymbol, - printList, - ) -where - --------------------------------------------------------------------------------- - -import MiniJuvix.Utils.Prelude -import Prettyprinter hiding - ( Doc, - Pretty (..), - ) -import qualified Prettyprinter as PP -import qualified Prettyprinter.Render.Terminal as Term - --------------------------------------------------------------------------------- - -type Doc = PP.Doc Term.AnsiStyle - -render :: PP.Doc Term.AnsiStyle -> Text -render = Term.renderStrict . layoutSmart defaultLayoutOptions - -hardlines :: [PP.Doc Term.AnsiStyle] -> PP.Doc Term.AnsiStyle -hardlines = mconcat . intersperse hardline - --------------------------------------------------------------------------------- --- Styling --------------------------------------------------------------------------------- - -data SpecialSymbol - = UniverseTypeSymbol - | PiTypeSymbol - | LambdaSymbol - | ArrowSymbol - | TensorTypeSymbol - | UnitTypeSymbol - | UnitSymbol - | SumTypeSymbol - | InlSymbol - | InrSymbol - | ManyQuantitySymbol - | ColonSymbol - | DoubleColonSymbol - -type Unicode = String - -type ASCII = String - -unicode :: SpecialSymbol -> Unicode -unicode UniverseTypeSymbol = "Ʉ" -unicode PiTypeSymbol = "Π" -unicode LambdaSymbol = "λ" -unicode ArrowSymbol = "→" -unicode TensorTypeSymbol = "⊗" -unicode UnitTypeSymbol = "𝟭" -unicode UnitSymbol = "*" -unicode SumTypeSymbol = "+" -unicode InlSymbol = "inl" -unicode InrSymbol = "inr" -unicode ManyQuantitySymbol = "ω" -unicode ColonSymbol = "∶" -unicode DoubleColonSymbol = "∷" - -ascii :: SpecialSymbol -> ASCII -ascii UniverseTypeSymbol = "U" -ascii PiTypeSymbol = "Pi" -ascii LambdaSymbol = "\\" -ascii ArrowSymbol = "->" -ascii TensorTypeSymbol = "*" -ascii UnitTypeSymbol = "Unit" -ascii UnitSymbol = "unit" -ascii SumTypeSymbol = "+" -ascii InlSymbol = "inl" -ascii InrSymbol = "inr" -ascii ManyQuantitySymbol = "_" -ascii ColonSymbol = ":" -ascii DoubleColonSymbol = "::" - -color :: SpecialSymbol -> Term.Color -color UniverseTypeSymbol = Term.Black -color PiTypeSymbol = Term.Black -color LambdaSymbol = Term.Black -color ArrowSymbol = Term.Black -color TensorTypeSymbol = Term.Black -color UnitTypeSymbol = Term.Black -color UnitSymbol = Term.Black -color SumTypeSymbol = Term.Black -color InlSymbol = Term.Black -color InrSymbol = Term.Black -color ManyQuantitySymbol = Term.Black -color ColonSymbol = Term.Black -color DoubleColonSymbol = Term.Black - -format :: Bool -> SpecialSymbol -> Doc -format True = PP.pretty . unicode -format False = PP.pretty . ascii - -annotateSpecialSymbol :: Bool -> SpecialSymbol -> Doc -annotateSpecialSymbol b s = annotate (Term.color (color s)) (format b s) - --------------------------------------------------------------------------------- - -class Pretty a where - pretty :: Bool -> a -> Doc - -printList :: [a] -> IO () -printList = undefined From 61df66d18654a04b98df13a65359970bcf2a8157 Mon Sep 17 00:00:00 2001 From: Jan Mas Rovira Date: Fri, 21 Jan 2022 09:50:37 +0100 Subject: [PATCH 6/6] replace relude by our own Prelude --- app/Main.hs | 160 +++++---- package.yaml | 3 +- src/MiniJuvix/Syntax/Concrete/Language.hs | 26 +- .../Syntax/Concrete/Scoped/Pretty/Ansi.hs | 14 +- .../Syntax/Concrete/Scoped/Pretty/Base.hs | 319 +++++++++--------- .../Syntax/Concrete/Scoped/Scoper.hs | 43 ++- src/MiniJuvix/Syntax/Core.hs | 2 +- src/MiniJuvix/Utils/Prelude.hs | 134 ++++++-- src/MiniJuvix/Utils/Version.hs | 5 +- 9 files changed, 395 insertions(+), 311 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index d8be6f3cc..1391b42e3 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,106 +1,121 @@ {-# LANGUAGE ApplicativeDo #-} + module Main (main) where -import MiniJuvix.Utils.Prelude -import qualified MiniJuvix.Syntax.Concrete.Parser as M -import qualified MiniJuvix.Syntax.Concrete.Language as M -import qualified MiniJuvix.Syntax.Concrete.Scoped.Scoper as M -import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Ansi as M -import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base as M -import Options.Applicative -import System.IO.Error -import Options.Applicative.Help.Pretty -import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base (Options(_optShowNameId)) -import Data.Text (unpack) -import Text.Show.Pretty import Control.Monad.Extra +import qualified MiniJuvix.Syntax.Concrete.Language as M +import qualified MiniJuvix.Syntax.Concrete.Parser as M +import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Ansi as M +import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base (Options (_optShowNameId)) +import qualified MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base as M +import qualified MiniJuvix.Syntax.Concrete.Scoped.Scoper as M +import MiniJuvix.Utils.Prelude +import Options.Applicative +import Options.Applicative.Help.Pretty +import System.IO.Error +import Text.Show.Pretty -data Command = - Scope ScopeOptions +data Command + = Scope ScopeOptions | Parse ParseOptions -data ScopeOptions = ScopeOptions { - _scopeRootDir :: FilePath - , _scopeInputFile :: FilePath - , _scopeShowIds :: Bool +data ScopeOptions = ScopeOptions + { _scopeRootDir :: FilePath, + _scopeInputFile :: FilePath, + _scopeShowIds :: Bool } -data ParseOptions = ParseOptions { - _parseInputFile :: FilePath, - _parseNoPrettyShow :: Bool +data ParseOptions = ParseOptions + { _parseInputFile :: FilePath, + _parseNoPrettyShow :: Bool } parseParse :: Parser ParseOptions parseParse = do - _parseInputFile <- argument str - (metavar "MINIJUVIX_FILE" - <> help "Path to a .mjuvix file" - ) - _parseNoPrettyShow <- switch - ( long "no-pretty-show" - <> help "Disable formatting of the Haskell AST" - ) + _parseInputFile <- + argument + str + ( metavar "MINIJUVIX_FILE" + <> help "Path to a .mjuvix file" + ) + _parseNoPrettyShow <- + switch + ( long "no-pretty-show" + <> help "Disable formatting of the Haskell AST" + ) pure ParseOptions {..} - parseScope :: Parser ScopeOptions parseScope = do - _scopeRootDir <- strOption - (long "rootDir" - <> short 'd' - <> metavar "DIR" - <> value "." - <> showDefault - <> help "Root directory") - _scopeInputFile <- argument str - (metavar "MINIJUVIX_FILE" - <> help "Path to a .mjuvix file" - ) - _scopeShowIds <- switch - ( long "show-name-ids" - <> help "Show the unique number of each identifier" - ) + _scopeRootDir <- + strOption + ( long "rootDir" + <> short 'd' + <> metavar "DIR" + <> value "." + <> showDefault + <> help "Root directory" + ) + _scopeInputFile <- + argument + str + ( metavar "MINIJUVIX_FILE" + <> help "Path to a .mjuvix file" + ) + _scopeShowIds <- + switch + ( long "show-name-ids" + <> help "Show the unique number of each identifier" + ) pure ScopeOptions {..} descr :: ParserInfo Command -descr = info (parseCommand <**> helper) - (fullDesc +descr = + info + (parseCommand <**> helper) + ( fullDesc <> progDesc "The MiniJuvix compiler." <> headerDoc (Just headDoc) <> footerDoc (Just foot) - ) + ) where - headDoc :: Doc - headDoc = dullblue $ bold $ underline "MiniJuvix help" - foot :: Doc - foot = bold "maintainers: " <> "jan@heliax.dev; jonathan@heliax.dev" + headDoc :: Doc + headDoc = dullblue $ bold $ underline "MiniJuvix help" + foot :: Doc + foot = bold "maintainers: " <> "jan@heliax.dev; jonathan@heliax.dev" parseCommand :: Parser Command -parseCommand = hsubparser $ mconcat [ - commandParse, - commandScope - ] +parseCommand = + hsubparser $ + mconcat + [ commandParse, + commandScope + ] where - commandParse :: Mod CommandFields Command - commandParse = command "parse" minfo - where - minfo :: ParserInfo Command - minfo = info (Parse <$> parseParse) - (progDesc "Parse a .mjuvix file") - - commandScope :: Mod CommandFields Command - commandScope = command "scope" minfo - where - minfo :: ParserInfo Command - minfo = info (Scope <$> parseScope) - (progDesc "Parse and scope a .mjuvix file") + commandParse :: Mod CommandFields Command + commandParse = command "parse" minfo + where + minfo :: ParserInfo Command + minfo = + info + (Parse <$> parseParse) + (progDesc "Parse a .mjuvix file") + commandScope :: Mod CommandFields Command + commandScope = command "scope" minfo + where + minfo :: ParserInfo Command + minfo = + info + (Scope <$> parseScope) + (progDesc "Parse and scope a .mjuvix file") mkPrettyOptions :: ScopeOptions -> M.Options -mkPrettyOptions ScopeOptions {..} = M.defaultOptions { - _optShowNameId = _scopeShowIds - } +mkPrettyOptions ScopeOptions {..} = + M.defaultOptions + { _optShowNameId = _scopeShowIds + } parseModuleIO :: FilePath -> IO (M.Module 'M.Parsed 'M.ModuleTop) parseModuleIO = fromRightIO id . M.runModuleParserIO @@ -118,6 +133,5 @@ go c = case c of m <- parseModuleIO _parseInputFile if _parseNoPrettyShow then print m else pPrint m - main :: IO () main = execParser descr >>= go diff --git a/package.yaml b/package.yaml index 64f5388cc..a8f426dc6 100644 --- a/package.yaml +++ b/package.yaml @@ -21,8 +21,10 @@ dependencies: - base == 4.15.* - bytestring == 0.10.* - containers == 0.6.* +- directory == 1.3.* - extra == 1.7.* - filepath == 1.4.* +- hashable == 1.3.* - megaparsec == 9.2.* - microlens-platform == 0.4.* - parser-combinators == 1.3.* @@ -31,7 +33,6 @@ dependencies: - prettyprinter == 1.7.* - prettyprinter-ansi-terminal == 1.1.* - process == 1.6.* -- relude == 1.0.* - semirings == 0.6.* - singletons == 3.0.* - Stream == 0.4.* diff --git a/src/MiniJuvix/Syntax/Concrete/Language.hs b/src/MiniJuvix/Syntax/Concrete/Language.hs index 51a88e2a5..16287b9ab 100644 --- a/src/MiniJuvix/Syntax/Concrete/Language.hs +++ b/src/MiniJuvix/Syntax/Concrete/Language.hs @@ -234,22 +234,22 @@ deriving stock instance (Lift (ExpressionType s), Lift (SymbolType s)) => Lift ( -- Pattern -------------------------------------------------------------------------------- -data PatternInfixApp = PatternInfixApp { - patInfixConstructor :: NameType 'Scoped, - patInfixLeft :: Pattern, - patInfixRight :: Pattern +data PatternInfixApp = PatternInfixApp + { patInfixConstructor :: NameType 'Scoped, + patInfixLeft :: Pattern, + patInfixRight :: Pattern } deriving stock (Show, Eq, Ord) -data PatternPostfixApp = PatternPostfixApp { - patPostfixConstructor :: NameType 'Scoped, - patPostfixParameter :: Pattern +data PatternPostfixApp = PatternPostfixApp + { patPostfixConstructor :: NameType 'Scoped, + patPostfixParameter :: Pattern } deriving stock (Show, Eq, Ord) -data PatternPrefixApp = PatternPrefixApp { - patPrefixConstructor :: NameType 'Scoped, - patPrefixParameter :: Pattern +data PatternPrefixApp = PatternPrefixApp + { patPrefixConstructor :: NameType 'Scoped, + patPrefixParameter :: Pattern } deriving stock (Show, Eq, Ord) @@ -826,9 +826,9 @@ data PostfixApplication = PostfixApplication -- Let block expression -------------------------------------------------------------------------------- -data LetBlock (s :: Stage) = LetBlock { - letClauses :: [LetClause s], - letExpression :: ExpressionType s +data LetBlock (s :: Stage) = LetBlock + { letClauses :: [LetClause s], + letExpression :: ExpressionType s } deriving stock instance diff --git a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs index f276de752..9fc1ca76f 100644 --- a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs +++ b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Ansi.hs @@ -1,11 +1,11 @@ module MiniJuvix.Syntax.Concrete.Scoped.Pretty.Ansi where -import Prettyprinter -import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base import MiniJuvix.Syntax.Concrete.Language +import MiniJuvix.Syntax.Concrete.Scoped.Name (NameKind (..)) +import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base import MiniJuvix.Utils.Prelude +import Prettyprinter import Prettyprinter.Render.Terminal -import MiniJuvix.Syntax.Concrete.Scoped.Name (NameKind(..)) printTopModuleDefault :: Module 'Scoped 'ModuleTop -> IO () printTopModuleDefault = printTopModule defaultOptions @@ -13,10 +13,10 @@ printTopModuleDefault = printTopModule defaultOptions printTopModule :: Options -> Module 'Scoped 'ModuleTop -> IO () printTopModule opts m = renderIO stdout docStream' where - docStream :: SimpleDocStream Ann - docStream = layoutPretty defaultLayoutOptions (prettyTopModule opts m) - docStream' :: SimpleDocStream AnsiStyle - docStream' = reAnnotateS stylize docStream + docStream :: SimpleDocStream Ann + docStream = layoutPretty defaultLayoutOptions (prettyTopModule opts m) + docStream' :: SimpleDocStream AnsiStyle + docStream' = reAnnotateS stylize docStream stylize :: Ann -> AnsiStyle stylize a = case a of diff --git a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs index 3683e3062..751d8599a 100644 --- a/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs +++ b/src/MiniJuvix/Syntax/Concrete/Scoped/Pretty/Base.hs @@ -1,37 +1,36 @@ module MiniJuvix.Syntax.Concrete.Scoped.Pretty.Base where - -import qualified MiniJuvix.Syntax.Concrete.Scoped.Name as S -import MiniJuvix.Utils.Prelude hiding (Reader, runReader, asks) -import MiniJuvix.Syntax.Concrete.Language -import Polysemy -import Polysemy.Reader -import Prettyprinter hiding (braces, parens) import Data.Singletons +import MiniJuvix.Syntax.Concrete.Language +import qualified MiniJuvix.Syntax.Concrete.Scoped.Name as S +import MiniJuvix.Utils.Prelude +import Prettyprinter hiding (braces, parens) - -data Ann = AnnKind S.NameKind +data Ann + = AnnKind S.NameKind | AnnKeyword | AnnDelimiter -data Options = Options { - _optOptimizeParens :: Bool, - _optShowNameId :: Bool, - _optIndent :: Int +data Options = Options + { _optOptimizeParens :: Bool, + _optShowNameId :: Bool, + _optIndent :: Int } defaultOptions :: Options -defaultOptions = Options { - _optOptimizeParens = True, - _optShowNameId = False, - _optIndent = 2 - } +defaultOptions = + Options + { _optOptimizeParens = True, + _optShowNameId = False, + _optIndent = 2 + } -- | Pretty prints a top module. prettyTopModule :: Options -> Module 'Scoped 'ModuleTop -> Doc Ann prettyTopModule opts = run . runReader opts . ppModule infixl 7 <+?> + (<+?>) :: Doc ann -> Maybe (Doc ann) -> Doc ann (<+?>) a = maybe a (a <+>) @@ -185,30 +184,33 @@ endSemicolon x = x <> kwSemicolon ppModule :: (SingI t, Members '[Reader Options] r) => Module 'Scoped t -> Sem r (Doc Ann) ppModule Module {..} = do - moduleBody' <- mapM (fmap endSemicolon . ppStatement) moduleBody >>= indented . vsep + moduleBody' <- mapM (fmap endSemicolon . ppStatement) moduleBody >>= indented . vsep modulePath' <- ppModulePathType modulePath - return $ kwModule <+> modulePath' <> kwSemicolon <> line - <> moduleBody' <> line - <> kwEnd <> kwSemicolon + return $ + kwModule <+> modulePath' <> kwSemicolon <> line + <> moduleBody' + <> line + <> kwEnd + <> kwSemicolon ppOperatorSyntaxDef :: Members '[Reader Options] r => OperatorSyntaxDef -> Sem r (Doc Ann) ppOperatorSyntaxDef OperatorSyntaxDef {..} = do opSymbol' <- ppSymbol opSymbol return $ ppFixity opFixity <+> opSymbol' where - ppFixity :: Fixity -> Doc Ann - ppFixity Fixity {..} = - ppArity <+> pretty fixityPrecedence - where - ppArity :: Doc Ann - ppArity = case fixityArity of - Unary p -> case p of - AssocPrefix -> kwPrefix - AssocPostfix -> kwPostfix - Binary p -> case p of - AssocRight -> kwInfixr - AssocLeft -> kwInfixl - AssocNone -> kwInfix + ppFixity :: Fixity -> Doc Ann + ppFixity Fixity {..} = + ppArity <+> pretty fixityPrecedence + where + ppArity :: Doc Ann + ppArity = case fixityArity of + Unary p -> case p of + AssocPrefix -> kwPrefix + AssocPostfix -> kwPostfix + Binary p -> case p of + AssocRight -> kwInfixr + AssocLeft -> kwInfixl + AssocNone -> kwInfix ppDataConstructorDef :: Members '[Reader Options] r => DataConstructorDef 'Scoped -> Sem r (Doc Ann) ppDataConstructorDef DataConstructorDef {..} = do @@ -222,18 +224,19 @@ ppDataTypeDef DataTypeDef {..} = do dataTypeParameters' <- hsep <$> mapM ppDataTypeParameter dataTypeParameters dataTypeType' <- ppTypeType dataTypeConstructors' <- ppBlock ppDataConstructorDef dataTypeConstructors - return $ kwInductive <+> dataTypeName' <+> dataTypeParameters' <+?> dataTypeType' - <+> dataTypeConstructors' + return $ + kwInductive <+> dataTypeName' <+> dataTypeParameters' <+?> dataTypeType' + <+> dataTypeConstructors' where - ppTypeType :: Sem r (Maybe (Doc Ann)) - ppTypeType = case dataTypeType of - Nothing -> return Nothing - Just e -> Just . (kwColon <+>) <$> ppExpression e - ppDataTypeParameter :: DataTypeParameter 'Scoped -> Sem r (Doc Ann) - ppDataTypeParameter DataTypeParameter {..} = do - dataTypeParameterName' <- ppSSymbol dataTypeParameterName - dataTypeParameterType' <- ppExpression dataTypeParameterType - return $ parens (dataTypeParameterName' <+> kwColon <+> dataTypeParameterType') + ppTypeType :: Sem r (Maybe (Doc Ann)) + ppTypeType = case dataTypeType of + Nothing -> return Nothing + Just e -> Just . (kwColon <+>) <$> ppExpression e + ppDataTypeParameter :: DataTypeParameter 'Scoped -> Sem r (Doc Ann) + ppDataTypeParameter DataTypeParameter {..} = do + dataTypeParameterName' <- ppSSymbol dataTypeParameterName + dataTypeParameterType' <- ppExpression dataTypeParameterType + return $ parens (dataTypeParameterName' <+> kwColon <+> dataTypeParameterType') dotted :: [Doc Ann] -> Doc Ann dotted = concatWith (surround kwDot) @@ -274,8 +277,8 @@ ppOpen OpenModule {..} = do openUsingHiding' <- ppUsingHiding return $ keyword "open" <+> openModuleName' <+> openUsingHiding' where - ppUsingHiding :: Sem r (Doc Ann) - ppUsingHiding = return $ pretty ("TODO" :: Text) + ppUsingHiding :: Sem r (Doc Ann) + ppUsingHiding = return $ pretty ("TODO" :: Text) ppTypeSignature :: Members '[Reader Options] r => TypeSignature 'Scoped -> Sem r (Doc Ann) ppTypeSignature TypeSignature {..} = do @@ -289,21 +292,21 @@ ppFunction Function {..} = do funReturn' <- ppExpressionAtom funReturn return $ funParameter' <+> kwArrowR <+> funReturn' where - ppUsage :: Maybe Usage -> Doc Ann - ppUsage m = case m of - Nothing -> kwColon - Just u -> case u of - UsageNone -> kwColonZero - UsageOnce -> kwColonOne - UsageOmega -> kwColonOmega - ppFunParameter :: FunctionParameter 'Scoped -> Sem r (Doc Ann) - ppFunParameter FunctionParameter {..} = do - case paramName of - Nothing -> ppExpressionAtom paramType - Just n -> do - paramName' <- ppSSymbol n - paramType' <- ppExpression paramType - return $ parens (paramName' <+> ppUsage paramUsage <+> paramType') + ppUsage :: Maybe Usage -> Doc Ann + ppUsage m = case m of + Nothing -> kwColon + Just u -> case u of + UsageNone -> kwColonZero + UsageOnce -> kwColonOne + UsageOmega -> kwColonOmega + ppFunParameter :: FunctionParameter 'Scoped -> Sem r (Doc Ann) + ppFunParameter FunctionParameter {..} = do + case paramName of + Nothing -> ppExpressionAtom paramType + Just n -> do + paramName' <- ppSSymbol n + paramType' <- ppExpression paramType + return $ parens (paramName' <+> ppUsage paramUsage <+> paramType') ppUniverse :: Members '[Reader Options] r => Universe -> Sem r (Doc Ann) ppUniverse (Universe n) = return $ kwType <+> pretty n @@ -314,10 +317,10 @@ ppLetBlock LetBlock {..} = do letExpression' <- ppExpression letExpression return $ kwLet <+> letClauses' <+> kwIn <+> letExpression' where - ppLetClause :: LetClause 'Scoped -> Sem r (Doc Ann) - ppLetClause c = case c of - LetTypeSig sig -> ppTypeSignature sig - LetFunClause cl -> ppFunctionClause cl + ppLetClause :: LetClause 'Scoped -> Sem r (Doc Ann) + ppLetClause c = case c of + LetTypeSig sig -> ppTypeSignature sig + LetFunClause cl -> ppFunctionClause cl ppBlock :: Members '[Reader Options] r => (a -> Sem r (Doc Ann)) -> [a] -> Sem r (Doc Ann) ppBlock ppItem items = mapM (fmap endSemicolon . ppItem) items >>= bracesIndent . vsep @@ -328,22 +331,22 @@ ppMatch Match {..} = do matchAlts' <- ppBlock ppMatchAlt matchAlts return $ kwMatch <+> matchExpression' <+> matchAlts' where - ppMatchAlt :: MatchAlt 'Scoped -> Sem r (Doc Ann) - ppMatchAlt MatchAlt {..} = do - matchAltPattern' <- ppPattern matchAltPattern - matchAltBody' <- ppExpression matchAltBody - return $ matchAltPattern' <+> kwMapsto <+> matchAltBody' + ppMatchAlt :: MatchAlt 'Scoped -> Sem r (Doc Ann) + ppMatchAlt MatchAlt {..} = do + matchAltPattern' <- ppPattern matchAltPattern + matchAltBody' <- ppExpression matchAltBody + return $ matchAltPattern' <+> kwMapsto <+> matchAltBody' ppLambda :: forall r. Members '[Reader Options] r => Lambda 'Scoped -> Sem r (Doc Ann) ppLambda Lambda {..} = do lambdaClauses' <- ppBlock ppLambdaClause lambdaClauses return $ kwLambda <+> lambdaClauses' where - ppLambdaClause :: LambdaClause 'Scoped -> Sem r (Doc Ann) - ppLambdaClause LambdaClause {..} = do - lambdaParameters' <- hsep . toList <$> mapM ppPattern lambdaParameters - lambdaBody' <- ppExpression lambdaBody - return $ lambdaParameters' <+> kwMapsto <+> lambdaBody' + ppLambdaClause :: LambdaClause 'Scoped -> Sem r (Doc Ann) + ppLambdaClause LambdaClause {..} = do + lambdaParameters' <- hsep . toList <$> mapM ppPattern lambdaParameters + lambdaBody' <- ppExpression lambdaBody + return $ lambdaParameters' <+> kwMapsto <+> lambdaBody' ppFunctionClause :: forall r. Members '[Reader Options] r => FunctionClause 'Scoped -> Sem r (Doc Ann) ppFunctionClause FunctionClause {..} = do @@ -353,17 +356,18 @@ ppFunctionClause FunctionClause {..} = do Just ne -> Just . hsep . toList <$> mapM ppPattern ne clauseBody' <- ppExpression clauseBody clauseWhere' <- sequence $ ppWhereBlock <$> clauseWhere - return $ clauseOwnerFunction' <+?> clausePatterns' <+> kwAssignment <+> clauseBody' - <+?> (((line <> kwWhere) <+>) <$> clauseWhere') + return $ + clauseOwnerFunction' <+?> clausePatterns' <+> kwAssignment <+> clauseBody' + <+?> (((line <> kwWhere) <+>) <$> clauseWhere') where - ppWhereBlock :: WhereBlock 'Scoped -> Sem r (Doc Ann) - ppWhereBlock WhereBlock {..} = ppBlock ppWhereClause whereClauses - where - ppWhereClause :: WhereClause 'Scoped -> Sem r (Doc Ann) - ppWhereClause c = case c of - WhereOpenModule o -> ppOpen o - WhereTypeSig sig -> ppTypeSignature sig - WhereFunClause fun -> ppFunctionClause fun + ppWhereBlock :: WhereBlock 'Scoped -> Sem r (Doc Ann) + ppWhereBlock WhereBlock {..} = ppBlock ppWhereClause whereClauses + where + ppWhereClause :: WhereClause 'Scoped -> Sem r (Doc Ann) + ppWhereClause c = case c of + WhereOpenModule o -> ppOpen o + WhereTypeSig sig -> ppTypeSignature sig + WhereFunClause fun -> ppFunctionClause fun ppAxiom :: Members '[Reader Options] r => AxiomDef 'Scoped -> Sem r (Doc Ann) ppAxiom AxiomDef {..} = do @@ -389,57 +393,57 @@ ppImport (Import (Module {..})) = do ppPattern :: forall r. Members '[Reader Options] r => Pattern -> Sem r (Doc Ann) ppPattern = goAtom where - isAtomicPat :: Pattern -> Bool - isAtomicPat p = case p of - PatternVariable {} -> True - PatternApplication {} -> False - PatternConstructor {} -> True - PatternInfixApplication {} -> False - PatternPostfixApplication {} -> False - PatternPrefixApplication {} -> False - PatternWildcard -> True - PatternEmpty -> True - goAtom :: Pattern -> Sem r (Doc Ann) - goAtom p = do - p' <- go p - return $ if isAtomicPat p then p' else parens p' - go :: Pattern -> Sem r (Doc Ann) - go p = case p of - PatternVariable v -> ppSSymbol v - PatternApplication l r -> do - l' <- goAtom l - r' <- goAtom r - return $ l' <+> r' - PatternWildcard -> return kwWildcard - PatternEmpty -> return $ parens mempty - PatternConstructor constr -> ppSName constr - PatternInfixApplication i -> ppPatternInfixApp i - PatternPrefixApplication i -> ppPatternPrefixApp i - PatternPostfixApplication i -> ppPatternPostfixApp i + isAtomicPat :: Pattern -> Bool + isAtomicPat p = case p of + PatternVariable {} -> True + PatternApplication {} -> False + PatternConstructor {} -> True + PatternInfixApplication {} -> False + PatternPostfixApplication {} -> False + PatternPrefixApplication {} -> False + PatternWildcard -> True + PatternEmpty -> True + goAtom :: Pattern -> Sem r (Doc Ann) + goAtom p = do + p' <- go p + return $ if isAtomicPat p then p' else parens p' + go :: Pattern -> Sem r (Doc Ann) + go p = case p of + PatternVariable v -> ppSSymbol v + PatternApplication l r -> do + l' <- goAtom l + r' <- goAtom r + return $ l' <+> r' + PatternWildcard -> return kwWildcard + PatternEmpty -> return $ parens mempty + PatternConstructor constr -> ppSName constr + PatternInfixApplication i -> ppPatternInfixApp i + PatternPrefixApplication i -> ppPatternPrefixApp i + PatternPostfixApplication i -> ppPatternPostfixApp i - ppPatternInfixApp :: PatternInfixApp -> Sem r (Doc Ann) - ppPatternInfixApp PatternInfixApp {..} = do - patInfixConstructor' <- ppSName patInfixConstructor - patInfixLeft' <- goAtom patInfixLeft - patInfixRight' <- goAtom patInfixRight - return $ patInfixLeft' <+> patInfixConstructor' <+> patInfixRight' + ppPatternInfixApp :: PatternInfixApp -> Sem r (Doc Ann) + ppPatternInfixApp PatternInfixApp {..} = do + patInfixConstructor' <- ppSName patInfixConstructor + patInfixLeft' <- goAtom patInfixLeft + patInfixRight' <- goAtom patInfixRight + return $ patInfixLeft' <+> patInfixConstructor' <+> patInfixRight' - ppPatternPrefixApp :: PatternPrefixApp -> Sem r (Doc Ann) - ppPatternPrefixApp PatternPrefixApp {..} = do - patPrefixConstructor' <- ppSName patPrefixConstructor - patPrefixParameter' <- goAtom patPrefixParameter - return $ patPrefixConstructor' <+> patPrefixParameter' + ppPatternPrefixApp :: PatternPrefixApp -> Sem r (Doc Ann) + ppPatternPrefixApp PatternPrefixApp {..} = do + patPrefixConstructor' <- ppSName patPrefixConstructor + patPrefixParameter' <- goAtom patPrefixParameter + return $ patPrefixConstructor' <+> patPrefixParameter' - ppPatternPostfixApp :: PatternPostfixApp -> Sem r (Doc Ann) - ppPatternPostfixApp PatternPostfixApp {..} = do - patPostfixConstructor' <- ppSName patPostfixConstructor - patPostfixParameter' <- goAtom patPostfixParameter - return $ patPostfixParameter' <+> patPostfixConstructor' + ppPatternPostfixApp :: PatternPostfixApp -> Sem r (Doc Ann) + ppPatternPostfixApp PatternPostfixApp {..} = do + patPostfixConstructor' <- ppSName patPostfixConstructor + patPostfixParameter' <- goAtom patPostfixParameter + return $ patPostfixParameter' <+> patPostfixConstructor' ppExpressionAtom :: forall r. Members '[Reader Options] r => Expression -> Sem r (Doc Ann) -ppExpressionAtom e = do - e' <- ppExpression e - return $ if isAtomic e then e' else parens e' +ppExpressionAtom e = do + e' <- ppExpression e + return $ if isAtomic e then e' else parens e' isAtomic :: Expression -> Bool isAtomic e = case e of @@ -454,39 +458,38 @@ isAtomic e = case e of ExpressionFunction {} -> False ppInfixApplication :: forall r. Members '[Reader Options] r => InfixApplication -> Sem r (Doc Ann) -ppInfixApplication InfixApplication {..} = do +ppInfixApplication InfixApplication {..} = do infixAppLeft' <- ppExpressionAtom infixAppLeft - infixAppOperator' <- ppSName infixAppOperator + infixAppOperator' <- ppSName infixAppOperator infixAppRight' <- ppExpressionAtom infixAppRight return $ infixAppLeft' <+> infixAppOperator' <+> infixAppRight' ppPostfixApplication :: forall r. Members '[Reader Options] r => PostfixApplication -> Sem r (Doc Ann) -ppPostfixApplication PostfixApplication {..} = do +ppPostfixApplication PostfixApplication {..} = do postfixAppParameter' <- ppExpressionAtom postfixAppParameter - postfixAppOperator' <- ppSName postfixAppOperator + postfixAppOperator' <- ppSName postfixAppOperator return $ postfixAppParameter' <+> postfixAppOperator' - ppExpression :: forall r. Members '[Reader Options] r => Expression -> Sem r (Doc Ann) ppExpression = go where - ppApplication :: Application -> Sem r (Doc Ann) - ppApplication (Application l r) = do - l' <- goAtom l - r' <- goAtom r - return $ l' <+> r' - goAtom :: Expression -> Sem r (Doc Ann) - goAtom e = do - e' <- go e - return $ if isAtomic e then e' else parens e' - go :: Expression -> Sem r (Doc Ann) - go e = case e of - ExpressionIdentifier n -> ppSName n - ExpressionApplication a -> ppApplication a - ExpressionInfixApplication a -> ppInfixApplication a - ExpressionPostfixApplication a -> ppPostfixApplication a - ExpressionLambda l -> ppLambda l - ExpressionMatch m -> ppMatch m - ExpressionLetBlock lb -> ppLetBlock lb - ExpressionUniverse u -> ppUniverse u - ExpressionFunction f -> ppFunction f + ppApplication :: Application -> Sem r (Doc Ann) + ppApplication (Application l r) = do + l' <- goAtom l + r' <- goAtom r + return $ l' <+> r' + goAtom :: Expression -> Sem r (Doc Ann) + goAtom e = do + e' <- go e + return $ if isAtomic e then e' else parens e' + go :: Expression -> Sem r (Doc Ann) + go e = case e of + ExpressionIdentifier n -> ppSName n + ExpressionApplication a -> ppApplication a + ExpressionInfixApplication a -> ppInfixApplication a + ExpressionPostfixApplication a -> ppPostfixApplication a + ExpressionLambda l -> ppLambda l + ExpressionMatch m -> ppMatch m + ExpressionLetBlock lb -> ppLetBlock lb + ExpressionUniverse u -> ppUniverse u + ExpressionFunction f -> ppFunction f diff --git a/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs b/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs index 30f954929..97d24b6b2 100644 --- a/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs +++ b/src/MiniJuvix/Syntax/Concrete/Scoped/Scoper.hs @@ -8,7 +8,6 @@ module MiniJuvix.Syntax.Concrete.Scoped.Scoper where import qualified Control.Monad.Combinators.Expr as P import qualified Data.HashMap.Strict as HashMap import qualified Data.HashSet as HashSet -import Data.Stream (Stream) import qualified Data.Stream as Stream import qualified Data.Text as Text import Lens.Micro.Platform @@ -17,12 +16,7 @@ import MiniJuvix.Syntax.Concrete.Language import MiniJuvix.Syntax.Concrete.Parser (runModuleParserIO) import MiniJuvix.Syntax.Concrete.Scoped.Name (NameKind (KNameConstructor)) import qualified MiniJuvix.Syntax.Concrete.Scoped.Name as S -import MiniJuvix.Utils.Prelude hiding (Reader, State, ask, asks, evalState, get, gets, local, modify, put, runReader, runState) -import Polysemy -import Polysemy.Error hiding (fromEither) -import Polysemy.NonDet -import Polysemy.Reader -import Polysemy.State +import MiniJuvix.Utils.Prelude import System.FilePath -------------------------------------------------------------------------------- @@ -348,7 +342,8 @@ checkOperatorSyntaxDef OperatorSyntaxDef {..} = do where checkNotDefined :: Sem r () checkNotDefined = - whenM (HashMap.member opSymbol <$> gets _scopeFixities) + whenM + (HashMap.member opSymbol <$> gets _scopeFixities) (throw (ErrDuplicateFixity opSymbol)) checkTypeSignature :: @@ -1022,13 +1017,13 @@ parseTerm :: forall r. Members '[Reader (Parse Expression), Embed Parse] r => Se parseTerm = do pExpr <- ask embed @Parse $ - parseUniverse - <|> parseNoInfixIdentifier - <|> parseParens pExpr - <|> parseFunction - <|> parseLambda - <|> parseMatch - <|> parseLetBlock + parseUniverse + <|> parseNoInfixIdentifier + <|> parseParens pExpr + <|> parseFunction + <|> parseLambda + <|> parseMatch + <|> parseLetBlock where parseLambda :: Parse Expression parseLambda = ExpressionLambda <$> P.token lambda mempty @@ -1116,7 +1111,7 @@ makePatternTable = do nameToPattern n@S.Name' {..} = case _nameKind of S.KNameConstructor -> PatternConstructor n S.KNameLocal - | NameUnqualified s <- _nameConcrete -> PatternVariable S.Name' {S._nameConcrete = s, ..} + | NameUnqualified s <- _nameConcrete -> PatternVariable S.Name' {S._nameConcrete = s, ..} _ -> error "impossible" getEntry :: SymbolInfo -> SymbolEntry getEntry (SymbolInfo m) = case toList m of @@ -1172,16 +1167,16 @@ makePatternTable = do parsePrePatTerm :: forall r. - Members '[Reader (ParsePat Pattern), Embed ParsePat, NonDet] r => + Members '[Reader (ParsePat Pattern), Embed ParsePat] r => Sem r Pattern parsePrePatTerm = do pPat <- ask embed @ParsePat $ - parseNoInfixConstructor - <|> parseVariable - <|> parseParens pPat - <|> parseWildcard - <|> parseEmpty + parseNoInfixConstructor + <|> parseVariable + <|> parseParens pPat + <|> parseWildcard + <|> parseEmpty where parseNoInfixConstructor :: ParsePat Pattern parseNoInfixConstructor = @@ -1249,9 +1244,9 @@ mkPatternParser table = embed @ParsePat pPattern pPattern :: ParsePat Pattern pPattern = P.makeExprParser pTerm table pTerm :: ParsePat Pattern - pTerm = runM (runNonDet parseTermRec) >>= maybe mzero pure + pTerm = runM parseTermRec where - parseTermRec :: Sem '[NonDet, Embed ParsePat] Pattern + parseTermRec :: Sem '[Embed ParsePat] Pattern parseTermRec = runReader pPattern parsePrePatTerm parsePatternSection :: diff --git a/src/MiniJuvix/Syntax/Core.hs b/src/MiniJuvix/Syntax/Core.hs index bffee321d..9af568066 100644 --- a/src/MiniJuvix/Syntax/Core.hs +++ b/src/MiniJuvix/Syntax/Core.hs @@ -6,7 +6,7 @@ module MiniJuvix.Syntax.Core where -------------------------------------------------------------------------------- -import MiniJuvix.Utils.Prelude +import MiniJuvix.Utils.Prelude hiding (Local) import Numeric.Natural (Natural) -------------------------------------------------------------------------------- diff --git a/src/MiniJuvix/Utils/Prelude.hs b/src/MiniJuvix/Utils/Prelude.hs index 9cc5a4ae7..5350d8128 100644 --- a/src/MiniJuvix/Utils/Prelude.hs +++ b/src/MiniJuvix/Utils/Prelude.hs @@ -1,35 +1,106 @@ -{- -* This Predude is =Protolude= except with a few changes - + _Additions_ - * ∨ :: Serves as an or function - * ∧ :: Serves as an and function - * |<< :: Serves as a map function - * >>| :: Serves as the flip map function - + _Changes_ - * The Capability library is imported and replaces the standard - =MTL= constructs in =Protolude= - * We don't import the Semiring typeclass from =Protolude=. --} - --- | Adapted from heliaxdev/Juvix/library/StandardLibrary/src/Juvix/Library.hs module MiniJuvix.Utils.Prelude ( module MiniJuvix.Utils.Prelude, - module Data.List.Extra, module Control.Monad.Extra, - module Relude, + module Data.Char, + module Data.Either.Extra, + module Data.Function, + module Data.List.Extra, + module Data.Maybe, + module Data.String, + module Data.Text.Encoding, + module GHC.Real, + module Data.Tuple.Extra, + module Data.Void, + module GHC.Enum, + module System.Directory, + module System.FilePath, + module Data.Singletons, + module Data.Hashable, + module GHC.Generics, + module Data.Bool, + module Data.List.NonEmpty, + module Data.Traversable, + module Data.Monoid, + module Polysemy, + module Polysemy.Reader, + module Polysemy.State, + module Polysemy.Error, + module Polysemy.Embed, + module Text.Show, + module Data.Eq, + module Data.Ord, + module Data.Semigroup, + module Data.Stream, + module GHC.Num, + module Data.Word, + module Data.Functor, + module Data.Int, + module System.IO, + module Control.Applicative, + module Data.Foldable, + Data, + Text, + pack, + unpack, + strip, + HashMap, + ByteString, + HashSet, + IsString (..), + Alternative (..), ) where -------------------------------------------------------------------------------- -import Control.Monad.Extra (maybeM) +import Control.Applicative +import Control.Monad.Extra +import Data.Bool +import Data.ByteString.Lazy (ByteString) +import Data.Char import qualified Data.Char as Char -import Data.List.Extra (groupSortOn, unsnoc) +import Data.Data +import Data.Either.Extra +import Data.Eq +import Data.Foldable +import Data.Function +import Data.Functor +import Data.HashMap.Strict (HashMap) +import Data.HashSet (HashSet) +import Data.Hashable +import Data.Int +import Data.List.Extra hiding (head, last) +import Data.List.NonEmpty (NonEmpty (..), head, last, nonEmpty) import qualified Data.List.NonEmpty as NonEmpty -import Relude hiding - ( Type, - one, - ) +import Data.Maybe +import Data.Monoid +import Data.Ord +import Data.Semigroup (Semigroup, (<>)) +import Data.Singletons +import Data.Stream (Stream) +import Data.String +import Data.Text (Text, pack, strip, unpack) +import Data.Text.Encoding +import Data.Traversable +import Data.Tuple.Extra +import Data.Void +import Data.Word +import GHC.Enum +import qualified GHC.Err as Err +import GHC.Generics (Generic) +import GHC.Num +import GHC.Real +import GHC.Stack.Types +import Polysemy +import Polysemy.Embed +import Polysemy.Error hiding (fromEither) +import Polysemy.Reader +import Polysemy.State +import System.Directory +import System.FilePath +import System.IO +import Text.Show (Show) +import qualified Text.Show as Show -------------------------------------------------------------------------------- -- Logical connectives @@ -89,6 +160,9 @@ traverseM f = fmap join . traverse f -- String related util functions. -------------------------------------------------------------------------------- +show :: (Show a, IsString str) => a -> str +show = fromString . Show.show + toUpperFirst :: String -> String toUpperFirst [] = [] toUpperFirst (x : xs) = Char.toUpper x : xs @@ -103,13 +177,6 @@ class Monoid m => Semiring m where one :: m times :: m -> m -> m --------------------------------------------------------------------------------- --- Maybe --------------------------------------------------------------------------------- - -fromMaybeM :: Monad m => m a -> m (Maybe a) -> m a -fromMaybeM n = maybeM n pure - -------------------------------------------------------------------------------- -- NonEmpty -------------------------------------------------------------------------------- @@ -118,8 +185,11 @@ nonEmptyUnsnoc :: NonEmpty a -> (Maybe (NonEmpty a), a) nonEmptyUnsnoc e = (NonEmpty.nonEmpty (NonEmpty.init e), NonEmpty.last e) -------------------------------------------------------------------------------- --- Tuple +-- Errors -------------------------------------------------------------------------------- -mapFirst :: (a -> b) -> (a, d) -> (b, d) -mapFirst f (a, b) = (f a, b) +error :: HasCallStack => Text -> a +error = Err.error . unpack + +undefined :: HasCallStack => a +undefined = Err.error "undefined" diff --git a/src/MiniJuvix/Utils/Version.hs b/src/MiniJuvix/Utils/Version.hs index a13da7f54..854c01ba5 100644 --- a/src/MiniJuvix/Utils/Version.hs +++ b/src/MiniJuvix/Utils/Version.hs @@ -2,7 +2,8 @@ module MiniJuvix.Utils.Version (getVersion) where ------------------------------------------------------------------------------ -import Control.Exception (IOException, try) +import Control.Exception (IOException) +import qualified Control.Exception as Exception import qualified Data.List as List import Data.Version (Version (versionTags)) import MiniJuvix.Utils.Prelude @@ -12,7 +13,7 @@ import System.Process (readProcessWithExitCode) ------------------------------------------------------------------------------ tryIO :: IO a -> IO (Either IOException a) -tryIO = try +tryIO = Exception.try commitInfo :: IO (Maybe String) commitInfo = do