Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77f2f900d8 | ||
|
|
ff5a5af9bc | ||
|
|
7a6518583f | ||
|
|
dda0e17358 | ||
|
|
46f0393a03 | ||
|
|
1803a1e058 | ||
|
|
ccf17faff8 | ||
|
|
14df00039f |
@@ -23,7 +23,7 @@ $ cabal test --test-show-details=direct
|
|||||||
$ rlpc -ddump-eval examples/factorial.hs
|
$ rlpc -ddump-eval examples/factorial.hs
|
||||||
# Compile and evaluate t.hs, with evaluation info dumped to t.log
|
# Compile and evaluate t.hs, with evaluation info dumped to t.log
|
||||||
$ rlpc -ddump-eval -l t.log t.hs
|
$ rlpc -ddump-eval -l t.log t.hs
|
||||||
# Print the raw structure describing the compiler options and die
|
# Print the raw structure describing the compiler options
|
||||||
# (option parsing still must succeed in order to print)
|
# (option parsing still must succeed in order to print)
|
||||||
$ rlpc -ddump-opts t.hs
|
$ rlpc -ddump-opts t.hs
|
||||||
```
|
```
|
||||||
|
|||||||
17
app/CoreDriver.hs
Normal file
17
app/CoreDriver.hs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
module CoreDriver
|
||||||
|
( driver
|
||||||
|
)
|
||||||
|
where
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
import Compiler.RLPC
|
||||||
|
import Control.Monad
|
||||||
|
|
||||||
|
import Core.Lex
|
||||||
|
import Core.Parse
|
||||||
|
import GM
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
driver :: RLPCIO ()
|
||||||
|
driver = forFiles_ $ \f ->
|
||||||
|
withSource f (lexCoreR >=> parseCoreProgR >=> evalProgR)
|
||||||
|
|
||||||
105
app/Main.hs
105
app/Main.hs
@@ -10,12 +10,16 @@ import Data.HashSet qualified as S
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Data.Text qualified as T
|
import Data.Text qualified as T
|
||||||
import Data.Text.IO qualified as TIO
|
import Data.Text.IO qualified as TIO
|
||||||
|
import Data.List
|
||||||
import System.IO
|
import System.IO
|
||||||
import System.Exit (exitSuccess)
|
import System.Exit (exitSuccess)
|
||||||
import Core
|
import Core
|
||||||
import TI
|
import TI
|
||||||
import GM
|
import GM
|
||||||
import Lens.Micro.Mtl
|
import Lens.Micro.Mtl
|
||||||
|
|
||||||
|
import CoreDriver qualified
|
||||||
|
import RlpDriver qualified
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
optParser :: ParserInfo RLPCOptions
|
optParser :: ParserInfo RLPCOptions
|
||||||
@@ -37,9 +41,15 @@ options = RLPCOptions
|
|||||||
{- -d -}
|
{- -d -}
|
||||||
<*> fmap S.fromList # many # option debugFlagReader
|
<*> fmap S.fromList # many # option debugFlagReader
|
||||||
( short 'd'
|
( short 'd'
|
||||||
<> help "dump evaluation logs"
|
<> help "pass debug flags"
|
||||||
<> metavar "DEBUG FLAG"
|
<> metavar "DEBUG FLAG"
|
||||||
)
|
)
|
||||||
|
{- -f -}
|
||||||
|
<*> fmap S.fromList # many # option compilerFlagReader
|
||||||
|
( short 'f'
|
||||||
|
<> help "pass compilation flags"
|
||||||
|
<> metavar "COMPILATION FLAG"
|
||||||
|
)
|
||||||
{- --evaluator, -e -}
|
{- --evaluator, -e -}
|
||||||
<*> option evaluatorReader
|
<*> option evaluatorReader
|
||||||
( long "evaluator"
|
( long "evaluator"
|
||||||
@@ -55,11 +65,27 @@ options = RLPCOptions
|
|||||||
\triggering the garbage collector"
|
\triggering the garbage collector"
|
||||||
<> value 50
|
<> value 50
|
||||||
)
|
)
|
||||||
|
<*> option languageReader
|
||||||
|
( long "language"
|
||||||
|
<> short 'x'
|
||||||
|
)
|
||||||
<*> some (argument str $ metavar "FILES...")
|
<*> some (argument str $ metavar "FILES...")
|
||||||
where
|
where
|
||||||
infixr 9 #
|
infixr 9 #
|
||||||
f # x = f x
|
f # x = f x
|
||||||
|
|
||||||
|
languageReader :: ReadM Language
|
||||||
|
languageReader = maybeReader $ \case
|
||||||
|
"rlp" -> Just LanguageRlp
|
||||||
|
"core" -> Just LanguageCore
|
||||||
|
_ -> Nothing
|
||||||
|
|
||||||
|
debugFlagReader :: ReadM DebugFlag
|
||||||
|
debugFlagReader = str
|
||||||
|
|
||||||
|
compilerFlagReader :: ReadM CompilerFlag
|
||||||
|
compilerFlagReader = str
|
||||||
|
|
||||||
evaluatorReader :: ReadM Evaluator
|
evaluatorReader :: ReadM Evaluator
|
||||||
evaluatorReader = maybeReader $ \case
|
evaluatorReader = maybeReader $ \case
|
||||||
"gm" -> Just EvaluatorGM
|
"gm" -> Just EvaluatorGM
|
||||||
@@ -69,82 +95,15 @@ evaluatorReader = maybeReader $ \case
|
|||||||
mmany :: (Alternative f, Monoid m) => f m -> f m
|
mmany :: (Alternative f, Monoid m) => f m -> f m
|
||||||
mmany v = liftA2 (<>) v (mmany v)
|
mmany v = liftA2 (<>) v (mmany v)
|
||||||
|
|
||||||
debugFlagReader :: ReadM DebugFlag
|
|
||||||
debugFlagReader = maybeReader $ \case
|
|
||||||
"dump-eval" -> Just DDumpEval
|
|
||||||
"dump-opts" -> Just DDumpOpts
|
|
||||||
"dump-ast" -> Just DDumpAST
|
|
||||||
_ -> Nothing
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- temp
|
|
||||||
data CompilerError = CompilerError String
|
|
||||||
deriving Show
|
|
||||||
|
|
||||||
instance Exception CompilerError
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
opts <- execParser optParser
|
opts <- execParser optParser
|
||||||
(_, es) <- evalRLPCIO opts driver
|
void $ evalRLPCIO opts driver
|
||||||
forM_ es $ \ (CompilerError e) -> print $ "warning: " <> e
|
|
||||||
pure ()
|
|
||||||
|
|
||||||
driver :: RLPCIO CompilerError ()
|
driver :: RLPCIO ()
|
||||||
driver = sequence_
|
driver = view rlpcLanguage >>= \case
|
||||||
[ dshowFlags
|
LanguageCore -> CoreDriver.driver
|
||||||
, ddumpAST
|
LanguageRlp -> RlpDriver.driver
|
||||||
, ddumpEval
|
|
||||||
]
|
|
||||||
|
|
||||||
dshowFlags :: RLPCIO CompilerError ()
|
|
||||||
dshowFlags = whenFlag flagDDumpOpts do
|
|
||||||
ask >>= liftIO . print
|
|
||||||
|
|
||||||
ddumpAST :: RLPCIO CompilerError ()
|
|
||||||
ddumpAST = whenFlag flagDDumpAST $ forFiles_ \o f -> do
|
|
||||||
liftIO $ withFile f ReadMode $ \h -> do
|
|
||||||
s <- TIO.hGetContents h
|
|
||||||
case parseProg o s of
|
|
||||||
Right (a,_) -> hPutStrLn stderr $ show a
|
|
||||||
Left e -> error "todo errors lol"
|
|
||||||
|
|
||||||
ddumpEval :: RLPCIO CompilerError ()
|
|
||||||
ddumpEval = whenFlag flagDDumpEval do
|
|
||||||
fs <- view rlpcInputFiles
|
|
||||||
forM_ fs $ \f -> liftIO (TIO.readFile f) >>= doProg
|
|
||||||
|
|
||||||
where
|
|
||||||
doProg :: Text -> RLPCIO CompilerError ()
|
|
||||||
doProg s = ask >>= \o -> case parseProg o s of
|
|
||||||
-- TODO: error handling
|
|
||||||
Left e -> addFatal . CompilerError $ show e
|
|
||||||
Right (a,_) -> do
|
|
||||||
log <- view rlpcLogFile
|
|
||||||
dumpEval <- chooseEval
|
|
||||||
case log of
|
|
||||||
Just f -> liftIO $ withFile f WriteMode $ dumpEval a
|
|
||||||
Nothing -> liftIO $ dumpEval a stderr
|
|
||||||
|
|
||||||
-- choose the appropriate model based on the compiler opts
|
|
||||||
chooseEval = do
|
|
||||||
ev <- view rlpcEvaluator
|
|
||||||
pure $ case ev of
|
|
||||||
EvaluatorGM -> v GM.hdbgProg
|
|
||||||
EvaluatorTI -> v TI.hdbgProg
|
|
||||||
where v f p h = f p h *> pure ()
|
|
||||||
|
|
||||||
parseProg :: RLPCOptions
|
|
||||||
-> Text
|
|
||||||
-> Either SrcError (Program', [SrcError])
|
|
||||||
parseProg o = evalRLPC o . (lexCore >=> parseCoreProg)
|
|
||||||
|
|
||||||
forFiles_ :: (Monad m)
|
|
||||||
=> (RLPCOptions -> FilePath -> RLPCT e m a)
|
|
||||||
-> RLPCT e m ()
|
|
||||||
forFiles_ k = do
|
|
||||||
fs <- view rlpcInputFiles
|
|
||||||
o <- ask
|
|
||||||
forM_ fs (k o)
|
|
||||||
|
|
||||||
|
|||||||
11
app/RlpDriver.hs
Normal file
11
app/RlpDriver.hs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module RlpDriver
|
||||||
|
( driver
|
||||||
|
)
|
||||||
|
where
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
import Compiler.RLPC
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
driver :: RLPCIO ()
|
||||||
|
driver = undefined
|
||||||
|
|
||||||
@@ -38,8 +38,7 @@ library
|
|||||||
, Rlp.Lex
|
, Rlp.Lex
|
||||||
, Rlp.Parse.Types
|
, Rlp.Parse.Types
|
||||||
, Compiler.Types
|
, Compiler.Types
|
||||||
|
, Data.Heap
|
||||||
other-modules: Data.Heap
|
|
||||||
, Data.Pretty
|
, Data.Pretty
|
||||||
, Core.Parse
|
, Core.Parse
|
||||||
, Core.Lex
|
, Core.Lex
|
||||||
@@ -73,6 +72,7 @@ library
|
|||||||
, semigroupoids
|
, semigroupoids
|
||||||
, comonad
|
, comonad
|
||||||
, lens
|
, lens
|
||||||
|
, text-ansi
|
||||||
|
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
default-language: GHC2021
|
default-language: GHC2021
|
||||||
@@ -85,8 +85,9 @@ library
|
|||||||
executable rlpc
|
executable rlpc
|
||||||
import: warnings
|
import: warnings
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
-- other-modules:
|
other-modules: RlpDriver
|
||||||
-- other-extensions:
|
, CoreDriver
|
||||||
|
|
||||||
build-depends: base >=4.17.0.0 && <4.20.0.0
|
build-depends: base >=4.17.0.0 && <4.20.0.0
|
||||||
, rlp
|
, rlp
|
||||||
, optparse-applicative >= 0.18.1 && < 0.19
|
, optparse-applicative >= 0.18.1 && < 0.19
|
||||||
|
|||||||
@@ -11,31 +11,32 @@ errors and the family of RLPC monads.
|
|||||||
-- only used for mtl instances
|
-- only used for mtl instances
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
{-# LANGUAGE DeriveGeneric, DerivingStrategies, DerivingVia #-}
|
{-# LANGUAGE DeriveGeneric, DerivingStrategies, DerivingVia #-}
|
||||||
|
{-# LANGUAGE BlockArguments, ViewPatterns #-}
|
||||||
module Compiler.RLPC
|
module Compiler.RLPC
|
||||||
( RLPC
|
(
|
||||||
, RLPCT(..)
|
-- * Rlpc Monad transformer
|
||||||
, RLPCIO
|
RLPCT(RLPCT),
|
||||||
, RLPCOptions(RLPCOptions)
|
-- ** Special cases
|
||||||
, IsRlpcError(..)
|
RLPC, RLPCIO
|
||||||
, RlpcError(..)
|
-- ** Running
|
||||||
, MsgEnvelope(..)
|
, runRLPCT
|
||||||
, addFatal
|
, evalRLPCT, evalRLPCIO, evalRLPC
|
||||||
, addWound
|
-- * Rlpc options
|
||||||
, MonadErrorful
|
, Language(..), Evaluator(..)
|
||||||
, Severity(..)
|
, DebugFlag(..), CompilerFlag(..)
|
||||||
, Evaluator(..)
|
-- ** Lenses
|
||||||
, evalRLPCT
|
, rlpcLogFile, rlpcDFlags, rlpcEvaluator, rlpcInputFiles, rlpcLanguage
|
||||||
, evalRLPCIO
|
-- * Misc. MTL-style functions
|
||||||
, evalRLPC
|
, liftErrorful, hoistRlpcT
|
||||||
, rlpcLogFile
|
-- * Misc. Rlpc Monad -related types
|
||||||
, rlpcDFlags
|
, RLPCOptions(RLPCOptions), IsRlpcError(..), RlpcError(..)
|
||||||
, rlpcEvaluator
|
, MsgEnvelope(..), Severity(..)
|
||||||
, rlpcInputFiles
|
, addDebugMsg
|
||||||
, DebugFlag(..)
|
, whenDFlag, whenFFlag
|
||||||
, whenDFlag
|
-- * Misc. Utilities
|
||||||
, whenFFlag
|
, forFiles_, withSource
|
||||||
, def
|
-- * Convenient re-exports
|
||||||
, liftErrorful
|
, addFatal, addWound, def
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
@@ -45,7 +46,9 @@ import Control.Monad
|
|||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Control.Monad.State (MonadState(state))
|
import Control.Monad.State (MonadState(state))
|
||||||
import Control.Monad.Errorful
|
import Control.Monad.Errorful
|
||||||
|
import Control.Monad.IO.Class
|
||||||
import Compiler.RlpcError
|
import Compiler.RlpcError
|
||||||
|
import Compiler.Types
|
||||||
import Data.Functor.Identity
|
import Data.Functor.Identity
|
||||||
import Data.Default.Class
|
import Data.Default.Class
|
||||||
import Data.Foldable
|
import Data.Foldable
|
||||||
@@ -55,19 +58,34 @@ import Data.Hashable (Hashable)
|
|||||||
import Data.HashSet (HashSet)
|
import Data.HashSet (HashSet)
|
||||||
import Data.HashSet qualified as S
|
import Data.HashSet qualified as S
|
||||||
import Data.Coerce
|
import Data.Coerce
|
||||||
|
import Data.Text (Text)
|
||||||
|
import Data.Text qualified as T
|
||||||
|
import Data.Text.IO qualified as T
|
||||||
|
import Text.ANSI qualified as Ansi
|
||||||
|
import Text.PrettyPrint hiding ((<>))
|
||||||
import Lens.Micro.Platform
|
import Lens.Micro.Platform
|
||||||
|
import Lens.Micro.Platform.Internal
|
||||||
import System.Exit
|
import System.Exit
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
newtype RLPCT m a = RLPCT {
|
newtype RLPCT m a = RLPCT {
|
||||||
runRLPCT :: ReaderT RLPCOptions (ErrorfulT (MsgEnvelope RlpcError) m) a
|
runRLPCT :: ReaderT RLPCOptions (ErrorfulT (MsgEnvelope RlpcError) m) a
|
||||||
}
|
}
|
||||||
deriving (Functor, Applicative, Monad, MonadReader RLPCOptions)
|
deriving ( Functor, Applicative, Monad
|
||||||
|
, MonadReader RLPCOptions, MonadErrorful (MsgEnvelope RlpcError))
|
||||||
|
|
||||||
|
rlpc :: (IsRlpcError e, Monad m)
|
||||||
|
=> (RLPCOptions -> (Maybe a, [MsgEnvelope e]))
|
||||||
|
-> RLPCT m a
|
||||||
|
rlpc f = RLPCT . ReaderT $ \opt ->
|
||||||
|
ErrorfulT . pure $ f opt & _2 . each . mapped %~ liftRlpcError
|
||||||
|
|
||||||
type RLPC = RLPCT Identity
|
type RLPC = RLPCT Identity
|
||||||
|
|
||||||
type RLPCIO = RLPCT IO
|
type RLPCIO = RLPCT IO
|
||||||
|
|
||||||
|
instance (MonadIO m) => MonadIO (RLPCT m) where
|
||||||
|
|
||||||
evalRLPC :: RLPCOptions
|
evalRLPC :: RLPCOptions
|
||||||
-> RLPC a
|
-> RLPC a
|
||||||
-> (Maybe a, [MsgEnvelope RlpcError])
|
-> (Maybe a, [MsgEnvelope RlpcError])
|
||||||
@@ -75,32 +93,28 @@ evalRLPC opt r = runRLPCT r
|
|||||||
& flip runReaderT opt
|
& flip runReaderT opt
|
||||||
& runErrorful
|
& runErrorful
|
||||||
|
|
||||||
evalRLPCT :: (Monad m)
|
evalRLPCT :: RLPCOptions
|
||||||
=> RLPCOptions
|
|
||||||
-> RLPCT m a
|
-> RLPCT m a
|
||||||
-> m (Maybe a, [MsgEnvelope RlpcError])
|
-> m (Maybe a, [MsgEnvelope RlpcError])
|
||||||
evalRLPCT = undefined
|
evalRLPCT opt r = runRLPCT r
|
||||||
|
& flip runReaderT opt
|
||||||
evalRLPCIO :: RLPCOptions -> RLPCIO a -> IO a
|
& runErrorfulT
|
||||||
evalRLPCIO opt r = do
|
|
||||||
(ma,es) <- evalRLPCT opt r
|
|
||||||
putRlpcErrs es
|
|
||||||
case ma of
|
|
||||||
Just x -> pure x
|
|
||||||
Nothing -> die "Failed, no code compiled."
|
|
||||||
|
|
||||||
putRlpcErrs :: [MsgEnvelope RlpcError] -> IO ()
|
|
||||||
putRlpcErrs = traverse_ print
|
|
||||||
|
|
||||||
liftErrorful :: (Monad m, IsRlpcError e) => ErrorfulT (MsgEnvelope e) m a -> RLPCT m a
|
liftErrorful :: (Monad m, IsRlpcError e) => ErrorfulT (MsgEnvelope e) m a -> RLPCT m a
|
||||||
liftErrorful e = RLPCT $ lift (fmap liftRlpcError `mapErrorful` e)
|
liftErrorful e = RLPCT $ lift (fmap liftRlpcError `mapErrorful` e)
|
||||||
|
|
||||||
|
hoistRlpcT :: (forall a. m a -> n a)
|
||||||
|
-> RLPCT m a -> RLPCT n a
|
||||||
|
hoistRlpcT f rma = RLPCT $ ReaderT $ \opt ->
|
||||||
|
ErrorfulT $ f $ evalRLPCT opt rma
|
||||||
|
|
||||||
data RLPCOptions = RLPCOptions
|
data RLPCOptions = RLPCOptions
|
||||||
{ _rlpcLogFile :: Maybe FilePath
|
{ _rlpcLogFile :: Maybe FilePath
|
||||||
, _rlpcDFlags :: HashSet DebugFlag
|
, _rlpcDFlags :: HashSet DebugFlag
|
||||||
, _rlpcFFlags :: HashSet CompilerFlag
|
, _rlpcFFlags :: HashSet CompilerFlag
|
||||||
, _rlpcEvaluator :: Evaluator
|
, _rlpcEvaluator :: Evaluator
|
||||||
, _rlpcHeapTrigger :: Int
|
, _rlpcHeapTrigger :: Int
|
||||||
|
, _rlpcLanguage :: Language
|
||||||
, _rlpcInputFiles :: [FilePath]
|
, _rlpcInputFiles :: [FilePath]
|
||||||
}
|
}
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -108,6 +122,9 @@ data RLPCOptions = RLPCOptions
|
|||||||
data Evaluator = EvaluatorGM | EvaluatorTI
|
data Evaluator = EvaluatorGM | EvaluatorTI
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
|
data Language = LanguageRlp | LanguageCore
|
||||||
|
deriving Show
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
instance Default RLPCOptions where
|
instance Default RLPCOptions where
|
||||||
@@ -118,16 +135,20 @@ instance Default RLPCOptions where
|
|||||||
, _rlpcEvaluator = EvaluatorGM
|
, _rlpcEvaluator = EvaluatorGM
|
||||||
, _rlpcHeapTrigger = 200
|
, _rlpcHeapTrigger = 200
|
||||||
, _rlpcInputFiles = []
|
, _rlpcInputFiles = []
|
||||||
|
, _rlpcLanguage = LanguageRlp
|
||||||
}
|
}
|
||||||
|
|
||||||
-- debug flags are passed with -dFLAG
|
-- debug flags are passed with -dFLAG
|
||||||
type DebugFlag = String
|
type DebugFlag = Text
|
||||||
|
|
||||||
type CompilerFlag = String
|
type CompilerFlag = Text
|
||||||
|
|
||||||
makeLenses ''RLPCOptions
|
makeLenses ''RLPCOptions
|
||||||
pure []
|
pure []
|
||||||
|
|
||||||
|
addDebugMsg :: (Monad m, IsText e) => Text -> e -> RLPCT m ()
|
||||||
|
addDebugMsg tag e = addWound . debugMsg tag $ Text [e ^. unpacked . packed]
|
||||||
|
|
||||||
-- TODO: rewrite this with prisms once microlens-pro drops :3
|
-- TODO: rewrite this with prisms once microlens-pro drops :3
|
||||||
whenDFlag :: (Monad m) => DebugFlag -> RLPCT m () -> RLPCT m ()
|
whenDFlag :: (Monad m) => DebugFlag -> RLPCT m () -> RLPCT m ()
|
||||||
whenDFlag f m = do
|
whenDFlag f m = do
|
||||||
@@ -143,3 +164,75 @@ whenFFlag f m = do
|
|||||||
let a = S.member f fs
|
let a = S.member f fs
|
||||||
when a m
|
when a m
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
evalRLPCIO :: RLPCOptions -> RLPCIO a -> IO a
|
||||||
|
evalRLPCIO opt r = do
|
||||||
|
(ma,es) <- evalRLPCT opt r
|
||||||
|
putRlpcErrs opt es
|
||||||
|
case ma of
|
||||||
|
Just x -> pure x
|
||||||
|
Nothing -> die "Failed, no code compiled."
|
||||||
|
|
||||||
|
putRlpcErrs :: RLPCOptions -> [MsgEnvelope RlpcError] -> IO ()
|
||||||
|
putRlpcErrs opts = filter byTag
|
||||||
|
>>> traverse_ (putStrLn . ('\n':) . prettyRlpcMsg)
|
||||||
|
where
|
||||||
|
dflags = opts ^. rlpcDFlags
|
||||||
|
|
||||||
|
byTag :: MsgEnvelope RlpcError -> Bool
|
||||||
|
byTag (view msgSeverity -> SevDebug t) =
|
||||||
|
t `S.member` dflags
|
||||||
|
|
||||||
|
prettyRlpcMsg :: MsgEnvelope RlpcError -> String
|
||||||
|
prettyRlpcMsg m@(view msgSeverity -> SevDebug _) = prettyRlpcDebugMsg m
|
||||||
|
prettyRlpcMsg m = render $ docRlpcErr m
|
||||||
|
|
||||||
|
prettyRlpcDebugMsg :: MsgEnvelope RlpcError -> String
|
||||||
|
prettyRlpcDebugMsg msg =
|
||||||
|
T.unpack . foldMap mkLine $ [ t' | t <- ts, t' <- T.lines t ]
|
||||||
|
where
|
||||||
|
mkLine s = "-d" <> tag <> ": " <> s <> "\n"
|
||||||
|
Text ts = msg ^. msgDiagnostic
|
||||||
|
SevDebug tag = msg ^. msgSeverity
|
||||||
|
|
||||||
|
docRlpcErr :: MsgEnvelope RlpcError -> Doc
|
||||||
|
docRlpcErr msg = header
|
||||||
|
$$ nest 2 bullets
|
||||||
|
$$ source
|
||||||
|
where
|
||||||
|
source = vcat $ zipWith (<+>) rule srclines
|
||||||
|
where
|
||||||
|
rule = repeat (ttext . Ansi.blue . Ansi.bold $ "|")
|
||||||
|
srclines = ["", "<problematic source code>", ""]
|
||||||
|
filename = msgColour "<input>"
|
||||||
|
pos = msgColour $ tshow (msg ^. msgSpan . srcspanLine)
|
||||||
|
<> ":"
|
||||||
|
<> tshow (msg ^. msgSpan . srcspanColumn)
|
||||||
|
|
||||||
|
header = ttext $ filename <> msgColour ":" <> pos <> msgColour ": "
|
||||||
|
<> errorColour "error" <> msgColour ":"
|
||||||
|
|
||||||
|
bullets = let Text ts = msg ^. msgDiagnostic
|
||||||
|
in vcat $ hang "•" 2 . ttext . msgColour <$> ts
|
||||||
|
|
||||||
|
msgColour = Ansi.white . Ansi.bold
|
||||||
|
errorColour = Ansi.red . Ansi.bold
|
||||||
|
ttext = text . T.unpack
|
||||||
|
tshow :: (Show a) => a -> Text
|
||||||
|
tshow = T.pack . show
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
forFiles_ :: (Monad m)
|
||||||
|
=> (FilePath -> RLPCT m a)
|
||||||
|
-> RLPCT m ()
|
||||||
|
forFiles_ k = do
|
||||||
|
fs <- view rlpcInputFiles
|
||||||
|
forM_ fs k
|
||||||
|
|
||||||
|
-- TODO: catch any exceptions, i.e. non-existent files should be handled by the
|
||||||
|
-- compiler
|
||||||
|
withSource :: (MonadIO m) => FilePath -> (Text -> RLPCT m a) -> RLPCT m a
|
||||||
|
withSource f k = liftIO (T.readFile f) >>= k
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ module Compiler.RlpcError
|
|||||||
, msgSeverity
|
, msgSeverity
|
||||||
, liftRlpcErrors
|
, liftRlpcErrors
|
||||||
, errorMsg
|
, errorMsg
|
||||||
|
, debugMsg
|
||||||
-- * Located Comonad
|
-- * Located Comonad
|
||||||
, Located(..)
|
, Located(..)
|
||||||
, SrcSpan(..)
|
, SrcSpan(..)
|
||||||
@@ -46,6 +47,7 @@ instance IsRlpcError RlpcError where
|
|||||||
|
|
||||||
data Severity = SevWarning
|
data Severity = SevWarning
|
||||||
| SevError
|
| SevError
|
||||||
|
| SevDebug Text
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
makeLenses ''MsgEnvelope
|
makeLenses ''MsgEnvelope
|
||||||
@@ -65,3 +67,11 @@ errorMsg s e = MsgEnvelope
|
|||||||
, _msgSeverity = SevError
|
, _msgSeverity = SevError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugMsg :: Text -> e -> MsgEnvelope e
|
||||||
|
debugMsg tag e = MsgEnvelope
|
||||||
|
-- TODO: not pretty, but it is a debug message after all
|
||||||
|
{ _msgSpan = SrcSpan 0 0 0 0
|
||||||
|
, _msgDiagnostic = e
|
||||||
|
, _msgSeverity = SevDebug tag
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
module Compiler.Types
|
module Compiler.Types
|
||||||
( SrcSpan(..)
|
( SrcSpan(..)
|
||||||
|
, srcspanLine, srcspanColumn, srcspanAbs, srcspanLen
|
||||||
, Located(..)
|
, Located(..)
|
||||||
, (<<~), (<~>)
|
, (<<~), (<~>)
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ module Compiler.Types
|
|||||||
import Control.Comonad
|
import Control.Comonad
|
||||||
import Data.Functor.Apply
|
import Data.Functor.Apply
|
||||||
import Data.Functor.Bind
|
import Data.Functor.Bind
|
||||||
|
import Control.Lens hiding ((<<~))
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Token wrapped with a span (line, column, absolute, length)
|
-- | Token wrapped with a span (line, column, absolute, length)
|
||||||
@@ -39,6 +41,16 @@ data SrcSpan = SrcSpan
|
|||||||
!Int -- ^ Length
|
!Int -- ^ Length
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
|
tupling :: Iso' SrcSpan (Int, Int, Int, Int)
|
||||||
|
tupling = iso (\ (SrcSpan a b c d) -> (a,b,c,d))
|
||||||
|
(\ (a,b,c,d) -> SrcSpan a b c d)
|
||||||
|
|
||||||
|
srcspanLine, srcspanColumn, srcspanAbs, srcspanLen :: Lens' SrcSpan Int
|
||||||
|
srcspanLine = tupling . _1
|
||||||
|
srcspanColumn = tupling . _2
|
||||||
|
srcspanAbs = tupling . _3
|
||||||
|
srcspanLen = tupling . _4
|
||||||
|
|
||||||
instance Semigroup SrcSpan where
|
instance Semigroup SrcSpan where
|
||||||
SrcSpan la ca aa sa <> SrcSpan lb cb ab sb = SrcSpan l c a s where
|
SrcSpan la ca aa sa <> SrcSpan lb cb ab sb = SrcSpan l c a s where
|
||||||
l = min la lb
|
l = min la lb
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{-# LANGUAGE StandaloneDeriving #-}
|
|
||||||
{-# LANGUAGE FunctionalDependencies #-}
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
{-# LANGUAGE TupleSections, PatternSynonyms #-}
|
{-# LANGUAGE PatternSynonyms #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
module Control.Monad.Errorful
|
module Control.Monad.Errorful
|
||||||
( ErrorfulT
|
( ErrorfulT(..)
|
||||||
, runErrorfulT
|
|
||||||
, Errorful
|
, Errorful
|
||||||
|
, pattern Errorful
|
||||||
|
, errorful
|
||||||
, runErrorful
|
, runErrorful
|
||||||
, mapErrorful
|
, mapErrorful
|
||||||
, MonadErrorful(..)
|
, MonadErrorful(..)
|
||||||
@@ -13,6 +13,7 @@ module Control.Monad.Errorful
|
|||||||
where
|
where
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
import Control.Monad.State.Strict
|
import Control.Monad.State.Strict
|
||||||
|
import Control.Monad.Reader
|
||||||
import Control.Monad.Trans
|
import Control.Monad.Trans
|
||||||
import Data.Functor.Identity
|
import Data.Functor.Identity
|
||||||
import Data.Coerce
|
import Data.Coerce
|
||||||
@@ -28,6 +29,9 @@ type Errorful e = ErrorfulT e Identity
|
|||||||
pattern Errorful :: (Maybe a, [e]) -> Errorful e a
|
pattern Errorful :: (Maybe a, [e]) -> Errorful e a
|
||||||
pattern Errorful a = ErrorfulT (Identity a)
|
pattern Errorful a = ErrorfulT (Identity a)
|
||||||
|
|
||||||
|
errorful :: (Applicative m) => (Maybe a, [e]) -> ErrorfulT e m a
|
||||||
|
errorful = ErrorfulT . pure
|
||||||
|
|
||||||
runErrorful :: Errorful e a -> (Maybe a, [e])
|
runErrorful :: Errorful e a -> (Maybe a, [e])
|
||||||
runErrorful m = coerce (runErrorfulT m)
|
runErrorful m = coerce (runErrorfulT m)
|
||||||
|
|
||||||
@@ -67,13 +71,13 @@ mapErrorful f (ErrorfulT m) = ErrorfulT $
|
|||||||
m & mapped . _2 . mapped %~ f
|
m & mapped . _2 . mapped %~ f
|
||||||
|
|
||||||
-- when microlens-pro drops we can write this as
|
-- when microlens-pro drops we can write this as
|
||||||
-- mapErrorful f = coerced . mapped . _2 . mappd %~ f
|
-- mapErrorful f = coerced . mapped . _2 . mapped %~ f
|
||||||
-- lol
|
-- lol
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- daily dose of n^2 instances
|
-- daily dose of n^2 instances
|
||||||
|
|
||||||
instance (Monad m, MonadErrorful e m) => MonadErrorful e (StateT s m) where
|
instance (Monad m, MonadErrorful e m) => MonadErrorful e (ReaderT r m) where
|
||||||
addWound = undefined
|
addWound = lift . addWound
|
||||||
addFatal = undefined
|
addFatal = lift . addFatal
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ checkCoreProg p = scDefs
|
|||||||
where scname = sc ^. _lhs._1
|
where scname = sc ^. _lhs._1
|
||||||
|
|
||||||
-- | @checkCoreProgR p@ returns @p@ if @p@ successfully typechecks.
|
-- | @checkCoreProgR p@ returns @p@ if @p@ successfully typechecks.
|
||||||
checkCoreProgR :: Program' -> RLPC Program'
|
checkCoreProgR :: (Applicative m) => Program' -> RLPCT m Program'
|
||||||
checkCoreProgR p = undefined
|
checkCoreProgR p = undefined
|
||||||
|
|
||||||
{-# WARNING checkCoreProgR "unimpl" #-}
|
{-# WARNING checkCoreProgR "unimpl" #-}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import Debug.Trace
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Data.Text qualified as T
|
import Data.Text qualified as T
|
||||||
import Data.String (IsString(..))
|
import Data.String (IsString(..))
|
||||||
|
import Data.Functor.Identity
|
||||||
import Core.Syntax
|
import Core.Syntax
|
||||||
import Compiler.RLPC
|
import Compiler.RLPC
|
||||||
-- TODO: unify Located definitions
|
-- TODO: unify Located definitions
|
||||||
@@ -180,8 +181,11 @@ lexCore s = case m of
|
|||||||
where
|
where
|
||||||
m = runAlex s lexStream
|
m = runAlex s lexStream
|
||||||
|
|
||||||
lexCoreR :: Text -> RLPC [Located CoreToken]
|
lexCoreR :: forall m. (Applicative m) => Text -> RLPCT m [Located CoreToken]
|
||||||
lexCoreR = lexCore
|
lexCoreR = hoistRlpcT generalise . lexCore
|
||||||
|
where
|
||||||
|
generalise :: forall a. Identity a -> m a
|
||||||
|
generalise (Identity a) = pure a
|
||||||
|
|
||||||
-- | @lexCore@, but the tokens are stripped of location info. Useful for
|
-- | @lexCore@, but the tokens are stripped of location info. Useful for
|
||||||
-- debugging
|
-- debugging
|
||||||
|
|||||||
@@ -17,9 +17,11 @@ module Core.Parse
|
|||||||
|
|
||||||
import Control.Monad ((>=>))
|
import Control.Monad ((>=>))
|
||||||
import Data.Foldable (foldl')
|
import Data.Foldable (foldl')
|
||||||
|
import Data.Functor.Identity
|
||||||
import Core.Syntax
|
import Core.Syntax
|
||||||
import Core.Lex
|
import Core.Lex
|
||||||
import Compiler.RLPC
|
import Compiler.RLPC
|
||||||
|
import Control.Monad
|
||||||
import Lens.Micro
|
import Lens.Micro
|
||||||
import Data.Default.Class (def)
|
import Data.Default.Class (def)
|
||||||
import Data.Hashable (Hashable)
|
import Data.Hashable (Hashable)
|
||||||
@@ -224,8 +226,16 @@ insScDef sc = programScDefs %~ (sc:)
|
|||||||
singletonScDef :: (Hashable b) => ScDef b -> Program b
|
singletonScDef :: (Hashable b) => ScDef b -> Program b
|
||||||
singletonScDef sc = insScDef sc mempty
|
singletonScDef sc = insScDef sc mempty
|
||||||
|
|
||||||
parseCoreProgR :: [Located CoreToken] -> RLPC Program'
|
parseCoreProgR :: forall m. (Monad m) => [Located CoreToken] -> RLPCT m Program'
|
||||||
parseCoreProgR = parseCoreProg
|
parseCoreProgR = ddumpast <=< (hoistRlpcT generalise . parseCoreProg)
|
||||||
|
where
|
||||||
|
generalise :: forall a. Identity a -> m a
|
||||||
|
generalise (Identity a) = pure a
|
||||||
|
|
||||||
|
ddumpast :: Program' -> RLPCT m Program'
|
||||||
|
ddumpast p = do
|
||||||
|
addDebugMsg "dump-ast" . show $ p
|
||||||
|
pure p
|
||||||
|
|
||||||
happyBind :: RLPC a -> (a -> RLPC b) -> RLPC b
|
happyBind :: RLPC a -> (a -> RLPC b) -> RLPC b
|
||||||
happyBind m k = m >>= k
|
happyBind m k = m >>= k
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ data Binding b = Binding b (Expr b)
|
|||||||
deriving instance (Eq b) => Eq (Binding b)
|
deriving instance (Eq b) => Eq (Binding b)
|
||||||
|
|
||||||
infixl 1 :=
|
infixl 1 :=
|
||||||
pattern (:=) :: b -> (Expr b) -> (Binding b)
|
pattern (:=) :: b -> Expr b -> Binding b
|
||||||
pattern k := v = Binding k v
|
pattern k := v = Binding k v
|
||||||
|
|
||||||
data Alter b = Alter AltCon [b] (Expr b)
|
data Alter b = Alter AltCon [b] (Expr b)
|
||||||
@@ -123,7 +123,7 @@ data AltCon = AltData Name
|
|||||||
| Default
|
| Default
|
||||||
deriving (Show, Read, Eq, Lift)
|
deriving (Show, Read, Eq, Lift)
|
||||||
|
|
||||||
data Lit = IntL Int
|
newtype Lit = IntL Int
|
||||||
deriving (Show, Read, Eq, Lift)
|
deriving (Show, Read, Eq, Lift)
|
||||||
|
|
||||||
type Name = T.Text
|
type Name = T.Text
|
||||||
@@ -201,7 +201,7 @@ instance HasLHS (Alter b) (Alter b) (AltCon, [b]) (AltCon, [b]) where
|
|||||||
instance HasLHS (ScDef b) (ScDef b) (b, [b]) (b, [b]) where
|
instance HasLHS (ScDef b) (ScDef b) (b, [b]) (b, [b]) where
|
||||||
_lhs = lens
|
_lhs = lens
|
||||||
(\ (ScDef n as _) -> (n,as))
|
(\ (ScDef n as _) -> (n,as))
|
||||||
(\ (ScDef _ _ e) (n',as') -> (ScDef n' as' e))
|
(\ (ScDef _ _ e) (n',as') -> ScDef n' as' e)
|
||||||
|
|
||||||
instance HasLHS (Binding b) (Binding b) b b where
|
instance HasLHS (Binding b) (Binding b) b b where
|
||||||
_lhs = lens
|
_lhs = lens
|
||||||
|
|||||||
17
src/GM.hs
17
src/GM.hs
@@ -8,6 +8,7 @@ Description : The G-Machine
|
|||||||
module GM
|
module GM
|
||||||
( hdbgProg
|
( hdbgProg
|
||||||
, evalProg
|
, evalProg
|
||||||
|
, evalProgR
|
||||||
, Node(..)
|
, Node(..)
|
||||||
, gmEvalProg
|
, gmEvalProg
|
||||||
, finalStateOf
|
, finalStateOf
|
||||||
@@ -34,6 +35,7 @@ import System.IO (Handle, hPutStrLn)
|
|||||||
import Data.String (IsString)
|
import Data.String (IsString)
|
||||||
import Data.Heap
|
import Data.Heap
|
||||||
import Debug.Trace
|
import Debug.Trace
|
||||||
|
import Compiler.RLPC
|
||||||
import Core2Core
|
import Core2Core
|
||||||
import Core
|
import Core
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
@@ -156,6 +158,21 @@ hdbgProg p hio = do
|
|||||||
[resAddr] = final ^. gmStack
|
[resAddr] = final ^. gmStack
|
||||||
res = hLookupUnsafe resAddr h
|
res = hLookupUnsafe resAddr h
|
||||||
|
|
||||||
|
evalProgR :: (Monad m) => Program' -> RLPCT m (Node, Stats)
|
||||||
|
evalProgR p = do
|
||||||
|
(renderOut . showState) `traverse_` states
|
||||||
|
renderOut . showStats $ sts
|
||||||
|
pure (res, sts)
|
||||||
|
where
|
||||||
|
renderOut r = addDebugMsg "dump-eval" $ render r ++ "\n"
|
||||||
|
states = eval . compile $ p
|
||||||
|
final = last states
|
||||||
|
|
||||||
|
sts = final ^. gmStats
|
||||||
|
-- the address of the result should be the one and only stack entry
|
||||||
|
[resAddr] = final ^. gmStack
|
||||||
|
res = hLookupUnsafe resAddr (final ^. gmHeap)
|
||||||
|
|
||||||
eval :: GmState -> [GmState]
|
eval :: GmState -> [GmState]
|
||||||
eval st = st : rest
|
eval st = st : rest
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ module Rlp.Lex
|
|||||||
, lexDebug
|
, lexDebug
|
||||||
, lexCont
|
, lexCont
|
||||||
, popLexState
|
, popLexState
|
||||||
|
, programInitState
|
||||||
|
, runP'
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
import Codec.Binary.UTF8.String (encodeChar)
|
import Codec.Binary.UTF8.String (encodeChar)
|
||||||
@@ -236,27 +238,9 @@ alexEOF = do
|
|||||||
pos <- getPos
|
pos <- getPos
|
||||||
pure (Located (spanFromPos pos 0) TokenEOF)
|
pure (Located (spanFromPos pos 0) TokenEOF)
|
||||||
|
|
||||||
initParseState :: Text -> ParseState
|
|
||||||
initParseState s = ParseState
|
|
||||||
{ _psLayoutStack = []
|
|
||||||
-- IMPORTANT: the initial state is `bol` to begin the top-level layout,
|
|
||||||
-- which then returns to state 0 which continues the normal lexing process.
|
|
||||||
, _psLexState = [layout_top,0]
|
|
||||||
, _psInput = initAlexInput s
|
|
||||||
, _psOpTable = mempty
|
|
||||||
}
|
|
||||||
|
|
||||||
initAlexInput :: Text -> AlexInput
|
|
||||||
initAlexInput s = AlexInput
|
|
||||||
{ _aiPrevChar = '\0'
|
|
||||||
, _aiSource = s
|
|
||||||
, _aiBytes = []
|
|
||||||
, _aiPos = (1,1,0)
|
|
||||||
}
|
|
||||||
|
|
||||||
runP' :: P a -> Text -> (ParseState, [MsgEnvelope RlpParseError], Maybe a)
|
runP' :: P a -> Text -> (ParseState, [MsgEnvelope RlpParseError], Maybe a)
|
||||||
runP' p s = runP p st where
|
runP' p s = runP p st where
|
||||||
st = initParseState s
|
st = initParseState [layout_top,0] s
|
||||||
|
|
||||||
lexToken :: P (Located RlpToken)
|
lexToken :: P (Located RlpToken)
|
||||||
lexToken = do
|
lexToken = do
|
||||||
@@ -310,7 +294,7 @@ popLayout = do
|
|||||||
psLayoutStack %= (drop 1)
|
psLayoutStack %= (drop 1)
|
||||||
case ctx of
|
case ctx of
|
||||||
Just l -> pure l
|
Just l -> pure l
|
||||||
Nothing -> error "uhh"
|
Nothing -> error "popLayout: layout stack empty! this is a bug."
|
||||||
|
|
||||||
pushLayout :: Layout -> P ()
|
pushLayout :: Layout -> P ()
|
||||||
pushLayout l = do
|
pushLayout l = do
|
||||||
@@ -368,10 +352,13 @@ explicitRBrace inp l = do
|
|||||||
doLayout :: LexerAction (Located RlpToken)
|
doLayout :: LexerAction (Located RlpToken)
|
||||||
doLayout _ _ = do
|
doLayout _ _ = do
|
||||||
i <- indentLevel
|
i <- indentLevel
|
||||||
traceM $ "doLayout: i: " <> show i
|
-- traceM $ "doLayout: i: " <> show i
|
||||||
pushLayout (Implicit i)
|
pushLayout (Implicit i)
|
||||||
popLexState
|
popLexState
|
||||||
insertLBrace
|
insertLBrace
|
||||||
|
|
||||||
|
programInitState :: Text -> ParseState
|
||||||
|
programInitState = initParseState [layout_top,0]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
{-# LANGUAGE LambdaCase, ViewPatterns #-}
|
{-# LANGUAGE LambdaCase, ViewPatterns #-}
|
||||||
module Rlp.Parse
|
module Rlp.Parse
|
||||||
( parseRlpProg
|
( parseRlpProg
|
||||||
|
, parseRlpProgR
|
||||||
, parseRlpExpr
|
, parseRlpExpr
|
||||||
|
, parseRlpExprR
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
import Compiler.RlpcError
|
import Compiler.RlpcError
|
||||||
|
import Compiler.RLPC
|
||||||
import Rlp.Lex
|
import Rlp.Lex
|
||||||
import Rlp.Syntax
|
import Rlp.Syntax
|
||||||
import Rlp.Parse.Types
|
import Rlp.Parse.Types
|
||||||
@@ -19,6 +22,7 @@ import Data.Functor.Bind
|
|||||||
import Control.Comonad
|
import Control.Comonad
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.Semigroup.Traversable
|
import Data.Semigroup.Traversable
|
||||||
|
import Data.Text (Text)
|
||||||
import Data.Text qualified as T
|
import Data.Text qualified as T
|
||||||
import Data.Void
|
import Data.Void
|
||||||
}
|
}
|
||||||
@@ -29,6 +33,7 @@ import Data.Void
|
|||||||
%monad { P }
|
%monad { P }
|
||||||
%lexer { lexCont } { Located _ TokenEOF }
|
%lexer { lexCont } { Located _ TokenEOF }
|
||||||
%error { parseError }
|
%error { parseError }
|
||||||
|
%errorhandlertype explist
|
||||||
%tokentype { Located RlpToken }
|
%tokentype { Located RlpToken }
|
||||||
|
|
||||||
%token
|
%token
|
||||||
@@ -85,6 +90,7 @@ DeclsV :: { [Decl' RlpcPs] }
|
|||||||
DeclsV : Decl VS Decls { $1 : $3 }
|
DeclsV : Decl VS Decls { $1 : $3 }
|
||||||
| Decl VS { [$1] }
|
| Decl VS { [$1] }
|
||||||
| Decl { [$1] }
|
| Decl { [$1] }
|
||||||
|
| {- epsilon -} { [] }
|
||||||
|
|
||||||
VS :: { Located RlpToken }
|
VS :: { Located RlpToken }
|
||||||
VS : ';' { $1 }
|
VS : ';' { $1 }
|
||||||
@@ -187,6 +193,13 @@ Con :: { Located PsName }
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
parseRlpExprR = undefined
|
||||||
|
|
||||||
|
parseRlpProgR :: (Monad m) => Text -> RLPCT m (RlpProgram RlpcPs)
|
||||||
|
parseRlpProgR s = liftErrorful $ pToErrorful parseRlpProg st
|
||||||
|
where
|
||||||
|
st = programInitState s
|
||||||
|
|
||||||
mkPsName :: Located RlpToken -> Located PsName
|
mkPsName :: Located RlpToken -> Located PsName
|
||||||
mkPsName = fmap extractName
|
mkPsName = fmap extractName
|
||||||
|
|
||||||
@@ -207,9 +220,9 @@ mkProgram ds = do
|
|||||||
pt <- use psOpTable
|
pt <- use psOpTable
|
||||||
pure $ RlpProgram (associate pt <$> ds)
|
pure $ RlpProgram (associate pt <$> ds)
|
||||||
|
|
||||||
parseError :: Located RlpToken -> P a
|
parseError :: (Located RlpToken, [String]) -> P a
|
||||||
parseError (Located ss t) = addFatal $
|
parseError ((Located ss t), exp) = addFatal $
|
||||||
errorMsg ss RlpParErrUnexpectedToken
|
errorMsg ss (RlpParErrUnexpectedToken t exp)
|
||||||
|
|
||||||
mkInfixD :: Assoc -> Int -> PsName -> P (Decl' RlpcPs)
|
mkInfixD :: Assoc -> Int -> PsName -> P (Decl' RlpcPs)
|
||||||
mkInfixD a p n = do
|
mkInfixD a p n = do
|
||||||
@@ -228,3 +241,4 @@ intOfToken :: Located RlpToken -> Int
|
|||||||
intOfToken (Located _ (TokenLitInt n)) = n
|
intOfToken (Located _ (TokenLitInt n)) = n
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ module Rlp.Parse.Types
|
|||||||
|
|
||||||
-- * Parser monad and state
|
-- * Parser monad and state
|
||||||
, P(..), ParseState(..), Layout(..), OpTable, OpInfo
|
, P(..), ParseState(..), Layout(..), OpTable, OpInfo
|
||||||
|
, initParseState, initAlexInput
|
||||||
|
, pToErrorful
|
||||||
-- ** Lenses
|
-- ** Lenses
|
||||||
, psLayoutStack, psLexState, psInput, psOpTable
|
, psLayoutStack, psLexState, psInput, psOpTable
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ import Data.Functor.Classes
|
|||||||
import Data.HashMap.Strict qualified as H
|
import Data.HashMap.Strict qualified as H
|
||||||
import Data.Void
|
import Data.Void
|
||||||
import Data.Word (Word8)
|
import Data.Word (Word8)
|
||||||
|
import Data.Text qualified as T
|
||||||
import Lens.Micro.TH
|
import Lens.Micro.TH
|
||||||
import Lens.Micro
|
import Lens.Micro
|
||||||
import Rlp.Syntax
|
import Rlp.Syntax
|
||||||
@@ -145,6 +148,11 @@ newtype P a = P {
|
|||||||
}
|
}
|
||||||
deriving (Functor)
|
deriving (Functor)
|
||||||
|
|
||||||
|
pToErrorful :: (Applicative m)
|
||||||
|
=> P a -> ParseState -> ErrorfulT (MsgEnvelope RlpParseError) m a
|
||||||
|
pToErrorful p st = ErrorfulT $ pure (ma,es) where
|
||||||
|
(_,es,ma) = runP p st
|
||||||
|
|
||||||
instance Applicative P where
|
instance Applicative P where
|
||||||
pure a = P $ \st -> (st, [], pure a)
|
pure a = P $ \st -> (st, [], pure a)
|
||||||
liftA2 = liftM2
|
liftA2 = liftM2
|
||||||
@@ -188,10 +196,28 @@ type OpInfo = (Assoc, Int)
|
|||||||
data RlpParseError = RlpParErrOutOfBoundsPrecedence Int
|
data RlpParseError = RlpParErrOutOfBoundsPrecedence Int
|
||||||
| RlpParErrDuplicateInfixD Name
|
| RlpParErrDuplicateInfixD Name
|
||||||
| RlpParErrLexical
|
| RlpParErrLexical
|
||||||
| RlpParErrUnexpectedToken
|
| RlpParErrUnexpectedToken RlpToken [String]
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Show)
|
||||||
|
|
||||||
instance IsRlpcError RlpParseError where
|
instance IsRlpcError RlpParseError where
|
||||||
|
liftRlpcError = \case
|
||||||
|
RlpParErrOutOfBoundsPrecedence n ->
|
||||||
|
Text [ "Illegal precedence in infixity declaration"
|
||||||
|
, "rl' currently only allows precedences between 0 and 9."
|
||||||
|
]
|
||||||
|
RlpParErrDuplicateInfixD s ->
|
||||||
|
Text [ "Conflicting infixity declarations for operator "
|
||||||
|
<> tshow s
|
||||||
|
]
|
||||||
|
RlpParErrLexical ->
|
||||||
|
Text [ "Unknown lexical error :(" ]
|
||||||
|
RlpParErrUnexpectedToken t exp ->
|
||||||
|
Text [ "Unexpected token " <> tshow t
|
||||||
|
, "Expected: " <> tshow exp
|
||||||
|
]
|
||||||
|
where
|
||||||
|
tshow :: (Show a) => a -> T.Text
|
||||||
|
tshow = T.pack . show
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -224,3 +250,21 @@ addFatalHere l e = P $ \st ->
|
|||||||
}
|
}
|
||||||
in (st, [e'], Nothing)
|
in (st, [e'], Nothing)
|
||||||
|
|
||||||
|
initParseState :: [Int] -> Text -> ParseState
|
||||||
|
initParseState ls s = ParseState
|
||||||
|
{ _psLayoutStack = []
|
||||||
|
-- IMPORTANT: the initial state is `bol` to begin the top-level layout,
|
||||||
|
-- which then returns to state 0 which continues the normal lexing process.
|
||||||
|
, _psLexState = ls
|
||||||
|
, _psInput = initAlexInput s
|
||||||
|
, _psOpTable = mempty
|
||||||
|
}
|
||||||
|
|
||||||
|
initAlexInput :: Text -> AlexInput
|
||||||
|
initAlexInput s = AlexInput
|
||||||
|
{ _aiPrevChar = '\0'
|
||||||
|
, _aiSource = s
|
||||||
|
, _aiBytes = []
|
||||||
|
, _aiPos = (1,1,0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user