14 Commits

Author SHA1 Message Date
crumbtoo
ba099b7028 organisation and cleaning
organisation and tidying
2024-01-30 14:04:43 -07:00
crumbtoo
e962bacd2e fixup! ttg boilerplate 2024-01-30 13:04:23 -07:00
crumbtoo
f0c652b861 fixup! ttg boilerplate 2024-01-30 13:03:07 -07:00
crumbtoo
6a41e123ea ttg boilerplate 2024-01-30 13:01:01 -07:00
crumbtoo
fbea3d6f3d let layout 2024-01-28 19:41:36 -07:00
crumbtoo
ab979cb934 i should've made a lisp man this sucks 2024-01-28 19:33:05 -07:00
crumbtoo
7d42f9b641 at long last
more

no more undefineds
2024-01-28 18:30:12 -07:00
crumbtoo
fdaa2a1afd abandon ship 2024-01-28 17:02:32 -07:00
crumbtoo
83dda869f8 show 2024-01-28 16:24:08 -07:00
crumbtoo
c74c192645 idk 2024-01-26 19:19:41 -07:00
crumbtoo
e00e4d3418 it's also a comonad. lol. 2024-01-26 17:53:05 -07:00
crumbtoo
8d0f324c63 oh my god guys!!! Located is a lax semimonoidal endofunctor on the category Hask!!!
![abstractionjak](https://media.discordapp.net/attachments/1101767463579951154/1200248978642567168/3877820-20SoyBooru.png?ex=65c57df8&is=65b308f8&hm=67da3acb61861cab6156df014b397d78fb8815fa163f2e992474d545beb668ba&=&format=webp&quality=lossless&width=880&height=868)
2024-01-26 17:25:59 -07:00
crumbtoo
6a6076f26e some 2024-01-26 15:12:10 -07:00
crumbtoo
559fd49f2b minor changes
putting this on hold; implementing TTG first
2024-01-25 15:52:56 -07:00
14 changed files with 516 additions and 400 deletions

View File

@@ -15,3 +15,5 @@
} }
``` ```
# Release 1.0.0

View File

@@ -1,5 +1,5 @@
HAPPY = happy HAPPY = happy
HAPPY_OPTS = -a -g -c HAPPY_OPTS = -a -g -c -i/tmp/t.info
ALEX = alex ALEX = alex
ALEX_OPTS = -g ALEX_OPTS = -g

View File

@@ -81,6 +81,7 @@ Listed in order of importance.
- [ ] CLI usage - [ ] CLI usage
- [ ] Tail call optimisation - [ ] Tail call optimisation
- [ ] Parsing rlp - [ ] Parsing rlp
- [ ] Trees That Grow
- [ ] Tests - [ ] Tests
- [x] Generic example programs - [x] Generic example programs
- [ ] Parser - [ ] Parser
@@ -103,6 +104,7 @@ Listed in order of importance.
- [ ] Actual compiler errors -- no more unexceptional `error` calls - [ ] Actual compiler errors -- no more unexceptional `error` calls
- [ ] Better CLI dump flags - [ ] Better CLI dump flags
- [ ] Annotate the AST with token positions for errors - [ ] Annotate the AST with token positions for errors
- [ ] More examples
### March Release Plan ### March Release Plan
- [ ] Tests - [ ] Tests

View File

@@ -63,7 +63,7 @@ options = RLPCOptions
evaluatorReader :: ReadM Evaluator evaluatorReader :: ReadM Evaluator
evaluatorReader = maybeReader $ \case evaluatorReader = maybeReader $ \case
"gm" -> Just EvaluatorGM "gm" -> Just EvaluatorGM
"tim" -> Just EvaluatorTI "ti" -> Just EvaluatorTI
_ -> Nothing _ -> Nothing
mmany :: (Alternative f, Monoid m) => f m -> f m mmany :: (Alternative f, Monoid m) => f m -> f m

View File

@@ -7,7 +7,7 @@ license: GPL-2.0-only
-- license-file: LICENSE -- license-file: LICENSE
author: crumbtoo author: crumbtoo
maintainer: crumb@disroot.org maintainer: crumb@disroot.org
-- copyright: copyright: Madeleine Sydney Ślaga
category: Language category: Language
build-type: Simple build-type: Simple
extra-doc-files: README.md extra-doc-files: README.md
@@ -37,6 +37,7 @@ library
, Rlp.Parse.Associate , Rlp.Parse.Associate
, Rlp.Lex , Rlp.Lex
, Rlp.Parse.Types , Rlp.Parse.Types
, Compiler.Types
other-modules: Data.Heap other-modules: Data.Heap
, Data.Pretty , Data.Pretty
@@ -48,7 +49,7 @@ library
build-tool-depends: happy:happy, alex:alex build-tool-depends: happy:happy, alex:alex
-- other-extensions: -- other-extensions:
build-depends: base ^>=4.18.0.0 build-depends: base >=4.17 && <4.20
-- 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
@@ -69,19 +70,24 @@ library
, data-fix >= 0.3.2 && < 0.4 , data-fix >= 0.3.2 && < 0.4
, utf8-string >= 1.0.2 && < 1.1 , utf8-string >= 1.0.2 && < 1.1
, extra >= 1.7.0 && < 2 , extra >= 1.7.0 && < 2
, semigroupoids
, comonad
, lens
hs-source-dirs: src hs-source-dirs: src
default-language: GHC2021 default-language: GHC2021
default-extensions: default-extensions:
OverloadedStrings OverloadedStrings
TypeFamilies
LambdaCase
executable rlpc executable rlpc
import: warnings import: warnings
main-is: Main.hs main-is: Main.hs
-- other-modules: -- other-modules:
-- other-extensions: -- other-extensions:
build-depends: base ^>=4.18.0.0 build-depends: base >=4.17.0.0 && <4.20.0.0
, rlp , rlp
, optparse-applicative >= 0.18.1 && < 0.19 , optparse-applicative >= 0.18.1 && < 0.19
, microlens >= 0.4.13 && < 0.5 , microlens >= 0.4.13 && < 0.5

View File

