12 Commits

Author SHA1 Message Date
crumbtoo
5416de8ee5 heap 2024-04-30 14:48:05 -06:00
crumbtoo
b0a04c255c fix splits 2024-04-29 12:35:44 -06:00
crumbtoo
da4c944eb3 code and stack improvements 2024-04-29 12:17:29 -06:00
crumbtoo
68aa0df2a4 overflow: scroll 2024-04-26 09:54:38 -06:00
crumbtoo
d4bc5d46d1 stackish 2024-04-26 09:38:11 -06:00
crumbtoo
64266e6cbe minimal code 2024-04-25 15:05:59 -06:00
crumbtoo
5876afec40 splits 2024-04-25 14:28:57 -06:00
crumbtoo
6f5c7ee284 socket 2024-04-24 13:10:26 -06:00
crumbtoo
3c234e6002 ugh 2024-04-23 12:38:03 -06:00
crumbtoo
447c8ceebf fuck you 2024-04-23 11:20:30 -06:00
crumbtoo
cf69c2ee90 ignore 2024-04-23 11:18:22 -06:00
crumbtoo
1a0ef46df8 bump 2024-04-15 10:02:36 -06:00
51 changed files with 3450 additions and 1749 deletions

View File

@@ -5,11 +5,12 @@ ALEX = alex
ALEX_OPTS = -g ALEX_OPTS = -g
SRC = src SRC = src
CABAL_BUILD = $(shell ./find-build.cl) CABAL_BUILD = $(shell ./find-build.clj)
all: parsers lexers all: parsers lexers
parsers: $(CABAL_BUILD)/Rlp/Parse.hs $(CABAL_BUILD)/Core/Parse.hs parsers: $(CABAL_BUILD)/Rlp/Parse.hs $(CABAL_BUILD)/Core/Parse.hs \
$(CABAL_BUILD)/Rlp/AltParse.hs
lexers: $(CABAL_BUILD)/Rlp/Lex.hs $(CABAL_BUILD)/Core/Lex.hs lexers: $(CABAL_BUILD)/Rlp/Lex.hs $(CABAL_BUILD)/Core/Lex.hs
$(CABAL_BUILD)/Rlp/Parse.hs: $(SRC)/Rlp/Parse.y $(CABAL_BUILD)/Rlp/Parse.hs: $(SRC)/Rlp/Parse.y

24
app.old/CoreDriver.hs Normal file
View File

@@ -0,0 +1,24 @@
module CoreDriver
( driver
)
where
--------------------------------------------------------------------------------
import Compiler.RLPC
import Control.Monad
import Data.Text qualified as T
import Control.Lens.Combinators
import Core.Lex
import Core.Parse
import GM
--------------------------------------------------------------------------------
driver :: RLPCIO ()
driver = forFiles_ $ \f ->
withSource f (lexCoreR >=> parseCoreProgR >=> evalProgR)
driverSource :: T.Text -> RLPCIO ()
driverSource = lexCoreR >=> parseCoreProgR >=> evalProgR >=> printRes
where
printRes = liftIO . print . view _1

140
app.old/Main.hs Normal file
View File

@@ -0,0 +1,140 @@
{-# LANGUAGE BlockArguments, LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
----------------------------------------------------------------------------------
import Compiler.RLPC
import Compiler.RlpcError
import Control.Exception
import Options.Applicative hiding (ParseError)
import Control.Monad
import Control.Monad.Reader
import Data.HashSet qualified as S
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.IO qualified as TIO
import Data.List
import Data.Maybe (listToMaybe)
import System.IO
import System.Exit (exitSuccess)
import Core
import TI
import GM
import Control.Lens.Combinators hiding (argument)
import CoreDriver qualified
import RlpDriver qualified
----------------------------------------------------------------------------------
optParser :: ParserInfo RLPCOptions
optParser = info (helper <*> options)
( fullDesc
<> progDesc "Compile rl' programs"
<> header "rlpc - The Inglorious rl' Compiler"
)
options :: Parser RLPCOptions
options = RLPCOptions
{- --log, -l -}
<$> optional # strOption
( long "log"
<> short 'l'
<> metavar "FILE"
<> help "output dumps to FILE. stderr is used if unset"
)
{- -d -}
<*> fmap S.fromList # many # option debugFlagReader
( short 'd'
<> help "pass debug flags"
<> metavar "DEBUG FLAG"
)
{- -f -}
<*> fmap S.fromList # many # option compilerFlagReader
( short 'f'
<> help "pass compilation flags"
<> metavar "COMPILATION FLAG"
)
{- --evaluator, -e -}
<*> option evaluatorReader
( long "evaluator"
<> short 'e'
<> metavar "gm|ti"
<> value EvaluatorGM
<> help "the intermediate layer used to model evaluation"
)
<*> option auto
( long "heap-trigger"
<> metavar "INT"
<> help "the number of nodes allowed on the heap before\
\triggering the garbage collector"
<> value 50
)
<*> optional # option languageReader
( long "language"
<> short 'x'
<> metavar "rlp|core"
<> help "the language to be compiled -- see README"
)
<*> some (argument str $ metavar "FILES...")
where
infixr 9 #
f # x = f x
languageReader :: ReadM Language
languageReader = maybeReader $ \case
"rlp" -> Just LanguageRlp
"core" -> Just LanguageCore
"rl" -> Just LanguageRlp
"cr" -> Just LanguageCore
_ -> Nothing
debugFlagReader :: ReadM DebugFlag
debugFlagReader = str
compilerFlagReader :: ReadM CompilerFlag
compilerFlagReader = str
evaluatorReader :: ReadM Evaluator
evaluatorReader = maybeReader $ \case
"gm" -> Just EvaluatorGM
"ti" -> Just EvaluatorTI
_ -> Nothing
mmany :: (Alternative f, Monoid m) => f m -> f m
mmany v = liftA2 (<>) v (mmany v)
----------------------------------------------------------------------------------
main :: IO ()
main = do
opts <- execParser optParser
void $ evalRLPCIO opts dispatch
dispatch :: RLPCIO ()
dispatch = getLang >>= \case
Just LanguageCore -> CoreDriver.driver
Just LanguageRlp -> RlpDriver.driver
Nothing -> addFatal err
where
-- TODO: why didn't i make the srcspan optional LOL
err = errorMsg (SrcSpan 0 0 0 0) $ Text
[ "Could not determine source language from filetype."
, "Possible Solutions:\n\
\ Suffix the file with `.cr' for Core, or `.rl' for rl'\n\
\ Specify a language with `rlpc -x core' or `rlpc -x rlp'"
]
where
getLang = liftA2 (<|>)
(view rlpcLanguage)
-- TODO: we only check the first file lol
((listToMaybe >=> inferLanguage) <$> view rlpcInputFiles)
driver :: RLPCIO ()
driver = undefined
inferLanguage :: FilePath -> Maybe Language
inferLanguage fp
| ".rl" `isSuffixOf` fp = Just LanguageRlp
| ".cr" `isSuffixOf` fp = Just LanguageCore
| otherwise = Nothing

19
app.old/RlpDriver.hs Normal file
View File

@@ -0,0 +1,19 @@
{-# LANGUAGE OverloadedStrings #-}
module RlpDriver
( driver
)
where
--------------------------------------------------------------------------------
import Compiler.RLPC
import Control.Monad
import Rlp.Lex
import Rlp.Parse
import Rlp2Core
import GM
--------------------------------------------------------------------------------
driver :: RLPCIO ()
driver = forFiles_ $ \f ->
withSource f (parseRlpProgR >=> desugarRlpProgR >=> evalProgR)

View File

@@ -10,6 +10,7 @@ import Control.Lens.Combinators
import Core.Lex import Core.Lex
import Core.Parse import Core.Parse
-- import Core.SystemF
import GM import GM
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -18,7 +19,8 @@ driver = forFiles_ $ \f ->
withSource f (lexCoreR >=> parseCoreProgR >=> evalProgR) withSource f (lexCoreR >=> parseCoreProgR >=> evalProgR)
driverSource :: T.Text -> RLPCIO () driverSource :: T.Text -> RLPCIO ()
driverSource = lexCoreR >=> parseCoreProgR >=> evalProgR >=> printRes driverSource = lexCoreR >=> parseCoreProgR
>=> evalProgR >=> printRes
where where
printRes = liftIO . print . view _1 printRes = liftIO . print . view _1

View File

@@ -2,6 +2,7 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module Main where module Main where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
import Control.Lens hiding (argument)
import Compiler.RLPC import Compiler.RLPC
import Compiler.RlpcError import Compiler.RlpcError
import Control.Exception import Control.Exception
@@ -23,6 +24,7 @@ import Control.Lens.Combinators hiding (argument)
import CoreDriver qualified import CoreDriver qualified
import RlpDriver qualified import RlpDriver qualified
import Server qualified
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
optParser :: ParserInfo RLPCOptions optParser :: ParserInfo RLPCOptions
@@ -74,7 +76,11 @@ options = RLPCOptions
<> metavar "rlp|core" <> metavar "rlp|core"
<> help "the language to be compiled -- see README" <> help "the language to be compiled -- see README"
) )
<*> some (argument str $ metavar "FILES...") <*> switch
( long "server"
<> short 's'
)
<*> many (argument str $ metavar "FILES...")
where where
infixr 9 # infixr 9 #
f # x = f x f # x = f x
@@ -107,7 +113,9 @@ mmany v = liftA2 (<>) v (mmany v)
main :: IO () main :: IO ()
main = do main = do
opts <- execParser optParser opts <- execParser optParser
void $ evalRLPCIO opts dispatch if opts ^. rlpcServer
then Server.server
else void $ evalRLPCIO opts dispatch
dispatch :: RLPCIO () dispatch :: RLPCIO ()
dispatch = getLang >>= \case dispatch = getLang >>= \case

View File

@@ -15,5 +15,5 @@ import GM
driver :: RLPCIO () driver :: RLPCIO ()
driver = forFiles_ $ \f -> driver = forFiles_ $ \f ->
withSource f (parseRlpProgR >=> desugarRlpProgR >=> evalProgR) withSource f (parseRlpProgR >=> undefined >=> desugarRlpProgR >=> evalProgR)

92
app/Server.hs Normal file
View File

@@ -0,0 +1,92 @@
{-# LANGUAGE LambdaCase, BlockArguments #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE OverloadedStrings #-}
module Server
( server
)
where
--------------------------------------------------------------------------------
import GHC.Generics (Generic, Generically(..))
import Data.Text.Encoding qualified as T
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.IO qualified as T
import Data.Pretty hiding (annotate, empty)
import Data.Aeson ( ToJSON(..), Value, (.:)
, FromJSON(..), encode, withObject
, decodeStrictText)
import Data.Function
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Concurrent
import Network.WebSockets qualified as WS
import Control.Exception
import GHC.IO
import Control.Lens hiding ((.=))
-- import Control.Comonad
-- import Data.Functor.Foldable
import Compiler.RLPC
import Compiler.JustRun
import GM
-- import Misc.CofreeF
-- import Rlp.AltSyntax
-- import Rlp.HindleyMilner
-- import Rlp.AltParse
--------------------------------------------------------------------------------
server :: IO ()
server = do
T.putStrLn "rlpc server started at 127.0.0.1:9002"
WS.runServer "127.0.0.1" 9002 application
application :: WS.ServerApp
application pending = do
WS.acceptRequest pending >>= talk
data Command = Annotate Text
| PartiallyAnnotate Text
| Evaluate Text
deriving Show
instance FromJSON Command where
parseJSON = withObject "command object" $ \v -> do
cmd :: Text <- v .: "command"
case cmd of
"evaluate" -> Evaluate <$> v .: "source"
"annotate" -> Annotate <$> v .: "source"
"partially-annotate" -> PartiallyAnnotate <$> v .: "source"
_ -> empty
data Response = Annotated Value
| PartiallyAnnotated Value
| Evaluated [GmState]
| Error Value
deriving (Generic)
deriving (ToJSON)
via Generically Response
talk :: WS.Connection -> IO ()
talk conn = (`catchAny` print) . forever $ do
msg <- WS.receiveData @Text conn
T.putStrLn $ "received: " <> msg
doCommand conn `traverse` decodeStrictText msg
doCommand :: WS.Connection -> Command -> IO ()
doCommand conn c = do
putStr "sending: "
let r = encode . respond $ c
print r
WS.sendTextData conn r
respond :: Command -> Response
respond (Annotate s)
= error "i'm a shitty programmer! try again with the dev branch lmfao"
respond (Evaluate s)
= justLexParseGmEval (T.unpack s)
& either (Error . toJSON) Evaluated

View File

@@ -1,9 +1,7 @@
fac : Int# -> Int#
fac n = case (==#) n 0 of fac n = case (==#) n 0 of
{ <1> -> 1 { <1> -> 1
; <0> -> *# n (fac (-# n 1)) ; <0> -> *# n (fac (-# n 1))
}; };
main : IO ()
main = fac 3; main = fac 3;

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env sbcl --script
(let* ((paths (directory "dist-newstyle/build/*/*/rlp-*/build/"))
(n (length paths)))
(cond ((< 1 n) (error ">1 build directories found. run `cabal clean`."))
((< n 1) (error "no build directories found. this shouldn't happen lol"))
(t (format t "~A" (car paths)))))

13
find-build.clj Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bb
(defn die [& msgs]
(binding [*out* *err*]
(run! println msgs))
(System/exit 1))
(let [paths (map str (fs/glob "." "dist-newstyle/build/*/*/rlp-*/build"))
n (count paths)]
(cond (< 1 n) (die ">1 build directories found. run `cabal clean`.")
(< n 1) (die "no build directories found. this shouldn't happen lol")
:else (-> paths first fs/real-path str println)))

View File

@@ -32,8 +32,6 @@ library
, Core.HindleyMilner , Core.HindleyMilner
, Control.Monad.Errorful , Control.Monad.Errorful
, Rlp.Syntax , Rlp.Syntax
, Rlp.Syntax.Backstage
, Rlp.Syntax.Types
-- , Rlp.Parse.Decls -- , Rlp.Parse.Decls
, Rlp.Parse , Rlp.Parse
, Rlp.Parse.Associate , Rlp.Parse.Associate
@@ -44,29 +42,25 @@ library
, Data.Heap , Data.Heap
, Data.Pretty , Data.Pretty
, Core.Parse , Core.Parse
, Core.Parse.Types
, Core.Lex , Core.Lex
, Core2Core , Core2Core
, Rlp2Core , Rlp2Core
, Control.Monad.Utils , Control.Monad.Utils
, Misc
, Misc.Lift1
, Core.SystemF
build-tool-depends: happy:happy, alex:alex build-tool-depends: happy:happy, alex:alex
-- other-extensions: -- other-extensions:
build-depends: base >=4.17 && <4.20 build-depends: base >=4.17 && <4.21
-- required for happy -- required for happy
, array >= 0.5.5 && < 0.6 , array >= 0.5.5 && < 0.6
, containers >= 0.6.7 && < 0.7 , containers >= 0.6.7 && < 0.7
, template-haskell >= 2.20.0 && < 2.21 , template-haskell >= 2.20.0 && < 2.23
, pretty >= 1.1.3 && < 1.2 , pretty >= 1.1.3 && < 1.2
, data-default >= 0.7.1 && < 0.8 , data-default >= 0.7.1 && < 0.8
, data-default-class >= 0.1.2 && < 0.2 , data-default-class >= 0.1.2 && < 0.2
, hashable >= 1.4.3 && < 1.5 , hashable >= 1.4.3 && < 1.5
, mtl >= 2.3.1 && < 2.4 , mtl >= 2.3.1 && < 2.4
, text >= 2.0.2 && < 2.2 , text >= 2.0.2 && < 2.3
, unordered-containers >= 0.2.20 && < 0.3 , unordered-containers >= 0.2.20 && < 0.3
, recursion-schemes >= 5.2.2 && < 5.3 , recursion-schemes >= 5.2.2 && < 5.3
, data-fix >= 0.3.2 && < 0.4 , data-fix >= 0.3.2 && < 0.4
@@ -79,12 +73,14 @@ library
, effectful-core ^>=2.3.0.0 , effectful-core ^>=2.3.0.0
, deriving-compat ^>=0.6.0 , deriving-compat ^>=0.6.0
, these >=0.2 && <2.0 , these >=0.2 && <2.0
, free >=5.2 , aeson
, bifunctors >=5.2
hs-source-dirs: src hs-source-dirs: src
default-language: GHC2021 default-language: GHC2021
ghc-options:
-fdefer-typed-holes
default-extensions: default-extensions:
OverloadedStrings OverloadedStrings
TypeFamilies TypeFamilies
@@ -94,13 +90,14 @@ library
DerivingVia DerivingVia
StandaloneDeriving StandaloneDeriving
DerivingStrategies DerivingStrategies
BlockArguments PartialTypeSignatures
executable rlpc executable rlpc
import: warnings import: warnings
main-is: Main.hs main-is: Main.hs
other-modules: RlpDriver other-modules: RlpDriver
, CoreDriver , CoreDriver
, Server
build-depends: base >=4.17.0.0 && <4.20.0.0 build-depends: base >=4.17.0.0 && <4.20.0.0
, rlp , rlp
@@ -108,7 +105,9 @@ executable rlpc
, mtl >= 2.3.1 && < 2.4 , mtl >= 2.3.1 && < 2.4
, unordered-containers >= 0.2.20 && < 0.3 , unordered-containers >= 0.2.20 && < 0.3
, lens >=5.2.3 && <6.0 , lens >=5.2.3 && <6.0
, text >= 2.0.2 && < 2.2 , text >= 2.0.2 && < 2.3
, aeson
, websockets
hs-source-dirs: app hs-source-dirs: app
default-language: GHC2021 default-language: GHC2021
@@ -125,10 +124,8 @@ test-suite rlp-test
, QuickCheck , QuickCheck
, hspec ==2.* , hspec ==2.*
, microlens , microlens
, lens >=5.2.3 && <6.0
other-modules: Arith other-modules: Arith
, GMSpec , GMSpec
, Core.HindleyMilnerSpec , Core.HindleyMilnerSpec
, Compiler.TypesSpec
build-tool-depends: hspec-discover:hspec-discover build-tool-depends: hspec-discover:hspec-discover

View File

@@ -12,14 +12,14 @@ module Compiler.JustRun
, justParseCore , justParseCore
, justTypeCheckCore , justTypeCheckCore
, justHdbg , justHdbg
, makeItPretty, makeItPretty' , justLexParseGmEval
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
import Core.Lex import Core.Lex
import Core.Parse import Core.Parse
import Core.HindleyMilner import Core.HindleyMilner
import Core.Syntax import Core.Syntax (Program')
import Compiler.RLPC import Compiler.RLPC
import Control.Arrow ((>>>)) import Control.Arrow ((>>>))
import Control.Monad ((>=>), void) import Control.Monad ((>=>), void)
@@ -31,7 +31,6 @@ import System.IO
import GM import GM
import Rlp.Parse import Rlp.Parse
import Rlp2Core import Rlp2Core
import Data.Pretty
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
justHdbg :: String -> IO GmState justHdbg :: String -> IO GmState
@@ -44,22 +43,20 @@ justLexCore s = lexCoreR (T.pack s)
& mapped . each %~ extract & mapped . each %~ extract
& rlpcToEither & rlpcToEither
justParseCore :: String -> Either [MsgEnvelope RlpcError] (Program Var) justParseCore :: String -> Either [MsgEnvelope RlpcError] Program'
justParseCore s = parse (T.pack s) justParseCore s = parse (T.pack s)
& rlpcToEither & rlpcToEither
where parse = lexCoreR @Identity >=> parseCoreProgR where parse = lexCoreR >=> parseCoreProgR
justLexParseGmEval :: String -> Either [MsgEnvelope RlpcError] [GmState]
justLexParseGmEval = parse >>> fmap (compile >>> eval) >>> rlpcToEither
where parse = (T.pack >>> lexCoreR) >=> parseCoreProgR
justTypeCheckCore :: String -> Either [MsgEnvelope RlpcError] Program' justTypeCheckCore :: String -> Either [MsgEnvelope RlpcError] Program'
justTypeCheckCore s = typechk (T.pack s) justTypeCheckCore s = typechk (T.pack s)
& rlpcToEither & rlpcToEither
where typechk = lexCoreR >=> parseCoreProgR >=> checkCoreProgR where typechk = lexCoreR >=> parseCoreProgR >=> checkCoreProgR
makeItPretty :: (Pretty a) => Either e a -> Either e Doc
makeItPretty = fmap pretty
makeItPretty' :: (Pretty (WithTerseBinds a)) => Either e a -> Either e Doc
makeItPretty' = fmap (pretty . WithTerseBinds)
rlpcToEither :: RLPC a -> Either [MsgEnvelope RlpcError] a rlpcToEither :: RLPC a -> Either [MsgEnvelope RlpcError] a
rlpcToEither r = case evalRLPC def r of rlpcToEither r = case evalRLPC def r of
(Just a, _) -> Right a (Just a, _) -> Right a

View File

@@ -26,8 +26,9 @@ module Compiler.RLPC
, DebugFlag(..), CompilerFlag(..) , DebugFlag(..), CompilerFlag(..)
-- ** Lenses -- ** Lenses
, rlpcLogFile, rlpcDFlags, rlpcEvaluator, rlpcInputFiles, rlpcLanguage , rlpcLogFile, rlpcDFlags, rlpcEvaluator, rlpcInputFiles, rlpcLanguage
, rlpcServer
-- * Misc. MTL-style functions -- * Misc. MTL-style functions
, liftErrorful, liftMaybe, hoistRlpcT , liftErrorful, hoistRlpcT
-- * Misc. Rlpc Monad -related types -- * Misc. Rlpc Monad -related types
, RLPCOptions(RLPCOptions), IsRlpcError(..), RlpcError(..) , RLPCOptions(RLPCOptions), IsRlpcError(..), RlpcError(..)
, MsgEnvelope(..), Severity(..) , MsgEnvelope(..), Severity(..)
@@ -108,9 +109,6 @@ evalRLPCT opt r = runRLPCT r
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)
liftMaybe :: (Monad m) => Maybe a -> RLPCT m a
liftMaybe m = RLPCT . lift . ErrorfulT . pure $ (m, [])
hoistRlpcT :: (forall a. m a -> n a) hoistRlpcT :: (forall a. m a -> n a)
-> RLPCT m a -> RLPCT n a -> RLPCT m a -> RLPCT n a
hoistRlpcT f rma = RLPCT $ ReaderT $ \opt -> hoistRlpcT f rma = RLPCT $ ReaderT $ \opt ->
@@ -123,6 +121,7 @@ data RLPCOptions = RLPCOptions
, _rlpcEvaluator :: Evaluator , _rlpcEvaluator :: Evaluator
, _rlpcHeapTrigger :: Int , _rlpcHeapTrigger :: Int
, _rlpcLanguage :: Maybe Language , _rlpcLanguage :: Maybe Language
, _rlpcServer :: Bool
, _rlpcInputFiles :: [FilePath] , _rlpcInputFiles :: [FilePath]
} }
deriving Show deriving Show
@@ -144,6 +143,7 @@ instance Default RLPCOptions where
, _rlpcHeapTrigger = 200 , _rlpcHeapTrigger = 200
, _rlpcInputFiles = [] , _rlpcInputFiles = []
, _rlpcLanguage = Nothing , _rlpcLanguage = Nothing
, _rlpcServer = False
} }
-- debug flags are passed with -dFLAG -- debug flags are passed with -dFLAG
@@ -223,9 +223,9 @@ docRlpcErr msg = header
rule = repeat (ttext . Ansi.blue . Ansi.bold $ "|") rule = repeat (ttext . Ansi.blue . Ansi.bold $ "|")
srclines = ["", "<problematic source code>", ""] srclines = ["", "<problematic source code>", ""]
filename = msgColour "<input>" filename = msgColour "<input>"
pos = msgColour $ tshow (msg ^. msgSpan . srcSpanLine) pos = msgColour $ tshow (msg ^. msgSpan . srcspanLine)
<> ":" <> ":"
<> tshow (msg ^. msgSpan . srcSpanColumn) <> tshow (msg ^. msgSpan . srcspanColumn)
header = ttext $ filename <> msgColour ":" <> pos <> msgColour ": " header = ttext $ filename <> msgColour ":" <> pos <> msgColour ": "
<> errorColour "error" <> msgColour ":" <> errorColour "error" <> msgColour ":"

