Annotated expr #4
@@ -133,7 +133,7 @@ ddumpEval = whenFlag flagDDumpEval do
|
|||||||
|
|
||||||
parseProg :: RLPCOptions
|
parseProg :: RLPCOptions
|
||||||
-> String
|
-> String
|
||||||
-> Either SrcError (Program, [SrcError])
|
-> Either SrcError (CoreProgram, [SrcError])
|
||||||
parseProg o = evalRLPC o . (lexCore >=> parseCoreProg)
|
parseProg o = evalRLPC o . (lexCore >=> parseCoreProg)
|
||||||
|
|
||||||
forFiles_ :: (Monad m)
|
forFiles_ :: (Monad m)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ extra-doc-files: README.md
|
|||||||
-- extra-source-files:
|
-- extra-source-files:
|
||||||
|
|
||||||
common warnings
|
common warnings
|
||||||
ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-unused-top-binds
|
-- ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-unused-top-binds
|
||||||
|
|
||||||
library
|
library
|
||||||
import: warnings
|
import: warnings
|
||||||
@@ -23,6 +23,7 @@ library
|
|||||||
, GM
|
, GM
|
||||||
, Compiler.RLPC
|
, Compiler.RLPC
|
||||||
, Core.Syntax
|
, Core.Syntax
|
||||||
|
, Core.Utils
|
||||||
|
|
||||||
other-modules: Data.Heap
|
other-modules: Data.Heap
|
||||||
, Data.Pretty
|
, Data.Pretty
|
||||||
@@ -31,6 +32,7 @@ library
|
|||||||
, Core.Examples
|
, Core.Examples
|
||||||
, Core.Lex
|
, Core.Lex
|
||||||
, Control.Monad.Errorful
|
, Control.Monad.Errorful
|
||||||
|
, Core2Core
|
||||||
|
|
||||||
build-tool-depends: happy:happy, alex:alex
|
build-tool-depends: happy:happy, alex:alex
|
||||||
|
|
||||||
@@ -47,6 +49,7 @@ library
|
|||||||
, unordered-containers
|
, unordered-containers
|
||||||
, hashable
|
, hashable
|
||||||
, pretty
|
, pretty
|
||||||
|
, recursion-schemes
|
||||||
|
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
default-language: GHC2021
|
default-language: GHC2021
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import Core.TH
|
|||||||
|
|
||||||
-- TODO: my shitty lexer isn't inserting semicolons
|
-- TODO: my shitty lexer isn't inserting semicolons
|
||||||
|
|
||||||
letrecExample :: Program
|
|
||||||
letrecExample = [coreProg|
|
letrecExample = [coreProg|
|
||||||
pair x y f = f x y;
|
pair x y f = f x y;
|
||||||
|
|
||||||
@@ -28,7 +27,6 @@ letrecExample = [coreProg|
|
|||||||
main = f 3 4;
|
main = f 3 4;
|
||||||
|]
|
|]
|
||||||
|
|
||||||
idExample :: Program
|
|
||||||
idExample = [coreProg|
|
idExample = [coreProg|
|
||||||
main = id 3;
|
main = id 3;
|
||||||
|]
|
|]
|
||||||
@@ -138,7 +136,7 @@ factorialGM = [coreProg|
|
|||||||
main = fac 3;
|
main = fac 3;
|
||||||
|]
|
|]
|
||||||
|
|
||||||
corePrelude :: Module
|
corePrelude :: Module Name
|
||||||
corePrelude = Module (Just ("Prelude", [])) $
|
corePrelude = Module (Just ("Prelude", [])) $
|
||||||
-- non-primitive defs
|
-- non-primitive defs
|
||||||
[coreProg|
|
[coreProg|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ import Data.Default.Class (def)
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
Module :: { Module }
|
Module :: { Module Name }
|
||||||
Module : module conname where Program Eof { Module (Just ($2, [])) $4 }
|
Module : module conname where Program Eof { Module (Just ($2, [])) $4 }
|
||||||
| Program Eof { Module Nothing $1 }
|
| Program Eof { Module Nothing $1 }
|
||||||
|
|
||||||
@@ -66,36 +66,36 @@ Eof :: { () }
|
|||||||
Eof : eof { () }
|
Eof : eof { () }
|
||||||
| error { () }
|
| error { () }
|
||||||
|
|
||||||
StandaloneProgram :: { Program }
|
StandaloneProgram :: { Program Name }
|
||||||
StandaloneProgram : Program eof { $1 }
|
StandaloneProgram : Program eof { $1 }
|
||||||
|
|
||||||
Program :: { Program }
|
Program :: { Program Name }
|
||||||
Program : ScDefs { Program $1 }
|
Program : ScDefs { Program $1 }
|
||||||
|
|
||||||
ScDefs :: { [ScDef] }
|
ScDefs :: { [ScDef Name] }
|
||||||
ScDefs : ScDef ';' ScDefs { $1 : $3 }
|
ScDefs : ScDef ';' ScDefs { $1 : $3 }
|
||||||
| ScDef ';' { [$1] }
|
| ScDef ';' { [$1] }
|
||||||
| ScDef { [$1] }
|
| ScDef { [$1] }
|
||||||
| {- epsilon -} { [] }
|
| {- epsilon -} { [] }
|
||||||
|
|
||||||
ScDef :: { ScDef }
|
ScDef :: { ScDef Name }
|
||||||
ScDef : Var ParList '=' Expr { ScDef $1 $2 $4 }
|
ScDef : Var ParList '=' Expr { ScDef $1 $2 $4 }
|
||||||
|
|
||||||
ParList :: { [Name] }
|
ParList :: { [Name] }
|
||||||
ParList : Var ParList { $1 : $2 }
|
ParList : Var ParList { $1 : $2 }
|
||||||
| {- epsilon -} { [] }
|
| {- epsilon -} { [] }
|
||||||
|
|
||||||
StandaloneExpr :: { Expr }
|
StandaloneExpr :: { Expr Name }
|
||||||
StandaloneExpr : Expr eof { $1 }
|
StandaloneExpr : Expr eof { $1 }
|
||||||
|
|
||||||
Expr :: { Expr }
|
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 }
|
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 }
|
||||||
|
|
||||||
@@ -103,48 +103,48 @@ Binders :: { [Name] }
|
|||||||
Binders : Var Binders { $1 : $2 }
|
Binders : Var Binders { $1 : $2 }
|
||||||
| Var { [$1] }
|
| Var { [$1] }
|
||||||
|
|
||||||
Application :: { Expr }
|
Application :: { Expr Name }
|
||||||
Application : Expr1 AppArgs { foldl' App $1 $2 }
|
Application : Expr1 AppArgs { foldl' App $1 $2 }
|
||||||
|
|
||||||
-- TODO: Application can probably be written as a single rule, without AppArgs
|
-- TODO: Application can probably be written as a single rule, without AppArgs
|
||||||
AppArgs :: { [Expr] }
|
AppArgs :: { [Expr Name] }
|
||||||
AppArgs : Expr1 AppArgs { $1 : $2 }
|
AppArgs : Expr1 AppArgs { $1 : $2 }
|
||||||
| Expr1 { [$1] }
|
| Expr1 { [$1] }
|
||||||
|
|
||||||
CaseExpr :: { Expr }
|
CaseExpr :: { Expr Name }
|
||||||
CaseExpr : case Expr of '{' Alters '}' { Case $2 $5 }
|
CaseExpr : case Expr of '{' Alters '}' { Case $2 $5 }
|
||||||
|
|
||||||
Alters :: { [Alter] }
|
Alters :: { [Alter Name] }
|
||||||
Alters : Alter ';' Alters { $1 : $3 }
|
Alters : Alter ';' Alters { $1 : $3 }
|
||||||
| Alter ';' { [$1] }
|
| Alter ';' { [$1] }
|
||||||
| Alter { [$1] }
|
| Alter { [$1] }
|
||||||
|
|
||||||
Alter :: { Alter }
|
Alter :: { Alter Name }
|
||||||
Alter : litint ParList '->' Expr { Alter $1 $2 $4 }
|
Alter : litint ParList '->' Expr { Alter (AltData $1) $2 $4 }
|
||||||
|
|
||||||
Expr1 :: { Expr }
|
Expr1 :: { Expr Name }
|
||||||
Expr1 : litint { IntE $1 }
|
Expr1 : litint { LitE $ IntL $1 }
|
||||||
| Id { Var $1 }
|
| Id { Var $1 }
|
||||||
| PackCon { $1 }
|
| PackCon { $1 }
|
||||||
| ExprPragma { $1 }
|
| ExprPragma { $1 }
|
||||||
| '(' Expr ')' { $2 }
|
| '(' Expr ')' { $2 }
|
||||||
|
|
||||||
ExprPragma :: { Expr }
|
ExprPragma :: { Expr Name }
|
||||||
ExprPragma : '{-#' Words '#-}' {% exprPragma $2 }
|
ExprPragma : '{-#' Words '#-}' {% exprPragma $2 }
|
||||||
|
|
||||||
Words :: { [String] }
|
Words :: { [String] }
|
||||||
Words : word Words { $1 : $2 }
|
Words : word Words { $1 : $2 }
|
||||||
| word { [$1] }
|
| word { [$1] }
|
||||||
|
|
||||||
PackCon :: { Expr }
|
PackCon :: { Expr Name }
|
||||||
PackCon : pack '{' litint litint '}' { Con $3 $4 }
|
PackCon : pack '{' litint litint '}' { Con $3 $4 }
|
||||||
|
|
||||||
Bindings :: { [Binding] }
|
Bindings :: { [Binding Name] }
|
||||||
Bindings : Binding ';' Bindings { $1 : $3 }
|
Bindings : Binding ';' Bindings { $1 : $3 }
|
||||||
| Binding ';' { [$1] }
|
| Binding ';' { [$1] }
|
||||||
| Binding { [$1] }
|
| Binding { [$1] }
|
||||||
|
|
||||||
Binding :: { Binding }
|
Binding :: { Binding Name }
|
||||||
Binding : Var '=' Expr { $1 := $3 }
|
Binding : Var '=' Expr { $1 := $3 }
|
||||||
|
|
||||||
Id :: { Name }
|
Id :: { Name }
|
||||||
@@ -169,7 +169,7 @@ parseError (Located y x l _ : _) = addFatal err
|
|||||||
, _errDiagnostic = SrcErrParse
|
, _errDiagnostic = SrcErrParse
|
||||||
}
|
}
|
||||||
|
|
||||||
parseTmp :: IO Module
|
parseTmp :: IO (Module Name)
|
||||||
parseTmp = do
|
parseTmp = do
|
||||||
s <- readFile "/tmp/t.hs"
|
s <- readFile "/tmp/t.hs"
|
||||||
case parse s of
|
case parse s of
|
||||||
@@ -178,7 +178,7 @@ parseTmp = do
|
|||||||
where
|
where
|
||||||
parse = evalRLPC def . (lexCore >=> parseCore)
|
parse = evalRLPC def . (lexCore >=> parseCore)
|
||||||
|
|
||||||
exprPragma :: [String] -> RLPC SrcError Expr
|
exprPragma :: [String] -> RLPC SrcError (Expr Name)
|
||||||
exprPragma ("AST" : e) = astPragma e
|
exprPragma ("AST" : e) = astPragma e
|
||||||
exprPragma _ = addFatal err
|
exprPragma _ = addFatal err
|
||||||
where err = SrcError
|
where err = SrcError
|
||||||
@@ -187,7 +187,7 @@ exprPragma _ = addFatal err
|
|||||||
, _errDiagnostic = SrcErrUnknownPragma "" -- TODO: missing pragma
|
, _errDiagnostic = SrcErrUnknownPragma "" -- TODO: missing pragma
|
||||||
}
|
}
|
||||||
|
|
||||||
astPragma :: [String] -> RLPC SrcError Expr
|
astPragma :: [String] -> RLPC SrcError (Expr Name)
|
||||||
astPragma = pure . read . unwords
|
astPragma = pure . read . unwords
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/Core/Rename.hs
Normal file
11
src/Core/Rename.hs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module Core.Rename
|
||||||
|
( renameCore
|
||||||
|
)
|
||||||
|
where
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
import Core.Syntax
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
renameCore :: Program Name -> Program Unique
|
||||||
|
renameCore = undefined
|
||||||
|
|
||||||
@@ -3,10 +3,13 @@ Module : Core.Syntax
|
|||||||
Description : Core ASTs and the like
|
Description : Core ASTs and the like
|
||||||
-}
|
-}
|
||||||
{-# LANGUAGE PatternSynonyms, OverloadedStrings #-}
|
{-# LANGUAGE PatternSynonyms, OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
module Core.Syntax
|
module Core.Syntax
|
||||||
( Expr(..)
|
( Expr(..)
|
||||||
|
, Literal(..)
|
||||||
, pattern (:$)
|
, pattern (:$)
|
||||||
, Binding(..)
|
, Binding(..)
|
||||||
|
, AltCon(..)
|
||||||
, pattern (:=)
|
, pattern (:=)
|
||||||
, Rec(..)
|
, Rec(..)
|
||||||
, Alter(..)
|
, Alter(..)
|
||||||
@@ -15,142 +18,113 @@ module Core.Syntax
|
|||||||
, ScDef(..)
|
, ScDef(..)
|
||||||
, Module(..)
|
, Module(..)
|
||||||
, Program(..)
|
, Program(..)
|
||||||
, bindersOf
|
, Program'
|
||||||
, rhssOf
|
, Expr'
|
||||||
, isAtomic
|
, ScDef'
|
||||||
, insertModule
|
, Alter'
|
||||||
, extractProgram
|
, Binding'
|
||||||
|
, HasRHS(_rhs)
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
import Data.Coerce
|
import Data.Coerce
|
||||||
import Data.Pretty
|
import Data.Pretty
|
||||||
|
import GHC.Generics
|
||||||
import Data.List (intersperse)
|
import Data.List (intersperse)
|
||||||
import Data.Function ((&))
|
import Data.Function ((&))
|
||||||
import Data.String
|
import Data.String
|
||||||
|
-- Lift instances for the Core quasiquoters
|
||||||
|
import Lens.Micro
|
||||||
import Language.Haskell.TH.Syntax (Lift)
|
import Language.Haskell.TH.Syntax (Lift)
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
data Expr = Var Name
|
data Expr b = Var Name
|
||||||
| Con Tag Int -- Con Tag Arity
|
| Con Tag Int -- Con Tag Arity
|
||||||
| Let Rec [Binding] Expr
|
| Case (Expr b) [Alter b]
|
||||||
| Case Expr [Alter]
|
| Lam [b] (Expr b)
|
||||||
| Lam [Name] Expr
|
| Let Rec [Binding b] (Expr b)
|
||||||
| App Expr Expr
|
| App (Expr b) (Expr b)
|
||||||
| IntE Int
|
| LitE Literal
|
||||||
deriving (Show, Read, Lift, Eq)
|
deriving (Show, Read, Lift)
|
||||||
|
|
||||||
|
deriving instance (Eq b) => Eq (Expr b)
|
||||||
|
|
||||||
infixl 2 :$
|
infixl 2 :$
|
||||||
pattern (:$) :: Expr -> Expr -> Expr
|
pattern (:$) :: Expr b -> Expr b -> Expr b
|
||||||
pattern f :$ x = App f x
|
pattern f :$ x = App f x
|
||||||
|
|
||||||
{-# COMPLETE Binding :: Binding #-}
|
{-# COMPLETE Binding :: Binding #-}
|
||||||
{-# COMPLETE (:=) :: Binding #-}
|
{-# COMPLETE (:=) :: Binding #-}
|
||||||
data Binding = Binding Name Expr
|
data Binding b = Binding b (Expr b)
|
||||||
deriving (Show, Read, Lift, Eq)
|
deriving (Show, Read, Lift)
|
||||||
|
|
||||||
|
deriving instance (Eq b) => Eq (Binding b)
|
||||||
|
|
||||||
infixl 1 :=
|
infixl 1 :=
|
||||||
pattern (:=) :: Name -> Expr -> Binding
|
pattern (:=) :: b -> (Expr b) -> (Binding b)
|
||||||
pattern k := v = Binding k v
|
pattern k := v = Binding k v
|
||||||
|
|
||||||
|
data Alter b = Alter AltCon [b] (Expr b)
|
||||||
|
deriving (Show, Read, Lift)
|
||||||
|
|
||||||
|
deriving instance (Eq b) => Eq (Alter b)
|
||||||
|
|
||||||
data Rec = Rec
|
data Rec = Rec
|
||||||
| NonRec
|
| NonRec
|
||||||
deriving (Show, Read, Eq, Lift)
|
deriving (Show, Read, Eq, Lift)
|
||||||
|
|
||||||
data Alter = Alter Tag [Name] Expr
|
data AltCon = AltData Tag
|
||||||
deriving (Show, Read, Lift, Eq)
|
| AltLiteral Literal
|
||||||
|
| Default
|
||||||
|
deriving (Show, Read, Eq, Lift)
|
||||||
|
|
||||||
|
data Literal = IntL Int
|
||||||
|
deriving (Show, Read, Eq, Lift)
|
||||||
|
|
||||||
type Name = String
|
type Name = String
|
||||||
type Tag = Int
|
type Tag = Int
|
||||||
|
|
||||||
data ScDef = ScDef Name [Name] Expr
|
data ScDef b = ScDef b [b] (Expr b)
|
||||||
deriving (Show, Lift, Eq)
|
|
||||||
|
|
||||||
data Module = Module (Maybe (Name, [Name])) Program
|
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift)
|
||||||
|
|
||||||
newtype Program = Program [ScDef]
|
data Module b = Module (Maybe (Name, [Name])) (Program b)
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift)
|
||||||
|
|
||||||
instance IsString Expr where
|
newtype Program b = Program [ScDef b]
|
||||||
|
deriving (Show, Lift)
|
||||||
|
|
||||||
|
type Program' = Program Name
|
||||||
|
type Expr' = Expr Name
|
||||||
|
type ScDef' = ScDef Name
|
||||||
|
type Alter' = Alter Name
|
||||||
|
type Binding' = Binding Name
|
||||||
|
|
||||||
|
instance IsString (Expr b) where
|
||||||
fromString = Var
|
fromString = Var
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
instance Semigroup (Program b) where
|
||||||
|
(<>) = coerce $ (<>) @[ScDef b]
|
||||||
|
|
||||||
instance Pretty Program where
|
instance Monoid (Program b) where
|
||||||
-- TODO: module header
|
|
||||||
prettyPrec (Program ss) _ = mconcat $ intersperse "\n\n" $ fmap pretty ss
|
|
||||||
|
|
||||||
instance Pretty ScDef where
|
|
||||||
prettyPrec (ScDef n as e) _ =
|
|
||||||
mconcat (intersperse " " $ fmap IStr (n:as))
|
|
||||||
<> " = " <> pretty e <> IBreak
|
|
||||||
|
|
||||||
instance Pretty Expr where
|
|
||||||
prettyPrec (Var k) = withPrec maxBound $ IStr k
|
|
||||||
prettyPrec (IntE n) = withPrec maxBound $ iShow n
|
|
||||||
prettyPrec (Con t a) = withPrec maxBound $
|
|
||||||
"Pack{" <> iShow t <> " " <> iShow a <> "}"
|
|
||||||
prettyPrec (Let r bs e) = withPrec 0 $
|
|
||||||
IStr (if r == Rec then "letrec " else "let ")
|
|
||||||
<> binds <> IBreak
|
|
||||||
<> "in " <> pretty e
|
|
||||||
where
|
|
||||||
binds = mconcat (f <$> init bs)
|
|
||||||
<> IIndent (pretty $ last bs)
|
|
||||||
f b = IIndent $ pretty b <> IBreak
|
|
||||||
prettyPrec (Lam ns e) = withPrec 0 $
|
|
||||||
IStr "λ" <> binds <> " -> " <> pretty e
|
|
||||||
where
|
|
||||||
binds = fmap IStr ns & intersperse " " & mconcat
|
|
||||||
prettyPrec (Case e as) = withPrec 0 $
|
|
||||||
"case " <> IIndent (pretty e <> " of" <> IBreak <> alts)
|
|
||||||
where
|
|
||||||
-- TODO: don't break on last alt
|
|
||||||
alts = mconcat $ fmap palt as
|
|
||||||
palt x = IIndent $ pretty x <> IBreak
|
|
||||||
prettyPrec (App f x) = \p -> bracketPrec 0 p $
|
|
||||||
case f of
|
|
||||||
-- application is left-associative; don't increase prec if the
|
|
||||||
-- expression being applied is itself an application
|
|
||||||
(_:$_) -> precPretty p f <> " " <> precPretty (succ p) x
|
|
||||||
_ -> precPretty (succ p) f <> " " <> precPretty (succ p) x
|
|
||||||
|
|
||||||
instance Pretty Alter where
|
|
||||||
prettyPrec (Alter t bs e) = withPrec 0 $
|
|
||||||
"<" <> IStr (show t) <> "> " <> binds <> " -> " <> pretty e
|
|
||||||
where
|
|
||||||
binds = mconcat $ intersperse " " (fmap IStr bs)
|
|
||||||
|
|
||||||
instance Pretty Binding where
|
|
||||||
prettyPrec (k := v) = withPrec 0 $ IStr k <> " = " <> precPretty 0 v
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
instance Semigroup Program where
|
|
||||||
(<>) = coerce $ (<>) @[ScDef]
|
|
||||||
|
|
||||||
instance Monoid Program where
|
|
||||||
mempty = Program []
|
mempty = Program []
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
bindersOf :: [(Name, b)] -> [Name]
|
class HasRHS s z | s -> z where
|
||||||
bindersOf = fmap fst
|
_rhs :: Lens' s (Expr z)
|
||||||
|
|
||||||
rhssOf :: [(Name, b)] -> [b]
|
instance HasRHS (Alter b) b where
|
||||||
rhssOf = fmap snd
|
_rhs = lens
|
||||||
|
(\ (Alter _ _ e) -> e)
|
||||||
|
(\ (Alter t as _) e' -> Alter t as e')
|
||||||
|
|
||||||
isAtomic :: Expr -> Bool
|
instance HasRHS (ScDef b) b where
|
||||||
isAtomic (Var _) = True
|
_rhs = lens
|
||||||
isAtomic _ = False
|
(\ (ScDef _ _ e) -> e)
|
||||||
|
(\ (ScDef n as _) e' -> ScDef n as e')
|
||||||
|
|
||||||
----------------------------------------------------------------------------------
|
instance HasRHS (Binding b) b where
|
||||||
|
_rhs = lens
|
||||||
-- TODO: export list awareness
|
(\ (_ := e) -> e)
|
||||||
insertModule :: Module -> Program -> Program
|
(\ (k := _) e' -> k := e')
|
||||||
insertModule (Module _ m) p = p <> m
|
|
||||||
|
|
||||||
extractProgram :: Module -> Program
|
|
||||||
extractProgram (Module _ p) = p
|
|
||||||
|
|
||||||
|
|||||||
72
src/Core/Utils.hs
Normal file
72
src/Core/Utils.hs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
-- for recursion schemes
|
||||||
|
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
|
||||||
|
-- for recursion schemes
|
||||||
|
{-# LANGUAGE TemplateHaskell, TypeFamilies #-}
|
||||||
|
|
||||||
|
module Core.Utils
|
||||||
|
( bindersOf
|
||||||
|
, rhssOf
|
||||||
|
, isAtomic
|
||||||
|
, insertModule
|
||||||
|
, extractProgram
|
||||||
|
, freeVariables
|
||||||
|
, ExprF(..)
|
||||||
|
)
|
||||||
|
where
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
import Data.Functor.Foldable.TH (makeBaseFunctor)
|
||||||
|
import Data.Functor.Foldable
|
||||||
|
import Data.Set (Set)
|
||||||
|
import Data.Set qualified as S
|
||||||
|
import Core.Syntax
|
||||||
|
import GHC.Exts (IsList(..))
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bindersOf :: (IsList l, Item l ~ b) => [Binding b] -> l
|
||||||
|
bindersOf bs = fromList $ fmap f bs
|
||||||
|
where f (k := _) = k
|
||||||
|
|
||||||
|
rhssOf :: (IsList l, Item l ~ Expr b) => [Binding b] -> l
|
||||||
|
rhssOf = fromList . fmap f
|
||||||
|
where f (_ := v) = v
|
||||||
|
|
||||||
|
isAtomic :: Expr b -> Bool
|
||||||
|
isAtomic (Var _) = True
|
||||||
|
isAtomic (LitE _) = True
|
||||||
|
isAtomic _ = False
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: export list awareness
|
||||||
|
insertModule :: Module b -> Program b -> Program b
|
||||||
|
insertModule (Module _ m) p = p <> m
|
||||||
|
|
||||||
|
extractProgram :: Module b -> Program b
|
||||||
|
extractProgram (Module _ p) = p
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
makeBaseFunctor ''Expr
|
||||||
|
|
||||||
|
freeVariables :: Expr' -> Set Name
|
||||||
|
freeVariables = cata go
|
||||||
|
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 = rhssOf bs :: [Expr']
|
||||||
|
ns = bindersOf bs
|
||||||
|
-- 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
|
||||||
|
|
||||||
85
src/Core2Core.hs
Normal file
85
src/Core2Core.hs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
module Core2Core
|
||||||
|
( core2core
|
||||||
|
|
||||||
|
-- internal utilities for convenience
|
||||||
|
, floatCase
|
||||||
|
)
|
||||||
|
where
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
import Data.Functor.Foldable
|
||||||
|
import Data.Maybe (fromJust)
|
||||||
|
import Data.Set qualified as S
|
||||||
|
import Data.List
|
||||||
|
import Control.Monad.Writer
|
||||||
|
import Control.Monad.State
|
||||||
|
import Lens.Micro
|
||||||
|
import Core.Syntax
|
||||||
|
import Core.Utils
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
core2core :: Program' -> Program'
|
||||||
|
core2core p = undefined
|
||||||
|
|
||||||
|
-- assumes the provided expression is in a strict context
|
||||||
|
-- replaceNonStrictCases :: [Name] -> Expr' -> (Expr', [ScDef'])
|
||||||
|
-- replaceNonStrictCases names = runWriter . cata goE
|
||||||
|
-- where
|
||||||
|
-- goE :: ExprF Name (Writer [ScDef'] Expr')
|
||||||
|
-- -> Writer [ScDef'] Expr'
|
||||||
|
-- -- strict context
|
||||||
|
-- goE (VarF k) = pure (Var k)
|
||||||
|
-- goE (CaseF e as) = e *> ae'
|
||||||
|
-- where
|
||||||
|
-- ae = (\ (Alter _ _ b) -> b) <$> as
|
||||||
|
-- ae' = mconcat <$> traverse replaceNonStrictCases ae
|
||||||
|
|
||||||
|
type Replacer = StateT [Name] (Writer [ScDef'])
|
||||||
|
|
||||||
|
-- TODO: formally define a "strict context" and reference that here
|
||||||
|
replaceNonStrictCases :: [Name] -> Expr' -> (Expr', [ScDef'])
|
||||||
|
replaceNonStrictCases names = runWriter . flip evalStateT names . goE
|
||||||
|
where
|
||||||
|
goE :: Expr' -> Replacer Expr'
|
||||||
|
goE (Var k) = pure (Var k)
|
||||||
|
goE (LitE l) = pure (LitE l)
|
||||||
|
goE (Let Rec bs e) = Let Rec <$> bs' <*> goE e
|
||||||
|
where bs' = travBs goE bs
|
||||||
|
goE e = goC e
|
||||||
|
|
||||||
|
goC :: Expr' -> Replacer Expr'
|
||||||
|
-- the only truly non-trivial case: when a case expr is found in a
|
||||||
|
-- non-strict context, we float it into a supercombinator, give it a
|
||||||
|
-- name consumed from the state, record the newly created sc within the
|
||||||
|
-- Writer, and finally return an expression appropriately calling the sc
|
||||||
|
goC p@(Case e as) = do
|
||||||
|
n <- name
|
||||||
|
let (e',sc) = floatCase n p
|
||||||
|
altBodies = (\(Alter _ _ b) -> b) <$> as
|
||||||
|
tell [sc]
|
||||||
|
goE e
|
||||||
|
traverse goE altBodies
|
||||||
|
pure e'
|
||||||
|
goC (f :$ x) = (:$) <$> goC f <*> goC x
|
||||||
|
goC (Let r bs e) = Let r <$> bs' <*> goE e
|
||||||
|
where bs' = travBs goC bs
|
||||||
|
|
||||||
|
name = state (fromJust . uncons)
|
||||||
|
|
||||||
|
-- extract the right-hand sides of a list of bindings, traverse each
|
||||||
|
-- one, and return the original list of bindings
|
||||||
|
travBs :: (Expr' -> Replacer Expr') -> [Binding'] -> Replacer [Binding']
|
||||||
|
travBs c bs = bs ^.. each . _rhs
|
||||||
|
& traverse goC
|
||||||
|
& const (pure bs)
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
-- expression that calls the sc with the necessary arguments
|
||||||
|
floatCase :: Name -> Expr' -> (Expr', ScDef')
|
||||||
|
floatCase n c@(Case e as) = (e', sc)
|
||||||
|
where
|
||||||
|
sc = ScDef n caseFrees c
|
||||||
|
caseFrees = S.toList $ freeVariables c
|
||||||
|
e' = foldl App (Var n) (Var <$> caseFrees)
|
||||||
|
|
||||||
59
src/GM.hs
59
src/GM.hs
@@ -30,6 +30,21 @@ import Debug.Trace
|
|||||||
import Core
|
import Core
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{-}
|
||||||
|
|
||||||
|
hdbgProg = undefined
|
||||||
|
evalProg = undefined
|
||||||
|
|
||||||
|
data Node = NNum Int
|
||||||
|
| NAp Addr Addr
|
||||||
|
| NInd Addr
|
||||||
|
| NUninitialised
|
||||||
|
| NConstr Tag [Addr] -- NConstr Tag Components
|
||||||
|
| NMarked Node
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
--}
|
||||||
|
|
||||||
data GmState = GmState
|
data GmState = GmState
|
||||||
{ _gmCode :: Code
|
{ _gmCode :: Code
|
||||||
, _gmStack :: Stack
|
, _gmStack :: Stack
|
||||||
@@ -103,7 +118,7 @@ pure []
|
|||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
evalProg :: Program -> Maybe (Node, Stats)
|
evalProg :: Program' -> Maybe (Node, Stats)
|
||||||
evalProg p = res <&> (,sts)
|
evalProg p = res <&> (,sts)
|
||||||
where
|
where
|
||||||
final = eval (compile p) & last
|
final = eval (compile p) & last
|
||||||
@@ -112,7 +127,7 @@ evalProg p = res <&> (,sts)
|
|||||||
resAddr = final ^. gmStack ^? _head
|
resAddr = final ^. gmStack ^? _head
|
||||||
res = resAddr >>= flip hLookup h
|
res = resAddr >>= flip hLookup h
|
||||||
|
|
||||||
hdbgProg :: Program -> Handle -> IO (Node, Stats)
|
hdbgProg :: Program' -> Handle -> IO (Node, Stats)
|
||||||
hdbgProg p hio = do
|
hdbgProg p hio = do
|
||||||
(renderOut . showState) `traverse_` states
|
(renderOut . showState) `traverse_` states
|
||||||
-- TODO: i'd like the statistics to be at the top of the file, but `sts`
|
-- TODO: i'd like the statistics to be at the top of the file, but `sts`
|
||||||
@@ -533,7 +548,7 @@ pop [] = []
|
|||||||
|
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
compile :: Program -> GmState
|
compile :: Program' -> GmState
|
||||||
compile p = GmState c [] [] h g sts
|
compile p = GmState c [] [] h g sts
|
||||||
where
|
where
|
||||||
-- find the entry point and evaluate it
|
-- find the entry point and evaluate it
|
||||||
@@ -560,7 +575,7 @@ compiledPrims =
|
|||||||
|
|
||||||
binop k i = (k, 2, [Push 1, Eval, Push 1, Eval, i, Update 2, Pop 2, Unwind])
|
binop k i = (k, 2, [Push 1, Eval, Push 1, Eval, i, Update 2, Pop 2, Unwind])
|
||||||
|
|
||||||
buildInitialHeap :: Program -> (GmHeap, Env)
|
buildInitialHeap :: Program' -> (GmHeap, Env)
|
||||||
buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
||||||
where
|
where
|
||||||
compiledScs = fmap compileSc ss <> compiledPrims
|
compiledScs = fmap compileSc ss <> compiledPrims
|
||||||
@@ -573,20 +588,20 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
-- >> [ref/compileSc]
|
-- >> [ref/compileSc]
|
||||||
-- type CompiledSC = (Name, Int, Code)
|
-- type CompiledSC = (Name, Int, Code)
|
||||||
|
|
||||||
compileSc :: ScDef -> CompiledSC
|
compileSc :: ScDef' -> CompiledSC
|
||||||
compileSc (ScDef n as b) = (n, d, compileR env b)
|
compileSc (ScDef n as b) = (n, d, compileR env b)
|
||||||
where
|
where
|
||||||
env = (NameKey <$> as) `zip` [0..]
|
env = (NameKey <$> as) `zip` [0..]
|
||||||
d = length as
|
d = length as
|
||||||
-- << [ref/compileSc]
|
-- << [ref/compileSc]
|
||||||
|
|
||||||
compileR :: Env -> Expr -> Code
|
compileR :: Env -> Expr' -> Code
|
||||||
compileR g e = compileE g e <> [Update d, Pop d, Unwind]
|
compileR g e = compileE g e <> [Update d, Pop d, Unwind]
|
||||||
where
|
where
|
||||||
d = length g
|
d = length g
|
||||||
|
|
||||||
-- compile an expression in a lazy context
|
-- compile an expression in a non-strict context
|
||||||
compileC :: Env -> Expr -> Code
|
compileC :: Env -> Expr' -> Code
|
||||||
compileC g (Var k)
|
compileC g (Var k)
|
||||||
| k `elem` domain = [Push n]
|
| k `elem` domain = [Push n]
|
||||||
| otherwise = [PushGlobal k]
|
| otherwise = [PushGlobal k]
|
||||||
@@ -596,7 +611,7 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
f (NameKey n, _) = Just n
|
f (NameKey n, _) = Just n
|
||||||
f _ = Nothing
|
f _ = Nothing
|
||||||
|
|
||||||
compileC _ (IntE n) = [PushInt n]
|
compileC _ (LitE l) = compileCL l
|
||||||
|
|
||||||
-- >> [ref/compileC]
|
-- >> [ref/compileC]
|
||||||
compileC g (App f x) = compileC g x
|
compileC g (App f x) = compileC g x
|
||||||
@@ -612,7 +627,7 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
-- kinda gross. revisit this
|
-- kinda gross. revisit this
|
||||||
addressed = bs `zip` reverse [0 .. d-1]
|
addressed = bs `zip` reverse [0 .. d-1]
|
||||||
|
|
||||||
compileBinder :: Env -> (Binding, Int) -> (Env, Code)
|
compileBinder :: Env -> (Binding', Int) -> (Env, Code)
|
||||||
compileBinder m (k := v, a) = (m',c)
|
compileBinder m (k := v, a) = (m',c)
|
||||||
where
|
where
|
||||||
m' = (NameKey k, a) : m
|
m' = (NameKey k, a) : m
|
||||||
@@ -630,7 +645,7 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
initialisers = mconcat $ compileBinder <$> addressed
|
initialisers = mconcat $ compileBinder <$> addressed
|
||||||
body = compileC g' e
|
body = compileC g' e
|
||||||
|
|
||||||
compileBinder :: (Binding, Int) -> Code
|
compileBinder :: (Binding', Int) -> Code
|
||||||
compileBinder (_ := v, a) = compileC g' v <> [Update a]
|
compileBinder (_ := v, a) = compileC g' v <> [Update a]
|
||||||
|
|
||||||
compileC _ (Con t n) = [PushConstr t n]
|
compileC _ (Con t n) = [PushConstr t n]
|
||||||
@@ -640,10 +655,16 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
|
|
||||||
compileC _ _ = error "yet to be implemented!"
|
compileC _ _ = error "yet to be implemented!"
|
||||||
|
|
||||||
|
compileCL :: Literal -> Code
|
||||||
|
compileCL (IntL n) = [PushInt n]
|
||||||
|
|
||||||
|
compileEL :: Literal -> Code
|
||||||
|
compileEL (IntL n) = [PushInt n]
|
||||||
|
|
||||||
-- compile an expression in a strict context such that a pointer to the
|
-- compile an expression in a strict context such that a pointer to the
|
||||||
-- expression is left on top of the stack in WHNF
|
-- expression is left on top of the stack in WHNF
|
||||||
compileE :: Env -> Expr -> Code
|
compileE :: Env -> Expr' -> Code
|
||||||
compileE _ (IntE n) = [PushInt n]
|
compileE _ (LitE l) = compileEL l
|
||||||
compileE g (Let NonRec bs e) =
|
compileE g (Let NonRec bs e) =
|
||||||
-- we use compileE instead of compileC
|
-- we use compileE instead of compileC
|
||||||
mconcat binders <> compileE g' e <> [Slide d]
|
mconcat binders <> compileE g' e <> [Slide d]
|
||||||
@@ -653,7 +674,7 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
-- kinda gross. revisit this
|
-- kinda gross. revisit this
|
||||||
addressed = bs `zip` reverse [0 .. d-1]
|
addressed = bs `zip` reverse [0 .. d-1]
|
||||||
|
|
||||||
compileBinder :: Env -> (Binding, Int) -> (Env, Code)
|
compileBinder :: Env -> (Binding', Int) -> (Env, Code)
|
||||||
compileBinder m (k := v, a) = (m',c)
|
compileBinder m (k := v, a) = (m',c)
|
||||||
where
|
where
|
||||||
m' = (NameKey k, a) : m
|
m' = (NameKey k, a) : m
|
||||||
@@ -674,7 +695,7 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
body = compileE g' e
|
body = compileE g' e
|
||||||
|
|
||||||
-- we use compileE instead of compileC
|
-- we use compileE instead of compileC
|
||||||
compileBinder :: (Binding, Int) -> Code
|
compileBinder :: (Binding', Int) -> Code
|
||||||
compileBinder (_ := v, a) = compileC g' v <> [Update a]
|
compileBinder (_ := v, a) = compileC g' v <> [Update a]
|
||||||
|
|
||||||
-- special cases for prim functions; essentially inlining
|
-- special cases for prim functions; essentially inlining
|
||||||
@@ -689,11 +710,11 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
|
|
||||||
compileE g e = compileC g e ++ [Eval]
|
compileE g e = compileC g e ++ [Eval]
|
||||||
|
|
||||||
compileD :: Env -> [Alter] -> [(Tag, Code)]
|
compileD :: Env -> [Alter'] -> [(Tag, Code)]
|
||||||
compileD g as = fmap (compileA g) as
|
compileD g as = fmap (compileA g) as
|
||||||
|
|
||||||
compileA :: Env -> Alter -> (Tag, Code)
|
compileA :: Env -> Alter' -> (Tag, Code)
|
||||||
compileA g (Alter t as e) = (t, [Split n] <> c <> [Slide n])
|
compileA g (Alter (AltData t) as e) = (t, [Split n] <> c <> [Slide n])
|
||||||
where
|
where
|
||||||
n = length as
|
n = length as
|
||||||
binds = (NameKey <$> as) `zip` [0..]
|
binds = (NameKey <$> as) `zip` [0..]
|
||||||
@@ -921,3 +942,5 @@ sweepNodes st = st & gmHeap %~ thread (f <$> addresses h)
|
|||||||
|
|
||||||
thread :: [a -> a] -> (a -> a)
|
thread :: [a -> a] -> (a -> a)
|
||||||
thread = appEndo . foldMap Endo
|
thread = appEndo . foldMap Endo
|
||||||
|
|
||||||
|
--}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ import Core.Examples
|
|||||||
import Core
|
import Core
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
hdbgProg = undefined
|
||||||
|
|
||||||
|
{-
|
||||||
|
|
||||||
data TiState = TiState Stack Dump TiHeap Env Stats
|
data TiState = TiState Stack Dump TiHeap Env Stats
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
@@ -611,3 +615,5 @@ gc st@(TiState s d h g sts) = TiState s d h' g sts
|
|||||||
marked = h & appEndo (foldMap Endo $ markFrom <$> as)
|
marked = h & appEndo (foldMap Endo $ markFrom <$> as)
|
||||||
h' = scanHeap marked
|
h' = scanHeap marked
|
||||||
|
|
||||||
|
--}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user