@@ -28,14 +28,12 @@ module Compiler.RLPC
, evalRLPCIO , evalRLPCIO
, evalRLPC , evalRLPC
, rlpcLogFile , rlpcLogFile
, rlpcDebugOpts , rlpcDFlags
, rlpcEvaluator , rlpcEvaluator
, rlpcInputFiles , rlpcInputFiles
, DebugFlag(..) , DebugFlag(..)
, whenFlag , whenDFlag
, flagDDumpEval , whenFFlag
, flagDDumpOpts
, flagDDumpAST
, def , def
, liftErrorful , liftErrorful
) )
@@ -43,6 +41,7 @@ module Compiler.RLPC
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
import Control.Arrow ((>>>)) import Control.Arrow ((>>>))
import Control.Exception import Control.Exception
import Control.Monad
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.State (MonadState(state)) import Control.Monad.State (MonadState(state))
import Control.Monad.Errorful import Control.Monad.Errorful
@@ -51,19 +50,19 @@ import Data.Functor.Identity
import Data.Default.Class import Data.Default.Class
import Data.Foldable import Data.Foldable
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Data.Maybe
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Data.HashSet (HashSet) import Data.HashSet (HashSet)
import Data.HashSet qualified as S import Data.HashSet qualified as S
import Data.Coerce import Data.Coerce
import Lens.Micro import Lens.Micro.Platform
import Lens.Micro.TH
import System.Exit import System.Exit
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
newtype RLPCT m a = RLPCT { newtype RLPCT m a = RLPCT {
runRLPCT :: ReaderT RLPCOptions (ErrorfulT (MsgEnvelope RlpcError) m) a runRLPCT :: ReaderT RLPCOptions (ErrorfulT (MsgEnvelope RlpcError) m) a
} }
deriving (Functor, Applicative, Monad) deriving (Functor, Applicative, Monad, MonadReader RLPCOptions)
type RLPC = RLPCT Identity type RLPC = RLPCT Identity
@@ -98,7 +97,8 @@ liftErrorful e = RLPCT $ lift (fmap liftRlpcError `mapErrorful` e)
data RLPCOptions = RLPCOptions data RLPCOptions = RLPCOptions
{ _rlpcLogFile :: Maybe FilePath { _rlpcLogFile :: Maybe FilePath
, _rlpcDebugOpts :: DebugOpts , _rlpcDFlags :: HashSet DebugFlag
, _rlpcFFlags :: HashSet CompilerFlag
, _rlpcEvaluator :: Evaluator , _rlpcEvaluator :: Evaluator
, _rlpcHeapTrigger :: Int , _rlpcHeapTrigger :: Int
, _rlpcInputFiles :: [FilePath] , _rlpcInputFiles :: [FilePath]
@@ -113,38 +113,33 @@ data Evaluator = EvaluatorGM | EvaluatorTI
instance Default RLPCOptions where instance Default RLPCOptions where
def = RLPCOptions def = RLPCOptions
{ _rlpcLogFile = Nothing { _rlpcLogFile = Nothing
, _rlpcDebugOpts = mempty , _rlpcDFlags = mempty
, _rlpcFFlags = mempty
, _rlpcEvaluator = EvaluatorGM , _rlpcEvaluator = EvaluatorGM
, _rlpcHeapTrigger = 200 , _rlpcHeapTrigger = 200
, _rlpcInputFiles = [] , _rlpcInputFiles = []
} }
type DebugOpts = HashSet DebugFlag -- debug flags are passed with -dFLAG
type DebugFlag = String
data DebugFlag = DDumpEval type CompilerFlag = String
| DDumpOpts
| DDumpAST
deriving (Show, Eq, Generic)
instance Hashable DebugFlag
makeLenses ''RLPCOptions makeLenses ''RLPCOptions
pure [] pure []
whenFlag :: (MonadReader s m) => SimpleGetter s Bool -> m () -> m () -- TODO: rewrite this with prisms once microlens-pro drops :3
whenFlag l m = asks (^. l) >>= \a -> if a then m else pure () whenDFlag :: (Monad m) => DebugFlag -> RLPCT m () -> RLPCT m ()
whenDFlag f m = do
-- mfw no `At` instance for HashSet
fs <- view rlpcDFlags
let a = S.member f fs
when a m
-- there's probably a better way to write this. my current knowledge of lenses whenFFlag :: (Monad m) => CompilerFlag -> RLPCT m () -> RLPCT m ()
-- is too weak. whenFFlag f m = do
flagGetter :: DebugFlag -> SimpleGetter RLPCOptions Bool -- mfw no `At` instance for HashSet
flagGetter d = to $ \s -> s ^. rlpcDebugOpts & S.member d fs <- view rlpcFFlags
let a = S.member f fs
flagDDumpEval :: SimpleGetter RLPCOptions Bool when a m
flagDDumpEval = flagGetter DDumpEval
flagDDumpOpts :: SimpleGetter RLPCOptions Bool
flagDDumpOpts = flagGetter DDumpOpts
flagDDumpAST :: SimpleGetter RLPCOptions Bool
flagDDumpAST = flagGetter DDumpAST

View File

@@ -5,12 +5,14 @@ module Compiler.RlpcError
, MsgEnvelope(..) , MsgEnvelope(..)
, Severity(..) , Severity(..)
, RlpcError(..) , RlpcError(..)
, SrcSpan(..)
, msgSpan , msgSpan
, msgDiagnostic , msgDiagnostic
, msgSeverity , msgSeverity
, liftRlpcErrors , liftRlpcErrors
, errorMsg , errorMsg
-- * Located Comonad
, Located(..)
, SrcSpan(..)
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -20,6 +22,7 @@ import Data.Text qualified as T
import GHC.Exts (IsString(..)) import GHC.Exts (IsString(..))
import Lens.Micro.Platform import Lens.Micro.Platform
import Lens.Micro.Platform.Internal import Lens.Micro.Platform.Internal
import Compiler.Types
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
data MsgEnvelope e = MsgEnvelope data MsgEnvelope e = MsgEnvelope
@@ -45,12 +48,6 @@ data Severity = SevWarning
| SevError | SevError
deriving Show deriving Show
data SrcSpan = SrcSpan
!Int -- ^ Line
!Int -- ^ Column
!Int -- ^ Length
deriving Show
makeLenses ''MsgEnvelope makeLenses ''MsgEnvelope
liftRlpcErrors :: (Functor m, IsRlpcError e) liftRlpcErrors :: (Functor m, IsRlpcError e)

66
src/Compiler/Types.hs Normal file
View File

@@ -0,0 +1,66 @@
module Compiler.Types
( SrcSpan(..)
, Located(..)
, (<<~), (<~>)
-- * Re-exports
, Comonad
, Apply
, Bind
)
where
--------------------------------------------------------------------------------
import Control.Comonad
import Data.Functor.Apply
import Data.Functor.Bind
--------------------------------------------------------------------------------
-- | Token wrapped with a span (line, column, absolute, length)
data Located a = Located SrcSpan a
deriving (Show, Functor)
instance Apply Located where
liftF2 f (Located sa p) (Located sb q)
= Located (sa <> sb) (p `f` q)
instance Bind Located where
Located sa a >>- k = Located (sa <> sb) b
where
Located sb b = k a
instance Comonad Located where
extract (Located _ a) = a
extend ck w@(Located p _) = Located p (ck w)
data SrcSpan = SrcSpan
!Int -- ^ Line
!Int -- ^ Column
!Int -- ^ Absolute
!Int -- ^ Length
deriving Show
instance Semigroup SrcSpan where
SrcSpan la ca aa sa <> SrcSpan lb cb ab sb = SrcSpan l c a s where
l = min la lb
c = min ca cb
a = min aa ab
s = case aa `compare` ab of
EQ -> max sa sb
LT -> max sa (ab + lb - aa)
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.
(<<~) :: (Comonad w) => (w a -> b) -> w a -> w b
(<<~) = (<<=)
infixl 4 <<~
-- | Similar to '(<*>)', but with a cokleisli arrow.
(<~>) :: (Comonad w, Bind w) => w (w a -> b) -> w a -> w b
mc <~> ma = mc >>- \f -> ma =>> f
infixl 4 <~>

View File

@@ -22,7 +22,8 @@ import Data.Text qualified as T
import Data.String (IsString(..)) import Data.String (IsString(..))
import Core.Syntax import Core.Syntax
import Compiler.RLPC import Compiler.RLPC
import Compiler.RlpcError -- TODO: unify Located definitions
import Compiler.RlpcError hiding (Located(..))
import Lens.Micro import Lens.Micro
import Lens.Micro.TH import Lens.Micro.TH
} }