View File

@@ -14,9 +14,6 @@ module Compiler.RlpcError
-- * Located Comonad -- * Located Comonad
, Located(..) , Located(..)
, SrcSpan(..) , SrcSpan(..)
-- * Common error messages
, undefinedVariableErr
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -26,6 +23,9 @@ import Data.Text qualified as T
import GHC.Exts (IsString(..)) import GHC.Exts (IsString(..))
import Control.Lens import Control.Lens
import Compiler.Types import Compiler.Types
import GHC.Generics ( Generic, Generic1
, Generically(..), Generically1(..) )
import Data.Aeson (ToJSON1(..), ToJSON(..))
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
data MsgEnvelope e = MsgEnvelope data MsgEnvelope e = MsgEnvelope
@@ -33,10 +33,18 @@ data MsgEnvelope e = MsgEnvelope
, _msgDiagnostic :: e , _msgDiagnostic :: e
, _msgSeverity :: Severity , _msgSeverity :: Severity
} }
deriving (Functor, Show) deriving (Functor, Show, Generic, Generic1)
newtype RlpcError = Text [Text] newtype RlpcError = Text [Text]
deriving Show deriving (Show, Generic)
deriving via Generically1 MsgEnvelope
instance ToJSON1 MsgEnvelope
deriving via Generically (MsgEnvelope e)
instance ToJSON e => ToJSON (MsgEnvelope e)
deriving via Generically RlpcError
instance ToJSON RlpcError
instance IsString RlpcError where instance IsString RlpcError where
fromString = Text . pure . T.pack fromString = Text . pure . T.pack
@@ -50,7 +58,10 @@ instance IsRlpcError RlpcError where
data Severity = SevWarning data Severity = SevWarning
| SevError | SevError
| SevDebug Text -- ^ Tag | SevDebug Text -- ^ Tag
deriving Show deriving (Show, Generic)
deriving via Generically Severity
instance ToJSON Severity
makeLenses ''MsgEnvelope makeLenses ''MsgEnvelope
@@ -77,8 +88,3 @@ debugMsg tag e = MsgEnvelope
, _msgSeverity = SevDebug tag , _msgSeverity = SevDebug tag
} }
undefinedVariableErr :: Text -> RlpcError
undefinedVariableErr n = Text
[ "Variable not in scope: `" <> n <> "'."
]

View File

