3 Commits

Author SHA1 Message Date
crumbtoo
1a0ef46df8 bump 2024-04-15 10:02:36 -06:00
crumbtoo
1436f1124f Merge branch 'main' into dev 2024-02-16 13:12:14 -07:00
crumb
36a17d092b rc (#13)
* update readme

* Literal -> Lit, LitE -> Lit

* commentary

* infer

* hindley milner inference :D

* comments and better type errors

* type IsString + test unification error

* infer nonrec let binds

infer nonrec let binds

* small

* LitE -> Lit

* LitE -> Lit

* TyInt -> TyCon "Int#"

* parse type sigs; program type sigs

* parse types

* parse programs (with types :D)

* parse programs (with type sigs :D)

* Name = Text

Name = Text

* RlpcError

* i'm on an airplane rn, my eyelids grow heavy, and i forgot my medication. should this be my final commit (of the week): gootbye

* kinda sorta typechecking

* back and medicated!

* errorful (it's not good)

* type-checked quasiquoters

* fix hm tests

* Compiler.JustRun

* lex \ instead of \\

* grammar reference

* 4:00 AM psychopath code

* oh boy am i going to hate this code in 12 hours

* application and lits

appl

* something

* goofy

* Show1 instances

* fixation fufilled - back to work!

* works

* labels

* infix decl

* expr fixups

* where

* cool

* aaaaa

* decls fix

* finally in a decent state

* replace uses of many+satisfy with takeWhileP

* layout

layouts

oh my layouts

* i did not realise my fs is case insensitive

* tysigs

* add version bounds

* grammar reference

* 4:00 AM psychopath code

* oh boy am i going to hate this code in 12 hours

* application and lits

appl

* something

* goofy

* Show1 instances

* fixation fufilled - back to work!

* works

* labels

* infix decl

* expr fixups

* where

* cool

* aaaaa

* decls fix

* finally in a decent state

* replace uses of many+satisfy with takeWhileP

* layout

layouts

oh my layouts

* i did not realise my fs is case insensitive

* tysigs

* its fine

* threaded lexer

* decent starting point

* man this sucks

* aagh

* okay layouts kinda

* kitten i'll be honest mommy's about to kill herself

* see previous commit and scale back the part where i'm joking

* version bounds

* we're so back

* fixy

* cool

* FIX REAL

* oh my god

* works

* now we're fucking GETTING SOMEWHERE

* i really need to learn git proper

* infix exprs

* remove debug flags

* renamerlp

* rename rlp

* compiles (kill me)

man

* RlpcError -> IsRlpcError

* when the "Test suite rlp-test: PASS" hits

i'm like atlas and the world is writing two lines of code

* errorful parser

* errorful parser

small

* msgenvelope

* errors!

* allow uppercase sc names in preperation for Rlp2Core

* letrec

* infer letrec expressions

* minor docs

* checklist

* minor docs

* stable enough for a demo hey?

* small fixups

* new tag syntax; preparing for Core patterns

new tag syntax; preparing for data names

* temporary pragma system

* resolve named data in case exprs

* named constr tests

* nearing release :3

* minor changes

putting this on hold; implementing TTG first

* some

* 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)

* it's also a comonad. lol.

* idk

* show

* abandon ship

* at long last

more

no more undefineds

* i should've made a lisp man this sucks

* let layout

* ttg boilerplate

* fixup! ttg boilerplate

* fixup! ttg boilerplate

* organisation and cleaning

organisation and tidying

* error messages

* driver progress

* formatting

* *R functions

* -ddump-ast

* debug tags

* -ddump-eval

* core driver

* XRec fix

* rlp2core base

* ccoool

* something

* rlp TH

* sc

* expandableAlt

* expandableAlt

* fix layout_let

* parse case exprs

* case unrolling

* rose

* her light cuts deep time and time again

('her' of course referring to the field of computer science)

* tidying

* NameSupply effect

* tidy

* fix incomplete byTag

* desugar

* WIP associate postproc

corecursive

* sigh i'm gonna have to nuke the ast again in a month

* remove old files

* remove old files

* fix top-level layout

* define datatags

* diagram

* diagram

* Update README.md

* ppr debug flags

ddump-parsed

* ppr typesigs

* ppr datatags

* remove unnecessary comment

* tidying

* .hs -> .cr

update examples

* fix evil parser bug (it was a fucking typo)

* fix evil lexer bug (it was actually quite subtle unlike prev.)

* examples

* examples

* letrec + typechecking core

* Update README.md

* Rlp2Core: simple let binds

* Rlp2Core: pattern let binds

* small core fixes

* update examples

* formatting

* typed coreExpr quoter

* typechecking things

* lt

* decent state!

* constants for bool tags

* print# gm primitive

* bind VarP after pats

* fix: tag nested data names

* gte gm prim

* more nightmare GM fixes

* QuickSort example works i'm gonig to cry

* remove debug code

* remove debug tracers

* ready?

* update readme

* remove bad, incorrct, outdated docs

---------

Co-authored-by: crumbtoo <crumb@disroot.org>
2024-02-13 13:22:23 -07:00
7 changed files with 286 additions and 377 deletions

View File

@@ -74,11 +74,6 @@ options = RLPCOptions
<> metavar "rlp|core" <> metavar "rlp|core"
<> help "the language to be compiled -- see README" <> help "the language to be compiled -- see README"
) )
<*> flag False True
( long "render"
<> short 'r'
<> help "render a diagram of each GM state"
)
<*> some (argument str $ metavar "FILES...") <*> some (argument str $ metavar "FILES...")
where where
infixr 9 # infixr 9 #