View File

@@ -10,6 +10,7 @@ module Rlp.Lex
, lexStream , lexStream
, lexDebug , lexDebug
, lexCont , lexCont
, popLexState
) )
where where
import Codec.Binary.UTF8.String (encodeChar) import Codec.Binary.UTF8.String (encodeChar)
@@ -57,7 +58,7 @@ $asciisym = [\!\#\$\%\&\*\+\.\/\<\=\>\?\@\\\^\|\-\~\:]
|infixr|infixl|infix |infixr|infixl|infix
@reservedop = @reservedop =
"=" | \\ | "->" | "|" "=" | \\ | "->" | "|" | "::"
rlp :- rlp :-
@@ -73,6 +74,17 @@ $white_no_nl+ ;
-- for the definition of `doBol` -- for the definition of `doBol`
<0> \n { beginPush bol } <0> \n { beginPush bol }
<layout>
{
}
-- layout keywords
<0>
{
"let" { constToken TokenLet `thenBeginPush` layout_let }
}
-- scan various identifiers and reserved words. order is important here! -- scan various identifiers and reserved words. order is important here!
<0> <0>
{ {
@@ -110,6 +122,14 @@ $white_no_nl+ ;
() { doBol } () { doBol }
} }
<layout_let>
{
\n { beginPush bol }
"{" { explicitLBrace }
"in" { constToken TokenIn `thenDo` (popLexState *> popLayout) }
() { doLayout }
}
<layout_top> <layout_top>
{ {
\n ; \n ;
@@ -144,6 +164,12 @@ thenBegin act c inp l = do
psLexState . _head .= c psLexState . _head .= c
pure a pure a
thenBeginPush :: LexerAction a -> Int -> LexerAction a
thenBeginPush act c inp l = do
a <- act inp l
pushLexState c
pure a
andBegin :: LexerAction a -> Int -> LexerAction a andBegin :: LexerAction a -> Int -> LexerAction a
andBegin act c inp l = do andBegin act c inp l = do
psLexState . _head .= c psLexState . _head .= c
@@ -164,10 +190,10 @@ alexGetByte inp = case inp ^. aiBytes of
-- report the previous char -- report the previous char
& aiPrevChar .~ c & aiPrevChar .~ c
-- update the position -- update the position
& aiPos %~ \ (ln,col) -> & aiPos %~ \ (ln,col,a) ->
if c == '\n' if c == '\n'
then (ln+1,1) then (ln+1, 1, a+1)
else (ln,col+1) else (ln, col+1, a+1)
pure (b, inp') pure (b, inp')
_ -> Just (head bs, inp') _ -> Just (head bs, inp')
@@ -187,19 +213,19 @@ pushLexState :: Int -> P ()
pushLexState n = psLexState %= (n:) pushLexState n = psLexState %= (n:)
readInt :: Text -> Int readInt :: Text -> Int
readInt = T.foldr f 0 where readInt = T.foldl f 0 where
f c n = digitToInt c + 10*n f n c = 10*n + digitToInt c
constToken :: RlpToken -> LexerAction (Located RlpToken) constToken :: RlpToken -> LexerAction (Located RlpToken)
constToken t inp l = do constToken t inp l = do
pos <- use (psInput . aiPos) pos <- use (psInput . aiPos)
pure (Located (pos,l) t) pure (Located (spanFromPos pos l) t)
tokenWith :: (Text -> RlpToken) -> LexerAction (Located RlpToken) tokenWith :: (Text -> RlpToken) -> LexerAction (Located RlpToken)
tokenWith tf inp l = do tokenWith tf inp l = do
pos <- getPos pos <- getPos
let t = tf (T.take l $ inp ^. aiSource) let t = tf (T.take l $ inp ^. aiSource)
pure (Located (pos,l) t) pure (Located (spanFromPos pos l) t)
getPos :: P Position getPos :: P Position
getPos = use (psInput . aiPos) getPos = use (psInput . aiPos)
@@ -207,7 +233,8 @@ getPos = use (psInput . aiPos)
alexEOF :: P (Located RlpToken) alexEOF :: P (Located RlpToken)
alexEOF = do alexEOF = do
inp <- getInput inp <- getInput
pure (Located undefined TokenEOF) pos <- getPos
pure (Located (spanFromPos pos 0) TokenEOF)
initParseState :: Text -> ParseState initParseState :: Text -> ParseState
initParseState s = ParseState initParseState s = ParseState
@@ -224,7 +251,7 @@ initAlexInput s = AlexInput
{ _aiPrevChar = '\0' { _aiPrevChar = '\0'
, _aiSource = s , _aiSource = s
, _aiBytes = [] , _aiBytes = []
, _aiPos = (1,1) , _aiPos = (1,1,0)
} }
runP' :: P a -> Text -> (ParseState, [MsgEnvelope RlpParseError], Maybe a) runP' :: P a -> Text -> (ParseState, [MsgEnvelope RlpParseError], Maybe a)
@@ -238,7 +265,7 @@ lexToken = do
st <- use id st <- use id
-- traceM $ "st: " <> show st -- traceM $ "st: " <> show st
case alexScan inp c of case alexScan inp c of
AlexEOF -> pure $ Located (inp ^. aiPos, 0) TokenEOF AlexEOF -> pure $ Located (spanFromPos (inp^.aiPos) 0) TokenEOF
AlexSkip inp' l -> do AlexSkip inp' l -> do
psInput .= inp' psInput .= inp'
lexToken lexToken
@@ -274,7 +301,7 @@ indentLevel = do
insertToken :: RlpToken -> P (Located RlpToken) insertToken :: RlpToken -> P (Located RlpToken)
insertToken t = do insertToken t = do
pos <- use (psInput . aiPos) pos <- use (psInput . aiPos)
pure (Located (pos, 0) t) pure (Located (spanFromPos pos 0) t)
popLayout :: P Layout popLayout :: P Layout
popLayout = do popLayout = do
@@ -341,6 +368,7 @@ explicitRBrace inp l = do
doLayout :: LexerAction (Located RlpToken) doLayout :: LexerAction (Located RlpToken)
doLayout _ _ = do doLayout _ _ = do
i <- indentLevel i <- indentLevel
traceM $ "doLayout: i: " <> show i
pushLayout (Implicit i) pushLayout (Implicit i)
popLexState popLexState
insertLBrace insertLBrace

View File

@@ -1,7 +1,8 @@
{ {
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase, ViewPatterns #-}
module Rlp.Parse module Rlp.Parse
( parseRlpProg ( parseRlpProg
, parseRlpExpr
) )
where where
import Compiler.RlpcError import Compiler.RlpcError
@@ -9,16 +10,21 @@ 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 Lens.Micro import Lens.Micro.Platform
import Lens.Micro.Mtl
import Lens.Micro.Platform ()
import Data.List.Extra import Data.List.Extra
import Data.Fix import Data.Fix
import Data.Functor.Const import Data.Functor.Const
import Data.Functor.Apply
import Data.Functor.Bind
import Control.Comonad
import Data.Functor
import Data.Semigroup.Traversable
import Data.Text qualified as T import Data.Text qualified as T
import Data.Void
} }
%name parseRlpProg StandaloneProgram %name parseRlpProg StandaloneProgram
%name parseRlpExpr StandaloneExpr
%monad { P } %monad { P }
%lexer { lexCont } { Located _ TokenEOF } %lexer { lexCont } { Located _ TokenEOF }
@@ -26,14 +32,15 @@ import Data.Text qualified as T
%tokentype { Located RlpToken } %tokentype { Located RlpToken }
%token %token
varname { Located _ (TokenVarName $$) } varname { Located _ (TokenVarName _) }
conname { Located _ (TokenConName $$) } conname { Located _ (TokenConName _) }
consym { Located _ (TokenConSym $$) } consym { Located _ (TokenConSym _) }
varsym { Located _ (TokenVarSym $$) } varsym { Located _ (TokenVarSym _) }
data { Located _ TokenData } data { Located _ TokenData }
litint { Located _ (TokenLitInt $$) } litint { Located _ (TokenLitInt _) }
'=' { Located _ TokenEquals } '=' { Located _ TokenEquals }
'|' { Located _ TokenPipe } '|' { Located _ TokenPipe }
'::' { Located _ TokenHasType }
';' { Located _ TokenSemicolon } ';' { Located _ TokenSemicolon }
'(' { Located _ TokenLParen } '(' { Located _ TokenLParen }
')' { Located _ TokenRParen } ')' { Located _ TokenRParen }
@@ -46,15 +53,22 @@ import Data.Text qualified as T
infixl { Located _ TokenInfixL } infixl { Located _ TokenInfixL }
infixr { Located _ TokenInfixR } infixr { Located _ TokenInfixR }
infix { Located _ TokenInfix } infix { Located _ TokenInfix }
let { Located _ TokenLet }
in { Located _ TokenIn }
%nonassoc '='
%right '->' %right '->'
%right in
%% %%
StandaloneProgram :: { RlpProgram' } StandaloneProgram :: { RlpProgram RlpcPs }
StandaloneProgram : '{' Decls '}' {% mkProgram $2 } StandaloneProgram : '{' Decls '}' {% mkProgram $2 }
| VL DeclsV VR {% mkProgram $2 } | VL DeclsV VR {% mkProgram $2 }
StandaloneExpr :: { RlpExpr RlpcPs }
: VL Expr VR { extract $2 }
VL :: { () } VL :: { () }
VL : vlbrace { () } VL : vlbrace { () }
@@ -62,12 +76,12 @@ VR :: { () }
VR : vrbrace { () } VR : vrbrace { () }
| error { () } | error { () }
Decls :: { [PartialDecl'] } Decls :: { [Decl' RlpcPs] }
Decls : Decl ';' Decls { $1 : $3 } Decls : Decl ';' Decls { $1 : $3 }
| Decl ';' { [$1] } | Decl ';' { [$1] }
| Decl { [$1] } | Decl { [$1] }
DeclsV :: { [PartialDecl'] } DeclsV :: { [Decl' RlpcPs] }
DeclsV : Decl VS Decls { $1 : $3 } DeclsV : Decl VS Decls { $1 : $3 }
| Decl VS { [$1] } | Decl VS { [$1] }
| Decl { [$1] } | Decl { [$1] }
@@ -76,97 +90,128 @@ VS :: { Located RlpToken }
VS : ';' { $1 } VS : ';' { $1 }
| vsemi { $1 } | vsemi { $1 }
Decl :: { PartialDecl' } Decl :: { Decl' RlpcPs }
: FunDecl { $1 } : FunDecl { $1 }
| TySigDecl { $1 }
| DataDecl { $1 } | DataDecl { $1 }
| InfixDecl { $1 } | InfixDecl { $1 }
InfixDecl :: { PartialDecl' } TySigDecl :: { Decl' RlpcPs }
: InfixWord litint InfixOp {% mkInfixD $1 $2 $3 } : Var '::' Type { (\e -> TySigD [extract e]) <<~ $1 <~> $3 }
InfixWord :: { Assoc } InfixDecl :: { Decl' RlpcPs }
: infixl { InfixL } : InfixWord litint InfixOp { $1 =>> \w ->
| infixr { InfixR } InfixD (extract $1) (extractInt $ extract $2)
| infix { Infix } (extract $3) }
DataDecl :: { PartialDecl' } InfixWord :: { Located Assoc }
: data Con TyParams '=' DataCons { DataD $2 $3 $5 } : infixl { $1 \$> InfixL }
| infixr { $1 \$> InfixR }
| infix { $1 \$> Infix }
TyParams :: { [Name] } DataDecl :: { Decl' RlpcPs }
: data Con TyParams '=' DataCons { $1 \$> DataD (extract $2) $3 $5 }
TyParams :: { [PsName] }
: {- epsilon -} { [] } : {- epsilon -} { [] }
| TyParams varname { $1 `snoc` $2 } | TyParams varname { $1 `snoc` (extractName . extract $ $2) }
DataCons :: { [ConAlt] } DataCons :: { [ConAlt RlpcPs] }
: DataCons '|' DataCon { $1 `snoc` $3 } : DataCons '|' DataCon { $1 `snoc` $3 }
| DataCon { [$1] } | DataCon { [$1] }
DataCon :: { ConAlt } DataCon :: { ConAlt RlpcPs }
: Con Type1s { ConAlt $1 $2 } : Con Type1s { ConAlt (extract $1) $2 }
Type1s :: { [Type] } Type1s :: { [RlpType' RlpcPs] }
: {- epsilon -} { [] } : {- epsilon -} { [] }
| Type1s Type1 { $1 `snoc` $2 } | Type1s Type1 { $1 `snoc` $2 }
Type1 :: { Type } Type1 :: { RlpType' RlpcPs }
: '(' Type ')' { $2 } : '(' Type ')' { $2 }
| conname { TyCon $1 } | conname { fmap ConT (mkPsName $1) }
| varname { TyVar $1 } | varname { fmap VarT (mkPsName $1) }
Type :: { Type } Type :: { RlpType' RlpcPs }
: Type '->' Type { $1 :-> $3 } : Type '->' Type { FunT <<~ $1 <~> $3 }
| Type1 { $1 } | Type1 { $1 }
FunDecl :: { PartialDecl' } FunDecl :: { Decl' RlpcPs }
FunDecl : Var Params '=' Expr { FunD $1 $2 (Const $4) Nothing } FunDecl : Var Params '=' Expr { $4 =>> \e ->
FunD (extract $1) $2 e Nothing }
Params :: { [Pat'] } Params :: { [Pat' RlpcPs] }
Params : {- epsilon -} { [] } Params : {- epsilon -} { [] }
| Params Pat1 { $1 `snoc` $2 } | Params Pat1 { $1 `snoc` $2 }
Pat1 :: { Pat' } Pat1 :: { Pat' RlpcPs }
: Var { VarP $1 } : Var { fmap VarP $1 }
| Lit { LitP $1 } | Lit { LitP <<= $1 }
Expr :: { PartialExpr' } Expr :: { RlpExpr' RlpcPs }
: Expr1 varsym Expr { Fix $ B $2 (unFix $1) (unFix $3) } : Expr1 InfixOp Expr { $2 =>> \o ->
OAppE (extract o) $1 $3 }
| Expr1 { $1 } | Expr1 { $1 }
| LetExpr { $1 }
Expr1 :: { PartialExpr' } LetExpr :: { RlpExpr' RlpcPs }
: '(' Expr ')' { wrapFix . Par . unwrapFix $ $2 } : let layout1(Binding) in Expr { $1 \$> LetE $2 $4 }
| Lit { Fix . E $ LitEF $1 }
| Var { Fix . E $ VarEF $1 }
-- TODO: happy prefers left-associativity. doing such would require adjusting layout1(p) : '{' layout_list1(';',p) '}' { $2 }
-- the code in Rlp.Parse.Associate to expect left-associative input rather than | VL layout_list1(VS,p) VR { $2 }
-- right.
InfixExpr :: { PartialExpr' }
: Expr1 varsym Expr { Fix $ B $2 (unFix $1) (unFix $3) }
InfixOp :: { Name } layout_list1(sep,p) : p { [$1] }
: consym { $1 } | layout_list1(sep,p) sep p { $1 `snoc` $3 }
| varsym { $1 }
Lit :: { Lit' } Binding :: { Binding' RlpcPs }
Lit : litint { IntL $1 } : Pat1 '=' Expr { PatB <<~ $1 <~> $3 }
Var :: { VarId } Expr1 :: { RlpExpr' RlpcPs }
Var : varname { NameVar $1 } : '(' Expr ')' { $1 .> $2 <. $3 }
| Lit { fmap LitE $1 }
| Var { fmap VarE $1 }
Con :: { ConId } InfixOp :: { Located PsName }
: conname { NameCon $1 } : consym { mkPsName $1 }
| varsym { mkPsName $1 }
-- TODO: microlens-pro save me microlens-pro (rewrite this with prisms)
Lit :: { Lit' RlpcPs }
: litint { $1 <&> (IntL . (\ (TokenLitInt n) -> n)) }
Var :: { Located PsName }
Var : varname { mkPsName $1 }
Con :: { Located PsName }
: conname { mkPsName $1 }
{ {
mkProgram :: [PartialDecl'] -> P RlpProgram' mkPsName :: Located RlpToken -> Located PsName
mkPsName = fmap extractName
extractName :: RlpToken -> PsName
extractName = \case
TokenVarName n -> n
TokenConName n -> n
TokenConSym n -> n
TokenVarSym n -> n
_ -> error "mkPsName: not an identifier"
extractInt :: RlpToken -> Int
extractInt (TokenLitInt n) = n
extractInt _ = error "extractInt: ugh"
mkProgram :: [Decl' RlpcPs] -> P (RlpProgram RlpcPs)
mkProgram ds = do mkProgram ds = do
pt <- use psOpTable pt <- use psOpTable
pure $ RlpProgram (associate pt <$> ds) pure $ RlpProgram (associate pt <$> ds)
parseError :: Located RlpToken -> P a parseError :: Located RlpToken -> P a
parseError (Located ((l,c),s) t) = addFatal $ parseError (Located ss t) = addFatal $
errorMsg (SrcSpan l c s) RlpParErrUnexpectedToken errorMsg ss RlpParErrUnexpectedToken
mkInfixD :: Assoc -> Int -> Name -> P PartialDecl' mkInfixD :: Assoc -> Int -> PsName -> P (Decl' RlpcPs)
mkInfixD a p n = do mkInfixD a p n = do
let opl :: Lens' ParseState (Maybe OpInfo) let opl :: Lens' ParseState (Maybe OpInfo)
opl = psOpTable . at n opl = psOpTable . at n
@@ -176,6 +221,10 @@ mkInfixD a p n = do
l = T.length n l = T.length n
Nothing -> pure (Just (a,p)) Nothing -> pure (Just (a,p))
) )
pure $ InfixD a p n pos <- use (psInput . aiPos)
pure $ Located (spanFromPos pos 0) (InfixD a p n)
intOfToken :: Located RlpToken -> Int
intOfToken (Located _ (TokenLitInt n)) = n
} }

View File

@@ -1,6 +1,7 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns, ImplicitParams #-} {-# LANGUAGE PatternSynonyms, ViewPatterns, ImplicitParams #-}
module Rlp.Parse.Associate module Rlp.Parse.Associate
{-# WARNING "temporarily unimplemented" #-}
( associate ( associate
) )
where where
@@ -13,88 +14,6 @@ import Rlp.Parse.Types
import Rlp.Syntax import Rlp.Syntax
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
associate :: OpTable -> PartialDecl' -> Decl' RlpExpr associate x y = y
associate pt (FunD n as b w) = FunD n as b' w {-# WARNING associate "temporarily undefined" #-}
where b' = let ?pt = pt in completeExpr (getConst b)
associate pt (TySigD ns t) = TySigD ns t
associate pt (DataD n as cs) = DataD n as cs
associate pt (InfixD a p n) = InfixD a p n
completeExpr :: (?pt :: OpTable) => PartialExpr' -> RlpExpr'
completeExpr = cata completePartial
completePartial :: (?pt :: OpTable) => PartialE -> RlpExpr'
completePartial (E e) = completeRlpExpr e
completePartial p@(B o l r) = completeB (build p)
completePartial (Par e) = completePartial e
completeRlpExpr :: (?pt :: OpTable) => RlpExprF' RlpExpr' -> RlpExpr'
completeRlpExpr = embed
completeB :: (?pt :: OpTable) => PartialE -> RlpExpr'
completeB p = case build p of
B o l r -> (o' `AppE` l') `AppE` r'
where
-- TODO: how do we know it's symbolic?
o' = VarE (SymVar o)
l' = completeB l
r' = completeB r
Par e -> completeB e
E e -> completeRlpExpr e
build :: (?pt :: OpTable) => PartialE -> PartialE
build e = go id e (rightmost e) where
rightmost :: PartialE -> PartialE
rightmost (B _ _ r) = rightmost r
rightmost p@(E _) = p
rightmost p@(Par _) = p
go :: (?pt :: OpTable)
=> (PartialE -> PartialE)
-> PartialE -> PartialE -> PartialE
go f p@(WithInfo o _ r) = case r of
E _ -> mkHole o (f . f')
Par _ -> mkHole o (f . f')
B _ _ _ -> go (mkHole o (f . f')) r
where f' r' = p & pR .~ r'
go f _ = id
mkHole :: (?pt :: OpTable)
=> OpInfo
-> (PartialE -> PartialE)
-> PartialE
-> PartialE
mkHole _ hole p@(Par _) = hole p
mkHole _ hole p@(E _) = hole p
mkHole (a,d) hole p@(WithInfo (a',d') _ _)
| d' < d = above
| d' > d = below
| d == d' = case (a,a') of
-- left-associative operators of equal precedence are
-- associated left
(InfixL,InfixL) -> above
-- right-associative operators are handled similarly
(InfixR,InfixR) -> below
-- non-associative operators of equal precedence, or equal
-- precedence operators of different associativities are
-- invalid
(_, _) -> error "invalid expression"
where
above = p & pL %~ hole
below = hole p
examplePrecTable :: OpTable
examplePrecTable = H.fromList
[ ("+", (InfixL,6))
, ("*", (InfixL,7))
, ("^", (InfixR,8))
, (".", (InfixR,7))
, ("~", (Infix, 9))
, ("=", (Infix, 4))
, ("&&", (Infix, 3))
, ("||", (Infix, 2))
, ("$", (InfixR,0))
, ("&", (InfixL,0))
]

View File

@@ -2,38 +2,26 @@
{-# LANGUAGE ImplicitParams, ViewPatterns, PatternSynonyms #-} {-# LANGUAGE ImplicitParams, ViewPatterns, PatternSynonyms #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
module Rlp.Parse.Types module Rlp.Parse.Types
( LexerAction (
, MsgEnvelope(..) -- * Trees That Grow
, RlpcError(..) RlpcPs
, AlexInput(..)
, Position(..) -- * Parser monad and state
, RlpToken(..) , P(..), ParseState(..), Layout(..), OpTable, OpInfo
, P(..) -- ** Lenses
, ParseState(..) , psLayoutStack, psLexState, psInput, psOpTable
, psLayoutStack
, psLexState -- * Other parser types
, psInput , RlpToken(..), AlexInput(..), Position(..), spanFromPos, LexerAction
, psOpTable , Located(..), PsName
, Layout(..) -- ** Lenses
, Located(..) , aiPrevChar, aiSource, aiBytes, aiPos, posLine, posColumn
, OpTable
, OpInfo , (<<~), (<~>)
, RlpParseError(..)
, PartialDecl' -- * Error handling
, Partial(..) , MsgEnvelope(..), RlpcError(..), RlpParseError(..)
, pL, pR , addFatal, addWound, addFatalHere, addWoundHere
, PartialE
, pattern WithInfo
, opInfoOrDef
, PartialExpr'
, aiPrevChar
, aiSource
, aiBytes
, aiPos
, addFatal
, addWound
, addFatalHere
, addWoundHere
) )
where where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -49,12 +37,46 @@ import Data.Functor.Foldable
import Data.Functor.Const import Data.Functor.Const
import Data.Functor.Classes import Data.Functor.Classes
import Data.HashMap.Strict qualified as H import Data.HashMap.Strict qualified as H
import Data.Void
import Data.Word (Word8) import Data.Word (Word8)
import Lens.Micro.TH import Lens.Micro.TH
import Lens.Micro import Lens.Micro
import Rlp.Syntax import Rlp.Syntax
import Compiler.Types
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Phantom type identifying rlpc's parser phase
data RlpcPs
type instance XRec RlpcPs f = Located (f RlpcPs)
type instance IdP RlpcPs = PsName
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 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 PsName = Text
--------------------------------------------------------------------------------
spanFromPos :: Position -> Int -> SrcSpan
spanFromPos (l,c,a) s = SrcSpan l c a s
{-# INLINE spanFromPos #-}
type LexerAction a = AlexInput -> Int -> P a type LexerAction a = AlexInput -> Int -> P a
data AlexInput = AlexInput data AlexInput = AlexInput
@@ -66,8 +88,9 @@ data AlexInput = AlexInput
deriving Show deriving Show
type Position = type Position =
( Int -- line ( Int -- ^ line
, Int -- column , Int -- ^ column
, Int -- ^ Absolutely
) )
posLine :: Lens' Position Int posLine :: Lens' Position Int
@@ -76,6 +99,9 @@ posLine = _1
posColumn :: Lens' Position Int posColumn :: Lens' Position Int
posColumn = _2 posColumn = _2
posAbsolute :: Lens' Position Int
posAbsolute = _3
data RlpToken data RlpToken
-- literals -- literals
= TokenLitInt Int = TokenLitInt Int
@@ -106,7 +132,7 @@ data RlpToken
| TokenLParen | TokenLParen
| TokenRParen | TokenRParen
-- 'virtual' control symbols, inserted by the lexer without any correlation -- 'virtual' control symbols, inserted by the lexer without any correlation
-- to a specific symbol -- to a specific part of the input
| TokenSemicolonV | TokenSemicolonV
| TokenLBraceV | TokenLBraceV
| TokenRBraceV | TokenRBraceV
@@ -154,9 +180,6 @@ data Layout = Explicit
| Implicit Int | Implicit Int
deriving (Show, Eq) deriving (Show, Eq)
data Located a = Located (Position, Int) a
deriving (Show)
type OpTable = H.HashMap Name OpInfo type OpTable = H.HashMap Name OpInfo
type OpInfo = (Assoc, Int) type OpInfo = (Assoc, Int)
@@ -171,47 +194,6 @@ data RlpParseError = RlpParErrOutOfBoundsPrecedence Int
instance IsRlpcError RlpParseError where instance IsRlpcError RlpParseError where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
-- absolute psycho shit (partial ASTs)
type PartialDecl' = Decl (Const PartialExpr') Name
data Partial a = E (RlpExprF Name a)
| B Name (Partial a) (Partial a)
| Par (Partial a)
deriving (Show, Functor)
pL :: Traversal' (Partial a) (Partial a)
pL k (B o l r) = (\l' -> B o l' r) <$> k l
pL _ x = pure x
pR :: Traversal' (Partial a) (Partial a)
pR k (B o l r) = (\r' -> B o l r') <$> k r
pR _ x = pure x
type PartialE = Partial RlpExpr'
-- i love you haskell
pattern WithInfo :: (?pt :: OpTable) => OpInfo -> PartialE -> PartialE -> PartialE
pattern WithInfo p l r <- B (opInfoOrDef -> p) l r
opInfoOrDef :: (?pt :: OpTable) => Name -> OpInfo
opInfoOrDef c = fromMaybe (InfixL,9) $ H.lookup c ?pt
-- required to satisfy constraint on Fix's show instance
instance Show1 Partial where
liftShowsPrec :: forall a. (Int -> a -> ShowS)
-> ([a] -> ShowS)
-> Int -> Partial a -> ShowS
liftShowsPrec sp sl p m = case m of
(E e) -> showsUnaryWith lshow "E" p e
(B f a b) -> showsTernaryWith showsPrec lshow lshow "B" p f a b
(Par e) -> showsUnaryWith lshow "Par" p e
where
lshow :: forall f. (Show1 f) => Int -> f a -> ShowS
lshow = liftShowsPrec sp sl
type PartialExpr' = Fix Partial
makeLenses ''AlexInput makeLenses ''AlexInput
makeLenses ''ParseState makeLenses ''ParseState
@@ -222,6 +204,7 @@ addWoundHere l e = P $ \st ->
{ _msgSpan = let pos = psInput . aiPos { _msgSpan = let pos = psInput . aiPos
in SrcSpan (st ^. pos . posLine) in SrcSpan (st ^. pos . posLine)
(st ^. pos . posColumn) (st ^. pos . posColumn)
(st ^. pos . posAbsolute)
l l
, _msgDiagnostic = e , _msgDiagnostic = e
, _msgSeverity = SevError , _msgSeverity = SevError
@@ -234,6 +217,7 @@ addFatalHere l e = P $ \st ->
{ _msgSpan = let pos = psInput . aiPos { _msgSpan = let pos = psInput . aiPos
in SrcSpan (st ^. pos . posLine) in SrcSpan (st ^. pos . posLine)
(st ^. pos . posColumn) (st ^. pos . posColumn)
(st ^. pos . posAbsolute)
l l
, _msgDiagnostic = e , _msgDiagnostic = e
, _msgSeverity = SevError , _msgSeverity = SevError

View File

@@ -1,40 +1,36 @@
-- recursion-schemes -- recursion-schemes
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-} {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable
-- recursion-schemes , TemplateHaskell, TypeFamilies #-}
{-# LANGUAGE TemplateHaskell, TypeFamilies #-}
{-# LANGUAGE OverloadedStrings, PatternSynonyms #-} {-# LANGUAGE OverloadedStrings, PatternSynonyms #-}
{-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-}
{-# LANGUAGE UndecidableInstances, ImpredicativeTypes #-}
module Rlp.Syntax module Rlp.Syntax
( RlpModule(..) (
, RlpProgram(..) -- * AST
, RlpProgram' RlpProgram(..)
, rlpmodName , Decl(..), Decl', RlpExpr(..), RlpExpr'
, rlpmodProgram , Pat(..), Pat'
, RlpExpr(..)
, RlpExpr'
, RlpExprF(..)
, RlpExprF'
, Decl(..)
, Decl'
, Bind(..)
, Where
, Where'
, ConAlt(..)
, Type(..)
, pattern (:->)
, Assoc(..) , Assoc(..)
, VarId(..) , Lit(..), Lit'
, ConId(..) , RlpType(..), RlpType'
, Pat(..) , ConAlt(..)
, Pat' , Binding(..), Binding'
, Lit(..)
, Lit'
, Name
-- TODO: ugh move this somewhere else later -- * Trees That Grow boilerplate
, showsTernaryWith -- ** Extension points
, IdP, XRec, UnXRec(..), MapXRec(..)
-- * Convenience re-exports -- *** Decl
, Text , XFunD, XTySigD, XInfixD, XDataD, XXDeclD
-- *** RlpExpr
, XLetE, XVarE, XLamE, XCaseE, XIfE, XAppE, XLitE
, XParE, XOAppE, XXRlpExprE
-- ** Pattern synonyms
-- *** Decl
, pattern FunD, pattern TySigD, pattern InfixD, pattern DataD
-- *** RlpExpr
, pattern LetE, pattern VarE, pattern LamE, pattern CaseE, pattern IfE
, pattern AppE, pattern LitE, pattern ParE, pattern OAppE
, pattern XRlpExprE
) )
where where
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
@@ -43,93 +39,180 @@ import Data.Text qualified as T
import Data.String (IsString(..)) import Data.String (IsString(..))
import Data.Functor.Foldable.TH (makeBaseFunctor) import Data.Functor.Foldable.TH (makeBaseFunctor)
import Data.Functor.Classes import Data.Functor.Classes
import Data.Kind (Type)
import Lens.Micro import Lens.Micro
import Lens.Micro.TH import Lens.Micro.TH
import Core.Syntax hiding (Lit) import Core.Syntax hiding (Lit, Type, Binding, Binding')
import Core (HasRHS(..), HasLHS(..)) import Core (HasRHS(..), HasLHS(..))
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
data RlpModule b = RlpModule data RlpModule p = RlpModule
{ _rlpmodName :: Text { _rlpmodName :: Text
, _rlpmodProgram :: RlpProgram b , _rlpmodProgram :: RlpProgram p
} }
newtype RlpProgram b = RlpProgram [Decl RlpExpr b] -- | dear god.
deriving Show type PhaseShow p =
( Show (XRec p Pat), Show (XRec p RlpExpr)
, Show (XRec p Lit), Show (IdP p)
, Show (XRec p RlpType)
, Show (XRec p Binding)
)
type RlpProgram' = RlpProgram Name newtype RlpProgram p = RlpProgram [Decl' p]
-- | The @e@ parameter is used for partial results. When parsing an input, we deriving instance (PhaseShow p, Show (XRec p Decl)) => Show (RlpProgram p)
-- first parse all top-level declarations in order to extract infix[lr]
-- declarations. This process yields a @[Decl (Const Text) Name]@, where @Const
-- Text@ stores the remaining unparsed function bodies. Once infixities are
-- accounted for, we may complete the parsing task and get a proper @[Decl
-- RlpExpr Name]@.
data Decl e b = FunD VarId [Pat b] (e b) (Maybe (Where b)) data RlpType p = FunConT
| TySigD [VarId] Type | FunT (RlpType' p) (RlpType' p)
| DataD ConId [Name] [ConAlt] | AppT (RlpType' p) (RlpType' p)
| InfixD Assoc Int Name | VarT (IdP p)
deriving Show | ConT (IdP p)
type Decl' e = Decl e Name type RlpType' p = XRec p RlpType
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' ()
type Decl' p = XRec p Decl
data Assoc = InfixL data Assoc = InfixL
| InfixR | InfixR
| Infix | Infix
deriving Show deriving (Show)
data ConAlt = ConAlt ConId [Type] data ConAlt p = ConAlt (IdP p) [RlpType' p]
deriving Show
data RlpExpr b = LetE [Bind b] (RlpExpr b) deriving instance (Show (IdP p), Show (XRec p RlpType)) => Show (ConAlt p)
| VarE VarId
| ConE ConId
| LamE [Pat b] (RlpExpr b)
| CaseE (RlpExpr b) [(Alt b, Where b)]
| IfE (RlpExpr b) (RlpExpr b) (RlpExpr b)
| AppE (RlpExpr b) (RlpExpr b)
| LitE (Lit b)
deriving Show
type RlpExpr' = RlpExpr Name data RlpExpr p = LetE' (XLetE 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)
type Where b = [Bind b] type family XLetE p
type Where' = [Bind Name] 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 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 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 (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
class UnXRec p where
unXRec :: XRec p f -> f p
class MapXRec p where
mapXRec :: (f p -> f' p') -> XRec p f -> XRec p' f'
type family XRec p (f :: Type -> Type) = (r :: Type) | r -> p f
type family IdP p
type Where p = [Binding p]
-- do we want guards? -- do we want guards?
data Alt b = AltA (Pat b) (RlpExpr b) data Alt p = AltA (Pat' p) (RlpExpr' p)
deriving Show
data Bind b = PatB (Pat b) (RlpExpr b) deriving instance (PhaseShow p) => Show (Alt p)
| FunB VarId [Pat b] (RlpExpr b)
deriving Show
data VarId = NameVar Text data Binding p = PatB (Pat' p) (RlpExpr' p)
| SymVar Text | FunB (IdP p) [Pat' p] (RlpExpr' p)
deriving Show
instance IsString VarId where type Binding' p = XRec p Binding
-- TODO: use symvar if it's an operator
fromString = NameVar . T.pack
data ConId = NameCon Text deriving instance (Show (XRec p Pat), Show (XRec p RlpExpr), Show (IdP p)
| SymCon Text ) => Show (Binding p)
deriving Show
data Pat b = VarP VarId data Pat p = VarP (IdP p)
| LitP (Lit b) | LitP (Lit' p)
| ConP ConId [Pat b] | ConP (IdP p) [Pat' p]
deriving Show
type Pat' = Pat Name deriving instance (PhaseShow p) => Show (Pat p)
data Lit b = IntL Int type Pat' p = XRec p Pat
data Lit p = IntL Int
| CharL Char | CharL Char
| ListL [RlpExpr b] | ListL [RlpExpr' p]
deriving Show
type Lit' = Lit Name deriving instance (PhaseShow p) => Show (Lit p)
type Lit' p = XRec p Lit
-- instance HasLHS Alt Alt Pat Pat where -- instance HasLHS Alt Alt Pat Pat where
-- _lhs = lens -- _lhs = lens
@@ -143,33 +226,17 @@ type Lit' = Lit Name
makeBaseFunctor ''RlpExpr makeBaseFunctor ''RlpExpr
deriving instance (Show b, Show a) => Show (RlpExprF b a) -- showsTernaryWith :: (Int -> x -> ShowS)
-- -> (Int -> y -> ShowS)
type RlpExprF' = RlpExprF Name -- -> (Int -> z -> ShowS)
-- -> String -> Int
-- society if derivable Show1 -- -> x -> y -> z
instance (Show b) => Show1 (RlpExprF b) where -- -> ShowS
liftShowsPrec sp _ p m = case m of -- showsTernaryWith sa sb sc name p a b c = showParen (p > 10)
(LetEF bs e) -> showsBinaryWith showsPrec sp "LetEF" p bs e -- $ showString name
(VarEF n) -> showsUnaryWith showsPrec "VarEF" p n -- . showChar ' ' . sa 11 a
(ConEF n) -> showsUnaryWith showsPrec "ConEF" p n -- . showChar ' ' . sb 11 b
(LamEF bs e) -> showsBinaryWith showsPrec sp "LamEF" p bs e -- . showChar ' ' . sc 11 c
(CaseEF e as) -> showsBinaryWith sp showsPrec "CaseEF" p e as
(IfEF a b c) -> showsTernaryWith sp sp sp "IfEF" p a b c
(AppEF f x) -> showsBinaryWith sp sp "AppEF" p f x
(LitEF l) -> showsUnaryWith showsPrec "LitEF" p l
showsTernaryWith :: (Int -> x -> ShowS)
-> (Int -> y -> ShowS)
-> (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
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------