@@ -1,81 +1,36 @@
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances, QuantifiedConstraints #-}
{-# LANGUAGE PatternSynonyms #-}
module Compiler.Types module Compiler.Types
( SrcSpan(..) ( SrcSpan(..)
, srcSpanLine, srcSpanColumn, srcSpanAbs, srcSpanLen , srcspanLine, srcspanColumn, srcspanAbs, srcspanLen
, pattern (:<$)
, Located(..) , Located(..)
, HasLocation(..)
, _Located , _Located
, nolo, nolo' , located
, nolo
, (<~>), (~>), (~~>), (<~~) , (<<~), (<~>), (<#>)
, comb2, comb3, comb4
, lochead
-- * Re-exports -- * Re-exports
, Comonad(extract) , Comonad
, Apply , Apply
, Bind , Bind
) )
where where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Language.Haskell.TH.Syntax (Lift)
import Control.Comonad import Control.Comonad
import Control.Comonad.Cofree
import Control.Comonad.Trans.Cofree qualified as Trans.Cofree
import Control.Comonad.Trans.Cofree (CofreeF)
import Data.Functor.Apply import Data.Functor.Apply
import Data.Functor.Bind import Data.Functor.Bind
import Data.Functor.Compose import Control.Lens hiding ((<<~))
import Data.Functor.Foldable import Language.Haskell.TH.Syntax (Lift)
import Data.Semigroup.Foldable import GHC.Generics ( Generic, Generic1
import Data.Fix hiding (cata, ana) , Generically(..), Generically1(..) )
import Data.Kind import Data.Aeson (ToJSON1(..), ToJSON(..))
import Control.Lens hiding ((<<~), (:<))
import Data.List.NonEmpty (NonEmpty)
import Data.Function (on)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Token wrapped with a span (line, column, absolute, length) -- | Token wrapped with a span (line, column, absolute, length)
data Located a = Located SrcSpan a data Located a = Located SrcSpan a
deriving (Show, Lift, Functor) deriving (Show, Lift, Functor)
data Floc f = Floc SrcSpan (f (Floc f)) located :: Lens (Located a) (Located b) a b
located = lens extract ($>)
pattern (:<$) :: a -> f b -> Trans.Cofree.CofreeF f a b
pattern a :<$ b = a Trans.Cofree.:< b
(<~>) :: a -> b -> SrcSpan
(<~>) = undefined
infixl 5 <~>
-- (~>) :: (CanGet k, CanSet k', HasLocation k a, HasLocation k' b)
-- => a -> b -> b
-- a ~> b =
(~>) = undefined
infixl 4 ~>
-- (~~>) :: (CanGet k, HasLocation k a, CanSet k', HasLocation k' b)
-- => (a -> b) -> a -> b
-- (~~>) :: (f SrcSpan -> b) -> Cofree f SrcSpan -> Cofree f SrcSpan
-- f ~~> (ss :< as) = ss :< f as
(~~>) = undefined
infixl 3 ~~>
-- (<~~) :: (GetLocation a, HasLocation b) => (a -> b) -> a -> b
-- a <~~ b = a b & location <>~ srcspan b
(<~~) = undefined
infixr 2 <~~
instance Apply Located where instance Apply Located where
liftF2 f (Located sa p) (Located sb q) liftF2 f (Located sa p) (Located sb q)
@@ -95,136 +50,56 @@ data SrcSpan = SrcSpan
!Int -- ^ Column !Int -- ^ Column
!Int -- ^ Absolute !Int -- ^ Absolute
!Int -- ^ Length !Int -- ^ Length
deriving (Show, Eq, Lift) deriving (Show, Lift, Generic)
deriving via Generically SrcSpan
instance ToJSON SrcSpan
tupling :: Iso' SrcSpan (Int, Int, Int, Int) tupling :: Iso' SrcSpan (Int, Int, Int, Int)
tupling = iso (\ (SrcSpan a b c d) -> (a,b,c,d)) tupling = iso (\ (SrcSpan a b c d) -> (a,b,c,d))
(\ (a,b,c,d) -> SrcSpan a b c d) (\ (a,b,c,d) -> SrcSpan a b c d)
srcSpanLine, srcSpanColumn, srcSpanAbs, srcSpanLen :: Lens' SrcSpan Int srcspanLine, srcspanColumn, srcspanAbs, srcspanLen :: Lens' SrcSpan Int
srcSpanLine = tupling . _1 srcspanLine = tupling . _1
srcSpanColumn = tupling . _2 srcspanColumn = tupling . _2
srcSpanAbs = tupling . _3 srcspanAbs = tupling . _3
srcSpanLen = tupling . _4 srcspanLen = tupling . _4
-- | debug tool -- | debug tool
nolo :: a -> Located a nolo :: a -> Located a
nolo = Located (SrcSpan 0 0 0 0) nolo = Located (SrcSpan 0 0 0 0)
nolo' :: f (Cofree f SrcSpan) -> Cofree f SrcSpan
nolo' as = SrcSpan 0 0 0 0 :< as
instance Semigroup SrcSpan where instance Semigroup SrcSpan where
-- multiple identities? what are the consequences of this...?
SrcSpan _ _ _ 0 <> SrcSpan l c a s = SrcSpan l c a s
SrcSpan l c a s <> SrcSpan _ _ _ 0 = SrcSpan l c a s
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
c = min ca cb c = min ca cb
a = min aa ab a = min aa ab
s = case aa `compare` ab of s = case aa `compare` ab of
EQ -> max sa sb EQ -> max sa sb
LT -> max sa (ab + sb - aa) LT -> max sa (ab + lb - aa)
GT -> max sb (aa + sa - ab) GT -> max sb (aa + la - ab)
-------------------------------------------------------------------------------- -- | A synonym for '(<<=)' with a tighter precedence and left-associativity for
-- use with '(<~>)' in a sort of, comonadic pseudo-applicative style.
data GetOrSet = Get | Set | GetSet (<<~) :: (Comonad w) => (w a -> b) -> w a -> w b
(<<~) = (<<=)
class CanGet (k :: GetOrSet) infixl 4 <<~
class CanSet (k :: GetOrSet) where
instance CanGet Get -- | Similar to '(<*>)', but with a cokleisli arrow.
instance CanGet GetSet
instance CanSet Set
instance CanSet GetSet
data GetSetLens (k :: GetOrSet) s t a b :: Type where (<~>) :: (Comonad w, Bind w) => w (w a -> b) -> w a -> w b
Getter_ :: (s -> a) -> GetSetLens Get s t a b mc <~> ma = mc >>- \f -> ma =>> f
Setter_ :: ((a -> b) -> s -> t) -> GetSetLens Set s t a b
GetterSetter :: (CanGet k', CanSet k')
=> (s -> a) -> (s -> b -> t) -> GetSetLens k' s t a b
type GetSetLens' k s a = GetSetLens k s s a a infixl 4 <~>
class HasLocation k s | s -> k where -- this is getting silly
-- location :: (Access k f, Functor f) => LensLike' f s SrcSpan
getSetLocation :: GetSetLens' k s SrcSpan
type family Access (k :: GetOrSet) f where (<#>) :: (Functor f) => f (a -> b) -> a -> f b
Access GetSet f = Functor f fab <#> a = fmap ($ a) fab
Access Set f = Settable f
Access Get f = (Functor f, Contravariant f)
instance HasLocation GetSet SrcSpan where infixl 4 <#>
getSetLocation = GetterSetter id (flip const)
-- location = fromGetSetLens getSetLocation
instance (CanSet k, HasLocation k a) => HasLocation Set (r -> a) where
getSetLocation = Setter_ $ \ss ra r -> ra r & fromSet getSetLocation %~ ss
-- location = fromSet getSetLocation
instance (HasLocation k a) => HasLocation k (Cofree f a) where
getSetLocation = case getSetLocation @_ @a of
Getter_ sa -> Getter_ $ \ (s :< _) -> sa s
Setter_ abst -> Setter_ $ \ss (s :< as) -> abst ss s :< as
GetterSetter sa sbt -> GetterSetter sa' sbt' where
sa' (s :< _) = sa s
sbt' (s :< as) b = sbt s b :< as
location :: (Access k f, Functor f, HasLocation k s)
=> LensLike' f s SrcSpan
location = fromGetSetLens getSetLocation
fromGetSetLens :: (Access k f, Functor f) => GetSetLens' k s a -> LensLike' f s a
fromGetSetLens gsl = case gsl of
Getter_ sa -> to sa
Setter_ abst -> setting abst
GetterSetter sa sbt -> lens sa sbt
fromGet :: (CanGet k) => GetSetLens k s t a b -> Getter s a
fromGet (Getter_ sa) = to sa
fromGet (GetterSetter sa _) = to sa
fromSet :: (CanSet k) => GetSetLens k s t a b -> Setter s t a b
fromSet (Setter_ abst) = setting abst
fromSet (GetterSetter sa sbt) = lens sa sbt
fromGetSet :: (CanGet k, CanSet k) => GetSetLens k s t a b -> Lens s t a b
fromGetSet (GetterSetter sa sbt) = lens sa sbt
--------------------------------------------------------------------------------
comb2 :: (Functor f, Semigroup m)
=> (Cofree f m -> Cofree f m -> f (Cofree f m))
-> Cofree f m -> Cofree f m -> Cofree f m
comb2 f a b = ss :< f a b
where ss = a `mextract` b
comb3 :: (Functor f, Semigroup m)
=> (Cofree f m -> Cofree f m -> Cofree f m -> f (Cofree f m))
-> Cofree f m -> Cofree f m -> Cofree f m -> Cofree f m
comb3 f a b c = ss :< f a b c
where ss = a `mapply` b `mextract` c
comb4 :: (Functor f, Semigroup m)
=> (Cofree f m -> Cofree f m -> Cofree f m -> Cofree f m
-> f (Cofree f m))
-> Cofree f m -> Cofree f m -> Cofree f m -> Cofree f m -> Cofree f m
comb4 f a b c d = ss :< f a b c d
where ss = a `mapply` b `mapply` c `mextract` d
mextract :: (Comonad w, Semigroup m) => w m -> w m -> m
mextract = (<>) `on` extract
mapply :: (Comonad w, Semigroup m) => w m -> w m -> w m
mapply a b = b <&> (<> extract a)
lochead :: Functor f
=> (f SrcSpan -> f SrcSpan) -> Located (f SrcSpan) -> Cofree f SrcSpan
lochead afs (Located ss fss) = ss :< unwrap (lochead afs $ Located ss fss)
--------------------------------------------------------------------------------
makePrisms ''Located makePrisms ''Located

View File

@@ -1,5 +1,6 @@
module Core module Core
( module Core.Syntax ( module Core.Syntax
, parseCore
, parseCoreProg , parseCoreProg
, parseCoreExpr , parseCoreExpr
, lexCore , lexCore

View File

@@ -10,9 +10,12 @@ import Core.Syntax
import Core.TH import Core.TH
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
letRecExample = undefined -- fac3 = undefined
-- sumList = undefined
-- constDivZero = undefined
-- idCase = undefined
{-- ---
letrecExample :: Program' letrecExample :: Program'
letrecExample = [coreProg| letrecExample = [coreProg|

View File

@@ -35,12 +35,6 @@ import Text.Printf
import Core.Syntax import Core.Syntax
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
infer = undefined
check = undefined
checkCoreProg = undefined
checkCoreProgR = undefined
checkCoreExprR = undefined
-- | Annotated typing context -- I have a feeling we're going to want this in the -- | Annotated typing context -- I have a feeling we're going to want this in the
-- future. -- future.
type Context b = [(b, Type)] type Context b = [(b, Type)]
@@ -80,8 +74,6 @@ instance IsRlpcError TypeError where
-- throw any number of fatal or nonfatal errors. Run with @runErrorful@. -- throw any number of fatal or nonfatal errors. Run with @runErrorful@.
type HMError = Errorful TypeError type HMError = Errorful TypeError
{--
-- | Assert that an expression unifies with a given type -- | Assert that an expression unifies with a given type
-- --
-- >>> let e = [coreProg|3|] -- >>> let e = [coreProg|3|]
@@ -284,4 +276,3 @@ demoContext =
, ("False", TyCon "Bool") , ("False", TyCon "Bool")
] ]
--}

View File

@@ -78,7 +78,7 @@ rlp :-
"{" { constTok TokenLBrace } "{" { constTok TokenLBrace }
"}" { constTok TokenRBrace } "}" { constTok TokenRBrace }
";" { constTok TokenSemicolon } ";" { constTok TokenSemicolon }
":" { constTok TokenHasType } "::" { constTok TokenHasType }
"@" { constTok TokenTypeApp } "@" { constTok TokenTypeApp }
"{-#" { constTok TokenLPragma `andBegin` pragma } "{-#" { constTok TokenLPragma `andBegin` pragma }

View File

@@ -5,12 +5,14 @@ Description : Parser for the Core language
-} -}
{-# LANGUAGE OverloadedStrings, ViewPatterns #-} {-# LANGUAGE OverloadedStrings, ViewPatterns #-}
module Core.Parse module Core.Parse
( parseCoreExpr ( parseCore
, parseCoreExpr
, parseCoreExprR , parseCoreExprR
, parseCoreProg , parseCoreProg
, parseCoreProgR , parseCoreProgR
, module Core.Lex -- temp convenience , module Core.Lex -- temp convenience
, SrcError , SrcError
, Module
) )
where where
@@ -30,19 +32,19 @@ import Data.Text.IO qualified as TIO
import Data.Text (Text) import Data.Text (Text)
import Data.Text qualified as T import Data.Text qualified as T
import Data.HashMap.Strict qualified as H import Data.HashMap.Strict qualified as H
import Core.Parse.Types
} }
%name parseCore Module
%name parseCoreExpr StandaloneExpr %name parseCoreExpr StandaloneExpr
%name parseCoreProg StandaloneProgram %name parseCoreProg StandaloneProgram
%tokentype { Located CoreToken } %tokentype { Located CoreToken }
%error { parseError } %error { parseError }
%monad { P } %monad { RLPC } { happyBind } { happyPure }
%token %token
let { Located _ TokenLet } let { Located _ TokenLet }
letrec { Located _ TokenLetrec } letrec { Located _ TokenLetrec }
module { Located _ TokenModule }
where { Located _ TokenWhere } where { Located _ TokenWhere }
case { Located _ TokenCase } case { Located _ TokenCase }
of { Located _ TokenOf } of { Located _ TokenOf }
@@ -66,27 +68,29 @@ import Core.Parse.Types
'{-#' { Located _ TokenLPragma } '{-#' { Located _ TokenLPragma }
'#-}' { Located _ TokenRPragma } '#-}' { Located _ TokenRPragma }
';' { Located _ TokenSemicolon } ';' { Located _ TokenSemicolon }
':' { Located _ TokenHasType } '::' { Located _ TokenHasType }
eof { Located _ TokenEOF } eof { Located _ TokenEOF }
%right '->'
%% %%
Module :: { Module Name }
Module : module conname where Program Eof { Module (Just ($2, [])) $4 }
| Program Eof { Module Nothing $1 }
Eof :: { () } Eof :: { () }
Eof : eof { () } Eof : eof { () }
| error { () } | error { () }
StandaloneProgram :: { Program Var } StandaloneProgram :: { Program Name }
StandaloneProgram : Program eof { $1 } StandaloneProgram : Program eof { $1 }
Program :: { Program Var } Program :: { Program Name }
: TypedScDef ';' Program { $3 & insTypeSig (fst $1) Program : ScTypeSig ';' Program { insTypeSig $1 $3 }
& insScDef (snd $1) } | ScTypeSig OptSemi { singletonTypeSig $1 }
| TypedScDef OptSemi { mempty & insTypeSig (fst $1) | ScDef ';' Program { insScDef $1 $3 }
& insScDef (snd $1) } | ScDef OptSemi { singletonScDef $1 }
| TLPragma Program {% doTLPragma $1 $2 } | TLPragma Program {% doTLPragma $1 $2 }
| TLPragma {% doTLPragma $1 mempty } | TLPragma {% doTLPragma $1 mempty }
TLPragma :: { Pragma } TLPragma :: { Pragma }
: '{-#' Words '#-}' { Pragma $2 } : '{-#' Words '#-}' { Pragma $2 }
@@ -100,152 +104,140 @@ OptSemi : ';' { () }
| {- epsilon -} { () } | {- epsilon -} { () }
ScTypeSig :: { (Name, Type) } ScTypeSig :: { (Name, Type) }
ScTypeSig : Id ':' Type { ($1, $3) } ScTypeSig : Var '::' Type { ($1,$3) }
TypedScDef :: { (Var, ScDef Var) } ScDefs :: { [ScDef Name] }
: Id ':' Type ';' Id ParList '=' Expr ScDefs : ScDef ';' ScDefs { $1 : $3 }
{ (MkVar $1 $3, mkTypedScDef $1 $3 $5 $6 $8) } | ScDef ';' { [$1] }
| ScDef { [$1] }
-- ScDefs :: { [ScDef PsName] } ScDef :: { ScDef Name }
-- ScDefs : ScDef ';' ScDefs { $1 : $3 } ScDef : Var ParList '=' Expr { ScDef $1 $2 $4 }
-- | ScDef ';' { [$1] } -- hack to allow constructors to be compiled into scs
-- | ScDef { [$1] } | Con ParList '=' Expr { ScDef $1 $2 $4 }
--
-- ScDef :: { ScDef PsName }
-- ScDef : Id ParList '=' Expr { ScDef (Left $1) $2
-- ($4 & binders %~ Right) }
Type :: { Type } Type :: { Type }
: TypeApp '->' TypeApp { $1 :-> $3 } Type : Type1 { $1 }
| TypeApp { $1 }
TypeApp :: { Type }
: TypeApp Type1 { TyApp $1 $2 }
| Type1 { $1 }
-- do we want to allow symbolic names for tyvars and tycons?
Type1 :: { Type } Type1 :: { Type }
Type1 : '(' Type ')' { $2 } Type1 : '(' Type ')' { $2 }
| Type1 '->' Type { $1 :-> $3 }
-- do we want to allow symbolic names for tyvars and tycons?
| varname { TyVar $1 } | varname { TyVar $1 }
| conname { if $1 == "Type" | conname { TyCon $1 }
then TyKindType else TyCon $1 }
ParList :: { [Name] } ParList :: { [Name] }
ParList : varname ParList { $1 : $2 } ParList : Var ParList { $1 : $2 }
| {- epsilon -} { [] } | {- epsilon -} { [] }
StandaloneExpr :: { Expr Var } StandaloneExpr :: { Expr Name }
StandaloneExpr : Expr eof { $1 } StandaloneExpr : Expr eof { $1 }
Expr :: { Expr Var } Expr :: { Expr Name }
Expr : LetExpr { $1 } Expr : LetExpr { $1 }
| 'λ' Binders '->' Expr { Lam $2 $4 } | 'λ' Binders '->' Expr { Lam $2 $4 }
| Application { $1 } | Application { $1 }
| CaseExpr { $1 } | CaseExpr { $1 }
| Expr1 { $1 } | Expr1 { $1 }
LetExpr :: { Expr Var } LetExpr :: { Expr Name }
LetExpr : let '{' Bindings '}' in Expr { Let NonRec $3 $6 } LetExpr : let '{' Bindings '}' in Expr { Let NonRec $3 $6 }
| letrec '{' Bindings '}' in Expr { Let Rec $3 $6 } | letrec '{' Bindings '}' in Expr { Let Rec $3 $6 }
Binders :: { [Var] } Binders :: { [Name] }
Binders : Var Binders { $1 : $2 } Binders : Var Binders { $1 : $2 }
| Var { [$1] } | Var { [$1] }
Application :: { Expr Var } Application :: { Expr Name }
Application : Application AppArg { App $1 $2 } Application : Expr1 AppArgs { foldl' App $1 $2 }
| Expr1 AppArg { App $1 $2 }
AppArg :: { Expr Var } AppArgs :: { [Expr Name] }
: '@' Type1 { Type $2 } AppArgs : Expr1 AppArgs { $1 : $2 }
| Expr1 { $1 } | Expr1 { [$1] }
CaseExpr :: { Expr Var } CaseExpr :: { Expr Name }
CaseExpr : case Expr of '{' Alters '}' { Case $2 $5 } CaseExpr : case Expr of '{' Alters '}' { Case $2 $5 }
Alters :: { [Alter Var] } Alters :: { [Alter Name] }
Alters : Alter ';' Alters { $1 : $3 } Alters : Alter ';' Alters { $1 : $3 }
| Alter ';' { [$1] } | Alter ';' { [$1] }
| Alter { [$1] } | Alter { [$1] }
Alter :: { Alter Var } Alter :: { Alter Name }
Alter : alttag AltParList '->' Expr { Alter (AltTag $1) $2 $4 } Alter : alttag ParList '->' Expr { Alter (AltTag $1) $2 $4 }
| conname AltParList '->' Expr { Alter (AltData $1) $2 $4 } | Con ParList '->' Expr { Alter (AltData $1) $2 $4 }
AltParList :: { [Var] } Expr1 :: { Expr Name }
: Var AltParList { $1 : $2 }
| {- epsilon -} { [] }
Expr1 :: { Expr Var }
Expr1 : litint { Lit $ IntL $1 } Expr1 : litint { Lit $ IntL $1 }
| Id { Var $1 } | Id { Var $1 }
| PackCon { $1 } | PackCon { $1 }
| '(' Expr ')' { $2 } | '(' Expr ')' { $2 }
PackCon :: { Expr Var } PackCon :: { Expr Name }
PackCon : pack '{' litint litint '}' { Con $3 $4 } PackCon : pack '{' litint litint '}' { Con $3 $4 }
Bindings :: { [Binding Var] } Bindings :: { [Binding Name] }
Bindings : Binding ';' Bindings { $1 : $3 } Bindings : Binding ';' Bindings { $1 : $3 }
| Binding ';' { [$1] } | Binding ';' { [$1] }
| Binding { [$1] } | Binding { [$1] }
Binding :: { Binding Var } Binding :: { Binding Name }
Binding : Var '=' Expr { $1 := $3 } Binding : Var '=' Expr { $1 := $3 }
Id :: { Name } Id :: { Name }
: varname { $1 } Id : Var { $1 }
| conname { $1 } | Con { $1 }
Var :: { Var } Var :: { Name }
Var : '(' varname ':' Type ')' { MkVar $2 $4 } Var : varname { $1 }
| varsym { $1 }
Con :: { Name }
Con : conname { $1 }
| consym { $1 }
{ {
parseError :: [Located CoreToken] -> P a parseError :: [Located CoreToken] -> RLPC a
parseError (Located _ t : _) = parseError (Located _ t : _) =
error $ "<line>" <> ":" <> "<col>" error $ "<line>" <> ":" <> "<col>"
<> ": parse error at token `" <> show t <> "'" <> ": parse error at token `" <> show t <> "'"
exprPragma :: [String] -> RLPC (Expr Var) {-# WARNING parseError "unimpl" #-}
exprPragma :: [String] -> RLPC (Expr Name)
exprPragma ("AST" : e) = undefined exprPragma ("AST" : e) = undefined
exprPragma _ = undefined exprPragma _ = undefined
astPragma :: [String] -> RLPC (Expr Var) {-# WARNING exprPragma "unimpl" #-}
astPragma :: [String] -> RLPC (Expr Name)
astPragma _ = undefined astPragma _ = undefined
-- insTypeSig :: (Hashable b) => (b, Type) -> Program b -> Program b {-# WARNING astPragma "unimpl" #-}
-- insTypeSig ts = programTypeSigs %~ uncurry H.insert ts
insTypeSig :: Var -> Program Var -> Program Var insTypeSig :: (Hashable b) => (b, Type) -> Program b -> Program b
insTypeSig w@(MkVar _ t) = programTypeSigs %~ H.insert w t insTypeSig ts = programTypeSigs %~ uncurry H.insert ts
-- singletonTypeSig :: (Hashable b) => (b, Type) -> Program b singletonTypeSig :: (Hashable b) => (b, Type) -> Program b
-- singletonTypeSig ts = insTypeSig ts mempty singletonTypeSig ts = insTypeSig ts mempty
insScDef :: (Hashable b) => ScDef b -> Program b -> Program b insScDef :: (Hashable b) => ScDef b -> Program b -> Program b
insScDef sc = programScDefs %~ (sc:) 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
parseCoreExprR :: (Monad m) => [Located CoreToken] -> RLPCT m (Expr Var) parseCoreExprR :: (Monad m) => [Located CoreToken] -> RLPCT m Expr'
parseCoreExprR = liftMaybe . snd . flip runP def . parseCoreExpr parseCoreExprR = hoistRlpcT generalise . parseCoreExpr
parseCoreProgR :: forall m. (Monad m) parseCoreProgR :: forall m. (Monad m) => [Located CoreToken] -> RLPCT m Program'
=> [Located CoreToken] -> RLPCT m (Program Var) parseCoreProgR = ddumpast <=< (hoistRlpcT generalise . parseCoreProg)
parseCoreProgR s = do where
let p = runP (parseCoreProg s) def ddumpast :: Program' -> RLPCT m Program'
case p of ddumpast p = do
(st, Just a) -> do addDebugMsg "dump-parsed-core" . show $ p
ddumpast a pure p
pure a
where
ddumpast :: Show a => Program a -> RLPCT m (Program a)
ddumpast p = do
addDebugMsg "dump-parsed-core" . 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
@@ -253,7 +245,7 @@ happyBind m k = m >>= k
happyPure :: a -> RLPC a happyPure :: a -> RLPC a
happyPure a = pure a happyPure a = pure a
doTLPragma :: Pragma -> Program Var -> P (Program Var) doTLPragma :: Pragma -> Program' -> RLPC Program'
-- TODO: warn unrecognised pragma -- TODO: warn unrecognised pragma
doTLPragma (Pragma []) p = pure p doTLPragma (Pragma []) p = pure p

View File

@@ -1,62 +0,0 @@
{-# LANGUAGE TemplateHaskell #-}
module Core.Parse.Types
( P(..)
, psTyVars
, def
, PsName
, mkTypedScDef
)
where
--------------------------------------------------------------------------------
import Control.Applicative
import Control.Monad
import Control.Monad.State
import Data.Default
import Data.Maybe
import Data.Tuple (swap)
import Control.Lens
import Core.Syntax
--------------------------------------------------------------------------------
newtype P a = P { runP :: PState -> (PState, Maybe a) }
deriving Functor
data PState = PState
{ _psTyVars :: [(Name, Kind)]
}
instance Applicative P where
pure a = P (, Just a)
P pf <*> P pa = P \st ->
let (st',mf) = pf st
(st'',ma) = pa st'
in (st'', mf <*> ma)
instance Monad P where
P pa >>= k = P \st ->
let (st',ma) = pa st
in case ma of
Just a -> runP (k a) st'
Nothing -> (st', Nothing)
instance MonadState PState P where
state = P . fmap ((_2 %~ Just) . review swapped)
instance Default PState where
def = undefined
makeLenses ''PState
type PsName = Either Name Var
--------------------------------------------------------------------------------
mkTypedScDef :: Name -> Type -> Name -> [Name] -> Expr Var -> ScDef Var
mkTypedScDef nt tt n as e | nt == n = ScDef n' as' e
where
n' = MkVar n tt
as' = zipWith MkVar as (tt ^.. arrowStops)

View File

@@ -7,38 +7,39 @@ Description : Core ASTs and the like
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
-- for recursion-schemes -- for recursion-schemes
{-# LANGUAGE DeriveTraversable, TypeFamilies #-} {-# LANGUAGE DeriveTraversable, TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Core.Syntax module Core.Syntax
( ( Expr(..)
-- * Core AST , ExprF(..)
ExprF(..), ExprF' , ExprF'(..)
, ScDef(..), ScDef' , Type(..)
, Program(..), Program' , pattern TyInt
, Type(..), Kind, pattern (:->), pattern TyInt , Lit(..)
, AlterF(..), Alter(..), Alter', AltCon(..) , pattern (:$)
, pattern Binding, pattern Alter , pattern (:@)
, Rec(..), Lit(..) , pattern (:->)
, Binding(..)
, AltCon(..)
, pattern (:=)
, Rec(..)
, Alter(..)
, Name
, Tag
, ScDef(..)
, Module(..)
, Program(..)
, Program'
, Pragma(..) , Pragma(..)
-- ** Variables and identifiers , unliftScDef
, Name, Var(..), Tag, pattern (:^) , programScDefs
, Binding, BindingF(..), pattern (:=), pattern (:$) , programTypeSigs
, type Binding' , programDataTags
-- ** Working with the fixed point of ExprF , Expr'
, Expr, Expr' , ScDef'
, pattern Con, pattern Var, pattern App, pattern Lam, pattern Let , Alter'
, pattern Case, pattern Type, pattern Lit , Binding'
, HasRHS(_rhs)
-- * Pretty-printing , HasLHS(_lhs)
, Pretty(pretty), WithTerseBinds(..) , Pretty(pretty)
-- * Optics
, programScDefs, programTypeSigs, programDataTags
, formalising
, HasRHS(_rhs), HasLHS(_lhs)
, _BindingF, _MkVar
-- ** Classy optics
, HasBinders(..), HasArrowStops(..), HasApplicants1(..), HasApplicants(..)
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -46,183 +47,109 @@ import Data.Coerce
import Data.Pretty import Data.Pretty
import Data.List (intersperse) import Data.List (intersperse)
import Data.Function ((&)) import Data.Function ((&))
import Data.Functor.Foldable
import Data.Functor.Foldable.TH (makeBaseFunctor)
import Data.String import Data.String
import Data.HashMap.Strict (HashMap) import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as H import Data.HashMap.Strict qualified as H
import Data.Hashable import Data.Hashable
import Data.Foldable (traverse_)
import Data.Functor
import Data.Monoid
import Data.Functor.Classes
import Data.Text qualified as T import Data.Text qualified as T
import Data.Char import Data.Char
import Data.These import Data.These
import Data.Bifoldable (bifoldr)
import GHC.Generics (Generic, Generically(..)) import GHC.Generics (Generic, Generically(..))
import Text.Show.Deriving
import Data.Eq.Deriving
import Data.Kind qualified
import Data.Fix hiding (cata, ana)
import Data.Bifunctor (Bifunctor(..))
import Data.Bifoldable (bifoldr, Bifoldable(..))
import Data.Bifunctor.TH
import Data.Bitraversable
import Data.Functor.Foldable
import Data.Functor.Foldable.TH (makeBaseFunctor)
-- Lift instances for the Core quasiquoters -- Lift instances for the Core quasiquoters
import Misc import Language.Haskell.TH.Syntax (Lift)
import Misc.Lift1
import Control.Lens import Control.Lens
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
data ExprF b a = VarF Name data Expr b = Var Name
| ConF Tag Int -- ^ Con Tag Arity | Con Tag Int -- ^ Con Tag Arity
| CaseF a [AlterF b a] | Case (Expr b) [Alter b]
| LamF [b] a | Lam [b] (Expr b)
| LetF Rec [BindingF b a] a | Let Rec [Binding b] (Expr b)
| AppF a a | App (Expr b) (Expr b)
| LitF Lit | Lit Lit
| TypeF Type deriving (Show, Read, Lift)
deriving (Functor, Foldable, Traversable)
type Expr b = Fix (ExprF b) deriving instance (Eq b) => Eq (Expr b)
instance IsString (ExprF b a) where
fromString = VarF . fromString
instance (IsString (f (Fix f))) => IsString (Fix f) where
fromString = Fix . fromString
data Type = TyFun data Type = TyFun
| TyVar Name | TyVar Name
| TyApp Type Type | TyApp Type Type
| TyCon Name | TyCon Name
| TyForall Var Type deriving (Show, Read, Lift, Eq)
| TyKindType
deriving (Show, Eq, Lift)
type Kind = Type
-- data TyCon = MkTyCon Name Kind
-- deriving (Eq, Show, Lift)
data Var = MkVar Name Type
deriving (Eq, Show, Lift)
pattern (:^) :: Name -> Type -> Var
pattern n :^ t = MkVar n t
instance Hashable Var where
hashWithSalt s (MkVar n _) = hashWithSalt s n
pattern Con :: Tag -> Int -> Expr b
pattern Con t a = Fix (ConF t a)
pattern Var :: Name -> Expr b
pattern Var b = Fix (VarF b)
pattern App :: Expr b -> Expr b -> Expr b
pattern App f x = Fix (AppF f x)
pattern Lam :: [b] -> Expr b -> Expr b
pattern Lam bs e = Fix (LamF bs e)
pattern Let :: Rec -> [Binding b] -> Expr b -> Expr b
pattern Let r bs e = Fix (LetF r bs e)
pattern Case :: Expr b -> [Alter b] -> Expr b
pattern Case e as = Fix (CaseF e as)
pattern Type :: Type -> Expr b
pattern Type t = Fix (TypeF t)
pattern Lit :: Lit -> Expr b
pattern Lit t = Fix (LitF t)
pattern TyInt :: Type pattern TyInt :: Type
pattern TyInt = TyCon "Int#" pattern TyInt = TyCon "Int#"
infixr 1 :->
pattern (:->) :: Type -> Type -> Type
pattern a :-> b = TyApp (TyApp TyFun a) b
data BindingF b a = BindingF b (ExprF b a)
deriving (Functor, Foldable, Traversable)
type Binding b = BindingF b (Fix (ExprF b))
type Binding' = Binding Name
-- collapse = foldFix embed
pattern Binding :: b -> Expr b -> Binding b
pattern Binding k v <- BindingF k (wrapFix -> v)
where Binding k v = BindingF k (unwrapFix v)
{-# COMPLETE (:=) #-}
{-# COMPLETE Binding #-}
infixl 1 :=
pattern (:=) :: b -> Expr b -> Binding b
pattern k := v = Binding k v
infixl 2 :$ infixl 2 :$
pattern (:$) :: Expr b -> Expr b -> Expr b pattern (:$) :: Expr b -> Expr b -> Expr b
pattern f :$ x = App f x pattern f :$ x = App f x
data AlterF b a = AlterF AltCon [b] (ExprF b a) infixl 2 :@
deriving (Functor, Foldable, Traversable) pattern (:@) :: Type -> Type -> Type
pattern f :@ x = TyApp f x
pattern Alter :: AltCon -> [b] -> Expr b -> Alter b infixr 1 :->
pattern Alter con bs e <- AlterF con bs (wrapFix -> e) pattern (:->) :: Type -> Type -> Type
where Alter con bs e = AlterF con bs (unwrapFix e) pattern a :-> b = TyApp (TyApp TyFun a) b
type Alter b = AlterF b (Fix (ExprF b)) {-# COMPLETE Binding :: Binding #-}
{-# COMPLETE (:=) :: Binding #-}
data Binding b = Binding b (Expr b)
deriving (Show, Read, Lift)
type Alter' = Alter Name deriving instance (Eq b) => Eq (Binding b)
-- pattern Alter :: AltCon -> [b] -> Expr b -> Alter b infixl 1 :=
-- pattern Alter con bs e <- Fix (AlterF con bs (undefined -> e)) pattern (:=) :: b -> Expr b -> Binding b
-- where Alter con bs e = Fix (AlterF con bs undefined) pattern k := v = Binding k v
data Alter b = Alter AltCon [b] (Expr b)
deriving (Show, Read, Lift)
deriving instance (Eq b) => Eq (Alter b)
newtype Pragma = Pragma [T.Text] newtype Pragma = Pragma [T.Text]
data Rec = Rec data Rec = Rec
| NonRec | NonRec
deriving (Show, Eq, Lift) deriving (Show, Read, Eq, Lift)
data AltCon = AltData Name data AltCon = AltData Name
| AltTag Tag | AltTag Tag
| AltLit Lit | AltLit Lit
| AltDefault | AltDefault
deriving (Show, Eq, Lift) deriving (Show, Read, Eq, Lift)
newtype Lit = IntL Int newtype Lit = IntL Int
deriving (Show, Eq, Lift) deriving (Show, Read, Eq, Lift)
type Name = T.Text type Name = T.Text
type Tag = Int type Tag = Int
data ScDef b = ScDef b [b] (Expr b) data ScDef b = ScDef b [b] (Expr b)
deriving (Show, Lift)
-- unliftScDef :: ScDef b -> Expr b unliftScDef :: ScDef b -> Expr b
-- unliftScDef (ScDef _ as e) = Lam as e unliftScDef (ScDef _ as e) = Lam as e
data Module b = Module (Maybe (Name, [Name])) (Program b) data Module b = Module (Maybe (Name, [Name])) (Program b)
deriving (Show, Lift)
data Program b = Program data Program b = Program
{ _programScDefs :: [ScDef b] { _programScDefs :: [ScDef b]
, _programTypeSigs :: HashMap b Type , _programTypeSigs :: HashMap b Type
, _programDataTags :: HashMap Name (Tag, Int) , _programDataTags :: HashMap b (Tag, Int)
-- ^ map constructors to their tag and arity -- ^ map constructors to their tag and arity
} }
deriving (Generic) deriving (Show, Lift, Generic)
deriving (Semigroup, Monoid) deriving (Semigroup, Monoid)
via Generically (Program b) via Generically (Program b)
makeLenses ''Program makeLenses ''Program
-- makeBaseFunctor ''Expr makeBaseFunctor ''Expr
pure [] pure []
-- this is a weird optic, stronger than Lens and Prism, but weaker than Iso. -- this is a weird optic, stronger than Lens and Prism, but weaker than Iso.
@@ -236,115 +163,65 @@ type ExprF' = ExprF Name
type Program' = Program Name type Program' = Program Name
type Expr' = Expr Name type Expr' = Expr Name
type ScDef' = ScDef Name type ScDef' = ScDef Name
-- type Alter' = Alter Name type Alter' = Alter Name
-- type Binding' = Binding Name type Binding' = Binding Name
-- instance IsString (Expr b) where instance IsString (Expr b) where
-- fromString = Var . fromString fromString = Var . fromString
instance IsString Type where
fromString "" = error "IsString Type string may not be empty"
fromString s
| isUpper c = TyCon . fromString $ s
| otherwise = TyVar . fromString $ s
where (c:_) = s
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
class HasRHS s t a b | s -> a, t -> b, s b -> t, t a -> s where class HasRHS s t a b | s -> a, t -> b, s b -> t, t a -> s where
_rhs :: Lens s t a b _rhs :: Lens s t a b
instance HasRHS (AlterF b a) (AlterF b a') (ExprF b a) (ExprF b a') where instance HasRHS (Alter b) (Alter b) (Expr b) (Expr b) where
_rhs = lens _rhs = lens
(\ (AlterF _ _ e) -> e) (\ (Alter _ _ e) -> e)
(\ (AlterF t as _) e' -> AlterF t as e') (\ (Alter t as _) e' -> Alter t as e')
instance HasRHS (ScDef b) (ScDef b) (Expr b) (Expr b) where instance HasRHS (ScDef b) (ScDef b) (Expr b) (Expr b) where
_rhs = lens _rhs = lens
(\ (ScDef _ _ e) -> e) (\ (ScDef _ _ e) -> e)
(\ (ScDef n as _) e' -> ScDef n as e') (\ (ScDef n as _) e' -> ScDef n as e')
instance HasRHS (BindingF b a) (BindingF b' a') (ExprF b a) (ExprF b' a') instance HasRHS (Binding b) (Binding b) (Expr b) (Expr b) where
_rhs = lens
(\ (_ := e) -> e)
(\ (k := _) e' -> k := e')
class HasLHS s t a b | s -> a, t -> b, s b -> t, t a -> s where class HasLHS s t a b | s -> a, t -> b, s b -> t, t a -> s where
_lhs :: Lens s t a b _lhs :: Lens s t a b
instance HasLHS (Alter b) (Alter b) (AltCon, [b]) (AltCon, [b]) where
_lhs = lens
(\ (Alter a bs _) -> (a,bs))
(\ (Alter _ _ e) (a',bs') -> Alter a' bs' e)
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
-- (\ (k := _) -> k) (\ (k := _) -> k)
-- (\ (_ := e) k' -> k' := e) (\ (_ := e) k' -> k' := e)
-- | This is not a valid isomorphism for expressions containing lambdas whose
-- bodies are themselves lambdas with multiple arguments:
--
-- >>> [coreExpr|\x -> \y z -> x|] ^. from (from formalising)
-- Lam ["x"] (Lam ["y"] (Lam ["z"] (Var "x")))
-- >>> [coreExpr|\x -> \y z -> x|]
-- Lam ["x"] (Lam ["y","z"] (Var "x"))
--
-- For this reason, it's best to consider 'formalising' as if it were two
-- unrelated unidirectional getters.
formalising :: Iso (Expr a) (Expr b) (Expr a) (Expr b)
formalising = iso sa bt where
sa :: Expr a -> Expr a
sa = ana \case
Lam [b] e -> LamF [b] e
Lam (b:bs) e -> LamF [b] (Lam bs e)
Let r (b:bs) e -> LetF r [b] (Let r bs e)
x -> project x
bt :: Expr b -> Expr b
bt = cata \case
LamF [b] (Lam bs e) -> Lam (b:bs) e
LetF r [b] (Let r' bs e) | r == r' -> Let r (b:bs) e
x -> embed x
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
newtype WithTerseBinds a = WithTerseBinds a -- TODO: print type sigs with corresponding scdefs
-- TODO: emit pragmas for datatags
class MakeTerse a where
type AsTerse a :: Data.Kind.Type
asTerse :: a -> AsTerse a
instance MakeTerse Var where
type AsTerse Var = Name
asTerse (MkVar n _) = n
instance (Hashable b, Pretty b, Pretty (AsTerse b), MakeTerse b)
=> Pretty (WithTerseBinds (Program b)) where
pretty (WithTerseBinds p)
= (datatags <> "\n")
$+$ defs
where
datatags = ifoldrOf (programDataTags . ifolded) cataDataTag mempty p
defs = vlinesOf (programJoinedDefs . to prettyGroup) p
programJoinedDefs :: Fold (Program b) (These (b, Type) (ScDef b))
programJoinedDefs = folding $ \p ->
foldMapOf programTypeSigs thisTs p
`u` foldMapOf programScDefs thatSc p
where u = H.unionWith unionThese
thisTs = ifoldMap @b @(HashMap b)
(\n t -> H.singleton n (This (n,t)))
thatSc = foldMap $ \sc ->
H.singleton (sc ^. _lhs . _1) (That sc)
prettyGroup :: These (b, Type) (ScDef b) -> Doc
prettyGroup = bifoldr vs vs mempty
. bimap (uncurry prettyTySig')
(pretty . WithTerseBinds)
where vs = vsepTerm ";"
cataDataTag n (t,a) acc = prettyDataTag n t a $+$ acc
instance (Hashable b, Pretty b) => Pretty (Program b) where instance (Hashable b, Pretty b) => Pretty (Program b) where
pretty p = (datatags <> "\n") pretty p = ifoldrOf (programDataTags . ifolded) cataDataTag mempty p
$+$ defs $+$ vlinesOf (programJoinedDefs . to prettyGroup) p
where where
datatags = ifoldrOf (programDataTags . ifolded) cataDataTag mempty p
defs = vlinesOf (programJoinedDefs . to prettyGroup) p
programJoinedDefs :: Fold (Program b) (These (b, Type) (ScDef b)) programJoinedDefs :: Fold (Program b) (These (b, Type) (ScDef b))
programJoinedDefs = folding $ \p -> programJoinedDefs = folding $ \p ->
foldMapOf programTypeSigs thisTs p foldMapOf programTypeSigs thisTs p
@@ -357,339 +234,67 @@ instance (Hashable b, Pretty b) => Pretty (Program b) where
H.singleton (sc ^. _lhs . _1) (That sc) H.singleton (sc ^. _lhs . _1) (That sc)
prettyGroup :: These (b, Type) (ScDef b) -> Doc prettyGroup :: These (b, Type) (ScDef b) -> Doc
prettyGroup = bifoldr vs vs mempty prettyGroup = bifoldr ($$) ($$) mempty . bimap prettyTySig pretty
. bimap (uncurry prettyTySig) pretty
where vs = vsepTerm ";" prettyTySig (n,t) = hsep [ttext n, "::", pretty t]
unionThese (This a) (That b) = These a b
unionThese (That b) (This a) = These a b
unionThese (These a b) _ = These a b
cataDataTag n (t,a) acc = prettyDataTag n t a $+$ acc cataDataTag n (t,a) acc = prettyDataTag n t a $+$ acc
unionThese :: These a b -> These a b -> These a b prettyDataTag n t a =
unionThese (This a) (That b) = These a b hsep ["{-#", "PackData", ttext n, ttext t, ttext a, "#-}"]
unionThese (That b) (This a) = These a b
unionThese (These a b) _ = These a b
prettyDataTag :: (Pretty n, Pretty t, Pretty a)
=> n -> t -> a -> Doc
prettyDataTag n t a =
hsep ["{-#", "PackData", ttext n, ttext t, ttext a, "#-}"]
prettyTySig :: (Pretty n, Pretty t) => n -> t -> Doc
prettyTySig n t = hsep [ttext n, ":", pretty t]
prettyTySig' :: (MakeTerse n, Pretty (AsTerse n), Pretty t) => n -> t -> Doc
prettyTySig' n t = hsep [ttext (asTerse n), ":", pretty t]
-- Pretty Type
-- TyApp | appPrec | left
-- (:->) | appPrec-1 | right
instance Pretty Type where instance Pretty Type where
prettyPrec _ (TyVar n) = ttext n prettyPrec _ (TyVar n) = ttext n
prettyPrec _ TyFun = "(->)" prettyPrec _ TyFun = "(->)"
prettyPrec _ (TyCon n) = ttext n prettyPrec _ (TyCon n) = ttext n
prettyPrec p (a :-> b) = maybeParens (p>appPrec-1) $ prettyPrec p (a :-> b) = maybeParens (p>0) $
hsep [prettyPrec appPrec a, "->", prettyPrec (appPrec-1) b] hsep [prettyPrec 1 a, "->", prettyPrec 0 b]
prettyPrec p (TyApp f x) = maybeParens (p>appPrec) $ prettyPrec p (TyApp f x) = maybeParens (p>1) $
prettyPrec appPrec f <+> prettyPrec appPrec1 x prettyPrec 1 f <+> prettyPrec 2 x
prettyPrec p (TyForall a m) = maybeParens (p>appPrec-2) $
"" <+> (prettyPrec appPrec1 a <> ".") <+> pretty m
prettyPrec _ TyKindType = "Type"
instance (Pretty b, Pretty (AsTerse b), MakeTerse b)
=> Pretty (WithTerseBinds (ScDef b)) where
pretty (WithTerseBinds sc) = hsep [name, as, "=", hang empty 1 e]
where
name = ttext $ sc ^. _lhs . _1 . to asTerse
as = sc & hsepOf (_lhs . _2 . each . to asTerse . to ttext)
e = pretty $ sc ^. _rhs
instance (Pretty b) => Pretty (ScDef b) where instance (Pretty b) => Pretty (ScDef b) where
pretty sc = hsep [name, as, "=", hang empty 1 e] pretty sc = hsep [name, as, "=", hang empty 1 e, ";"]
where where
name = ttext $ sc ^. _lhs . _1 name = ttext $ sc ^. _lhs . _1
as = sc & hsepOf (_lhs . _2 . each . to ttext) as = sc & hsepOf (_lhs . _2 . each . to ttext)
e = pretty $ sc ^. _rhs e = pretty $ sc ^. _rhs
instance (Pretty (f (Fix f))) => Pretty (Fix f) where instance (Pretty b) => Pretty (Expr b) where
prettyPrec d (Fix f) = prettyPrec d f prettyPrec _ (Var n) = ttext n
prettyPrec _ (Con t a) = "Pack{" <> (ttext t <+> ttext a) <> "}"
-- Pretty Expr prettyPrec _ (Lam bs e) = hsep ["λ", hsep (prettyPrec 1 <$> bs), "->", pretty e]
-- LamF | appPrec1 | right prettyPrec _ (Let r bs e) = hsep [word, explicitLayout bs]
-- AppF | appPrec | left $+$ hsep ["in", pretty e]
where word = if r == Rec then "letrec" else "let"
instance (Pretty b, Pretty a) => Pretty (ExprF b a) where prettyPrec p (App f x) = maybeParens (p>0) $
prettyPrec _ (VarF n) = ttext n prettyPrec 0 f <+> prettyPrec 1 x
prettyPrec _ (ConF t a) = "Pack{" <> (ttext t <+> ttext a) <> "}" prettyPrec _ (Lit l) = pretty l
prettyPrec p (LamF bs e) = maybeParens (p>0) $ prettyPrec p (Case e as) = maybeParens (p>0) $
hsep ["λ", hsep (prettyPrec appPrec1 <$> bs), "->", pretty e]
prettyPrec p (LetF r bs e) = maybeParens (p>0)
$ hsep [pretty r, explicitLayout bs]
$+$ hsep ["in", pretty e]
prettyPrec p (AppF f x) = maybeParens (p>appPrec) $
prettyPrec appPrec f <+> prettyPrec appPrec1 x
prettyPrec p (LitF l) = prettyPrec p l
prettyPrec p (CaseF e as) = maybeParens (p>0) $
"case" <+> pretty e <+> "of" "case" <+> pretty e <+> "of"
$+$ nest 2 (explicitLayout as) $+$ nest 2 (explicitLayout as)
prettyPrec p (TypeF t) = "@" <> prettyPrec appPrec1 t
instance Pretty Rec where instance (Pretty b) => Pretty (Alter b) where
pretty Rec = "letrec" pretty (Alter c as e) =
pretty NonRec = "let"
instance (Pretty b, Pretty a) => Pretty (AlterF b a) where
pretty (AlterF c as e) =
hsep [pretty c, hsep (pretty <$> as), "->", pretty e] hsep [pretty c, hsep (pretty <$> as), "->", pretty e]
instance Pretty AltCon where instance Pretty AltCon where
pretty (AltData n) = ttext n pretty (AltData n) = ttext n
pretty (AltLit l) = pretty l pretty (AltLit l) = pretty l
pretty (AltTag t) = "<" <> ttext t <> ">" pretty (AltTag t) = ttext t
pretty AltDefault = "_" pretty AltDefault = "_"
instance Pretty Lit where instance Pretty Lit where
pretty (IntL n) = ttext n pretty (IntL n) = ttext n
instance (Pretty b, Pretty a) => Pretty (BindingF b a) where instance (Pretty b) => Pretty (Binding b) where
pretty (BindingF k v) = hsep [pretty k, "=", pretty v] pretty (k := v) = hsep [pretty k, "=", pretty v]
explicitLayout :: (Pretty a) => [a] -> Doc explicitLayout :: (Pretty a) => [a] -> Doc
explicitLayout as = vcat inner <+> "}" where explicitLayout as = vcat inner <+> "}" where
inner = zipWith (<+>) delims (pretty <$> as) inner = zipWith (<+>) delims (pretty <$> as)
delims = "{" : repeat ";" delims = "{" : repeat ";"
instance Pretty Var where
prettyPrec p (MkVar n t) = maybeParens (p>0) $
hsep [pretty n, ":", pretty t]
--------------------------------------------------------------------------------
-- instance Functor Alter where
-- fmap f (Alter con bs e) = Alter con (f <$> bs) e'
-- where
-- e' = foldFix (embed . bimap' f id) e
-- bimap' = $(makeBimap ''ExprF)
-- instance Foldable Alter where
-- instance Traversable Alter where
-- instance Functor Binding where
-- instance Foldable Binding where
-- instance Traversable Binding where
liftShowsPrecExpr :: (Show b)
=> (Int -> a -> ShowS)
-> ([a] -> ShowS)
-> Int -> ExprF b a -> ShowS
liftShowsPrecExpr = $(makeLiftShowsPrec ''ExprF)
showsPrec1Expr :: (Show b, Show a)
=> Int -> ExprF b a -> ShowS
showsPrec1Expr = $(makeShowsPrec1 ''ExprF)
instance (Show b) => Show1 (AlterF b) where
liftShowsPrec sp spl d (AlterF con bs e) =
showsTernaryWith showsPrec showsPrec (liftShowsPrecExpr sp spl)
"AlterF" d con bs e
instance (Show b) => Show1 (BindingF b) where
liftShowsPrec sp spl d (BindingF k v) =
showsBinaryWith showsPrec (liftShowsPrecExpr sp spl)
"BindingF" d k v
instance (Show b, Show a) => Show (BindingF b a) where
showsPrec d (BindingF k v)
= showParen (d > 10)
$ showString "BindingF" . showChar ' '
. showsPrec 11 k . showChar ' '
. showsPrec1Expr 11 v
instance (Show b, Show a) => Show (AlterF b a) where
showsPrec d (AlterF con bs e)
= showParen (d > 10)
$ showString "AlterF" . showChar ' '
. showsPrec 11 con . showChar ' '
. showsPrec 11 bs . showChar ' '
. showsPrec1Expr 11 e
deriveShow1 ''ExprF
deriving instance (Show b, Show a) => Show (ExprF b a)
-- deriving instance (Show b, Show a) => Show (BindingF b a)
-- deriving instance (Show b, Show a) => Show (AlterF b a)
deriving instance Show b => Show (ScDef b)
deriving instance Show b => Show (Program b)
bimapExpr :: (b -> b') -> (a -> a')
-> ExprF b a -> ExprF b' a'
bimapExpr = $(makeBimap ''ExprF)
bifoldrExpr :: (b -> c -> c)
-> (a -> c -> c)
-> c -> ExprF b a -> c
bifoldrExpr = $(makeBifoldr ''ExprF)
bitraverseExpr :: Applicative f
=> (b -> f b')
-> (a -> f a')
-> ExprF b a -> f (ExprF b' a')
bitraverseExpr = $(makeBitraverse ''ExprF)
instance Bifunctor AlterF where
bimap f g (AlterF con bs e) = AlterF con (f <$> bs) (bimapExpr f g e)
instance Bifunctor BindingF where
bimap f g (BindingF k v) = BindingF (f k) (bimapExpr f g v)
instance Bifoldable AlterF where
bifoldr f g z (AlterF con bs e) = bifoldrExpr f g z' e where
z' = foldr f z bs
instance Bitraversable AlterF where
bitraverse f g (AlterF con bs e) =
AlterF con <$> traverse f bs <*> bitraverseExpr f g e
instance Bifoldable BindingF where
bifoldr f g z (BindingF k v) = bifoldrExpr f g (f k z) v
instance Bitraversable BindingF where
bitraverse f g (BindingF k v) =
BindingF <$> f k <*> bitraverseExpr f g v
deriveBifunctor ''ExprF
deriveBifoldable ''ExprF
deriveBitraversable ''ExprF
instance Lift b => Lift1 (ExprF b) where
lift1 (VarF k) = liftCon 'VarF (lift k)
lift1 (AppF f x) = liftCon2 'AppF (lift f) (lift x)
lift1 (LamF b e) = liftCon2 'LamF (lift b) (lift e)
lift1 (LetF r bs e) = liftCon3 'LetF (lift r) (lift bs) (lift e)
lift1 (CaseF e as) = liftCon2 'CaseF (lift e) (lift as)
lift1 (TypeF t) = liftCon 'TypeF (lift t)
lift1 (LitF l) = liftCon 'LitF (lift l)
lift1 (ConF t a) = liftCon2 'ConF (lift t) (lift a)
deriving instance (Lift b, Lift a) => Lift (ExprF b a)
deriving instance (Lift b, Lift a) => Lift (BindingF b a)
deriving instance (Lift b, Lift a) => Lift (AlterF b a)
deriving instance Lift b => Lift (ScDef b)
deriving instance Lift b => Lift (Program b)
--------------------------------------------------------------------------------
class HasApplicants1 s t a b | s -> a, t -> b, s b -> t, t a -> s where
applicants1 :: Traversal s t a b
class HasApplicants s t a b | s -> a, t -> b, s b -> t, t a -> s where
applicants :: Traversal s t a b
instance HasApplicants1 Type Type Type Type where
applicants1 k (TyApp f x) = TyApp <$> applicants1 k f <*> k x
applicants1 k x = k x
instance HasApplicants Type Type Type Type where
applicants k (TyApp f x) = TyApp <$> applicants k f <*> k x
applicants k x = pure x
-- instance HasArguments (ExprF b (Fix (ExprF b))) (ExprF b (Fix (ExprF b)))
-- (Fix (ExprF b)) (Fix (ExprF b)) where
-- arguments k (AppF f x) = AppF <$> arguments k f <*> k x
-- arguments k x = unwrapFix <$> k (wrapFix x)
-- instance HasArguments (f (Fix f)) (f (Fix f)) (Fix f) (Fix f)
-- => HasArguments (Fix f) (Fix f) (Fix f) (Fix f) where
-- arguments :: forall g. Applicative g
-- => LensLike' g (Fix f) (Fix f)
-- arguments k (Fix f) = Fix <$> arguments k f
-- arguments :: Traversal' (Expr b) (Expr b)
-- arguments k (App f x) = App <$> arguments k f <*> k x
-- arguments k x = k x
class HasBinders s t a b | s -> a, t -> b, s b -> t, t a -> s where
binders :: Traversal s t a b
instance HasBinders (ScDef b) (ScDef b') b b' where
binders k (ScDef b as e) = ScDef <$> k b <*> traverse k as <*> binders k e
instance (Hashable b, Hashable b')
=> HasBinders (Program b) (Program b') b b' where
binders :: forall f. (Applicative f)
=> LensLike f (Program b) (Program b') b b'
binders k p
= Program
<$> traverse (binders k) (_programScDefs p)
<*> (getAp . ifoldMap toSingleton $ _programTypeSigs p)
<*> pure (_programDataTags p)
where
toSingleton :: b -> Type -> Ap f (HashMap b' Type)
toSingleton b t = Ap $ (`H.singleton` t) <$> k b
instance HasBinders a a' b b'
=> HasBinders (ExprF b a) (ExprF b' a') b b' where
binders :: forall f. (Applicative f)
=> LensLike f (ExprF b a) (ExprF b' a') b b'
binders k = go where
go :: ExprF b a -> f (ExprF b' a')
go (LamF bs e) = LamF <$> traverse k bs <*> binders k e
go (CaseF e as) = CaseF <$> binders k e <*> eachbind as
go (LetF r bs e) = LetF r <$> eachbind bs <*> binders k e
go f = bitraverse k (binders k) f
eachbind :: forall p. Bitraversable p => [p b a] -> f [p b' a']
eachbind bs = bitraverse k (binders k) `traverse` bs
instance HasBinders a a b b'
=> HasBinders (AlterF b a) (AlterF b' a) b b' where
binders k (AlterF con bs e) =
AlterF con <$> traverse k bs <*> traverseOf binders k e
instance HasBinders a a b b'
=> HasBinders (BindingF b a) (BindingF b' a) b b' where
binders k (BindingF b v) = BindingF <$> k b <*> binders k v
instance (HasBinders (f b (Fix (f b))) (f b' (Fix (f b'))) b b')
=> HasBinders (Fix (f b)) (Fix (f b')) b b' where
binders k (Fix f) = Fix <$> binders k f
class HasArrowStops s t a b | s -> a, t -> b, s b -> t, t a -> s where
arrowStops :: Traversal s t a b
instance HasArrowStops Type Type Type Type where
arrowStops k (s :-> t) = (:->) <$> k s <*> arrowStops k t
arrowStops k t = k t
--------------------------------------------------------------------------------
liftEqExpr :: (Eq b)
=> (a -> a' -> Bool)
-> ExprF b a -> ExprF b a' -> Bool
liftEqExpr = $(makeLiftEq ''ExprF)
instance (Eq b, Eq a) => Eq (BindingF b a) where
BindingF ka va == BindingF kb vb =
ka == kb && va `eq` vb
where eq = liftEqExpr (==)
instance (Eq b, Eq a) => Eq (AlterF b a) where
AlterF cona bsa ea == AlterF conb bsb eb =
cona == conb && bsa == bsb && ea `eq` eb
where eq = liftEqExpr (==)
instance (Eq b) => Eq1 (AlterF b) where
liftEq f (AlterF cona bsa ea) (AlterF conb bsb eb) =
cona == conb && bsa == bsb && ea `eq` eb
where eq = liftEqExpr f
instance (Eq b) => Eq1 (BindingF b) where
liftEq f (BindingF ka va) (BindingF kb vb) =
ka == kb && va `eq` vb
where eq = liftEqExpr f
deriveEq1 ''ExprF
deriving instance (Eq b, Eq a) => Eq (ExprF b a)
makePrisms ''BindingF
makePrisms ''Var

View File

@@ -1,235 +0,0 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedLists #-}
module Core.SystemF
( lintCoreProgR
)
where
--------------------------------------------------------------------------------
import GHC.Generics (Generic, Generically(..))
import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as H
import Data.Function (on)
import Data.Traversable
import Data.Foldable
import Data.List.Extra
import Control.Monad.Utils
import Control.Monad
import Data.Text qualified as T
import Data.Pretty
import Text.Printf
import Control.Comonad
import Control.Comonad.Cofree
import Data.Fix
import Data.Functor
import Control.Lens hiding ((:<))
import Control.Lens.Unsound
import Compiler.RLPC
import Compiler.RlpcError
import Core
--------------------------------------------------------------------------------
data Gamma = Gamma
{ _gammaVars :: HashMap Name Type
, _gammaTyVars :: HashMap Name Kind
, _gammaTyCons :: HashMap Name Kind
}
deriving (Generic)
deriving (Semigroup, Monoid)
via (Generically Gamma)
makeLenses ''Gamma
lintCoreProgR :: (Monad m) => Program Var -> RLPCT m (Program Name)
lintCoreProgR = undefined
lint :: Program Var -> Program Name
lint = undefined
type ET = Cofree (ExprF Var) Type
type SysF = Either SystemFError
data SystemFError = SystemFErrorUndefinedVariable Name
| SystemFErrorKindMismatch Kind Kind
| SystemFErrorCouldNotMatch Type Type
deriving Show
instance IsRlpcError SystemFError where
liftRlpcError = \case
SystemFErrorUndefinedVariable n ->
undefinedVariableErr n
SystemFErrorKindMismatch k k' ->
Text [ T.pack $ printf "Could not match kind `%s' with `%s'"
(pretty k) (pretty k')
]
SystemFErrorCouldNotMatch t t' ->
Text [ T.pack $ printf "Could not match type `%s' with `%s'"
(pretty t) (pretty t')
]
justLintCoreExpr = fmap (fmap (prettyPrec appPrec1)) . lintE demoContext
lintE :: Gamma -> Expr Var -> SysF ET
lintE g = \case
Var n -> lookupVar g n <&> (:< VarF n)
Lit (IntL n) -> pure $ TyInt :< LitF (IntL n)
Type t -> kindOf g t <&> (:< TypeF t)
App f x
-- type application
| Right (TyForall (a :^ k) m :< f') <- lintE g f
, Right (k' :< TypeF t) <- lintE g x
, k == k'
-> pure $ subst a t m :< f'
-- value application
| Right fw@((s :-> t) :< _) <- lintE g f
, Right xw@(s' :< _) <- lintE g x
, s == s'
-> pure $ t :< AppF fw xw
Lam bs e -> do
e'@(t :< _) <- lintE g' e
pure $ foldr arrowify t bs :< LamF bs e'
where
g' = foldMap suppl bs <> g
suppl (MkVar n t)
| isKind t = mempty & gammaTyVars %~ H.insert n t
| otherwise = mempty & gammaVars %~ H.insert n t
arrowify (MkVar n s) s'
| isKind s = TyForall (n :^ s) s'
| otherwise = s :-> s'
Let Rec bs e -> do
e'@(t :< _) <- lintE g' e
bs' <- (uncurry checkBind . (_2 %~ wrapFix)) `traverse` binds
pure $ t :< LetF Rec bs' e'
where
binds = bs ^.. each . _BindingF
vs = binds ^.. each . _1 . _MkVar
g' = supplementVars vs g
checkBind v@(MkVar n t) e = case lintE g' e of
Right (t' :< e') | t == t' -> Right (BindingF v e')
| otherwise -> Left (SystemFErrorCouldNotMatch t t')
Left e -> Left e
Let NonRec bs e -> do
(g',bs') <- mapAccumLM checkBind g bs
e'@(t :< _) <- lintE g' e
pure $ t :< LetF NonRec bs' e'
where
checkBind :: Gamma -> BindingF Var (Expr Var)
-> SysF (Gamma, BindingF Var ET)
checkBind g (BindingF v@(n :^ t) e) = case lintE g (wrapFix e) of
Right (t' :< e')
| t == t' -> Right (supplementVar n t g, BindingF v e')
| otherwise -> Left (SystemFErrorCouldNotMatch t t')
Left e -> Left e
Case e as -> do
e'@(et :< _) <- lintE g e
(ts,as') <- unzip <$> checkAlt et `traverse` as
case allUnify ts of
Just err -> Left err
Nothing -> pure $ head ts :< CaseF e' as'
where
checkAlt :: Type -> Alter Var -> SysF (Type, AlterF Var ET)
checkAlt scrutineeType (AlterF (AltData con) bs e) = do
ct <- lookupVar g con
ct' <- foldrMOf applicants (elimForall g) ct scrutineeType
zipWithM_ fzip bs (ct' ^.. arrowStops)
(t :< e') <- lintE (supplementVars (varsToPairs bs) g) (wrapFix e)
pure (t, AlterF (AltData con) bs e')
where
fzip (MkVar _ t) t'
| t == t' = Right ()
| otherwise = Left (SystemFErrorCouldNotMatch t t')
allUnify :: [Type] -> Maybe SystemFError
allUnify [] = Nothing
allUnify [t] = Nothing
allUnify (t:t':ts)
| t == t' = allUnify ts
| otherwise = Just (SystemFErrorCouldNotMatch t t')
elimForall :: Gamma -> Type -> Type -> SysF Type
elimForall g t (TyForall (n :^ k) m) = do
k' <- kindOf g t
case k == k' of
True -> pure $ subst n t m
False -> Left $ SystemFErrorKindMismatch k k'
elimForall _ m _ = pure m
varsToPairs :: [Var] -> [(Name, Type)]
varsToPairs = toListOf (each . _MkVar)
checkAgainst :: Gamma -> Var -> Expr Var -> SysF ET
checkAgainst g v@(MkVar n t) e = case lintE g e of
Right e'@(t' :< _) | t == t' -> Right e'
| otherwise -> Left (SystemFErrorCouldNotMatch t t')
Left a -> Left a
supplementVars :: [(Name, Type)] -> Gamma -> Gamma
supplementVars vs = gammaVars <>~ H.fromList vs
supplementVar :: Name -> Type -> Gamma -> Gamma
supplementVar n t = gammaVars %~ H.insert n t
supplementTyVar :: Name -> Kind -> Gamma -> Gamma
supplementTyVar n t = gammaTyVars %~ H.insert n t
subst :: Name -> Type -> Type -> Type
subst k v (TyVar n) | k == n = v
subst k v (TyForall (MkVar n k') t)
| k /= n = TyForall (MkVar n k') (subst k v t)
| otherwise = TyForall (MkVar n k') t
subst k v (TyApp f x) = (TyApp `on` subst k v) f x
subst _ _ x = x
isKind :: Type -> Bool
isKind (s :-> t) = isKind s && isKind t
isKind TyKindType = True
isKind _ = False
kindOf :: Gamma -> Type -> SysF Kind
kindOf g (TyVar n) = lookupTyVar g n
kindOf _ TyKindType = pure TyKindType
kindOf g (TyCon n) = lookupCon g n
kindOf _ e = error (show e)
lookupCon :: Gamma -> Name -> SysF Kind
lookupCon g n = case g ^. gammaTyCons . at n of
Just k -> Right k
Nothing -> Left (SystemFErrorUndefinedVariable n)
lookupVar :: Gamma -> Name -> SysF Type
lookupVar g n = case g ^. gammaVars . at n of
Just t -> Right t
Nothing -> Left (SystemFErrorUndefinedVariable n)
lookupTyVar :: Gamma -> Name -> SysF Kind
lookupTyVar g n = case g ^. gammaTyVars . at n of
Just k -> Right k
Nothing -> Left (SystemFErrorUndefinedVariable n)
demoContext :: Gamma
demoContext = Gamma
{ _gammaVars =
[ ("id", TyForall ("a" :^ TyKindType) $ TyVar "a" :-> TyVar "a")
, ("Just", TyForall ("a" :^ TyKindType) $
TyVar "a" :-> (TyCon "Maybe" `TyApp` TyVar "a"))
, ("Nothing", TyForall ("a" :^ TyKindType) $
TyCon "Maybe" `TyApp` TyVar "a")
]
, _gammaTyVars = []
, _gammaTyCons =
[ ("Int#", TyKindType)
, ("Maybe", TyKindType :-> TyKindType)
]
}

View File

@@ -5,8 +5,8 @@ Description : Core quasiquoters
module Core.TH module Core.TH
( coreExpr ( coreExpr
, coreProg , coreProg
-- , coreExprT , coreExprT
-- , coreProgT , coreProgT
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -33,18 +33,16 @@ coreExpr :: QuasiQuoter
coreExpr = mkqq $ lexCoreR >=> parseCoreExprR coreExpr = mkqq $ lexCoreR >=> parseCoreExprR
-- | Type-checked @coreProg@ -- | Type-checked @coreProg@
-- coreProgT :: QuasiQuoter coreProgT :: QuasiQuoter
-- coreProgT = mkqq $ lexCoreR >=> parseCoreProgR >=> checkCoreProgR coreProgT = mkqq $ lexCoreR >=> parseCoreProgR >=> checkCoreProgR
-- coreExprT :: QuasiQuoter coreExprT :: QuasiQuoter
-- coreExprT = mkqq $ lexCoreR >=> parseCoreExprR >=> checkCoreExprR g coreExprT = mkqq $ lexCoreR >=> parseCoreExprR >=> checkCoreExprR g
-- where where
-- g = [ ("+#", TyInt :-> TyInt :-> TyInt) g = [ ("+#", TyCon "Int#" :-> TyCon "Int#" :-> TyCon "Int#")
-- , ("id", TyForall (MkVar "a" TyKindType) $ , ("id", TyCon "a" :-> TyCon "a")
-- TyVar "a" :-> TyVar "a") , ("fix", (TyCon "a" :-> TyCon "a") :-> TyCon "a")
-- , ("fix", TyForall (MkVar "a" TyKindType) $ ]
-- (TyVar "a" :-> TyVar "a") :-> TyVar "a")
-- ]
mkqq :: (Lift a) => (Text -> RLPCIO a) -> QuasiQuoter mkqq :: (Lift a) => (Text -> RLPCIO a) -> QuasiQuoter
mkqq p = QuasiQuoter mkqq p = QuasiQuoter

View File

@@ -2,6 +2,8 @@ module Core.Utils
( programRhss ( programRhss
, programGlobals , programGlobals
, isAtomic , isAtomic
-- , insertModule
, extractProgram
, freeVariables , freeVariables
) )
where where
@@ -28,29 +30,34 @@ isAtomic _ = False
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
freeVariables :: Expr b -> Set b -- TODO: export list awareness
freeVariables = undefined -- insertModule :: Module b -> Program b -> Program b
-- insertModule (Module _ p) = programScDefs %~ (<>m)
-- freeVariables :: Expr' -> Set Name extractProgram :: Module b -> Program b
-- freeVariables = cata go extractProgram (Module _ p) = p
-- where
-- go :: ExprF Name (Set Name) -> Set Name
-- go (VarF k) = S.singleton k
-- -- TODO: collect free vars in rhss of bs
-- go (LetF _ bs e) = (e `S.union` esFree) `S.difference` ns
-- where
-- es = bs ^.. each . _rhs :: [Expr']
-- ns = S.fromList $ bs ^.. each . _lhs
-- -- TODO: this feels a little wrong. maybe a different scheme is
-- -- appropriate
-- esFree = foldMap id $ freeVariables <$> es
-- go (CaseF e as) = e `S.union` asFree ----------------------------------------------------------------------------------
-- where
-- -- asFree = foldMap id $ freeVariables <$> (fmap altToLam as) freeVariables :: Expr' -> Set Name
-- asFree = foldMap (freeVariables . altToLam) as freeVariables = cata go
-- -- we map alts to lambdas to avoid writing a 'freeVariablesAlt' where
-- altToLam (Alter _ ns e) = Lam ns e go :: ExprF Name (Set Name) -> Set Name
-- go (LamF bs e) = e `S.difference` (S.fromList bs) go (VarF k) = S.singleton k
-- go e = foldMap id e -- TODO: collect free vars in rhss of bs
go (LetF _ bs e) = (e `S.union` esFree) `S.difference` ns
where
es = bs ^.. each . _rhs :: [Expr']
ns = S.fromList $ bs ^.. each . _lhs
-- TODO: this feels a little wrong. maybe a different scheme is
-- appropriate
esFree = foldMap id $ freeVariables <$> es
go (CaseF e as) = e `S.union` asFree
where
asFree = foldMap id $ freeVariables <$> (fmap altToLam as)
-- we map alts to lambdas to avoid writing a 'freeVariablesAlt'
altToLam (Alter _ ns e) = Lam ns e
go (LamF bs e) = e `S.difference` (S.fromList bs)
go e = foldMap id e

View File

@@ -116,7 +116,7 @@ floatNonStrictCases g = goE
goE e goE e
traverse_ goE altBodies traverse_ goE altBodies
pure e' pure e'
goC (App f x) = App <$> goC f <*> goC x goC (f :$ x) = (:$) <$> goC f <*> goC x
goC (Let r bs e) = Let r <$> bs' <*> goE e goC (Let r bs e) = Let r <$> bs' <*> goE e
where bs' = travBs goC bs where bs' = travBs goC bs
goC (Lit l) = pure (Lit l) goC (Lit l) = pure (Lit l)
@@ -128,9 +128,10 @@ floatNonStrictCases g = goE
-- extract the right-hand sides of a list of bindings, traverse each -- extract the right-hand sides of a list of bindings, traverse each
-- one, and return the original list of bindings -- one, and return the original list of bindings
travBs :: (Expr' -> Floater Expr') -> [Binding'] -> Floater [Binding'] travBs :: (Expr' -> Floater Expr') -> [Binding'] -> Floater [Binding']
travBs c bs = undefined travBs c bs = bs ^.. each . _rhs
& traverse goC
& const (pure bs)
-- ^ ??? what the fuck? -- ^ ??? what the fuck?
-- ^ 24/02/22: what is this shit lol?
-- when provided with a case expr, floatCase will float the case into a -- when provided with a case expr, floatCase will float the case into a
-- supercombinator of its free variables. the sc is returned along with an -- supercombinator of its free variables. the sc is returned along with an

View File

@@ -28,10 +28,27 @@ import Data.Map.Strict qualified as M
import Data.List (intersect) import Data.List (intersect)
import GHC.Stack (HasCallStack) import GHC.Stack (HasCallStack)
import Control.Lens import Control.Lens
import Data.Aeson
import GHC.Generics ( Generic1, Generic
, Generically1(..), Generically(..))
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
data Heap a = Heap [Addr] (Map Addr a) data Heap a = Heap [Addr] (Map Addr a)
deriving Show deriving (Show, Generic, Generic1)
deriving (ToJSON1, FromJSON1)
via Generically1 Heap
instance ToJSON a => ToJSON (Heap a) where
toJSON (Heap as m) = toJSON m
instance FromJSON (Heap a) where
parseJSON = _
-- deriving via Generically (Heap a)
-- instance ToJSON a => ToJSON (Heap a)
-- deriving via Generically (Heap a)
-- instance FromJSON a => FromJSON (Heap a)
type Addr = Int type Addr = Int

View File

@@ -1,4 +1,3 @@
{-# LANGUAGE QuantifiedConstraints #-}
module Data.Pretty module Data.Pretty
( Pretty(..) ( Pretty(..)
, rpretty , rpretty
@@ -7,11 +6,8 @@ module Data.Pretty
, hsepOf, vsepOf , hsepOf, vsepOf
, vcatOf , vcatOf
, vlinesOf , vlinesOf
, vsepTerm
, module Text.PrettyPrint , module Text.PrettyPrint
, maybeParens , maybeParens
, appPrec
, appPrec1
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -19,13 +15,10 @@ import Text.PrettyPrint hiding ((<>))
import Text.PrettyPrint.HughesPJ hiding ((<>)) import Text.PrettyPrint.HughesPJ hiding ((<>))
import Text.Printf import Text.Printf
import Data.String (IsString(..)) import Data.String (IsString(..))
import Data.Text.Lens hiding ((:<)) import Data.Text.Lens
import Data.Monoid import Data.Monoid
import Control.Lens
-- instances
import Control.Comonad.Cofree
import Data.Text qualified as T import Data.Text qualified as T
import Control.Lens
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
class Pretty a where class Pretty a where
@@ -34,7 +27,7 @@ class Pretty a where
{-# MINIMAL pretty | prettyPrec #-} {-# MINIMAL pretty | prettyPrec #-}
pretty = prettyPrec 0 pretty = prettyPrec 0
prettyPrec = const pretty prettyPrec a _ = pretty a
rpretty :: (IsString s, Pretty a) => a -> s rpretty :: (IsString s, Pretty a) => a -> s
rpretty = fromString . render . pretty rpretty = fromString . render . pretty
@@ -52,9 +45,6 @@ instance (Show a) => Pretty (Showing a) where
deriving via Showing Int instance Pretty Int deriving via Showing Int instance Pretty Int
class (forall a. Pretty a => Pretty (f a)) => Pretty1 f where
liftPrettyPrec :: (Int -> a -> Doc) -> f a -> Doc
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ttext :: Pretty t => t -> Doc ttext :: Pretty t => t -> Doc
@@ -73,19 +63,3 @@ vlinesOf :: Getting (Endo Doc) s Doc -> s -> Doc
vlinesOf l = foldrOf l (\a b -> a $+$ "" $+$ b) mempty vlinesOf l = foldrOf l (\a b -> a $+$ "" $+$ b) mempty
-- hack(?) to separate chunks with a blankline -- hack(?) to separate chunks with a blankline
vsepTerm :: Doc -> Doc -> Doc -> Doc
vsepTerm term a b = (a <> term) $+$ b
--------------------------------------------------------------------------------
appPrec, appPrec1 :: Int
appPrec = 10
appPrec1 = 11
instance PrintfArg Doc where
formatArg d fmt
| fmtChar (vFmt 'D' fmt) == 'D' = formatString (render d) fmt'
| otherwise = errorBadFormat $ fmtChar fmt
where
fmt' = fmt { fmtChar = 's', fmtPrecision = Nothing }

View File

@@ -18,6 +18,8 @@ module GM
, finalStateOf , finalStateOf
, resultOf , resultOf
, resultOfExpr , resultOfExpr
, compile
, eval
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -42,6 +44,12 @@ import Data.String (IsString)
import Data.Heap import Data.Heap
import Debug.Trace import Debug.Trace
import Compiler.RLPC import Compiler.RLPC
-- for visualisation
import Data.Aeson hiding (Key)
import Data.Aeson.Text
import GHC.Generics (Generic, Generically(..))
import Core2Core import Core2Core
import Core import Core
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -78,7 +86,7 @@ data GmState = GmState
, _gmEnv :: Env , _gmEnv :: Env
, _gmStats :: Stats , _gmStats :: Stats
} }
deriving Show deriving (Show, Generic)
type Code = [Instr] type Code = [Instr]
type Stack = [Addr] type Stack = [Addr]
@@ -88,7 +96,7 @@ type GmHeap = Heap Node
data Key = NameKey Name data Key = NameKey Name
| ConstrKey Tag Int | ConstrKey Tag Int
deriving (Show, Eq) deriving (Show, Eq, Generic)
-- >> [ref/Instr] -- >> [ref/Instr]
data Instr = Unwind data Instr = Unwind
@@ -111,7 +119,7 @@ data Instr = Unwind
| Split Int | Split Int
| Print | Print
| Halt | Halt
deriving (Show, Eq) deriving (Show, Eq, Generic)
-- << [ref/Instr] -- << [ref/Instr]
data Node = NNum Int data Node = NNum Int
@@ -124,7 +132,7 @@ data Node = NNum Int
| NUninitialised | NUninitialised
| NConstr Tag [Addr] -- NConstr Tag Components | NConstr Tag [Addr] -- NConstr Tag Components
| NMarked Node | NMarked Node
deriving (Show, Eq) deriving (Show, Eq, Generic)
-- TODO: log executed instructions -- TODO: log executed instructions
data Stats = Stats data Stats = Stats
@@ -134,7 +142,7 @@ data Stats = Stats
, _stsDereferences :: Int , _stsDereferences :: Int
, _stsGCCycles :: Int , _stsGCCycles :: Int
} }
deriving Show deriving (Show, Generic)
instance Default Stats where instance Default Stats where
def = Stats 0 0 0 0 0 def = Stats 0 0 0 0 0
@@ -178,18 +186,48 @@ hdbgProg p hio = do
evalProgR :: (Monad m) => Program' -> RLPCT m (Node, Stats) evalProgR :: (Monad m) => Program' -> RLPCT m (Node, Stats)
evalProgR p = do evalProgR p = do
(renderOut . showState) `traverse_` states putState `traverse_` states
renderOut . showStats $ sts putStats sts
pure (res, sts) pure res
where where
renderOut r = addDebugMsg "dump-eval" $ render r ++ "\n" states = eval . compile $ p
states = eval . compile $ p res@(_, sts) = results states
final = last states
sts = final ^. gmStats putState :: Monad m => GmState -> RLPCT m ()
-- the address of the result should be the one and only stack entry putState st = do
[resAddr] = final ^. gmStack addDebugMsg "dump-eval" $ render (showState st) ++ "\n"
res = hLookupUnsafe resAddr (final ^. gmHeap) addDebugMsg "dump-eval-json" $
view strict . encodeToLazyText $ st
putStats :: Monad m => Stats -> RLPCT m ()
putStats sts = do
addDebugMsg "dump-eval" $ render (showStats sts) ++ "\n"
results :: [GmState] -> (Node, Stats)
results states = (res, sts) where
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)
-- evalProgR :: (Monad m) => Program' -> RLPCT m (Node, Stats)
-- evalProgR p = do
-- (renderOut . showState) `traverse_` states
-- renderOut . showStats $ sts
-- pure (res, sts)
-- where
-- renderOut r = do
-- addDebugMsg "dump-eval" $ render r ++ "\n"
-- addDebugMsg "dump-eval-json" $
-- view strict . encodeToLazyText $ r
-- 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
@@ -1060,3 +1098,17 @@ resultOfExpr e = resultOf $
[ ScDef "main" [] e [ ScDef "main" [] e
] ]
--------------------------------------------------------------------------------
-- visualisation
deriving via Generically Instr instance FromJSON Instr
deriving via Generically Instr instance ToJSON Instr
deriving via Generically Node instance FromJSON Node
deriving via Generically Node instance ToJSON Node
deriving via Generically Stats instance FromJSON Stats
deriving via Generically Stats instance ToJSON Stats
deriving via Generically Key instance FromJSON Key
deriving via Generically Key instance ToJSON Key
deriving via Generically GmState instance FromJSON GmState
deriving via Generically GmState instance ToJSON GmState

View File

@@ -1,17 +0,0 @@
module Misc where
--------------------------------------------------------------------------------
import Data.Functor.Classes
--------------------------------------------------------------------------------
showsTernaryWith :: (Int -> a -> ShowS)
-> (Int -> b -> ShowS)
-> (Int -> c -> ShowS)
-> String -> Int -> a -> b -> c -> ShowS
showsTernaryWith sp1 sp2 sp3 name d x y z
= showParen (d > 10)
$ showString name . showChar ' '
. sp1 11 x . showChar ' '
. sp2 11 y . showChar ' '
. sp3 11 z

View File

@@ -1,41 +0,0 @@
{-# LANGUAGE TemplateHaskell #-}
module Misc.Lift1
( Lift1(..)
, liftCon, liftCon2, liftCon3
, Lift(..)
)
where
--------------------------------------------------------------------------------
import Language.Haskell.TH hiding (Type, Name)
import Language.Haskell.TH.Syntax hiding (Type, Name)
import Language.Haskell.TH.Syntax qualified as TH
import Language.Haskell.TH.Quote
import Data.Kind qualified
import GHC.Generics
import Data.Fix
--------------------------------------------------------------------------------
class Lift1 (f :: Data.Kind.Type -> Data.Kind.Type) where
lift1 :: (Quote m, Lift t) => f t -> m Exp
liftCon :: Quote m => TH.Name -> m Exp -> m Exp
liftCon n = fmap (AppE (ConE n))
liftCon2 :: Quote m => TH.Name -> m Exp -> m Exp -> m Exp
liftCon2 n a b = do
a' <- a
b' <- b
pure $ ConE n `AppE` a' `AppE` b'
liftCon3 :: Quote m => TH.Name -> m Exp -> m Exp -> m Exp -> m Exp
liftCon3 n a b c = do
a' <- a
b' <- b
c' <- c
pure $ ConE n `AppE` a' `AppE` b' `AppE` c'
instance Lift1 f => Lift (Fix f) where
lift (Fix f) = AppE (ConE 'Fix) <$> lift1 f

View File

@@ -8,7 +8,6 @@ module Rlp.Lex
, Located(..) , Located(..)
, lexToken , lexToken
, lexStream , lexStream
, lexStream'
, lexDebug , lexDebug
, lexCont , lexCont
, popLexState , popLexState
@@ -30,7 +29,6 @@ import Data.Word
import Data.Default import Data.Default
import Control.Lens import Control.Lens
import Compiler.Types
import Debug.Trace import Debug.Trace
import Rlp.Parse.Types import Rlp.Parse.Types
} }
@@ -276,12 +274,11 @@ lexCont :: (Located RlpToken -> P a) -> P a
lexCont = (lexToken >>=) lexCont = (lexToken >>=)
lexStream :: P [RlpToken] lexStream :: P [RlpToken]
lexStream = fmap extract <$> lexStream' lexStream = do
t <- lexToken
lexStream' :: P [Located RlpToken] case t of
lexStream' = lexToken >>= \case Located _ TokenEOF -> pure [TokenEOF]
t@(Located _ TokenEOF) -> pure [t] Located _ t -> (t:) <$> lexStream
t -> (t:) <$> lexStream'
lexDebug :: (Located RlpToken -> P a) -> P a lexDebug :: (Located RlpToken -> P a) -> P a
lexDebug k = do lexDebug k = do

View File

@@ -5,17 +5,15 @@ module Rlp.Parse
, parseRlpProgR , parseRlpProgR
, parseRlpExpr , parseRlpExpr
, parseRlpExprR , parseRlpExprR
, runP'
) )
where where
import Compiler.RlpcError import Compiler.RlpcError
import Compiler.RLPC import Compiler.RLPC
import Control.Comonad.Cofree
import Rlp.Lex import Rlp.Lex
import Rlp.Syntax import Rlp.Syntax
import Rlp.Parse.Types import Rlp.Parse.Types
import Rlp.Parse.Associate import Rlp.Parse.Associate
import Control.Lens hiding (snoc, (.>), (<.), (<<~), (:<)) import Control.Lens hiding (snoc, (.>), (<.), (<<~))
import Data.List.Extra import Data.List.Extra
import Data.Fix import Data.Fix
import Data.Functor.Const import Data.Functor.Const
@@ -73,11 +71,12 @@ import Compiler.Types
%% %%
StandaloneProgram :: { Program RlpcPs SrcSpan } StandaloneProgram :: { RlpProgram RlpcPs }
StandaloneProgram : layout0(Decl) {% mkProgram $1 } StandaloneProgram : '{' Decls '}' {% mkProgram $2 }
| VL DeclsV VR {% mkProgram $2 }
StandaloneExpr :: { Expr' RlpcPs SrcSpan } StandaloneExpr :: { RlpExpr RlpcPs }
: VL Expr VR { $2 } : VL Expr VR { extract $2 }
VL :: { () } VL :: { () }
VL : vlbrace { () } VL : vlbrace { () }
@@ -86,105 +85,125 @@ VR :: { () }
VR : vrbrace { () } VR : vrbrace { () }
| error { () } | error { () }
VS :: { () } Decls :: { [Decl' RlpcPs] }
VS : ';' { () } Decls : Decl ';' Decls { $1 : $3 }
| vsemi { () } | Decl ';' { [$1] }
| Decl { [$1] }
Decl :: { Decl RlpcPs SrcSpan } DeclsV :: { [Decl' RlpcPs] }
DeclsV : Decl VS DeclsV { $1 : $3 }
| Decl VS { [$1] }
| Decl { [$1] }
VS :: { Located RlpToken }
VS : ';' { $1 }
| vsemi { $1 }
Decl :: { Decl' RlpcPs }
: FunDecl { $1 } : FunDecl { $1 }
| TySigDecl { $1 } | TySigDecl { $1 }
| DataDecl { $1 } | DataDecl { $1 }
| InfixDecl { $1 } | InfixDecl { $1 }
TySigDecl :: { Decl RlpcPs SrcSpan } TySigDecl :: { Decl' RlpcPs }
: Var '::' Type { TySigD [$1] $3 } : Var '::' Type { (\e -> TySigD [extract e]) <<~ $1 <~> $3 }
InfixDecl :: { Decl RlpcPs SrcSpan } InfixDecl :: { Decl' RlpcPs }
: InfixWord litint InfixOp {% mkInfixD $1 ($2 ^. _litint) $3 } : InfixWord litint InfixOp { $1 =>> \w ->
InfixD (extract $1) (extractInt $ extract $2)
(extract $3) }
InfixWord :: { Assoc } InfixWord :: { Located Assoc }
: infixl { InfixL } : infixl { $1 \$> InfixL }
| infixr { InfixR } | infixr { $1 \$> InfixR }
| infix { Infix } | infix { $1 \$> Infix }
DataDecl :: { Decl RlpcPs SrcSpan } DataDecl :: { Decl' RlpcPs }
: data Con TyParams '=' DataCons { DataD $2 $3 $5 } : data Con TyParams '=' DataCons { $1 \$> DataD (extract $2) $3 $5 }
TyParams :: { [PsName] } TyParams :: { [PsName] }
: {- epsilon -} { [] } : {- epsilon -} { [] }
| TyParams varname { $1 `snoc` extractName $2 } | TyParams varname { $1 `snoc` (extractName . extract $ $2) }
DataCons :: { [ConAlt RlpcPs] } DataCons :: { [ConAlt RlpcPs] }
: DataCons '|' DataCon { $1 `snoc` $3 } : DataCons '|' DataCon { $1 `snoc` $3 }
| DataCon { [$1] } | DataCon { [$1] }
DataCon :: { ConAlt RlpcPs } DataCon :: { ConAlt RlpcPs }
: Con Type1s { ConAlt $1 $2 } : Con Type1s { ConAlt (extract $1) $2 }
Type1s :: { [Ty RlpcPs] } Type1s :: { [RlpType' RlpcPs] }
: {- epsilon -} { [] } : {- epsilon -} { [] }
| Type1s Type1 { $1 `snoc` $2 } | Type1s Type1 { $1 `snoc` $2 }
Type1 :: { Ty RlpcPs } Type1 :: { RlpType' RlpcPs }
: '(' Type ')' { $2 } : '(' Type ')' { $2 }
| conname { ConT (extractName $1) } | conname { fmap ConT (mkPsName $1) }
| varname { VarT (extractName $1) } | varname { fmap VarT (mkPsName $1) }
Type :: { Ty RlpcPs } Type :: { RlpType' RlpcPs }
: Type '->' Type { FunT $1 $3 } : Type '->' Type { FunT <<~ $1 <~> $3 }
| TypeApp { $1 } | TypeApp { $1 }
TypeApp :: { Ty RlpcPs } TypeApp :: { RlpType' RlpcPs }
: Type1 { $1 } : Type1 { $1 }
| TypeApp Type1 { AppT $1 $2 } | TypeApp Type1 { AppT <<~ $1 <~> $2 }
FunDecl :: { Decl RlpcPs SrcSpan } FunDecl :: { Decl' RlpcPs }
FunDecl : Var Params '=' Expr { FunD $1 $2 $4 Nothing } FunDecl : Var Params '=' Expr { $4 =>> \e ->
FunD (extract $1) $2 e Nothing }
Params :: { [Pat RlpcPs] } Params :: { [Pat' RlpcPs] }
Params : {- epsilon -} { [] } Params : {- epsilon -} { [] }
| Params Pat1 { $1 `snoc` $2 } | Params Pat1 { $1 `snoc` $2 }
Pat :: { Pat RlpcPs } Pat :: { Pat' RlpcPs }
: Con Pat1s { ConP $1 $2 } : Con Pat1s { $1 =>> \cn ->
ConP (extract $1) $2 }
| Pat1 { $1 } | Pat1 { $1 }
Pat1s :: { [Pat RlpcPs] } Pat1s :: { [Pat' RlpcPs] }
: Pat1s Pat1 { $1 `snoc` $2 } : Pat1s Pat1 { $1 `snoc` $2 }
| Pat1 { [$1] } | Pat1 { [$1] }
Pat1 :: { Pat RlpcPs } Pat1 :: { Pat' RlpcPs }
: Con { ConP $1 [] } : Con { fmap (`ConP` []) $1 }
| Var { VarP $1 } | Var { fmap VarP $1 }
| Lit { LitP $1 } | Lit { LitP <<= $1 }
| '(' Pat ')' { $2 } | '(' Pat ')' { $1 .> $2 <. $3 }
Expr :: { Expr' RlpcPs SrcSpan } Expr :: { RlpExpr' RlpcPs }
-- infixities delayed till next release :( -- infixities delayed till next release :(
-- : Expr1 InfixOp Expr { undefined } -- : Expr1 InfixOp Expr { $2 =>> \o ->
: AppExpr { $1 } -- OAppE (extract o) $1 $3 }
| TempInfixExpr { $1 } : TempInfixExpr { $1 }
| LetExpr { $1 } | LetExpr { $1 }
| CaseExpr { $1 } | CaseExpr { $1 }
| AppExpr { $1 }
TempInfixExpr :: { Expr' RlpcPs SrcSpan } TempInfixExpr :: { RlpExpr' RlpcPs }
TempInfixExpr : Expr1 InfixOp TempInfixExpr {% tempInfixExprErr $1 $3 } TempInfixExpr : Expr1 InfixOp TempInfixExpr {% tempInfixExprErr $1 $3 }
| Expr1 InfixOp Expr1 { nolo' $ InfixEF $2 $1 $3 } | Expr1 InfixOp Expr1 { $2 =>> \o ->
OAppE (extract o) $1 $3 }
AppExpr :: { Expr' RlpcPs SrcSpan } AppExpr :: { RlpExpr' RlpcPs }
: Expr1 { $1 } : Expr1 { $1 }
| AppExpr Expr1 { comb2 AppEF $1 $2 } | AppExpr Expr1 { AppE <<~ $1 <~> $2 }
LetExpr :: { Expr' RlpcPs SrcSpan } LetExpr :: { RlpExpr' RlpcPs }
: let layout1(Binding) in Expr { nolo' $ LetEF NonRec $2 $4 } : let layout1(Binding) in Expr { $1 \$> LetE $2 $4 }
| letrec layout1(Binding) in Expr { nolo' $ LetEF Rec $2 $4 } | letrec layout1(Binding) in Expr { $1 \$> LetrecE $2 $4 }
CaseExpr :: { Expr' RlpcPs SrcSpan } CaseExpr :: { RlpExpr' RlpcPs }
: case Expr of layout0(Alt) { nolo' $ CaseEF $2 $4 } : case Expr of layout0(CaseAlt)
{ CaseE <<~ $2 <#> $4 }
-- TODO: where-binds -- TODO: where-binds
Alt :: { Alt' RlpcPs SrcSpan } CaseAlt :: { (Alt RlpcPs, Where RlpcPs) }
: Pat '->' Expr { AltA $1 (view _unwrap $3) Nothing } : Alt { ($1, []) }
Alt :: { Alt RlpcPs }
: Pat '->' Expr { AltA $1 $3 }
-- layout0(p : β) :: [β] -- layout0(p : β) :: [β]
layout0(p) : '{' layout_list0(';',p) '}' { $2 } layout0(p) : '{' layout_list0(';',p) '}' { $2 }
@@ -203,68 +222,38 @@ layout1(p) : '{' layout_list1(';',p) '}' { $2 }
layout_list1(sep,p) : p { [$1] } layout_list1(sep,p) : p { [$1] }
| layout_list1(sep,p) sep p { $1 `snoc` $3 } | layout_list1(sep,p) sep p { $1 `snoc` $3 }
Binding :: { Binding' RlpcPs SrcSpan } Binding :: { Binding' RlpcPs }
: Pat '=' Expr { PatB $1 (view _unwrap $3) } : Pat '=' Expr { PatB <<~ $1 <~> $3 }
Expr1 :: { Expr' RlpcPs SrcSpan } Expr1 :: { RlpExpr' RlpcPs }
: '(' Expr ')' { $2 } : '(' Expr ')' { $1 .> $2 <. $3 }
| Lit { nolo' $ LitEF $1 } | Lit { fmap LitE $1 }
| Var { case $1 of Located ss _ -> ss :< VarEF $1 } | Var { fmap VarE $1 }
| Con { case $1 of Located ss _ -> ss :< VarEF $1 } | Con { fmap VarE $1 }
InfixOp :: { PsName } InfixOp :: { Located PsName }
: consym { extractName $1 } : consym { mkPsName $1 }
| varsym { extractName $1 } | varsym { mkPsName $1 }
-- TODO: microlens-pro save me microlens-pro (rewrite this with prisms) -- TODO: microlens-pro save me microlens-pro (rewrite this with prisms)
Lit :: { Lit RlpcPs } Lit :: { Lit' RlpcPs }
: litint { $1 ^. to extract : litint { $1 <&> (IntL . (\ (TokenLitInt n) -> n)) }
. singular _TokenLitInt
. to IntL }
Var :: { PsName } Var :: { Located PsName }
Var : varname { $1 <&> view (singular _TokenVarName) } Var : varname { mkPsName $1 }
| varsym { $1 <&> view (singular _TokenVarSym) } | varsym { mkPsName $1 }
Con :: { PsName } Con :: { Located PsName }
: conname { $1 <&> view (singular _TokenConName) } : conname { mkPsName $1 }
{ {
parseRlpProgR :: (Monad m) => Text -> RLPCT m (Program RlpcPs SrcSpan) parseRlpExprR :: (Monad m) => Text -> RLPCT m (RlpExpr RlpcPs)
parseRlpProgR s = do
a <- liftErrorful $ pToErrorful parseRlpProg st
addDebugMsg @_ @String "dump-parsed" $ show a
pure a
where
st = programInitState s
parseRlpExprR :: (Monad m) => Text -> RLPCT m (Expr' RlpcPs SrcSpan)
parseRlpExprR s = liftErrorful $ pToErrorful parseRlpExpr st parseRlpExprR s = liftErrorful $ pToErrorful parseRlpExpr st
where where
st = programInitState s st = programInitState s
mkInfixD :: Assoc -> Int -> PsName -> P (Decl RlpcPs SrcSpan) parseRlpProgR :: (Monad m) => Text -> RLPCT m (RlpProgram RlpcPs)
mkInfixD a p ln@(Located ss 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))
)
pos <- use (psInput . aiPos)
pure $ InfixD a p ln
{--
parseRlpExprR :: (Monad m) => Text -> RLPCT m (Expr RlpcPs)
parseRlpExprR s = liftErrorful $ pToErrorful parseRlpExpr st
where
st = programInitState s
parseRlpProgR :: (Monad m) => Text -> RLPCT m (Program RlpcPs)
parseRlpProgR s = do parseRlpProgR s = do
a <- liftErrorful $ pToErrorful parseRlpProg st a <- liftErrorful $ pToErrorful parseRlpProg st
addDebugMsg @_ @String "dump-parsed" $ show a addDebugMsg @_ @String "dump-parsed" $ show a
@@ -287,48 +276,37 @@ extractInt :: RlpToken -> Int
extractInt (TokenLitInt n) = n extractInt (TokenLitInt n) = n
extractInt _ = error "extractInt: ugh" extractInt _ = error "extractInt: ugh"
mkProgram :: [Decl RlpcPs SrcSpan] -> P (Program RlpcPs SrcSpan) mkProgram :: [Decl' RlpcPs] -> P (RlpProgram RlpcPs)
mkProgram ds = do mkProgram ds = do
pt <- use psOpTable pt <- use psOpTable
pure $ Program (associate pt <$> ds) pure $ RlpProgram (associate pt <$> ds)
parseError :: (Located RlpToken, [String]) -> P a
parseError ((Located ss t), exp) = addFatal $
errorMsg ss (RlpParErrUnexpectedToken t exp)
mkInfixD :: Assoc -> Int -> PsName -> P (Decl' RlpcPs)
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))
)
pos <- use (psInput . aiPos)
pure $ Located (spanFromPos pos 0) (InfixD a p n)
intOfToken :: Located RlpToken -> Int intOfToken :: Located RlpToken -> Int
intOfToken (Located _ (TokenLitInt n)) = n intOfToken (Located _ (TokenLitInt n)) = n
tempInfixExprErr :: Expr RlpcPs -> Expr RlpcPs -> P a tempInfixExprErr :: RlpExpr' RlpcPs -> RlpExpr' RlpcPs -> P a
tempInfixExprErr (Located a _) (Located b _) = tempInfixExprErr (Located a _) (Located b _) =
addFatal $ errorMsg (a <> b) $ RlpParErrOther addFatal $ errorMsg (a <> b) $ RlpParErrOther
[ "The rl' frontend is currently in beta. Support for infix expressions is minimal, sorry! :(" [ "The rl' frontend is currently in beta. Support for infix expressions is minimal, sorry! :("
, "In the mean time, don't mix any infix operators." , "In the mean time, don't mix any infix operators."
] ]
--}
_litint :: Getter (Located RlpToken) Int
_litint = to extract
. singular _TokenLitInt
tempInfixExprErr :: Expr' RlpcPs SrcSpan -> Expr' RlpcPs SrcSpan -> P a
tempInfixExprErr (a :< _) (b :< _) =
addFatal $ errorMsg (a <> b) $ RlpParErrOther
[ "The rl' frontend is currently in beta. Support for infix expressions is minimal, sorry! :("
, "In the mean time, don't mix any infix operators."
]
mkProgram :: [Decl RlpcPs SrcSpan] -> P (Program RlpcPs SrcSpan)
mkProgram ds = do
pt <- use psOpTable
pure $ Program (associate pt <$> ds)
extractName :: Located RlpToken -> PsName
extractName (Located ss (TokenVarSym n)) = Located ss n
extractName (Located ss (TokenVarName n)) = Located ss n
extractName (Located ss (TokenConName n)) = Located ss n
extractName (Located ss (TokenConSym n)) = Located ss n
parseError :: (Located RlpToken, [String]) -> P a
parseError ((Located ss t), exp) = addFatal $
errorMsg ss (RlpParErrUnexpectedToken t exp)
} }

View File

@@ -16,7 +16,7 @@ import Rlp.Parse.Types
import Rlp.Syntax import Rlp.Syntax
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
associate :: OpTable -> Decl RlpcPs a -> Decl RlpcPs a associate :: OpTable -> Decl' RlpcPs -> Decl' RlpcPs
associate _ p = p associate _ p = p
{-# WARNING associate "unimplemented" #-} {-# WARNING associate "unimplemented" #-}

View File

@@ -1,7 +1,6 @@
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ImplicitParams, ViewPatterns, PatternSynonyms #-} {-# LANGUAGE ImplicitParams, ViewPatterns, PatternSynonyms #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE UndecidableInstances #-}
module Rlp.Parse.Types module Rlp.Parse.Types
( (
-- * Trees That Grow -- * Trees That Grow
@@ -18,9 +17,10 @@ module Rlp.Parse.Types
, RlpToken(..), AlexInput(..), Position(..), spanFromPos, LexerAction , RlpToken(..), AlexInput(..), Position(..), spanFromPos, LexerAction
, Located(..), PsName , Located(..), PsName
-- ** Lenses -- ** Lenses
, _TokenLitInt, _TokenVarName, _TokenConName, _TokenVarSym
, aiPrevChar, aiSource, aiBytes, aiPos, posLine, posColumn , aiPrevChar, aiSource, aiBytes, aiPos, posLine, posColumn
, (<<~), (<~>)
-- * Error handling -- * Error handling
, MsgEnvelope(..), RlpcError(..), RlpParseError(..) , MsgEnvelope(..), RlpcError(..), RlpParseError(..)
, addFatal, addWound, addFatalHere, addWoundHere , addFatal, addWound, addFatalHere, addWoundHere
@@ -28,7 +28,6 @@ module Rlp.Parse.Types
where where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Core.Syntax (Name) import Core.Syntax (Name)
import Text.Show.Deriving
import Control.Monad import Control.Monad
import Control.Monad.State.Strict import Control.Monad.State.Strict
import Control.Monad.Errorful import Control.Monad.Errorful
@@ -54,9 +53,34 @@ import Compiler.Types
data RlpcPs data RlpcPs
type instance NameP RlpcPs = PsName type instance XRec RlpcPs a = Located a
type instance IdP RlpcPs = PsName
type PsName = Located Text type instance XFunD RlpcPs = ()
type instance XDataD RlpcPs = ()
type instance XInfixD RlpcPs = ()
type instance XTySigD RlpcPs = ()
type instance XXDeclD RlpcPs = ()
type instance XLetE RlpcPs = ()
type instance XLetrecE RlpcPs = ()
type instance XVarE RlpcPs = ()
type instance XLamE RlpcPs = ()
type instance XCaseE RlpcPs = ()
type instance XIfE RlpcPs = ()
type instance XAppE RlpcPs = ()
type instance XLitE RlpcPs = ()
type instance XParE RlpcPs = ()
type instance XOAppE RlpcPs = ()
type instance XXRlpExprE RlpcPs = ()
type PsName = Text
instance MapXRec RlpcPs where
mapXRec = fmap
instance UnXRec RlpcPs where
unXRec = extract
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -94,10 +118,10 @@ data RlpToken
-- literals -- literals
= TokenLitInt Int = TokenLitInt Int
-- identifiers -- identifiers
| TokenVarName Text | TokenVarName Name
| TokenConName Text | TokenConName Name
| TokenVarSym Text | TokenVarSym Name
| TokenConSym Text | TokenConSym Name
-- reserved words -- reserved words
| TokenData | TokenData
| TokenCase | TokenCase
@@ -128,31 +152,6 @@ data RlpToken
| TokenEOF | TokenEOF
deriving (Show) deriving (Show)
_TokenLitInt :: Prism' RlpToken Int
_TokenLitInt = prism TokenLitInt $ \case
TokenLitInt n -> Right n
x -> Left x
_TokenVarName :: Prism' RlpToken Text
_TokenVarName = prism TokenVarName $ \case
TokenVarName n -> Right n
x -> Left x
_TokenVarSym :: Prism' RlpToken Text
_TokenVarSym = prism TokenVarSym $ \case
TokenVarSym n -> Right n
x -> Left x
_TokenConName :: Prism' RlpToken Text
_TokenConName = prism TokenConName $ \case
TokenConName n -> Right n
x -> Left x
_TokenConSym :: Prism' RlpToken Text
_TokenConSym = prism TokenConSym $ \case
TokenConSym n -> Right n
x -> Left x
newtype P a = P { newtype P a = P {
runP :: ParseState runP :: ParseState
-> (ParseState, [MsgEnvelope RlpParseError], Maybe a) -> (ParseState, [MsgEnvelope RlpParseError], Maybe a)
@@ -282,14 +281,13 @@ initAlexInput s = AlexInput
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
deriving instance Lift (RlpProgram RlpcPs)
-- deriving instance Lift (Program RlpcPs) deriving instance Lift (Decl RlpcPs)
-- deriving instance Lift (Decl RlpcPs) deriving instance Lift (Pat RlpcPs)
-- deriving instance Lift (Pat RlpcPs) deriving instance Lift (Lit RlpcPs)
-- deriving instance Lift (Lit RlpcPs) deriving instance Lift (RlpExpr RlpcPs)
-- deriving instance Lift (Expr RlpcPs) deriving instance Lift (Binding RlpcPs)
-- deriving instance Lift (Binding RlpcPs) deriving instance Lift (RlpType RlpcPs)
-- deriving instance Lift (Ty RlpcPs) deriving instance Lift (Alt RlpcPs)
-- deriving instance Lift (Alt RlpcPs) deriving instance Lift (ConAlt RlpcPs)
-- deriving instance Lift (ConAlt RlpcPs)

View File

@@ -1,10 +1,362 @@
-- recursion-schemes
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable
, TemplateHaskell, TypeFamilies #-}
{-# LANGUAGE OverloadedStrings, PatternSynonyms, ViewPatterns #-}
{-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-}
{-# LANGUAGE UndecidableInstances, ImpredicativeTypes #-}
module Rlp.Syntax module Rlp.Syntax
( module Rlp.Syntax.Backstage (
, module Rlp.Syntax.Types -- * AST
RlpProgram(..)
, progDecls
, Decl(..), Decl', RlpExpr(..), RlpExpr', RlpExprF(..)
, Pat(..), Pat'
, Alt(..), Where
, Assoc(..)
, Lit(..), Lit'
, RlpType(..), RlpType'
, ConAlt(..)
, Binding(..), Binding'
, _PatB, _FunB
, _VarP, _LitP, _ConP
-- * Trees That Grow boilerplate
-- ** Extension points
, IdP, IdP', XRec, UnXRec(..), MapXRec(..)
-- *** Decl
, XFunD, XTySigD, XInfixD, XDataD, XXDeclD
-- *** RlpExpr
, XLetE, XLetrecE, XVarE, XLamE, XCaseE, XIfE, XAppE, XLitE
, XParE, XOAppE, XXRlpExprE
-- ** Pattern synonyms
-- *** Decl
, pattern FunD, pattern TySigD, pattern InfixD, pattern DataD
, pattern FunD'', pattern TySigD'', pattern InfixD'', pattern DataD''
-- *** RlpExpr
, pattern LetE, pattern LetrecE, pattern VarE, pattern LamE, pattern CaseE
, pattern IfE , pattern AppE, pattern LitE, pattern ParE, pattern OAppE
, pattern XRlpExprE
-- *** RlpType
, pattern FunConT'', pattern FunT'', pattern AppT'', pattern VarT''
, pattern ConT''
-- *** Pat
, pattern VarP'', pattern LitP'', pattern ConP''
-- *** Binding
, pattern PatB''
) )
where where
-------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
import Rlp.Syntax.Backstage import Data.Text (Text)
import Rlp.Syntax.Types import Data.Text qualified as T
import Data.String (IsString(..))
import Data.Functor.Foldable
import Data.Functor.Foldable.TH (makeBaseFunctor)
import Data.Functor.Classes
import Data.Functor.Identity
import Data.Kind (Type)
import GHC.Generics
import Language.Haskell.TH.Syntax (Lift)
import Control.Lens
import Core.Syntax hiding (Lit, Type, Binding, Binding')
import Core (HasRHS(..), HasLHS(..))
----------------------------------------------------------------------------------
data RlpModule p = RlpModule
{ _rlpmodName :: Text
, _rlpmodProgram :: RlpProgram p
}
-- | dear god.
type PhaseShow p =
( Show (XRec p (Pat p)), Show (XRec p (RlpExpr p))
, Show (XRec p (Lit p)), Show (IdP p)
, Show (XRec p (RlpType p))
, Show (XRec p (Binding p))
)
newtype RlpProgram p = RlpProgram [Decl' p]
progDecls :: Lens' (RlpProgram p) [Decl' p]
progDecls = lens
(\ (RlpProgram ds) -> ds)
(const RlpProgram)
deriving instance (PhaseShow p, Show (XRec p (Decl p))) => Show (RlpProgram p)
data RlpType p = FunConT
| FunT (RlpType' p) (RlpType' p)
| AppT (RlpType' p) (RlpType' p)
| VarT (IdP p)
| ConT (IdP p)
type RlpType' p = XRec p (RlpType p)
pattern FunConT'' :: (UnXRec p) => RlpType' p
pattern FunT'' :: (UnXRec p) => RlpType' p -> RlpType' p -> RlpType' p
pattern AppT'' :: (UnXRec p) => RlpType' p -> RlpType' p -> RlpType' p
pattern VarT'' :: (UnXRec p) => IdP p -> RlpType' p
pattern ConT'' :: (UnXRec p) => IdP p -> RlpType' p
pattern FunConT'' <- (unXRec -> FunConT)
pattern FunT'' s t <- (unXRec -> FunT s t)
pattern AppT'' s t <- (unXRec -> AppT s t)
pattern VarT'' n <- (unXRec -> VarT n)
pattern ConT'' n <- (unXRec -> ConT n)
deriving instance (PhaseShow p)
=> Show (RlpType p)
data Decl p = FunD' (XFunD p) (IdP p) [Pat' p] (RlpExpr' p) (Maybe (Where p))
| TySigD' (XTySigD p) [IdP p] (RlpType' p)
| DataD' (XDataD p) (IdP p) [IdP p] [ConAlt p]
| InfixD' (XInfixD p) Assoc Int (IdP p)
| XDeclD' !(XXDeclD p)
deriving instance
( Show (XFunD p), Show (XTySigD p)
, Show (XDataD p), Show (XInfixD p)
, Show (XXDeclD p)
, PhaseShow p
)
=> Show (Decl p)
type family XFunD p
type family XTySigD p
type family XDataD p
type family XInfixD p
type family XXDeclD p
pattern FunD :: (XFunD p ~ ())
=> IdP p -> [Pat' p] -> RlpExpr' p -> Maybe (Where p)
-> Decl p
pattern TySigD :: (XTySigD p ~ ()) => [IdP p] -> RlpType' p -> Decl p
pattern DataD :: (XDataD p ~ ()) => IdP p -> [IdP p] -> [ConAlt p] -> Decl p
pattern InfixD :: (XInfixD p ~ ()) => Assoc -> Int -> IdP p -> Decl p
pattern XDeclD :: (XXDeclD p ~ ()) => Decl p
pattern FunD n as e wh = FunD' () n as e wh
pattern TySigD ns t = TySigD' () ns t
pattern DataD n as cs = DataD' () n as cs
pattern InfixD a p n = InfixD' () a p n
pattern XDeclD = XDeclD' ()
pattern FunD'' :: (UnXRec p)
=> IdP p -> [Pat' p] -> RlpExpr' p -> Maybe (Where p)
-> Decl' p
pattern TySigD'' :: (UnXRec p)
=> [IdP p] -> RlpType' p -> Decl' p
pattern DataD'' :: (UnXRec p)
=> IdP p -> [IdP p] -> [ConAlt p] -> Decl' p
pattern InfixD'' :: (UnXRec p)
=> Assoc -> Int -> IdP p -> Decl' p
pattern FunD'' n as e wh <- (unXRec -> FunD' _ n as e wh)
pattern TySigD'' ns t <- (unXRec -> TySigD' _ ns t)
pattern DataD'' n as ds <- (unXRec -> DataD' _ n as ds)
pattern InfixD'' a p n <- (unXRec -> InfixD' _ a p n)
type Decl' p = XRec p (Decl p)
data Assoc = InfixL
| InfixR
| Infix
deriving (Show, Lift)
data ConAlt p = ConAlt (IdP p) [RlpType' p]
deriving instance (Show (IdP p), Show (XRec p (RlpType p))) => Show (ConAlt p)
data RlpExpr p = LetE' (XLetE p) [Binding' p] (RlpExpr' p)
| LetrecE' (XLetrecE p) [Binding' p] (RlpExpr' p)
| VarE' (XVarE p) (IdP p)
| LamE' (XLamE p) [Pat p] (RlpExpr' p)
| CaseE' (XCaseE p) (RlpExpr' p) [(Alt p, Where p)]
| IfE' (XIfE p) (RlpExpr' p) (RlpExpr' p) (RlpExpr' p)
| AppE' (XAppE p) (RlpExpr' p) (RlpExpr' p)
| LitE' (XLitE p) (Lit p)
| ParE' (XParE p) (RlpExpr' p)
| OAppE' (XOAppE p) (IdP p) (RlpExpr' p) (RlpExpr' p)
| XRlpExprE' !(XXRlpExprE p)
deriving (Generic)
type family XLetE p
type family XLetrecE p
type family XVarE p
type family XLamE p
type family XCaseE p
type family XIfE p
type family XAppE p
type family XLitE p
type family XParE p
type family XOAppE p
type family XXRlpExprE p
pattern LetE :: (XLetE p ~ ()) => [Binding' p] -> RlpExpr' p -> RlpExpr p
pattern LetrecE :: (XLetrecE p ~ ()) => [Binding' p] -> RlpExpr' p -> RlpExpr p
pattern VarE :: (XVarE p ~ ()) => IdP p -> RlpExpr p
pattern LamE :: (XLamE p ~ ()) => [Pat p] -> RlpExpr' p -> RlpExpr p
pattern CaseE :: (XCaseE p ~ ()) => RlpExpr' p -> [(Alt p, Where p)] -> RlpExpr p
pattern IfE :: (XIfE p ~ ()) => RlpExpr' p -> RlpExpr' p -> RlpExpr' p -> RlpExpr p
pattern AppE :: (XAppE p ~ ()) => RlpExpr' p -> RlpExpr' p -> RlpExpr p
pattern LitE :: (XLitE p ~ ()) => Lit p -> RlpExpr p
pattern ParE :: (XParE p ~ ()) => RlpExpr' p -> RlpExpr p
pattern OAppE :: (XOAppE p ~ ()) => IdP p -> RlpExpr' p -> RlpExpr' p -> RlpExpr p
pattern XRlpExprE :: (XXRlpExprE p ~ ()) => RlpExpr p
pattern LetE bs e = LetE' () bs e
pattern LetrecE bs e = LetrecE' () bs e
pattern VarE n = VarE' () n
pattern LamE as e = LamE' () as e
pattern CaseE e as = CaseE' () e as
pattern IfE c a b = IfE' () c a b
pattern AppE f x = AppE' () f x
pattern LitE l = LitE' () l
pattern ParE e = ParE' () e
pattern OAppE n a b = OAppE' () n a b
pattern XRlpExprE = XRlpExprE' ()
deriving instance
( Show (XLetE p), Show (XLetrecE p), Show (XVarE p)
, Show (XLamE p), Show (XCaseE p), Show (XIfE p)
, Show (XAppE p), Show (XLitE p), Show (XParE p)
, Show (XOAppE p), Show (XXRlpExprE p)
, PhaseShow p
) => Show (RlpExpr p)
type RlpExpr' p = XRec p (RlpExpr p)
class UnXRec p where
unXRec :: XRec p a -> a
class WrapXRec p where
wrapXRec :: a -> XRec p a
class MapXRec p where
mapXRec :: (a -> b) -> XRec p a -> XRec p b
-- old definition:
-- type family XRec p (f :: Type -> Type) = (r :: Type) | r -> p f
type family XRec p a = (r :: Type) | r -> p a
type family IdP p
type IdP' p = XRec p (IdP p)
type Where p = [Binding p]
-- do we want guards?
data Alt p = AltA (Pat' p) (RlpExpr' p)
deriving instance (PhaseShow p) => Show (Alt p)
data Binding p = PatB (Pat' p) (RlpExpr' p)
| FunB (IdP p) [Pat' p] (RlpExpr' p)
type Binding' p = XRec p (Binding p)
pattern PatB'' :: (UnXRec p) => Pat' p -> RlpExpr' p -> Binding' p
pattern PatB'' p e <- (unXRec -> PatB p e)
deriving instance (Show (XRec p (Pat p)), Show (XRec p (RlpExpr p)), Show (IdP p)
) => Show (Binding p)
data Pat p = VarP (IdP p)
| LitP (Lit' p)
| ConP (IdP p) [Pat' p]
pattern VarP'' :: (UnXRec p) => IdP p -> Pat' p
pattern LitP'' :: (UnXRec p) => Lit' p -> Pat' p
pattern ConP'' :: (UnXRec p) => IdP p -> [Pat' p] -> Pat' p
pattern VarP'' n <- (unXRec -> VarP n)
pattern LitP'' l <- (unXRec -> LitP l)
pattern ConP'' c as <- (unXRec -> ConP c as)
deriving instance (PhaseShow p) => Show (Pat p)
type Pat' p = XRec p (Pat p)
data Lit p = IntL Int
| CharL Char
| ListL [RlpExpr' p]
deriving instance (PhaseShow p) => Show (Lit p)
type Lit' p = XRec p (Lit p)
-- instance HasLHS Alt Alt Pat Pat where
-- _lhs = lens
-- (\ (AltA p _) -> p)
-- (\ (AltA _ e) p' -> AltA p' e)
-- instance HasRHS Alt Alt RlpExpr RlpExpr where
-- _rhs = lens
-- (\ (AltA _ e) -> e)
-- (\ (AltA p _) e' -> AltA p e')
-- makeBaseFunctor ''RlpExpr
-- showsTernaryWith :: (Int -> x -> ShowS)
-- -> (Int -> y -> ShowS)
-- -> (Int -> z -> ShowS)
-- -> String -> Int
-- -> x -> y -> z
-- -> ShowS
-- showsTernaryWith sa sb sc name p a b c = showParen (p > 10)
-- $ showString name
-- . showChar ' ' . sa 11 a
-- . showChar ' ' . sb 11 b
-- . showChar ' ' . sc 11 c
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
makeLenses ''RlpModule
makePrisms ''Pat
makePrisms ''Binding
--------------------------------------------------------------------------------
data RlpExprF p a = LetE'F (XLetE p) [Binding' p] a
| LetrecE'F (XLetrecE p) [Binding' p] a
| VarE'F (XVarE p) (IdP p)
| LamE'F (XLamE p) [Pat p] a
| CaseE'F (XCaseE p) a [(Alt p, Where p)]
| IfE'F (XIfE p) a a a
| AppE'F (XAppE p) a a
| LitE'F (XLitE p) (Lit p)
| ParE'F (XParE p) a
| OAppE'F (XOAppE p) (IdP p) a a
| XRlpExprE'F !(XXRlpExprE p)
deriving (Functor, Foldable, Traversable, Generic)
type instance Base (RlpExpr p) = RlpExprF p
instance (UnXRec p) => Recursive (RlpExpr p) where
project = \case
LetE' xx bs e -> LetE'F xx bs (unXRec e)
LetrecE' xx bs e -> LetrecE'F xx bs (unXRec e)
VarE' xx n -> VarE'F xx n
LamE' xx ps e -> LamE'F xx ps (unXRec e)
CaseE' xx e as -> CaseE'F xx (unXRec e) as
IfE' xx a b c -> IfE'F xx (unXRec a) (unXRec b) (unXRec c)
AppE' xx f x -> AppE'F xx (unXRec f) (unXRec x)
LitE' xx l -> LitE'F xx l
ParE' xx e -> ParE'F xx (unXRec e)
OAppE' xx f a b -> OAppE'F xx f (unXRec a) (unXRec b)
XRlpExprE' xx -> XRlpExprE'F xx
instance (WrapXRec p) => Corecursive (RlpExpr p) where
embed = \case
LetE'F xx bs e -> LetE' xx bs (wrapXRec e)
LetrecE'F xx bs e -> LetrecE' xx bs (wrapXRec e)
VarE'F xx n -> VarE' xx n
LamE'F xx ps e -> LamE' xx ps (wrapXRec e)
CaseE'F xx e as -> CaseE' xx (wrapXRec e) as
IfE'F xx a b c -> IfE' xx (wrapXRec a) (wrapXRec b) (wrapXRec c)
AppE'F xx f x -> AppE' xx (wrapXRec f) (wrapXRec x)
LitE'F xx l -> LitE' xx l
ParE'F xx e -> ParE' xx (wrapXRec e)
OAppE'F xx f a b -> OAppE' xx f (wrapXRec a) (wrapXRec b)
XRlpExprE'F xx -> XRlpExprE' xx

View File

@@ -1,35 +0,0 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
module Rlp.Syntax.Backstage
( strip
)
where
--------------------------------------------------------------------------------
import Data.Fix hiding (cata)
import Data.Functor.Classes
import Data.Functor.Foldable
import Rlp.Syntax.Types
import Text.Show.Deriving
import Language.Haskell.TH.Syntax (Lift)
--------------------------------------------------------------------------------
-- oprhan instances because TH
instance (Show (NameP p)) => Show1 (Alt p) where
liftShowsPrec = $(makeLiftShowsPrec ''Alt)
instance (Show (NameP p)) => Show1 (Binding p) where
liftShowsPrec = $(makeLiftShowsPrec ''Binding)
instance (Show (NameP p)) => Show1 (ExprF p) where
liftShowsPrec = $(makeLiftShowsPrec ''ExprF)
deriving instance (Lift (NameP p), Lift a) => Lift (Expr' p a)
deriving instance (Lift (NameP p), Lift a) => Lift (Decl p a)
deriving instance (Show (NameP p), Show a) => Show (Decl p a)
deriving instance (Show (NameP p), Show a) => Show (Program p a)
strip :: Functor f => Cofree f a -> Fix f
strip (_ :< as) = Fix $ strip <$> as

View File

@@ -1,143 +0,0 @@
-- recursion-schemes
{-# LANGUAGE DeriveTraversable, TemplateHaskell, TypeFamilies #-}
{-# LANGUAGE OverloadedStrings, PatternSynonyms, ViewPatterns #-}
{-# LANGUAGE UndecidableInstances, ImpredicativeTypes #-}
module Rlp.Syntax.Types
(
NameP
, SimpleP
, Assoc(..)
, ConAlt(..)
, Alt(..), Alt'
, Ty(..)
, Binding(..), Binding'
, Expr', ExprF(..)
, Rec(..)
, Lit(..)
, Pat(..)
, Decl(..)
, Program(..)
, Where
-- * Re-exports
, Cofree(..)
, Trans.Cofree.CofreeF
, SrcSpan(..)
)
where
----------------------------------------------------------------------------------
import Data.Text (Text)
import Data.Text qualified as T
import Data.String (IsString(..))
import Data.Functor.Classes
import Data.Functor.Identity
import Data.Functor.Compose
import Data.Fix
import Data.Kind (Type)
import GHC.Generics
import Language.Haskell.TH.Syntax (Lift)
import Control.Lens hiding ((:<))
import Control.Comonad.Trans.Cofree qualified as Trans.Cofree
import Control.Comonad.Cofree
import Data.Functor.Foldable
import Data.Functor.Foldable.TH (makeBaseFunctor)
import Compiler.Types (SrcSpan(..), Located(..))
import Core.Syntax qualified as Core
import Core (Rec(..), HasRHS(..), HasLHS(..))
----------------------------------------------------------------------------------
data SimpleP
type instance NameP SimpleP = String
type family NameP p
data ExprF p a = LetEF Rec [Binding p a] a
| VarEF (NameP p)
| LamEF [Pat p] a
| CaseEF a [Alt p a]
| IfEF a a a
| AppEF a a
| LitEF (Lit p)
| ParEF a
| InfixEF (NameP p) a a
deriving (Functor, Foldable, Traversable)
data ConAlt p = ConAlt (NameP p) [Ty p]
deriving instance (Lift (NameP p)) => Lift (ConAlt p)
deriving instance (Show (NameP p)) => Show (ConAlt p)
data Ty p = ConT (NameP p)
| VarT (NameP p)
| FunT (Ty p) (Ty p)
| AppT (Ty p) (Ty p)
deriving instance (Show (NameP p)) => Show (Ty p)
deriving instance (Lift (NameP p)) => Lift (Ty p)
data Pat p = VarP (NameP p)
| LitP (Lit p)
| ConP (NameP p) [Pat p]
deriving instance (Lift (NameP p)) => Lift (Pat p)
deriving instance (Show (NameP p)) => Show (Pat p)
data Lit p = IntL Int
deriving Show
deriving instance (Lift (NameP p)) => Lift (Lit p)
data Assoc = InfixL | InfixR | Infix
deriving (Lift, Show)
deriving instance (Show (NameP p), Show a) => Show (ExprF p a)
deriving instance (Lift (NameP p), Lift a) => Lift (ExprF p a)
data Binding p a = PatB (Pat p) (ExprF p a)
deriving (Functor, Foldable, Traversable)
deriving instance (Lift (NameP p), Lift a) => Lift (Binding p a)
deriving instance (Show (NameP p), Show a) => Show (Binding p a)
type Binding' p a = Binding p (Cofree (ExprF p) a)
type Where p a = [Binding p a]
data Alt p a = AltA (Pat p) (ExprF p a) (Maybe (Where p a))
deriving (Functor, Foldable, Traversable)
deriving instance (Show (NameP p), Show a) => Show (Alt p a)
deriving instance (Lift (NameP p), Lift a) => Lift (Alt p a)
type Expr p = Fix (ExprF p)
type Alt' p a = Alt p (Cofree (ExprF p) a)
--------------------------------------------------------------------------------
data Program p a = Program
{ _programDecls :: [Decl p a]
}
data Decl p a = FunD (NameP p) [Pat p] (Expr' p a) (Maybe (Where p a))
| TySigD [NameP p] (Ty p)
| DataD (NameP p) [NameP p] [ConAlt p]
| InfixD Assoc Int (NameP p)
type Decl' p a = Decl p (Cofree (ExprF p) a)
type Expr' p = Cofree (ExprF p)
makeLenses ''Program
loccof :: Iso' (Cofree f SrcSpan) (Located (f (Cofree f SrcSpan)))
loccof = iso sa bt where
sa :: Cofree f SrcSpan -> Located (f (Cofree f SrcSpan))
sa (ss :< as) = Located ss as
bt :: Located (f (Cofree f SrcSpan)) -> Cofree f SrcSpan
bt (Located ss as) = ss :< as

View File

@@ -17,12 +17,10 @@ import Rlp.Parse
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
rlpProg :: QuasiQuoter rlpProg :: QuasiQuoter
rlpProg = undefined rlpProg = mkqq parseRlpProgR
-- rlpProg = mkqq parseRlpProgR
rlpExpr :: QuasiQuoter rlpExpr :: QuasiQuoter
rlpExpr = undefined rlpExpr = mkqq parseRlpExprR
-- rlpExpr = mkqq parseRlpExprR
mkq :: (Lift a) => (Text -> RLPCIO a) -> String -> Q Exp mkq :: (Lift a) => (Text -> RLPCIO a) -> String -> Q Exp
mkq parse = evalAndParse >=> lift where mkq parse = evalAndParse >=> lift where

View File

@@ -41,12 +41,6 @@ import Rlp.Syntax as Rlp
import Rlp.Parse.Types (RlpcPs, PsName) import Rlp.Parse.Types (RlpcPs, PsName)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
desugarRlpProgR = undefined
desugarRlpProg = undefined
desugarRlpExpr = undefined
{--
type Tree a = Either Name (Name, Branch a) type Tree a = Either Name (Name, Branch a)
-- | Rose tree branch representing "nested" "patterns" in the Core language. That -- | Rose tree branch representing "nested" "patterns" in the Core language. That
@@ -240,5 +234,3 @@ typeToCore (VarT'' x) = TyVar (dsNameToName x)
dsNameToName :: IdP RlpcPs -> Name dsNameToName :: IdP RlpcPs -> Name
dsNameToName = id dsNameToName = id
-}

View File

@@ -1,67 +0,0 @@
{-# LANGUAGE ParallelListComp #-}
module Compiler.TypesSpec
( spec
)
where
--------------------------------------------------------------------------------
import Control.Lens.Combinators
import Data.Function ((&))
import Test.QuickCheck
import Test.Hspec
import Compiler.Types (SrcSpan(..), srcSpanAbs, srcSpanLen)
--------------------------------------------------------------------------------
spec :: Spec
spec = do
describe "SrcSpan" $ do
-- it "associates under closure"
-- prop_SrcSpan_mul_associative
it "commutes under closure"
prop_SrcSpan_mul_commutative
it "equals itself when squared"
prop_SrcSpan_mul_square_eq
prop_SrcSpan_mul_associative :: Property
prop_SrcSpan_mul_associative = property $ \a b c ->
-- very crudely approximate when overflow will occur; bail we think it
-- will
(([a,b,c] :: [SrcSpan]) & allOf (each . (srcSpanAbs <> srcSpanLen))
(< (maxBound @Int `div` 3)))
==> (a <> b) <> c === a <> (b <> c :: SrcSpan)
prop_SrcSpan_mul_commutative :: Property
prop_SrcSpan_mul_commutative = property $ \a b ->
a <> b === (b <> a :: SrcSpan)
prop_SrcSpan_mul_square_eq :: Property
prop_SrcSpan_mul_square_eq = property $ \a ->
a <> a === (a :: SrcSpan)
instance Arbitrary SrcSpan where
arbitrary = do
l <- chooseInt (1, maxBound)
c <- chooseInt (1, maxBound)
a <- chooseInt (0, maxBound)
`suchThat` (\n -> n >= pred l + pred c)
s <- chooseInt (0, maxBound)
pure $ SrcSpan l c a s
shrink (SrcSpan l c a s) =
[ SrcSpan l' c' a' s'
| (l',c',a',s') <- shrinkParts
, l' >= 1
, c' >= 1
, a' >= pred l' + pred c'
]
where
-- shfl as = unsafePerformIO (generate $ shuffle as)
shrinkParts =
[ (l',c',a',s')
| l' <- shrinkIntegral l
| c' <- shrinkIntegral c
| a' <- shrinkIntegral a
| s' <- shrinkIntegral s
]

21
visualisers/gmvis/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
node_modules/
public/js
/target
/checkouts
/src/gen
pom.xml
pom.xml.asc
*.iml
*.jar
*.log
.shadow-cljs
.idea
.lein-*
.nrepl-*
.DS_Store
.hgignore
.hg/

1362
visualisers/gmvis/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
{"name":"gmvis","version":"0.0.1","private":true,"devDependencies":{"shadow-cljs":"2.28.3"},"dependencies":{"ace-builds":"^1.32.7","react":"^18.3.0","react-ace":"11.0.1","react-dom":"18.3.0","react-resplit":"^1.3.1","react-tooltip":"^5.26.3"}}

View File

@@ -0,0 +1,156 @@
@import "solarized-light.css";
html, body, #mount
{ height: 100%
; width: 100%
}
body
{ max-width: 90%
; margin: 0 auto
; padding: 0
}
.split-root
{ height: 100%
}
.split-splitter
{ width: 100%
; height: 100%
; background: #ccc
}
.split-pane
{ margin: 0
; padding: 0
; overflow: scroll
; display: flex
; flex-direction: column
}
.pane-content
{ margin: 0.5em
}
.view-header
{ margin: 0
; flex-shrink: 0
}
.stack-view
{ display: flex
; flex-direction: column
; justify-content: space-between
/* to fill the container */
; flex-grow: 1
}
.stack-entry-container
{ display: flex
; flex-direction: column-reverse
; align-content: flex-end
}
.stack-entry-container.even > .stack-entry:nth-of-type(even)
{ background: #0000007f
; color: white
}
.stack-entry-container.odd > .stack-entry:nth-of-type(odd)
{ background: #0000007f
; color: white
}
.stack-entry
{ display: flex
; flex-direction: row
; justify-content: space-between
; font-family: monospace;
}
.stack-entry-addr
{ align-self: flex-end
; opacity: 70%
}
.dump-view
{}
.heap-view
{}
/* .split-pane:has(> .code-view) */
/* { overflow: hidden */
/* } */
.code-view
{ display: flex
; flex-direction: column
; align-items: stretch
; align-content: stretch
; justify-content: flex-start
; flex-grow: 1
}
.code-view .code-instr-container
{ display: grid
; overflow: scroll
; flex-shrink: 4
; min-height: 0
}
.code-view .instr
{ font-family: monospace;
}
.code-instr-container.even > .instr:nth-of-type(even)
{ background: #0000007f
; color: white
}
.code-instr-container.odd > .instr:nth-of-type(odd)
{ background: #0000007f
; color: white
}
.code-view .code-button-container
{ display: flex
; flex-direction: row
/* ; align-self: flex-end */
; justify-content: space-between
; margin-top: auto
; flex-shrink: 0
}
.heap-view
{
}
.heap-entry-container
{ display: flex
; flex-direction: column
}
.heap-entry-container > .heap-entry:nth-of-type(even)
{ background: #0000007f
; color: white
}
.heap-entry
{ display: flex
; flex-direction: row
; justify-content: space-between
; font-family: monospace;
}
.heap-entry-addr
{ white-space: nowrap
}
/* .heap-entry-container.odd > .heap-entry:nth-of-type(odd) */
/* { background: #0000007f */
/* ; color: white */
/* } */

View File

@@ -0,0 +1,304 @@
@import url(http://fonts.googleapis.com/css?family=Inconsolata);
@import url(http://fonts.googleapis.com/css?family=PT+Sans);
@import url(http://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700);
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
audio,
canvas,
video {
display: inline-block;
}
audio:not([controls]) {
display: none;
height: 0;
}
[hidden] {
display: none;
}
html {
font-family: sans-serif;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
body {
margin: 0;
}
a:focus {
outline: thin dotted;
}
a:active,
a:hover {
outline: 0;
}
h1 {
font-size: 2em;
}
abbr[title] {
border-bottom: 1px dotted;
}
b,
strong {
font-weight: bold;
}
dfn {
font-style: italic;
}
mark {
background: #ff0;
color: #000;
}
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
img {
border: 0;
width: 100%;
}
svg:not(:root) {
overflow: hidden;
}
figure {
margin: 0;
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
legend {
border: 0;
padding: 0;
}
button,
input,
select,
textarea {
font-family: inherit;
font-size: 100%;
margin: 0;
}
button,
input {
line-height: normal;
}
button,
html input[type="button"],
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button;
cursor: pointer;
}
button[disabled],
input[disabled] {
cursor: default;
}
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box;
padding: 0;
}
input[type="search"] {
-webkit-appearance: textfield;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
textarea {
overflow: auto;
vertical-align: top;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
html {
font-family: 'PT Sans', sans-serif;
}
pre,
code {
font-family: 'Inconsolata', sans-serif;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'PT Sans Narrow', sans-serif;
font-weight: 700;
}
html {
background-color: #eee8d5;
color: #657b83;
margin: 1em;
}
body {
background-color: #fdf6e3;
margin: 0 auto;
max-width: 23cm;
border: 1pt solid #93a1a1;
padding: 1em;
}
code {
background-color: #eee8d5;
padding: 2px;
}
a {
color: #b58900;
}
a:visited {
color: #cb4b16;
}
a:hover {
color: #cb4b16;
}
h1 {
color: #d33682;
}
h2,
h3,
h4,
h5,
h6 {
color: #859900;
}
pre {
background-color: #fdf6e3;
color: #657b83;
border: 1pt solid #93a1a1;
padding: 1em;
box-shadow: 5pt 5pt 8pt #eee8d5;
}
pre code {
background-color: #fdf6e3;
}
h1 {
font-size: 2.8em;
}
h2 {
font-size: 2.4em;
}
h3 {
font-size: 1.8em;
}
h4 {
font-size: 1.4em;
}
h5 {
font-size: 1.3em;
}
h6 {
font-size: 1.15em;
}
.tag {
background-color: #eee8d5;
color: #d33682;
padding: 0 0.2em;
}
.todo,
.next,
.done {
color: #fdf6e3;
background-color: #dc322f;
padding: 0 0.2em;
}
.tag {
-webkit-border-radius: 0.35em;
-moz-border-radius: 0.35em;
border-radius: 0.35em;
}
.TODO {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #2aa198;
}
.NEXT {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #268bd2;
}
.ACTIVE {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #268bd2;
}
.DONE {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #859900;
}
.WAITING {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #cb4b16;
}
.HOLD {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #d33682;
}
.NOTE {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #d33682;
}
.CANCELLED {
-webkit-border-radius: 0.2em;
-moz-border-radius: 0.2em;
border-radius: 0.2em;
background-color: #859900;
}

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/main.css">
<title>The G-Machine</title>
<style type="text/css" media="screen">
</style>
</head>
<body>
<div id="mount">
</div>
<script src="/js/main.js"></script>
</body>
</html>

View File

@@ -0,0 +1,25 @@
{:source-paths
["src"]
:dependencies
[[cider/cider-nrepl "0.24.0"]
[nilenso/wscljs "0.2.0"]
[org.clojure/core.match "1.1.0"]
[reagent "0.10.0"]
[cljsjs/react "17.0.2-0"]
[cljsjs/react-dom "17.0.2-0"]
[cljsx "1.0.0"]]
:dev-http
{8020 "public"}
:builds
{:app
{:target :browser
:output-dir "public/js"
:asset-path "/js"
:modules
{:main ; becomes public/js/main.js
{:init-fn main/init}}}}}

View File

@@ -0,0 +1,63 @@
(ns main
(:require
[ui :as ui]
[wscljs.client :as ws]
[wscljs.format :as fmt]
[clojure.string :as str]
[cljs.core.match :refer-macros [match]]
[reagent.dom :as rdom]))
;------------------------------------------------------------------------------;
(def *rlp-socket nil)
;------------------------------------------------------------------------------;
(defn on-message [e]
(let [r (js->clj (js/JSON.parse (.-data e)) :keywordize-keys true)]
(match r
{:tag "Evaluated" :contents c}
(reset! ui/current-evaluation c)
:else
(js/console.warn "unrecognised response from rlp"))))
(defn send [msg]
(ws/send *rlp-socket msg fmt/json))
(defn on-open []
(println "socket opened")
(send {:command "evaluate"
:source (str/join "\n"
["fac n = case (==#) n 0 of"
" { <1> -> 1"
" ; <0> -> *# n (fac (-# n 1))"
" };"
""
"main = fac 3;"])}))
(defn init-rlp-socket []
(set! *rlp-socket (ws/create "ws://127.0.0.1:9002"
{:on-message on-message
:on-open on-open
:on-close #(println "socket closed")
:on-error #(println "error: " %)})))
;; this is called before any code is reloaded
(defn ^:dev/before-load stop []
(ws/close *rlp-socket)
(js/console.log "stop"))
;; start is called by init and after code reloading finishes
(defn ^:dev/after-load start []
(js/console.log "start")
(rdom/render [ui/Main]
(js/document.getElementById "mount"))
(init-rlp-socket))
;; init is called ONCE when the page loads
;; this is called in the index.html and must be exported
;; so it is available even in :advanced release builds
(defn init []
(js/console.log "init")
(start))

View File

@@ -0,0 +1,230 @@
(ns ui
(:require
[clojure.pprint :refer (cl-format)]
[wscljs.client :as ws]
[wscljs.format :as fmt]
[clojure.string :as str]
[cljs.core.match :refer-macros [match]]
["react-ace$default" :as AceEditor]
["react-resplit" :refer (Resplit)]
["ace-builds/src-noconflict/mode-haskell"]
["ace-builds/src-noconflict/theme-solarized_light"]
["ace-builds/src-noconflict/keybinding-vim"]
[reagent.core :as r]
[reagent.dom :as rdom]))
;------------------------------------------------------------------------------;
(def current-evaluation (r/atom []))
; (def current-index (r/atom 5))
(defonce current-index (r/atom 0))
(def +split-width+ "4px")
;------------------------------------------------------------------------------;
(defn gen-key []
(js/self.crypto.randomUUID))
(defn add-key [e]
(let [uuid (js/self.crypto.randomUUID)]
(match e
[tag props & children] (concat [tag (assoc props :key uuid)] children))))
;------------------------------------------------------------------------------;
(declare ppr-node)
(declare ppr-node*)
;------------------------------------------------------------------------------;
(defn Root [props & children]
[:> Resplit.Root (assoc props :class "split-root")
[:<> children]])
(defn Pane [props & children]
[:> Resplit.Pane (assoc props :class "split-pane")
[:<> children]])
(defn Splitter [props & children]
[:> Resplit.Splitter (assoc props :class "split-splitter")
[:<> children]])
(defn Header [text]
[:h5 {:class "view-header"}
text])
;------------------------------------------------------------------------------;
(defn Dump []
[:div {:class "pane-content dump-view"}
[Header "Dump"]])
;------------------------------------------------------------------------------;
(defn HeapEntry [heap addr-key]
(let [addr (js/Number (name addr-key))]
[:div {:class "heap-entry"
:key (gen-key)}
[:div {:class "heap-entry-addr"}
(cl-format nil "&~3D" addr)]
[:div {:class "heap-entry-node"}
(ppr-node heap addr)]]))
(defn Heap [heap]
[:div {:class "pane-content heap-view"}
[Header "Heap"]
[:div {:class "heap-entry-container"}
[:<> (map (partial HeapEntry heap) (keys heap))]]])
;------------------------------------------------------------------------------;
(defn deref-addr [heap addr]
(get heap
(keyword (str addr))
nil))
(defn words [& ws]
(->> ws
(map str)
(str/join \space)))
(defn maybe-parens [c s]
(if c
(str "(" s ")")
s))
(def app-prec 10)
(def app-prec+1 11)
(def app-prec-1 9)
(defn ppr-list [heap addrs]
(match addrs
[] "[]"
_ (str "[" (->> addrs
(map (partial ppr-node* 0 heap))
(interpose ", ")
(concat)) "]")))
(defn ppr-node* [p heap addr]
(match (deref-addr heap addr)
{:tag "NGlobal" :contents [arity code]}
(maybe-parens (> p 0)
(words "Global" arity "<code>"))
{:tag "NNum" :contents k}
(maybe-parens (> p 0)
(words "Number" k))
{:tag "NAp" :contents [f x]}
(maybe-parens (> p app-prec)
(words (ppr-node* app-prec heap f)
"@"
(ppr-node* app-prec+1 heap x)))
{:tag "NConstr" :contents [tag as]}
(maybe-parens (> p 0)
(words "Constructor"
tag
(ppr-list heap as)))
{:tag "NInd" :contents addr*}
(maybe-parens (> p 0)
(words "Indirection"
(ppr-node* app-prec+1 heap addr*)))
{:tag "NUninitialised"}
"<Uninitialised>"
{:tag "NMarked" :contents node*}
(maybe-parens (> p 0)
(words "Marked"
"<node>"))
nil (str "<broken pointer: &" addr ">")
a (str "other" a)))
(defn ppr-node [heap addr]
(ppr-node* 0 heap addr))
(defn StackEntry [heap addr]
[:div {:class "stack-entry"
:key (gen-key)}
(ppr-node heap addr)
[:div {:class "stack-entry-addr"}
(str "&" addr)]])
(defn StackEntryContainer [children]
[:div {:class "stack-entry-container even"}
[:<> children]])
(defn Stack [heap s]
[:div {:class "pane-content stack-view"}
[Header "Stack"]
[StackEntryContainer (map (partial StackEntry heap) (reverse s))]])
#_ (swap! current-index #(+ % 1))
#_ (swap! current-index #(- % 1))
;------------------------------------------------------------------------------;
(defn ppr-instr [{op :tag c :contents}]
(match op
"CaseJump" (words op "<cases>")
_ (words op c)))
(defn Instr [instr]
[:code {:class "instr"
:key (gen-key)}
(ppr-instr instr)])
(defn CodeButtons []
[:div {:class "code-button-container"}
[:button {:onClick #(swap! current-index dec)}
"<"]
[:code @current-index]
[:button {:onClick #(swap! current-index inc)}
">"]])
(defn CodeInstrContainer [children]
[:div {:class (if (even? (count children))
"code-instr-container even"
"code-instr-container odd")}
[:<> children]])
(defn Code [code]
[:div {:class "pane-content code-view"}
[Header "Next instructions"]
[CodeInstrContainer (map Instr code)]
[CodeButtons]])
;------------------------------------------------------------------------------;
(defn GM [{code :_gmCode
stack :_gmStack
heap :_gmHeap}]
[Root {:direction "horizontal"}
[Pane {:order 0 :initialSize "0.333fr"}
[Heap heap]]
[Splitter {:order 1 :size +split-width+}]
[Pane {:order 2 :initialSize "0.333fr"}
[Root {:direction "vertical"}
[Pane {:order 0 :initialSize "0.5fr"}
[Stack heap stack]]
[Splitter {:order 1 :size +split-width+}]
[Pane {:order 2 :initialSize "0.5fr"}
[Code code]]]]
[Splitter {:order 3 :size +split-width+}]
[Pane {:order 4 :initialSize "0.333fr"}
[Dump]]])
(defn Main []
(prn @current-evaluation)
(prn @current-index)
(if-let [st (nth @current-evaluation
@current-index
nil)]
[GM st]
[:h1 "no evaluation"]))