View File

@@ -22,9 +22,6 @@ library
exposed-modules: Core exposed-modules: Core
, TI , TI
, GM , GM
, GM.Visual
, GM.Types
, GM.Print
, Compiler.RLPC , Compiler.RLPC
, Compiler.RlpcError , Compiler.RlpcError
, Compiler.JustRun , Compiler.JustRun
@@ -53,17 +50,17 @@ library
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.1 , 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
@@ -76,9 +73,6 @@ 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
, diagrams
, diagrams-lib
, diagrams-cairo
hs-source-dirs: src hs-source-dirs: src
default-language: GHC2021 default-language: GHC2021
@@ -105,7 +99,7 @@ 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.1 , text >= 2.0.2 && < 2.3
hs-source-dirs: app hs-source-dirs: app
default-language: GHC2021 default-language: GHC2021

View File

@@ -120,7 +120,6 @@ data RLPCOptions = RLPCOptions
, _rlpcEvaluator :: Evaluator , _rlpcEvaluator :: Evaluator
, _rlpcHeapTrigger :: Int , _rlpcHeapTrigger :: Int
, _rlpcLanguage :: Maybe Language , _rlpcLanguage :: Maybe Language
, _rlpcRender :: Bool
, _rlpcInputFiles :: [FilePath] , _rlpcInputFiles :: [FilePath]
} }
deriving Show deriving Show
@@ -142,7 +141,6 @@ instance Default RLPCOptions where
, _rlpcHeapTrigger = 200 , _rlpcHeapTrigger = 200
, _rlpcInputFiles = [] , _rlpcInputFiles = []
, _rlpcLanguage = Nothing , _rlpcLanguage = Nothing
, _rlpcRender = False
} }
-- debug flags are passed with -dFLAG -- debug flags are passed with -dFLAG

319
src/GM.hs
View File

