8 Commits

Author SHA1 Message Date
crumbtoo
77f2f900d8 core driver 2024-02-01 15:24:16 -07:00
crumbtoo
ff5a5af9bc -ddump-eval 2024-02-01 12:14:43 -07:00
crumbtoo
7a6518583f debug tags 2024-02-01 11:57:37 -07:00
crumbtoo
dda0e17358 -ddump-ast 2024-02-01 11:37:52 -07:00
crumbtoo
46f0393a03 *R functions 2024-02-01 10:37:51 -07:00
crumbtoo
1803a1e058 formatting 2024-02-01 09:05:58 -07:00
crumbtoo
ccf17faff8 driver progress 2024-01-30 16:19:03 -07:00
crumbtoo
14df00039f error messages 2024-01-30 15:56:45 -07:00
17 changed files with 344 additions and 161 deletions

View File

@@ -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
View 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)

View File

@@ -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
View File

@@ -0,0 +1,11 @@
module RlpDriver
( driver
)
where
--------------------------------------------------------------------------------
import Compiler.RLPC
--------------------------------------------------------------------------------
driver :: RLPCIO ()
driver = undefined

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -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" #-}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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]
} }

View File

@@ -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
} }

View File

@@ -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)
}