Compare commits
39 Commits
happy-fron
...
frontend-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce11dfdd7 | ||
|
|
3d45e12676 | ||
|
|
22b5b47795 | ||
|
|
cefdf6ffae | ||
|
|
e3b18c8915 | ||
|
|
692d22afb9 | ||
|
|
c146e1c450 | ||
|
|
5a659d22dd | ||
|
|
1a881399ab | ||
|
|
257d02da87 | ||
|
|
f47f325e34 | ||
|
|
f22d4238f5 | ||
|
|
4e1c9dd750 | ||
|
|
d6ac991105 | ||
|
|
d5663c1aad | ||
|
|
7e6bee3d4a | ||
|
|
5ec625e0fd | ||
|
|
9196e20e08 | ||
|
|
cb9ec43c14 | ||
|
|
8ad967fac0 | ||
|
|
55dbc9de70 | ||
|
|
05226373ee | ||
|
|
981c5d8a83 | ||
|
|
86cd1075ca | ||
|
|
1d43c1d304 | ||
|
|
4b44f57066 | ||
|
|
90a9594e8f | ||
|
|
074350768c | ||
|
|
37d9e6f219 | ||
|
|
cb7cdf7ed7 | ||
|
|
2f783d96e8 | ||
|
|
a71c099fe0 | ||
|
|
d1e64eb12d | ||
|
|
f31726b43d | ||
|
|
8aa9bb843f | ||
|
|
9a357a99b7 | ||
|
|
060d48f9e1 | ||
|
|
bf4abeb8b4 | ||
|
|
7ed565fc24 |
@@ -8,8 +8,8 @@ CABAL_BUILD = dist-newstyle/build/x86_64-osx/ghc-9.6.2/rlp-0.1.0.0/build
|
||||
|
||||
all: parsers lexers
|
||||
|
||||
parsers: $(CABAL_BUILD)/Rlp/Parse.hs
|
||||
lexers: $(CABAL_BUILD)/Rlp/Lex.hs
|
||||
parsers: $(CABAL_BUILD)/Rlp/Parse.hs $(CABAL_BUILD)/Core/Parse.hs
|
||||
lexers: $(CABAL_BUILD)/Rlp/Lex.hs $(CABAL_BUILD)/Core/Lex.hs
|
||||
|
||||
$(CABAL_BUILD)/Rlp/Parse.hs: $(SRC)/Rlp/Parse.y
|
||||
$(HAPPY) $(HAPPY_OPTS) $< -o $@
|
||||
@@ -17,3 +17,9 @@ $(CABAL_BUILD)/Rlp/Parse.hs: $(SRC)/Rlp/Parse.y
|
||||
$(CABAL_BUILD)/Rlp/Lex.hs: $(SRC)/Rlp/Lex.x
|
||||
$(ALEX) $(ALEX_OPTS) $< -o $@
|
||||
|
||||
$(CABAL_BUILD)/Core/Parse.hs: $(SRC)/Core/Parse.y
|
||||
$(HAPPY) $(HAPPY_OPTS) $< -o $@
|
||||
|
||||
$(CABAL_BUILD)/Core/Lex.hs: $(SRC)/Core/Lex.x
|
||||
$(ALEX) $(ALEX_OPTS) $< -o $@
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ category: Language
|
||||
build-type: Simple
|
||||
extra-doc-files: README.md
|
||||
-- extra-source-files:
|
||||
tested-with: GHC==9.6.2
|
||||
|
||||
common warnings
|
||||
-- ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-unused-top-binds
|
||||
@@ -72,6 +73,9 @@ library
|
||||
hs-source-dirs: src
|
||||
default-language: GHC2021
|
||||
|
||||
default-extensions:
|
||||
OverloadedStrings
|
||||
|
||||
executable rlpc
|
||||
import: warnings
|
||||
main-is: Main.hs
|
||||
|
||||
BIN
src/.DS_Store
vendored
BIN
src/.DS_Store
vendored
Binary file not shown.
@@ -26,21 +26,23 @@ import Data.Function ((&))
|
||||
import GM
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
justLexSrc :: String -> Either RlpcError [CoreToken]
|
||||
justLexSrc :: String -> Either [MsgEnvelope RlpcError] [CoreToken]
|
||||
justLexSrc s = lexCoreR (T.pack s)
|
||||
& fmap (map $ \ (Located _ _ _ t) -> t)
|
||||
& rlpcToEither
|
||||
|
||||
justParseSrc :: String -> Either RlpcError Program'
|
||||
justParseSrc :: String -> Either [MsgEnvelope RlpcError] Program'
|
||||
justParseSrc s = parse (T.pack s)
|
||||
& rlpcToEither
|
||||
where parse = lexCoreR >=> parseCoreProgR
|
||||
|
||||
justTypeCheckSrc :: String -> Either RlpcError Program'
|
||||
justTypeCheckSrc :: String -> Either [MsgEnvelope RlpcError] Program'
|
||||
justTypeCheckSrc s = typechk (T.pack s)
|
||||
& rlpcToEither
|
||||
where typechk = lexCoreR >=> parseCoreProgR >=> checkCoreProgR
|
||||
|
||||
rlpcToEither :: RLPC e a -> Either e a
|
||||
rlpcToEither = evalRLPC def >>> fmap fst
|
||||
rlpcToEither :: RLPC a -> Either [MsgEnvelope RlpcError] a
|
||||
rlpcToEither r = case evalRLPC def r of
|
||||
(Just a, _) -> Right a
|
||||
(Nothing, es) -> Left es
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ module Compiler.RLPC
|
||||
, RLPCT(..)
|
||||
, RLPCIO
|
||||
, RLPCOptions(RLPCOptions)
|
||||
, RlpcError(..)
|
||||
, IsRlpcError(..)
|
||||
, rlpc
|
||||
, RlpcError(..)
|
||||
, MsgEnvelope(..)
|
||||
, addFatal
|
||||
, addWound
|
||||
, MonadErrorful
|
||||
@@ -27,9 +27,6 @@ module Compiler.RLPC
|
||||
, evalRLPCT
|
||||
, evalRLPCIO
|
||||
, evalRLPC
|
||||
, addRlpcWound
|
||||
, addRlpcFatal
|
||||
, liftRlpcErrs
|
||||
, rlpcLogFile
|
||||
, rlpcDebugOpts
|
||||
, rlpcEvaluator
|
||||
@@ -40,6 +37,7 @@ module Compiler.RLPC
|
||||
, flagDDumpOpts
|
||||
, flagDDumpAST
|
||||
, def
|
||||
, liftErrorful
|
||||
)
|
||||
where
|
||||
----------------------------------------------------------------------------------
|
||||
@@ -51,6 +49,7 @@ import Control.Monad.Errorful
|
||||
import Compiler.RlpcError
|
||||
import Data.Functor.Identity
|
||||
import Data.Default.Class
|
||||
import Data.Foldable
|
||||
import GHC.Generics (Generic)
|
||||
import Data.Hashable (Hashable)
|
||||
import Data.HashSet (HashSet)
|
||||
@@ -58,48 +57,44 @@ import Data.HashSet qualified as S
|
||||
import Data.Coerce
|
||||
import Lens.Micro
|
||||
import Lens.Micro.TH
|
||||
import System.Exit
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: fancy errors
|
||||
newtype RLPCT e m a = RLPCT {
|
||||
runRLPCT :: ReaderT RLPCOptions (ErrorfulT e m) a
|
||||
newtype RLPCT m a = RLPCT {
|
||||
runRLPCT :: ReaderT RLPCOptions (ErrorfulT (MsgEnvelope RlpcError) m) a
|
||||
}
|
||||
-- TODO: incorrect ussage of MonadReader. RLPC should have its own
|
||||
-- environment access functions
|
||||
deriving (Functor, Applicative, Monad, MonadReader RLPCOptions)
|
||||
deriving (Functor, Applicative, Monad)
|
||||
|
||||
deriving instance (MonadIO m) => MonadIO (RLPCT e m)
|
||||
type RLPC = RLPCT Identity
|
||||
|
||||
instance MonadTrans (RLPCT e) where
|
||||
lift = RLPCT . lift . lift
|
||||
|
||||
instance (MonadState s m) => MonadState s (RLPCT e m) where
|
||||
state = lift . state
|
||||
|
||||
type RLPC e = RLPCT e Identity
|
||||
|
||||
type RLPCIO e = RLPCT e IO
|
||||
|
||||
evalRLPCT :: RLPCOptions
|
||||
-> RLPCT e m a
|
||||
-> m (Either e (a, [e]))
|
||||
evalRLPCT o = runRLPCT >>> flip runReaderT o >>> runErrorfulT
|
||||
type RLPCIO = RLPCT IO
|
||||
|
||||
evalRLPC :: RLPCOptions
|
||||
-> RLPC e a
|
||||
-> Either e (a, [e])
|
||||
evalRLPC o m = coerce $ evalRLPCT o m
|
||||
-> RLPC a
|
||||
-> (Maybe a, [MsgEnvelope RlpcError])
|
||||
evalRLPC opt r = runRLPCT r
|
||||
& flip runReaderT opt
|
||||
& runErrorful
|
||||
|
||||
evalRLPCIO :: (Exception e)
|
||||
=> RLPCOptions
|
||||
-> RLPCIO e a
|
||||
-> IO (a, [e])
|
||||
evalRLPCIO o m = do
|
||||
m' <- evalRLPCT o m
|
||||
case m' of
|
||||
-- TODO: errors
|
||||
Left e -> throwIO e
|
||||
Right a -> pure a
|
||||
evalRLPCT :: (Monad m)
|
||||
=> RLPCOptions
|
||||
-> RLPCT m a
|
||||
-> m (Maybe a, [MsgEnvelope RlpcError])
|
||||
evalRLPCT = undefined
|
||||
|
||||
evalRLPCIO :: RLPCOptions -> RLPCIO a -> IO a
|
||||
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 e = RLPCT $ lift (fmap liftRlpcError `mapErrorful` e)
|
||||
|
||||
data RLPCOptions = RLPCOptions
|
||||
{ _rlpcLogFile :: Maybe FilePath
|
||||
@@ -113,32 +108,6 @@ data RLPCOptions = RLPCOptions
|
||||
data Evaluator = EvaluatorGM | EvaluatorTI
|
||||
deriving Show
|
||||
|
||||
data Severity = Error
|
||||
| Warning
|
||||
| Debug
|
||||
deriving Show
|
||||
|
||||
-- temporary until we have a new doc building system
|
||||
type ErrorDoc = String
|
||||
|
||||
instance (Monad m) => MonadErrorful e (RLPCT e m) where
|
||||
addWound = RLPCT . lift . addWound
|
||||
addFatal = RLPCT . lift . addFatal
|
||||
|
||||
liftRlpcErrs :: (IsRlpcError e, Monad m)
|
||||
=> RLPCT e m a -> RLPCT RlpcError m a
|
||||
liftRlpcErrs m = RLPCT . ReaderT $ \r ->
|
||||
mapErrors liftRlpcErr $ runRLPCT >>> (`runReaderT` r) $ m
|
||||
|
||||
addRlpcWound :: (IsRlpcError e, Monad m) => e -> RLPCT RlpcError m ()
|
||||
addRlpcWound = addWound . liftRlpcErr
|
||||
|
||||
addRlpcFatal :: (IsRlpcError e, Monad m) => e -> RLPCT RlpcError m ()
|
||||
addRlpcFatal = addWound . liftRlpcErr
|
||||
|
||||
rlpc :: (Monad m) => ErrorfulT e m a -> RLPCT e m a
|
||||
rlpc = RLPCT . ReaderT . const
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
instance Default RLPCOptions where
|
||||
|
||||
@@ -1,15 +1,70 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
|
||||
module Compiler.RlpcError
|
||||
( RlpcError(..)
|
||||
, IsRlpcError(..)
|
||||
( IsRlpcError(..)
|
||||
, MsgEnvelope(..)
|
||||
, Severity(..)
|
||||
, RlpcError(..)
|
||||
, SrcSpan(..)
|
||||
, msgSpan
|
||||
, msgDiagnostic
|
||||
, msgSeverity
|
||||
, liftRlpcErrors
|
||||
, errorMsg
|
||||
)
|
||||
where
|
||||
----------------------------------------------------------------------------------
|
||||
import Control.Monad.Errorful
|
||||
import Data.Text (Text)
|
||||
import Data.Text qualified as T
|
||||
import GHC.Exts (IsString(..))
|
||||
import Lens.Micro.Platform
|
||||
import Lens.Micro.Platform.Internal
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
data RlpcError = RlpcErr String -- temp
|
||||
data MsgEnvelope e = MsgEnvelope
|
||||
{ _msgSpan :: SrcSpan
|
||||
, _msgDiagnostic :: e
|
||||
, _msgSeverity :: Severity
|
||||
}
|
||||
deriving (Functor, Show)
|
||||
|
||||
newtype RlpcError = Text [Text]
|
||||
deriving Show
|
||||
|
||||
class IsRlpcError a where
|
||||
liftRlpcErr :: a -> RlpcError
|
||||
instance IsString RlpcError where
|
||||
fromString = Text . pure . T.pack
|
||||
|
||||
class IsRlpcError e where
|
||||
liftRlpcError :: e -> RlpcError
|
||||
|
||||
instance IsRlpcError RlpcError where
|
||||
liftRlpcError = id
|
||||
|
||||
data Severity = SevWarning
|
||||
| SevError
|
||||
deriving Show
|
||||
|
||||
data SrcSpan = SrcSpan
|
||||
!Int -- ^ Line
|
||||
!Int -- ^ Column
|
||||
!Int -- ^ Length
|
||||
deriving Show
|
||||
|
||||
makeLenses ''MsgEnvelope
|
||||
|
||||
liftRlpcErrors :: (Functor m, IsRlpcError e)
|
||||
=> ErrorfulT e m a
|
||||
-> ErrorfulT RlpcError m a
|
||||
liftRlpcErrors = mapErrorful liftRlpcError
|
||||
|
||||
instance (IsRlpcError e) => IsRlpcError (MsgEnvelope e) where
|
||||
liftRlpcError msg = msg ^. msgDiagnostic & liftRlpcError
|
||||
|
||||
errorMsg :: SrcSpan -> e -> MsgEnvelope e
|
||||
errorMsg s e = MsgEnvelope
|
||||
{ _msgSpan = s
|
||||
, _msgDiagnostic = e
|
||||
, _msgSeverity = SevError
|
||||
}
|
||||
|
||||
|
||||
@@ -1,73 +1,79 @@
|
||||
{-# LANGUAGE StandaloneDeriving #-}
|
||||
{-# LANGUAGE FunctionalDependencies #-}
|
||||
{-# LANGUAGE TupleSections, PatternSynonyms #-}
|
||||
{-# LANGUAGE UndecidableInstances #-}
|
||||
module Control.Monad.Errorful
|
||||
( ErrorfulT
|
||||
, runErrorfulT
|
||||
, Errorful
|
||||
, runErrorful
|
||||
, mapErrors
|
||||
, mapErrorful
|
||||
, MonadErrorful(..)
|
||||
)
|
||||
where
|
||||
----------------------------------------------------------------------------------
|
||||
import Control.Monad.State.Strict
|
||||
import Control.Monad.Trans
|
||||
import Data.Functor.Identity
|
||||
import Data.Coerce
|
||||
import Data.HashSet (HashSet)
|
||||
import Data.HashSet qualified as H
|
||||
import Lens.Micro
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
newtype ErrorfulT e m a = ErrorfulT { runErrorfulT :: m (Either e (a, [e])) }
|
||||
newtype ErrorfulT e m a = ErrorfulT { runErrorfulT :: m (Maybe a, [e]) }
|
||||
|
||||
type Errorful e = ErrorfulT e Identity
|
||||
|
||||
pattern Errorful :: (Either e (a, [e])) -> Errorful e a
|
||||
pattern Errorful :: (Maybe a, [e]) -> Errorful e a
|
||||
pattern Errorful a = ErrorfulT (Identity a)
|
||||
|
||||
runErrorful :: Errorful e a -> Either e (a, [e])
|
||||
runErrorful :: Errorful e a -> (Maybe a, [e])
|
||||
runErrorful m = coerce (runErrorfulT m)
|
||||
|
||||
class (Applicative m) => MonadErrorful e m | m -> e where
|
||||
addWound :: e -> m ()
|
||||
addFatal :: e -> m a
|
||||
|
||||
-- not sure if i want to add this yet...
|
||||
-- catchWound :: m a -> (e -> m a) -> m a
|
||||
addWound :: e -> m ()
|
||||
addFatal :: e -> m a
|
||||
|
||||
instance (Applicative m) => MonadErrorful e (ErrorfulT e m) where
|
||||
addWound e = ErrorfulT $ pure . Right $ ((), [e])
|
||||
addFatal e = ErrorfulT $ pure . Left $ e
|
||||
addWound e = ErrorfulT $ pure (Just (), [e])
|
||||
addFatal e = ErrorfulT $ pure (Nothing, [e])
|
||||
|
||||
instance MonadTrans (ErrorfulT e) where
|
||||
lift m = ErrorfulT (Right . (,[]) <$> m)
|
||||
lift m = ErrorfulT ((\x -> (Just x,[])) <$> m)
|
||||
|
||||
instance (MonadIO m) => MonadIO (ErrorfulT e m) where
|
||||
liftIO = lift . liftIO
|
||||
|
||||
instance (Functor m) => Functor (ErrorfulT e m) where
|
||||
fmap f (ErrorfulT m) = ErrorfulT $ fmap (_1 %~ f) <$> m
|
||||
fmap f (ErrorfulT m) = ErrorfulT (m & mapped . _1 . _Just %~ f)
|
||||
|
||||
instance (Applicative m) => Applicative (ErrorfulT e m) where
|
||||
pure a = ErrorfulT (pure . Right $ (a, []))
|
||||
pure a = ErrorfulT . pure $ (Just a, [])
|
||||
|
||||
m <*> a = ErrorfulT (m' `apply` a')
|
||||
where
|
||||
m' = runErrorfulT m
|
||||
a' = runErrorfulT a
|
||||
-- TODO: strict concatenation
|
||||
apply = liftA2 $ liftA2 (\ (f,e1) (x,e2) -> (f x, e1 ++ e2))
|
||||
ErrorfulT m <*> ErrorfulT n = ErrorfulT $ m `apply` n where
|
||||
apply :: m (Maybe (a -> b), [e]) -> m (Maybe a, [e]) -> m (Maybe b, [e])
|
||||
apply = liftA2 $ \ (mf,e1) (ma,e2) -> (mf <*> ma, e1 <> e2)
|
||||
|
||||
instance (Monad m) => Monad (ErrorfulT e m) where
|
||||
ErrorfulT m >>= k = ErrorfulT $ do
|
||||
m' <- m
|
||||
case m' of
|
||||
Right (a,es) -> runErrorfulT (k a)
|
||||
Left e -> pure (Left e)
|
||||
(a,es) <- m
|
||||
case a of
|
||||
Just x -> runErrorfulT (k x)
|
||||
Nothing -> pure (Nothing, es)
|
||||
|
||||
mapErrors :: (Monad m) => (e -> e') -> ErrorfulT e m a -> ErrorfulT e' m a
|
||||
mapErrors f m = ErrorfulT $ do
|
||||
x <- runErrorfulT m
|
||||
case x of
|
||||
Left e -> pure . Left $ f e
|
||||
Right (a,es) -> pure . Right $ (a, f <$> es)
|
||||
mapErrorful :: (Functor m) => (e -> e') -> ErrorfulT e m a -> ErrorfulT e' m a
|
||||
mapErrorful f (ErrorfulT m) = ErrorfulT $
|
||||
m & mapped . _2 . mapped %~ f
|
||||
|
||||
-- when microlens-pro drops we can write this as
|
||||
-- mapErrorful f = coerced . mapped . _2 . mappd %~ f
|
||||
-- lol
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- daily dose of n^2 instances
|
||||
|
||||
instance (Monad m, MonadErrorful e m) => MonadErrorful e (StateT s m) where
|
||||
addWound = undefined
|
||||
addFatal = undefined
|
||||
|
||||
|
||||
@@ -15,6 +15,13 @@ import Core.Syntax
|
||||
import Core.TH
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
-- fac3 = undefined
|
||||
-- sumList = undefined
|
||||
-- constDivZero = undefined
|
||||
-- idCase = undefined
|
||||
|
||||
---
|
||||
|
||||
letrecExample :: Program'
|
||||
letrecExample = [coreProg|
|
||||
pair x y f = f x y;
|
||||
@@ -216,3 +223,4 @@ idCase = [coreProg|
|
||||
-- , ScDef "Cons" [] $ Con 2 2
|
||||
-- ]
|
||||
|
||||
--}
|
||||
|
||||
@@ -3,6 +3,7 @@ Module : Core.HindleyMilner
|
||||
Description : Hindley-Milner type system
|
||||
-}
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
module Core.HindleyMilner
|
||||
( Context'
|
||||
, infer
|
||||
@@ -16,15 +17,17 @@ module Core.HindleyMilner
|
||||
----------------------------------------------------------------------------------
|
||||
import Lens.Micro
|
||||
import Lens.Micro.Mtl
|
||||
import Lens.Micro.Platform
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Text qualified as T
|
||||
import Data.HashMap.Strict qualified as H
|
||||
import Data.Foldable (traverse_)
|
||||
import Compiler.RLPC
|
||||
import Control.Monad (foldM, void)
|
||||
import Control.Monad (foldM, void, forM)
|
||||
import Control.Monad.Errorful (Errorful, addFatal)
|
||||
import Control.Monad.State
|
||||
import Control.Monad.Utils (mapAccumLM)
|
||||
import Text.Printf
|
||||
import Core.Syntax
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
@@ -48,9 +51,20 @@ data TypeError
|
||||
| TyErrMissingTypeSig Name
|
||||
deriving (Show, Eq)
|
||||
|
||||
-- TODO:
|
||||
instance IsRlpcError TypeError where
|
||||
liftRlpcErr = RlpcErr . show
|
||||
liftRlpcError = \case
|
||||
-- todo: use anti-parser instead of show
|
||||
TyErrCouldNotUnify t u -> Text
|
||||
[ T.pack $ printf "Could not match type `%s' with `%s'."
|
||||
(show t) (show u)
|
||||
, "Expected: " <> tshow t
|
||||
, "Got: " <> tshow u
|
||||
]
|
||||
TyErrRecursiveType t x -> Text
|
||||
[ T.pack $ printf "recursive type error lol"
|
||||
]
|
||||
|
||||
where tshow = T.pack . show
|
||||
|
||||
-- | Synonym for @Errorful [TypeError]@. This means an @HMError@ action may
|
||||
-- throw any number of fatal or nonfatal errors. Run with @runErrorful@.
|
||||
@@ -88,10 +102,10 @@ checkCoreProg p = scDefs
|
||||
where scname = sc ^. _lhs._1
|
||||
|
||||
-- | @checkCoreProgR p@ returns @p@ if @p@ successfully typechecks.
|
||||
checkCoreProgR :: Program' -> RLPC RlpcError Program'
|
||||
checkCoreProgR p = do
|
||||
liftRlpcErrs . rlpc . checkCoreProg $ p
|
||||
pure p
|
||||
checkCoreProgR :: Program' -> RLPC Program'
|
||||
checkCoreProgR p = undefined
|
||||
|
||||
{-# WARNING checkCoreProgR "unimpl" #-}
|
||||
|
||||
-- | Infer the type of an expression under some context.
|
||||
--
|
||||
@@ -140,7 +154,27 @@ gather = \g e -> runStateT (go g e) ([],0) <&> \ (t,(cs,_)) -> (t,cs) where
|
||||
Let NonRec bs e -> do
|
||||
g' <- buildLetContext g bs
|
||||
go g' e
|
||||
-- TODO letrec, lambda, case
|
||||
Let Rec bs e -> do
|
||||
g' <- buildLetrecContext g bs
|
||||
go g' e
|
||||
|
||||
-- TODO lambda, case
|
||||
|
||||
buildLetrecContext :: Context' -> [Binding']
|
||||
-> StateT ([Constraint], Int) HMError Context'
|
||||
buildLetrecContext g bs = do
|
||||
let f ag (k := _) = do
|
||||
n <- uniqueVar
|
||||
pure ((k,n) : ag)
|
||||
rg <- foldM f g bs
|
||||
let k ag (k := v) = do
|
||||
t <- go rg v
|
||||
pure ((k,t) : ag)
|
||||
foldM k g bs
|
||||
|
||||
-- | augment a context with the inferred types of each binder. the returned
|
||||
-- context is linearly accumulated, meaning that the context used to infer each binder
|
||||
-- will include the inferred types of all previous binder
|
||||
|
||||
buildLetContext :: Context' -> [Binding']
|
||||
-> StateT ([Constraint], Int) HMError Context'
|
||||
@@ -218,3 +252,20 @@ subst x t (TyVar y) | x == y = t
|
||||
subst x t (a :-> b) = subst x t a :-> subst x t b
|
||||
subst _ _ e = e
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
demoContext :: Context'
|
||||
demoContext =
|
||||
[ ("fix", (TyVar "a" :-> TyVar "a") :-> TyVar "a")
|
||||
, ("add", TyInt :-> TyInt :-> TyInt)
|
||||
, ("==", TyInt :-> TyInt :-> TyCon "Bool")
|
||||
, ("True", TyCon "Bool")
|
||||
, ("False", TyCon "Bool")
|
||||
]
|
||||
|
||||
pprintType :: Type -> String
|
||||
pprintType (s :-> t) = "(" <> pprintType s <> " -> " <> pprintType t <> ")"
|
||||
pprintType TyFun = "(->)"
|
||||
pprintType (TyVar x) = x ^. unpacked
|
||||
pprintType (TyCon t) = t ^. unpacked
|
||||
|
||||
|
||||
@@ -167,24 +167,19 @@ lexWith :: (Text -> CoreToken) -> Lexer
|
||||
lexWith f (AlexPn _ y x,_,_,s) l = pure $ Located y x l (f $ T.take l s)
|
||||
|
||||
-- | The main lexer driver.
|
||||
lexCore :: Text -> RLPC SrcError [Located CoreToken]
|
||||
lexCore :: Text -> RLPC [Located CoreToken]
|
||||
lexCore s = case m of
|
||||
Left e -> addFatal err
|
||||
where err = SrcError
|
||||
{ _errSpan = (0,0,0) -- TODO: location
|
||||
, _errSeverity = Error
|
||||
, _errDiagnostic = SrcErrLexical e
|
||||
}
|
||||
Left e -> error "core lex error"
|
||||
Right ts -> pure ts
|
||||
where
|
||||
m = runAlex s lexStream
|
||||
|
||||
lexCoreR :: Text -> RLPC RlpcError [Located CoreToken]
|
||||
lexCoreR = liftRlpcErrs . lexCore
|
||||
lexCoreR :: Text -> RLPC [Located CoreToken]
|
||||
lexCoreR = lexCore
|
||||
|
||||
-- | @lexCore@, but the tokens are stripped of location info. Useful for
|
||||
-- debugging
|
||||
lexCore' :: Text -> RLPC SrcError [CoreToken]
|
||||
lexCore' :: Text -> RLPC [CoreToken]
|
||||
lexCore' s = fmap f <$> lexCore s
|
||||
where f (Located _ _ _ t) = t
|
||||
|
||||
@@ -201,11 +196,11 @@ data ParseError = ParErrLexical String
|
||||
|
||||
-- TODO:
|
||||
instance IsRlpcError SrcError where
|
||||
liftRlpcErr = RlpcErr . show
|
||||
liftRlpcError = Text . pure . T.pack . show
|
||||
|
||||
-- TODO:
|
||||
instance IsRlpcError ParseError where
|
||||
liftRlpcErr = RlpcErr . show
|
||||
liftRlpcError = Text . pure . T.pack . show
|
||||
|
||||
alexEOF :: Alex (Located CoreToken)
|
||||
alexEOF = Alex $ \ st@(AlexState { alex_pos = AlexPn _ y x }) ->
|
||||
|
||||
@@ -10,7 +10,6 @@ module Core.Parse
|
||||
, parseCoreProg
|
||||
, parseCoreProgR
|
||||
, module Core.Lex -- temp convenience
|
||||
, parseTmp
|
||||
, SrcError
|
||||
, Module
|
||||
)
|
||||
@@ -34,7 +33,7 @@ import Data.HashMap.Strict qualified as H
|
||||
%name parseCoreProg StandaloneProgram
|
||||
%tokentype { Located CoreToken }
|
||||
%error { parseError }
|
||||
%monad { RLPC SrcError }
|
||||
%monad { RLPC } { happyBind } { happyPure }
|
||||
|
||||
%token
|
||||
let { Located _ _ _ TokenLet }
|
||||
@@ -99,6 +98,8 @@ ScDefs : ScDef ';' ScDefs { $1 : $3 }
|
||||
|
||||
ScDef :: { ScDef Name }
|
||||
ScDef : Var ParList '=' Expr { ScDef $1 $2 $4 }
|
||||
-- hack to allow constructors to be compiled into scs
|
||||
| Con ParList '=' Expr { ScDef $1 $2 $4 }
|
||||
|
||||
Type :: { Type }
|
||||
Type : Type1 { $1 }
|
||||
@@ -189,34 +190,23 @@ Con : '(' consym ')' { $2 }
|
||||
|
||||
{
|
||||
|
||||
parseError :: [Located CoreToken] -> RLPC SrcError a
|
||||
parseError (Located y x l _ : _) = addFatal err
|
||||
where err = SrcError
|
||||
{ _errSpan = (y,x,l)
|
||||
, _errSeverity = Error
|
||||
, _errDiagnostic = SrcErrParse
|
||||
}
|
||||
parseError :: [Located CoreToken] -> RLPC a
|
||||
parseError (Located y x l t : _) =
|
||||
error $ show y <> ":" <> show x
|
||||
<> ": parse error at token `" <> show t <> "'"
|
||||
|
||||
parseTmp :: IO (Module Name)
|
||||
parseTmp = do
|
||||
s <- TIO.readFile "/tmp/t.hs"
|
||||
case parse s of
|
||||
Left e -> error (show e)
|
||||
Right (ts,_) -> pure ts
|
||||
where
|
||||
parse = evalRLPC def . (lexCore >=> parseCore)
|
||||
{-# WARNING parseError "unimpl" #-}
|
||||
|
||||
exprPragma :: [String] -> RLPC SrcError (Expr Name)
|
||||
exprPragma ("AST" : e) = astPragma e
|
||||
exprPragma _ = addFatal err
|
||||
where err = SrcError
|
||||
{ _errSpan = (0,0,0) -- TODO: span
|
||||
, _errSeverity = Warning
|
||||
, _errDiagnostic = SrcErrUnknownPragma "" -- TODO: missing pragma
|
||||
}
|
||||
exprPragma :: [String] -> RLPC (Expr Name)
|
||||
exprPragma ("AST" : e) = undefined
|
||||
exprPragma _ = undefined
|
||||
|
||||
astPragma :: [String] -> RLPC SrcError (Expr Name)
|
||||
astPragma = pure . read . unwords
|
||||
{-# WARNING exprPragma "unimpl" #-}
|
||||
|
||||
astPragma :: [String] -> RLPC (Expr Name)
|
||||
astPragma _ = undefined
|
||||
|
||||
{-# WARNING astPragma "unimpl" #-}
|
||||
|
||||
insTypeSig :: (Hashable b) => (b, Type) -> Program b -> Program b
|
||||
insTypeSig ts = programTypeSigs %~ uncurry H.insert ts
|
||||
@@ -230,8 +220,14 @@ insScDef sc = programScDefs %~ (sc:)
|
||||
singletonScDef :: (Hashable b) => ScDef b -> Program b
|
||||
singletonScDef sc = insScDef sc mempty
|
||||
|
||||
parseCoreProgR :: [Located CoreToken] -> RLPC RlpcError Program'
|
||||
parseCoreProgR = liftRlpcErrs . parseCoreProg
|
||||
parseCoreProgR :: [Located CoreToken] -> RLPC Program'
|
||||
parseCoreProgR = parseCoreProg
|
||||
|
||||
happyBind :: RLPC a -> (a -> RLPC b) -> RLPC b
|
||||
happyBind m k = m >>= k
|
||||
|
||||
happyPure :: a -> RLPC a
|
||||
happyPure a = pure a
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ module Core.TH
|
||||
( coreExpr
|
||||
, coreProg
|
||||
, coreProgT
|
||||
, core
|
||||
)
|
||||
where
|
||||
----------------------------------------------------------------------------------
|
||||
@@ -14,74 +13,38 @@ import Language.Haskell.TH
|
||||
import Language.Haskell.TH.Syntax hiding (Module)
|
||||
import Language.Haskell.TH.Quote
|
||||
import Control.Monad ((>=>))
|
||||
import Control.Monad.IO.Class
|
||||
import Control.Arrow ((>>>))
|
||||
import Compiler.RLPC
|
||||
import Data.Default.Class (def)
|
||||
import Data.Text (Text)
|
||||
import Data.Text qualified as T
|
||||
import Core.Parse
|
||||
import Core.Lex
|
||||
import Core.Syntax
|
||||
import Core.HindleyMilner (checkCoreProgR)
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: write in terms of a String -> QuasiQuoter
|
||||
|
||||
core :: QuasiQuoter
|
||||
core = QuasiQuoter
|
||||
{ quoteExp = qCore
|
||||
, quotePat = error "core quasiquotes may only be used in expressions"
|
||||
, quoteType = error "core quasiquotes may only be used in expressions"
|
||||
, quoteDec = error "core quasiquotes may only be used in expressions"
|
||||
}
|
||||
|
||||
coreProg :: QuasiQuoter
|
||||
coreProg = QuasiQuoter
|
||||
{ quoteExp = qCoreProg
|
||||
, quotePat = error "core quasiquotes may only be used in expressions"
|
||||
, quoteType = error "core quasiquotes may only be used in expressions"
|
||||
, quoteDec = error "core quasiquotes may only be used in expressions"
|
||||
}
|
||||
coreProg = mkqq $ lexCoreR >=> parseCoreProgR
|
||||
|
||||
coreExpr :: QuasiQuoter
|
||||
coreExpr = QuasiQuoter
|
||||
{ quoteExp = qCoreExpr
|
||||
, quotePat = error "core quasiquotes may only be used in expressions"
|
||||
, quoteType = error "core quasiquotes may only be used in expressions"
|
||||
, quoteDec = error "core quasiquotes may only be used in expressions"
|
||||
}
|
||||
coreExpr = mkqq $ lexCoreR >=> parseCoreExpr
|
||||
|
||||
-- | Type-checked @coreProg@
|
||||
coreProgT :: QuasiQuoter
|
||||
coreProgT = QuasiQuoter
|
||||
{ quoteExp = qCoreProgT
|
||||
coreProgT = mkqq $ lexCoreR >=> parseCoreProgR >=> checkCoreProgR
|
||||
|
||||
mkqq :: (Lift a) => (Text -> RLPC a) -> QuasiQuoter
|
||||
mkqq p = QuasiQuoter
|
||||
{ quoteExp = mkq p
|
||||
, quotePat = error "core quasiquotes may only be used in expressions"
|
||||
, quoteType = error "core quasiquotes may only be used in expressions"
|
||||
, quoteDec = error "core quasiquotes may only be used in expressions"
|
||||
}
|
||||
|
||||
qCore :: String -> Q Exp
|
||||
qCore s = case parse (T.pack s) of
|
||||
Left e -> error (show e)
|
||||
Right (m,ts) -> lift m
|
||||
where
|
||||
parse = evalRLPC def . (lexCore >=> parseCore)
|
||||
|
||||
qCoreExpr :: String -> Q Exp
|
||||
qCoreExpr s = case parseExpr (T.pack s) of
|
||||
Left e -> error (show e)
|
||||
Right (m,ts) -> lift m
|
||||
where
|
||||
parseExpr = evalRLPC def . (lexCore >=> parseCoreExpr)
|
||||
|
||||
qCoreProg :: String -> Q Exp
|
||||
qCoreProg s = case parse (T.pack s) of
|
||||
Left e -> error (show e)
|
||||
Right (m,ts) -> lift m
|
||||
where
|
||||
parse = evalRLPC def . (lexCoreR >=> parseCoreProgR)
|
||||
|
||||
qCoreProgT :: String -> Q Exp
|
||||
qCoreProgT s = case parse (T.pack s) of
|
||||
Left e -> error (show e)
|
||||
Right (m,_) -> lift m
|
||||
where
|
||||
parse = evalRLPC def . (lexCoreR >=> parseCoreProgR >=> checkCoreProgR)
|
||||
mkq :: (Lift a) => (Text -> RLPC a) -> String -> Q Exp
|
||||
mkq parse s = case evalRLPC def (parse $ T.pack s) of
|
||||
(Just a, _) -> lift a
|
||||
(Nothing, _) -> error "todo: aaahhbbhjhbdjhabsjh"
|
||||
|
||||
|
||||
@@ -7,12 +7,14 @@ module Rlp.Lex
|
||||
, RlpToken(..)
|
||||
, Located(..)
|
||||
, lexToken
|
||||
, lexStream
|
||||
, lexDebug
|
||||
, lexCont
|
||||
)
|
||||
where
|
||||
import Codec.Binary.UTF8.String (encodeChar)
|
||||
import Control.Monad
|
||||
import Control.Monad.Errorful
|
||||
import Core.Syntax (Name)
|
||||
import Data.Functor.Identity
|
||||
import Data.Char (digitToInt)
|
||||
@@ -52,6 +54,7 @@ $asciisym = [\!\#\$\%\&\*\+\.\/\<\=\>\?\@\\\^\|\-\~\:]
|
||||
|
||||
@reservedname =
|
||||
case|data|do|import|in|let|letrec|module|of|where
|
||||
|infixr|infixl|infix
|
||||
|
||||
@reservedop =
|
||||
"=" | \\ | "->" | "|"
|
||||
@@ -90,6 +93,8 @@ $white_no_nl+ ;
|
||||
-- control characters
|
||||
<0>
|
||||
{
|
||||
"(" { constToken TokenLParen }
|
||||
")" { constToken TokenRParen }
|
||||
"{" { explicitLBrace }
|
||||
"}" { explicitRBrace }
|
||||
";" { constToken TokenSemicolon }
|
||||
@@ -121,6 +126,9 @@ lexReservedName = \case
|
||||
"of" -> TokenOf
|
||||
"let" -> TokenLet
|
||||
"in" -> TokenIn
|
||||
"infix" -> TokenInfix
|
||||
"infixl" -> TokenInfixL
|
||||
"infixr" -> TokenInfixR
|
||||
|
||||
lexReservedOp :: Text -> RlpToken
|
||||
lexReservedOp = \case
|
||||
@@ -201,13 +209,6 @@ alexEOF = do
|
||||
inp <- getInput
|
||||
pure (Located undefined TokenEOF)
|
||||
|
||||
execP :: P a -> ParseState -> Maybe a
|
||||
execP p st = runP p st & snd
|
||||
|
||||
execP' :: P a -> Text -> Maybe a
|
||||
execP' p s = execP p st where
|
||||
st = initParseState s
|
||||
|
||||
initParseState :: Text -> ParseState
|
||||
initParseState s = ParseState
|
||||
{ _psLayoutStack = []
|
||||
@@ -226,6 +227,10 @@ initAlexInput s = AlexInput
|
||||
, _aiPos = (1,1)
|
||||
}
|
||||
|
||||
runP' :: P a -> Text -> (ParseState, [MsgEnvelope RlpParseError], Maybe a)
|
||||
runP' p s = runP p st where
|
||||
st = initParseState s
|
||||
|
||||
lexToken :: P (Located RlpToken)
|
||||
lexToken = do
|
||||
inp <- getInput
|
||||
@@ -240,6 +245,7 @@ lexToken = do
|
||||
AlexToken inp' l act -> do
|
||||
psInput .= inp'
|
||||
act inp l
|
||||
AlexError inp' -> addFatalHere 1 RlpParErrLexical
|
||||
|
||||
lexCont :: (Located RlpToken -> P a) -> P a
|
||||
lexCont = (lexToken >>=)
|
||||
@@ -258,7 +264,7 @@ lexDebug k = do
|
||||
k t
|
||||
|
||||
lexTest :: Text -> Maybe [RlpToken]
|
||||
lexTest s = execP' lexStream s
|
||||
lexTest s = runP' lexStream s ^. _3
|
||||
|
||||
indentLevel :: P Int
|
||||
indentLevel = do
|
||||
|
||||
@@ -1,28 +1,35 @@
|
||||
{
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
module Rlp.Parse
|
||||
( parseRlpProgram
|
||||
( parseRlpProg
|
||||
)
|
||||
where
|
||||
import Compiler.RlpcError
|
||||
import Rlp.Lex
|
||||
import Rlp.Syntax
|
||||
import Rlp.Parse.Types
|
||||
import Rlp.Parse.Associate
|
||||
import Lens.Micro
|
||||
import Lens.Micro.Mtl
|
||||
import Lens.Micro.Platform ()
|
||||
import Data.List.Extra
|
||||
import Data.Fix
|
||||
import Data.Functor.Const
|
||||
import Data.Text qualified as T
|
||||
}
|
||||
|
||||
%name parseRlpProgram StandaloneProgram
|
||||
%name parseRlpProg StandaloneProgram
|
||||
|
||||
%monad { P }
|
||||
%lexer { lexDebug } { Located _ TokenEOF }
|
||||
%lexer { lexCont } { Located _ TokenEOF }
|
||||
%error { parseError }
|
||||
%tokentype { Located RlpToken }
|
||||
|
||||
%token
|
||||
varname { Located _ (TokenVarName $$) }
|
||||
conname { Located _ (TokenConName $$) }
|
||||
consym { Located _ (TokenConSym $$) }
|
||||
varsym { Located _ (TokenVarSym $$) }
|
||||
data { Located _ TokenData }
|
||||
litint { Located _ (TokenLitInt $$) }
|
||||
'=' { Located _ TokenEquals }
|
||||
@@ -36,6 +43,9 @@ import Data.Functor.Const
|
||||
'}' { Located _ TokenRBrace }
|
||||
vlbrace { Located _ TokenLBraceV }
|
||||
vrbrace { Located _ TokenRBraceV }
|
||||
infixl { Located _ TokenInfixL }
|
||||
infixr { Located _ TokenInfixR }
|
||||
infix { Located _ TokenInfix }
|
||||
|
||||
%right '->'
|
||||
|
||||
@@ -67,8 +77,17 @@ VS : ';' { $1 }
|
||||
| vsemi { $1 }
|
||||
|
||||
Decl :: { PartialDecl' }
|
||||
Decl : FunDecl { $1 }
|
||||
: FunDecl { $1 }
|
||||
| DataDecl { $1 }
|
||||
| InfixDecl { $1 }
|
||||
|
||||
InfixDecl :: { PartialDecl' }
|
||||
: InfixWord litint InfixOp {% mkInfixD $1 $2 $3 }
|
||||
|
||||
InfixWord :: { Assoc }
|
||||
: infixl { InfixL }
|
||||
| infixr { InfixR }
|
||||
| infix { Infix }
|
||||
|
||||
DataDecl :: { PartialDecl' }
|
||||
: data Con TyParams '=' DataCons { DataD $2 $3 $5 }
|
||||
@@ -109,9 +128,24 @@ Pat1 :: { Pat' }
|
||||
| Lit { LitP $1 }
|
||||
|
||||
Expr :: { PartialExpr' }
|
||||
Expr : Lit { Fix . E $ LitEF $1 }
|
||||
: Expr1 varsym Expr { Fix $ B $2 (unFix $1) (unFix $3) }
|
||||
| Expr1 { $1 }
|
||||
|
||||
Expr1 :: { PartialExpr' }
|
||||
: '(' Expr ')' { wrapFix . Par . unwrapFix $ $2 }
|
||||
| Lit { Fix . E $ LitEF $1 }
|
||||
| Var { Fix . E $ VarEF $1 }
|
||||
|
||||
-- TODO: happy prefers left-associativity. doing such would require adjusting
|
||||
-- the code in Rlp.Parse.Associate to expect left-associative input rather than
|
||||
-- right.
|
||||
InfixExpr :: { PartialExpr' }
|
||||
: Expr1 varsym Expr { Fix $ B $2 (unFix $1) (unFix $3) }
|
||||
|
||||
InfixOp :: { Name }
|
||||
: consym { $1 }
|
||||
| varsym { $1 }
|
||||
|
||||
Lit :: { Lit' }
|
||||
Lit : litint { IntL $1 }
|
||||
|
||||
@@ -129,6 +163,19 @@ mkProgram ds = do
|
||||
pure $ RlpProgram (associate pt <$> ds)
|
||||
|
||||
parseError :: Located RlpToken -> P a
|
||||
parseError = error . show
|
||||
parseError (Located ((l,c),s) t) = addFatal $
|
||||
errorMsg (SrcSpan l c s) RlpParErrUnexpectedToken
|
||||
|
||||
mkInfixD :: Assoc -> Int -> Name -> P PartialDecl'
|
||||
mkInfixD a p n = do
|
||||
let opl :: Lens' ParseState (Maybe OpInfo)
|
||||
opl = psOpTable . at n
|
||||
opl <~ (use opl >>= \case
|
||||
Just o -> addWoundHere l e >> pure (Just o) where
|
||||
e = RlpParErrDuplicateInfixD n
|
||||
l = T.length n
|
||||
Nothing -> pure (Just (a,p))
|
||||
)
|
||||
pure $ InfixD a p n
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE PatternSynonyms, ViewPatterns, ImplicitParams #-}
|
||||
module Rlp.Parse.Associate
|
||||
( associate
|
||||
|
||||
@@ -1,11 +1,47 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE ImplicitParams, ViewPatterns, PatternSynonyms #-}
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
module Rlp.Parse.Types where
|
||||
module Rlp.Parse.Types
|
||||
( LexerAction
|
||||
, MsgEnvelope(..)
|
||||
, RlpcError(..)
|
||||
, AlexInput(..)
|
||||
, Position(..)
|
||||
, RlpToken(..)
|
||||
, P(..)
|
||||
, ParseState(..)
|
||||
, psLayoutStack
|
||||
, psLexState
|
||||
, psInput
|
||||
, psOpTable
|
||||
, Layout(..)
|
||||
, Located(..)
|
||||
, OpTable
|
||||
, OpInfo
|
||||
, RlpParseError(..)
|
||||
, PartialDecl'
|
||||
, Partial(..)
|
||||
, pL, pR
|
||||
, PartialE
|
||||
, pattern WithInfo
|
||||
, opInfoOrDef
|
||||
, PartialExpr'
|
||||
, aiPrevChar
|
||||
, aiSource
|
||||
, aiBytes
|
||||
, aiPos
|
||||
, addFatal
|
||||
, addWound
|
||||
, addFatalHere
|
||||
, addWoundHere
|
||||
)
|
||||
where
|
||||
--------------------------------------------------------------------------------
|
||||
import Core.Syntax (Name)
|
||||
import Control.Monad
|
||||
import Control.Monad.State.Class
|
||||
import Control.Monad.State.Strict
|
||||
import Control.Monad.Errorful
|
||||
import Compiler.RlpcError
|
||||
import Data.Text (Text)
|
||||
import Data.Maybe
|
||||
import Data.Fix
|
||||
@@ -34,6 +70,12 @@ type Position =
|
||||
, Int -- column
|
||||
)
|
||||
|
||||
posLine :: Lens' Position Int
|
||||
posLine = _1
|
||||
|
||||
posColumn :: Lens' Position Int
|
||||
posColumn = _2
|
||||
|
||||
data RlpToken
|
||||
-- literals
|
||||
= TokenLitInt Int
|
||||
@@ -48,6 +90,9 @@ data RlpToken
|
||||
| TokenOf
|
||||
| TokenLet
|
||||
| TokenIn
|
||||
| TokenInfixL
|
||||
| TokenInfixR
|
||||
| TokenInfix
|
||||
-- reserved ops
|
||||
| TokenArrow
|
||||
| TokenPipe
|
||||
@@ -68,24 +113,34 @@ data RlpToken
|
||||
| TokenEOF
|
||||
deriving (Show)
|
||||
|
||||
newtype P a = P { runP :: ParseState -> (ParseState, Maybe a) }
|
||||
newtype P a = P {
|
||||
runP :: ParseState
|
||||
-> (ParseState, [MsgEnvelope RlpParseError], Maybe a)
|
||||
}
|
||||
deriving (Functor)
|
||||
|
||||
instance Applicative P where
|
||||
pure a = P $ \st -> (st,Just a)
|
||||
pure a = P $ \st -> (st, [], pure a)
|
||||
liftA2 = liftM2
|
||||
|
||||
instance Monad P where
|
||||
p >>= k = P $ \st ->
|
||||
let (st',a) = runP p st
|
||||
in case a of
|
||||
Just x -> runP (k x) st'
|
||||
Nothing -> (st', Nothing)
|
||||
let (st',es,ma) = runP p st
|
||||
in case ma of
|
||||
Just a -> runP (k a) st'
|
||||
& _2 %~ (es<>)
|
||||
Nothing -> (st',es,Nothing)
|
||||
|
||||
{-# INLINE (>>=) #-}
|
||||
|
||||
instance MonadState ParseState P where
|
||||
state f = P $ \st ->
|
||||
let (a,st') = f st
|
||||
in (st', Just a)
|
||||
in (st', [], Just a)
|
||||
|
||||
instance MonadErrorful (MsgEnvelope RlpParseError) P where
|
||||
addWound e = P $ \st -> (st, [e], Just ())
|
||||
addFatal e = P $ \st -> (st, [e], Nothing)
|
||||
|
||||
data ParseState = ParseState
|
||||
{ _psLayoutStack :: [Layout]
|
||||
@@ -108,11 +163,14 @@ type OpInfo = (Assoc, Int)
|
||||
-- data WithLocation a = WithLocation [String] a
|
||||
|
||||
data RlpParseError = RlpParErrOutOfBoundsPrecedence Int
|
||||
| RlpParErrDuplicateInfixD
|
||||
deriving (Eq, Ord, Show)
|
||||
| RlpParErrDuplicateInfixD Name
|
||||
| RlpParErrLexical
|
||||
| RlpParErrUnexpectedToken
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
instance IsRlpcError RlpParseError where
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
-- absolute psycho shit (partial ASTs)
|
||||
|
||||
type PartialDecl' = Decl (Const PartialExpr') Name
|
||||
@@ -158,3 +216,27 @@ type PartialExpr' = Fix Partial
|
||||
makeLenses ''AlexInput
|
||||
makeLenses ''ParseState
|
||||
|
||||
addWoundHere :: Int -> RlpParseError -> P ()
|
||||
addWoundHere l e = P $ \st ->
|
||||
let e' = MsgEnvelope
|
||||
{ _msgSpan = let pos = psInput . aiPos
|
||||
in SrcSpan (st ^. pos . posLine)
|
||||
(st ^. pos . posColumn)
|
||||
l
|
||||
, _msgDiagnostic = e
|
||||
, _msgSeverity = SevError
|
||||
}
|
||||
in (st, [e'], Just ())
|
||||
|
||||
addFatalHere :: Int -> RlpParseError -> P a
|
||||
addFatalHere l e = P $ \st ->
|
||||
let e' = MsgEnvelope
|
||||
{ _msgSpan = let pos = psInput . aiPos
|
||||
in SrcSpan (st ^. pos . posLine)
|
||||
(st ^. pos . posColumn)
|
||||
l
|
||||
, _msgDiagnostic = e
|
||||
, _msgSeverity = SevError
|
||||
}
|
||||
in (st, [e'], Nothing)
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ data Assoc = InfixL
|
||||
data ConAlt = ConAlt ConId [Type]
|
||||
deriving Show
|
||||
|
||||
data RlpExpr b = LetE [Bind b] (RlpExpr b)
|
||||
data RlpExpr b = LetE Rec [Bind b] (RlpExpr b)
|
||||
| VarE VarId
|
||||
| ConE ConId
|
||||
| LamE [Pat b] (RlpExpr b)
|
||||
@@ -150,14 +150,14 @@ type RlpExprF' = RlpExprF Name
|
||||
-- society if derivable Show1
|
||||
instance (Show b) => Show1 (RlpExprF b) where
|
||||
liftShowsPrec sp _ p m = case m of
|
||||
(LetEF bs e) -> showsBinaryWith showsPrec sp "LetEF" p bs e
|
||||
(VarEF n) -> showsUnaryWith showsPrec "VarEF" p n
|
||||
(ConEF n) -> showsUnaryWith showsPrec "ConEF" p n
|
||||
(LamEF bs e) -> showsBinaryWith showsPrec sp "LamEF" p bs e
|
||||
(CaseEF e as) -> showsBinaryWith sp showsPrec "CaseEF" p e as
|
||||
(IfEF a b c) -> showsTernaryWith sp sp sp "IfEF" p a b c
|
||||
(AppEF f x) -> showsBinaryWith sp sp "AppEF" p f x
|
||||
(LitEF l) -> showsUnaryWith showsPrec "LitEF" p l
|
||||
(LetEF r bs e) -> showsTernaryWith showsPrec showsPrec sp "LetEF" p r bs e
|
||||
(VarEF n) -> showsUnaryWith showsPrec "VarEF" p n
|
||||
(ConEF n) -> showsUnaryWith showsPrec "ConEF" p n
|
||||
(LamEF bs e) -> showsBinaryWith showsPrec sp "LamEF" p bs e
|
||||
(CaseEF e as) -> showsBinaryWith sp showsPrec "CaseEF" p e as
|
||||
(IfEF a b c) -> showsTernaryWith sp sp sp "IfEF" p a b c
|
||||
(AppEF f x) -> showsBinaryWith sp sp "AppEF" p f x
|
||||
(LitEF l) -> showsUnaryWith showsPrec "LitEF" p l
|
||||
|
||||
showsTernaryWith :: (Int -> x -> ShowS)
|
||||
-> (Int -> y -> ShowS)
|
||||
|
||||
@@ -38,9 +38,13 @@ spec = do
|
||||
let e = [coreExpr|3|]
|
||||
in check' [] (TyCon "Bool") e `shouldSatisfy` isLeft
|
||||
|
||||
infer' :: Context' -> Expr' -> Either TypeError Type
|
||||
infer' g e = fmap fst . runErrorful $ infer g e
|
||||
infer' :: Context' -> Expr' -> Either [TypeError] Type
|
||||
infer' g e = case runErrorful $ infer g e of
|
||||
(Just t, _) -> Right t
|
||||
(Nothing, es) -> Left es
|
||||
|
||||
check' :: Context' -> Type -> Expr' -> Either TypeError ()
|
||||
check' g t e = fmap fst . runErrorful $ check g t e
|
||||
check' :: Context' -> Type -> Expr' -> Either [TypeError] ()
|
||||
check' g t e = case runErrorful $ check g t e of
|
||||
(Just t, _) -> Right ()
|
||||
(Nothing, es) -> Left es
|
||||
|
||||
|
||||
Reference in New Issue
Block a user