@@ -11,11 +11,6 @@ module GM
, evalProgR , evalProgR
, GmState(..) , GmState(..)
, gmCode, gmStack, gmDump, gmHeap, gmEnv, gmStats , gmCode, gmStack, gmDump, gmHeap, gmEnv, gmStats
, stsReductions
, stsPrimReductions
, stsAllocations
, stsDereferences
, stsGCCycles
, Node(..) , Node(..)
, showState , showState
, gmEvalProg , gmEvalProg
@@ -34,9 +29,10 @@ import Data.Tuple (swap)
import Control.Lens import Control.Lens
import Data.Text.Lens (IsText, packed, unpacked) import Data.Text.Lens (IsText, packed, unpacked)
import Text.Printf import Text.Printf
import Text.PrettyPrint hiding ((<>))
import Text.PrettyPrint.HughesPJ (maybeParens)
import Data.Foldable (traverse_) import Data.Foldable (traverse_)
import System.IO (Handle, hPutStrLn) import System.IO (Handle, hPutStrLn)
import Text.PrettyPrint (render)
-- TODO: an actual output system -- TODO: an actual output system
-- TODO: an actual output system -- TODO: an actual output system
-- TODO: an actual output system -- TODO: an actual output system
@@ -45,12 +41,9 @@ import System.IO.Unsafe (unsafePerformIO)
import Data.String (IsString) import Data.String (IsString)
import Data.Heap import Data.Heap
import Debug.Trace import Debug.Trace
import Compiler.RLPC import Compiler.RLPC
import Core2Core import Core2Core
import Core import Core
import GM.Types
import GM.Print
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
tag_Unit_unit :: Int tag_Unit_unit :: Int
@@ -62,19 +55,105 @@ tag_Bool_True = 1
tag_Bool_False :: Int tag_Bool_False :: Int
tag_Bool_False = 0 tag_Bool_False = 0
{-}
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
{ _gmCode :: Code
, _gmStack :: Stack
, _gmDump :: Dump
, _gmHeap :: GmHeap
, _gmEnv :: Env
, _gmStats :: Stats
}
deriving Show
type Code = [Instr]
type Stack = [Addr]
type Dump = [(Code, Stack)]
type Env = [(Key, Addr)]
type GmHeap = Heap Node
data Key = NameKey Name
| ConstrKey Tag Int
deriving (Show, Eq)
-- >> [ref/Instr]
data Instr = Unwind
| PushGlobal Name
| PushConstr Tag Int
| PushInt Int
| Push Int
| MkAp
| Slide Int
| Update Int
| Pop Int
| Alloc Int
| Eval
-- arith
| Neg | Add | Sub | Mul | Div
-- comparison
| Equals | Lesser | GreaterEq
| Pack Tag Int -- Pack Tag Arity
| CaseJump [(Tag, Code)]
| Split Int
| Print
| Halt
deriving (Show, Eq)
-- << [ref/Instr]
data Node = NNum Int
| NAp Addr Addr
-- NGlobal is the GM equivalent of NSupercomb. rather than storing a
-- template to be instantiated, NGlobal holds the global's arity and
-- the pre-compiled code :3
| NGlobal Int Code
| NInd Addr
| NUninitialised
| NConstr Tag [Addr] -- NConstr Tag Components
| NMarked Node
deriving (Show, Eq)
-- TODO: log executed instructions
data Stats = Stats
{ _stsReductions :: Int
, _stsPrimReductions :: Int
, _stsAllocations :: Int
, _stsDereferences :: Int
, _stsGCCycles :: Int
}
deriving Show
instance Default Stats where
def = Stats 0 0 0 0 0
-- TODO: _gmGlobals should not have a setter
makeLenses ''GmState
makeLenses ''Stats
pure []
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
evalProg :: Program' -> [GmState] evalProg :: Program' -> Maybe (Node, Stats)
evalProg = eval . compile evalProg p = res <&> (,sts)
where
-- evalProg :: Program' -> Maybe (Node, Stats) final = eval (compile p) & last
-- evalProg p = res <&> (,sts) h = final ^. gmHeap
-- where sts = final ^. gmStats
-- final = eval (compile p) & last resAddr = final ^. gmStack ^? _head
-- h = final ^. gmHeap res = resAddr >>= flip hLookup h
-- sts = final ^. gmStats
-- resAddr = final ^. gmStack ^? _head
-- res = resAddr >>= flip hLookup h
hdbgProg :: Program' -> Handle -> IO GmState hdbgProg :: Program' -> Handle -> IO GmState
hdbgProg p hio = do hdbgProg p hio = do
@@ -736,8 +815,185 @@ buildInitialHeap (view programScDefs -> ss) = mapAccumL allocateSc mempty compil
argOffset :: Int -> Env -> Env argOffset :: Int -> Env -> Env
argOffset n = each . _2 %~ (+n) argOffset n = each . _2 %~ (+n)
showCon :: (IsText a) => Tag -> Int -> a
showCon t n = printf "Pack{%d %d}" t n ^. packed
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
pprTabstop :: Int
pprTabstop = 4
qquotes :: Doc -> Doc
qquotes d = "`" <> d <> "'"
showStats :: Stats -> Doc
showStats sts = "==== Stats ============" $$ stats
where
stats = text $ printf
"Reductions : %5d\n\
\Prim Reductions : %5d\n\
\Allocations : %5d\n\
\GC Cycles : %5d"
(sts ^. stsReductions)
(sts ^. stsPrimReductions)
(sts ^. stsAllocations)
(sts ^. stsGCCycles)
showState :: GmState -> Doc
showState st = vcat
[ "==== GmState " <> int stnum <> " "
<> text (replicate (28 - 13 - 1 - digitalWidth stnum) '=')
, "-- Next instructions -------"
, info $ showCodeShort c
, "-- Stack -------------------"
, info $ showStack st
, "-- Heap --------------------"
, info $ showHeap st
, "-- Dump --------------------"
, info $ showDump st
]
where
stnum = st ^. (gmStats . stsReductions)
c = st ^. gmCode
-- indent data
info = nest pprTabstop
showCodeShort :: Code -> Doc
showCodeShort c = braces c'
where
c' | length c > 3 = list (showInstr <$> take 3 c) <> "; ..."
| otherwise = list (showInstr <$> c)
list = hcat . punctuate "; "
showStackShort :: Stack -> Doc
showStackShort s = brackets s'
where
-- no access to heap, otherwise we'd use showNodeAt
s' | length s > 3 = list (showEntry <$> take 3 s) <> ", ..."
| otherwise = list (showEntry <$> s)
list = hcat . punctuate ", "
showEntry = text . show
showStack :: GmState -> Doc
showStack st = vcat $ uncurry showEntry <$> si
where
h = st ^. gmHeap
s = st ^. gmStack
-- stack with labeled indices
si = [0..] `zip` s
w = maxWidth (addresses h)
showIndex n = padInt w n <> ": "
showEntry :: Int -> Addr -> Doc
showEntry n a = showIndex n <> showNodeAt st a
showDump :: GmState -> Doc
showDump st = vcat $ uncurry showEntry <$> di
where
d = st ^. gmDump
di = [0..] `zip` d
showIndex n = padInt w n <> ": "
w = maxWidth (fst <$> di)
showEntry :: Int -> (Code, Stack) -> Doc
showEntry n (c,s) = showIndex n <> nest pprTabstop entry
where
entry = ("Stack : " <> showCodeShort c)
$$ ("Code : " <> showStackShort s)
padInt :: Int -> Int -> Doc
padInt m n = text (replicate (m - digitalWidth n) ' ') <> int n
maxWidth :: [Int] -> Int
maxWidth ns = digitalWidth $ maximum ns
digitalWidth :: Int -> Int
digitalWidth = length . show
showHeap :: GmState -> Doc
showHeap st = vcat $ showEntry <$> addrs
where
showAddr n = padInt w n <> ": "
w = maxWidth addrs
h = st ^. gmHeap
addrs = addresses h
showEntry :: Addr -> Doc
showEntry a = showAddr a <> showNodeAt st a
showNodeAt :: GmState -> Addr -> Doc
showNodeAt = showNodeAtP 0
showNodeAtP :: Int -> GmState -> Addr -> Doc
showNodeAtP p st a = case hLookup a h of
Just (NNum n) -> int n <> "#"
Just (NGlobal _ _) -> textt name
where
g = st ^. gmEnv
name = case lookup a (swap <$> g) of
Just (NameKey n) -> n
Just (ConstrKey t n) -> showCon t n
_ -> errTxtInvalidAddress
-- TODO: left-associativity
Just (NAp f x) -> pprec $ showNodeAtP (p+1) st f
<+> showNodeAtP (p+1) st x
Just (NInd a') -> pprec $ "NInd -> " <> showNodeAtP (p+1) st a'
Just (NConstr t as) -> pprec $ "NConstr"
<+> int t
<+> brackets (list $ showNodeAtP 0 st <$> as)
where list = hcat . punctuate ", "
Just NUninitialised -> "<uninitialised>"
Nothing -> errTxtInvalidAddress
where
h = st ^. gmHeap
pprec = maybeParens (p > 0)
showSc :: GmState -> (Name, Addr) -> Doc
showSc st (k,a) = "Supercomb " <> qquotes (textt k) <> colon
$$ code
where
code = case hLookup a (st ^. gmHeap) of
Just (NGlobal _ c) -> showCode c
Just _ -> errTxtInvalidObject
Nothing -> errTxtInvalidAddress
errTxtInvalidObject, errTxtInvalidAddress :: (IsString a) => a
errTxtInvalidObject = "<invalid object>"
errTxtInvalidAddress = "<invalid address>"
showCode :: Code -> Doc
showCode c = "Code" <+> braces instrs
where instrs = vcat $ showInstr <$> c
showInstr :: Instr -> Doc
showInstr (CaseJump alts) = "CaseJump" $$ nest pprTabstop alternatives
where
showAlt (t,c) = "<" <> int t <> ">" <> showCodeShort c
alternatives = foldr (\a acc -> showAlt a $$ acc) mempty alts
showInstr i = text $ show i
textt :: (IsText a) => a -> Doc
textt t = t ^. unpacked & text
----------------------------------------------------------------------------------
lookupN :: Name -> Env -> Maybe Addr
lookupN k = lookup (NameKey k)
lookupC :: Tag -> Int -> Env -> Maybe Addr
lookupC t n = lookup (ConstrKey t n)
----------------------------------------------------------------------------------
gc :: GmState -> GmState
gc st = (sweepNodes . markNodes $ st)
& gmStats . stsGCCycles %~ succ
markNodes :: GmState -> GmState markNodes :: GmState -> GmState
markNodes st = st & gmHeap %~ thread (markFrom <$> roots) markNodes st = st & gmHeap %~ thread (markFrom <$> roots)
where where
@@ -780,18 +1036,6 @@ 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
gc :: GmState -> GmState
gc st = (sweepNodes . markNodes $ st)
& gmStats . stsGCCycles %~ succ
--------------------------------------------------------------------------------
lookupN :: Name -> Env -> Maybe Addr
lookupN k = lookup (NameKey k)
lookupC :: Tag -> Int -> Env -> Maybe Addr
lookupC t n = lookup (ConstrKey t n)
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
gmEvalProg :: Program' -> GmState gmEvalProg :: Program' -> GmState
@@ -803,11 +1047,12 @@ finalStateOf f = f . gmEvalProg
resultOf :: Program' -> Maybe Node resultOf :: Program' -> Maybe Node
resultOf p = do resultOf p = do
a <- res a <- res
hLookup a h n <- hLookup a h
where pure n
res = st ^? gmStack . _head where
st = gmEvalProg p res = st ^? gmStack . _head
h = st ^. gmHeap st = gmEvalProg p
h = st ^. gmHeap
resultOfExpr :: Expr' -> Maybe Node resultOfExpr :: Expr' -> Maybe Node
resultOfExpr e = resultOf $ resultOfExpr e = resultOf $

View File

@@ -1,186 +0,0 @@
module GM.Print
( showState
, showStats
, showNodeAt
)
where
--------------------------------------------------------------------------------
import Data.Monoid
import Data.String (IsString(..))
import Data.Text.Lens (IsText, packed, unpacked)
import Text.Printf
import Text.PrettyPrint hiding ((<>))
import Text.PrettyPrint.HughesPJ (maybeParens)
import Control.Lens
import Data.Heap
import Core.Syntax
import GM.Types
--------------------------------------------------------------------------------
pprTabstop :: Int
pprTabstop = 4
qquotes :: Doc -> Doc
qquotes d = "`" <> d <> "'"
showStats :: Stats -> Doc
showStats sts = "==== Stats ============" $$ stats
where
stats = text $ printf
"Reductions : %5d\n\
\Prim Reductions : %5d\n\
\Allocations : %5d\n\
\GC Cycles : %5d"
(sts ^. stsReductions)
(sts ^. stsPrimReductions)
(sts ^. stsAllocations)
(sts ^. stsGCCycles)
showState :: GmState -> Doc
showState st = vcat
[ "==== GmState " <> int stnum <> " "
<> text (replicate (28 - 13 - 1 - digitalWidth stnum) '=')
, "-- Next instructions -------"
, info $ showCodeShort c
, "-- Stack -------------------"
, info $ showStack st
, "-- Heap --------------------"
, info $ showHeap st
, "-- Dump --------------------"
, info $ showDump st
]
where
stnum = st ^. (gmStats . stsReductions)
c = st ^. gmCode
-- indent data
info = nest pprTabstop
showCodeShort :: Code -> Doc
showCodeShort c = braces c'
where
c' | length c > 3 = list (showInstr <$> take 3 c) <> "; ..."
| otherwise = list (showInstr <$> c)
list = hcat . punctuate "; "
showStackShort :: Stack -> Doc
showStackShort s = brackets s'
where
-- no access to heap, otherwise we'd use showNodeAt
s' | length s > 3 = list (showEntry <$> take 3 s) <> ", ..."
| otherwise = list (showEntry <$> s)
list = hcat . punctuate ", "
showEntry = text . show
showStack :: GmState -> Doc
showStack st = vcat $ uncurry showEntry <$> si
where
h = st ^. gmHeap
s = st ^. gmStack
-- stack with labeled indices
si = [0..] `zip` s
w = maxWidth (addresses h)
showIndex n = padInt w n <> ": "
showEntry :: Int -> Addr -> Doc
showEntry n a = showIndex n <> showNodeAt st a
showDump :: GmState -> Doc
showDump st = vcat $ uncurry showEntry <$> di
where
d = st ^. gmDump
di = [0..] `zip` d
showIndex n = padInt w n <> ": "
w = maxWidth (fst <$> di)
showEntry :: Int -> (Code, Stack) -> Doc
showEntry n (c,s) = showIndex n <> nest pprTabstop entry
where
entry = ("Stack : " <> showCodeShort c)
$$ ("Code : " <> showStackShort s)
padInt :: Int -> Int -> Doc
padInt m n = text (replicate (m - digitalWidth n) ' ') <> int n
maxWidth :: [Int] -> Int
maxWidth ns = digitalWidth $ maximum ns
digitalWidth :: Int -> Int
digitalWidth = length . show
showHeap :: GmState -> Doc
showHeap st = vcat $ showEntry <$> addrs
where
showAddr n = padInt w n <> ": "
w = maxWidth addrs
h = st ^. gmHeap
addrs = addresses h
showEntry :: Addr -> Doc
showEntry a = showAddr a <> showNodeAt st a
showNodeAt :: GmState -> Addr -> Doc
showNodeAt = showNodeAtP 0
showNodeAtP :: Int -> GmState -> Addr -> Doc
showNodeAtP p st a = case hLookup a h of
Just (NNum n) -> int n <> "#"
Just (NGlobal _ _) -> textt name
where
g = st ^. gmEnv
name = case lookup a (view swapped <$> g) of
Just (NameKey n) -> n
Just (ConstrKey t n) -> showCon t n
_ -> errTxtInvalidAddress
-- TODO: left-associativity
Just (NAp f x) -> pprec $ showNodeAtP (p+1) st f
<+> showNodeAtP (p+1) st x
Just (NInd a') -> pprec $ "NInd -> " <> showNodeAtP (p+1) st a'
Just (NConstr t as) -> pprec $ "NConstr"
<+> int t
<+> brackets (list $ showNodeAtP 0 st <$> as)
where list = hcat . punctuate ", "
Just NUninitialised -> "<uninitialised>"
Nothing -> errTxtInvalidAddress
where
h = st ^. gmHeap
pprec = maybeParens (p > 0)
showSc :: GmState -> (Name, Addr) -> Doc
showSc st (k,a) = "Supercomb " <> qquotes (textt k) <> colon
$$ code
where
code = case hLookup a (st ^. gmHeap) of
Just (NGlobal _ c) -> showCode c
Just _ -> errTxtInvalidObject
Nothing -> errTxtInvalidAddress
errTxtInvalidObject, errTxtInvalidAddress :: (IsString a) => a
errTxtInvalidObject = "<invalid object>"
errTxtInvalidAddress = "<invalid address>"
showCode :: Code -> Doc
showCode c = "Code" <+> braces instrs
where instrs = vcat $ showInstr <$> c
showInstr :: Instr -> Doc
showInstr (CaseJump alts) = "CaseJump" $$ nest pprTabstop alternatives
where
showAlt (t,c) = "<" <> int t <> ">" <> showCodeShort c
alternatives = foldr (\a acc -> showAlt a $$ acc) mempty alts
showInstr i = text $ show i
textt :: (IsText a) => a -> Doc
textt t = t ^. unpacked & text
----------------------------------------------------------------------------------
showCon :: (IsText a) => Tag -> Int -> a
showCon t n = printf "Pack{%d %d}" t n ^. packed

View File

@@ -1,83 +0,0 @@
{-# LANGUAGE TemplateHaskell #-}
module GM.Types where
--------------------------------------------------------------------------------
import Control.Lens.Combinators
import Data.Heap
import Data.Default
import Core.Syntax
--------------------------------------------------------------------------------
data GmState = GmState
{ _gmCode :: Code
, _gmStack :: Stack
, _gmDump :: Dump
, _gmHeap :: GmHeap
, _gmEnv :: Env
, _gmStats :: Stats
}
deriving Show
type Code = [Instr]
type Stack = [Addr]
type Dump = [(Code, Stack)]
type Env = [(Key, Addr)]
type GmHeap = Heap Node
data Key = NameKey Name
| ConstrKey Tag Int
deriving (Show, Eq)
-- >> [ref/Instr]
data Instr = Unwind
| PushGlobal Name
| PushConstr Tag Int
| PushInt Int
| Push Int
| MkAp
| Slide Int
| Update Int
| Pop Int
| Alloc Int
| Eval
-- arith
| Neg | Add | Sub | Mul | Div
-- comparison
| Equals | Lesser | GreaterEq
| Pack Tag Int -- Pack Tag Arity
| CaseJump [(Tag, Code)]
| Split Int
| Print
| Halt
deriving (Show, Eq)
-- << [ref/Instr]
data Node = NNum Int
| NAp Addr Addr
-- NGlobal is the GM equivalent of NSupercomb. rather than storing a
-- template to be instantiated, NGlobal holds the global's arity and
-- the pre-compiled code :3
| NGlobal Int Code
| NInd Addr
| NUninitialised
| NConstr Tag [Addr] -- NConstr Tag Components
| NMarked Node
deriving (Show, Eq)
-- TODO: log executed instructions
data Stats = Stats
{ _stsReductions :: Int
, _stsPrimReductions :: Int
, _stsAllocations :: Int
, _stsDereferences :: Int
, _stsGCCycles :: Int
}
deriving Show
instance Default Stats where
def = Stats 0 0 0 0 0
-- TODO: _gmGlobals should not have a setter
makeLenses ''GmState
makeLenses ''Stats

View File

@@ -1,54 +0,0 @@
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module GM.Visual
( renderGmState
)
where
--------------------------------------------------------------------------------
import Text.Printf
import Data.Function ((&), on)
import Text.PrettyPrint qualified as P
import Diagrams.Prelude
import Diagrams.Backend.Cairo
import GM.Types
import GM.Print
--------------------------------------------------------------------------------
renderGmState :: GmState -> IO ()
renderGmState st = renderCairo path size (drawState st)
where
size = mkSizeSpec2D (Just 1000) (Just 1000)
path = printf "/tmp/render/%04d.png" n
n = st ^. gmStats . stsReductions
drawState :: GmState -> Diagram B
drawState = drawStack
drawStack :: GmState -> Diagram B
drawStack st = st & vcatOf (gmStack . each . to cell)
where
cell a = rect 10 5
<> text (printf "%04x: %s" a (P.render . showNodeAt st $ a))
vcatOf :: (InSpace V2 n a, Floating n, Juxtaposable a, HasOrigin a, Monoid' a)
=> Getting (Endo [a]) s a -> s -> a
vcatOf l = vcat . (^.. l)
newtype Vap a = Vap { getVap :: a }
instance (InSpace V2 n a, Juxtaposable a, Semigroup a)
=> Semigroup (Vap a) where (<>) = (Vap .) . ((===) `on` getVap)
instance (InSpace V2 n a, Juxtaposable a, Monoid a)
=> Monoid (Vap a) where mempty = Vap mempty
newtype Hap a = Hap { getHap :: a }
instance (InSpace V2 n a, Juxtaposable a, Semigroup a)
=> Semigroup (Hap a) where (<>) = (Hap .) . ((|||) `on` getHap)
instance (InSpace V2 n a, Juxtaposable a, Monoid a)
=> Monoid (Hap a) where mempty = Hap mempty