strict arith
This commit is contained in:
@@ -147,6 +147,29 @@ Core Transition Rules
|
|||||||
& m
|
& m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#. Again, building on the previous rules, this rule makes the machine consider
|
||||||
|
unapplied supercombinators to be in WHNF
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
\gmrule
|
||||||
|
{ \mathtt{Unwind} : \nillist
|
||||||
|
& a_0 : \ldots : a_n : \nillist
|
||||||
|
& \langle i, s \rangle : d
|
||||||
|
& h
|
||||||
|
\begin{bmatrix}
|
||||||
|
a_0 : \mathtt{NGlobal} \; k \; c
|
||||||
|
\end{bmatrix}
|
||||||
|
& m
|
||||||
|
}
|
||||||
|
{ i
|
||||||
|
& a_n : s
|
||||||
|
& d
|
||||||
|
& h
|
||||||
|
& m \\
|
||||||
|
\SetCell[c=2]{c}
|
||||||
|
\text{when $n < k$}
|
||||||
|
}
|
||||||
|
|
||||||
#. If an application is on top of the stack, :code:`Unwind` continues unwinding
|
#. If an application is on top of the stack, :code:`Unwind` continues unwinding
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ data Expr = Var Name
|
|||||||
| Lam [Name] Expr
|
| Lam [Name] Expr
|
||||||
| App Expr Expr
|
| App Expr Expr
|
||||||
| IntE Int
|
| IntE Int
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift, Eq)
|
||||||
|
|
||||||
infixl 2 :$
|
infixl 2 :$
|
||||||
pattern (:$) :: Expr -> Expr -> Expr
|
pattern (:$) :: Expr -> Expr -> Expr
|
||||||
pattern f :$ x = App f x
|
pattern f :$ x = App f x
|
||||||
|
|
||||||
data Binding = Binding Name Expr
|
data Binding = Binding Name Expr
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift, Eq)
|
||||||
|
|
||||||
infixl 1 :=
|
infixl 1 :=
|
||||||
pattern (:=) :: Name -> Expr -> Binding
|
pattern (:=) :: Name -> Expr -> Binding
|
||||||
@@ -55,12 +55,12 @@ data Rec = Rec
|
|||||||
deriving (Show, Eq, Lift)
|
deriving (Show, Eq, Lift)
|
||||||
|
|
||||||
data Alter = Alter Int [Name] Expr
|
data Alter = Alter Int [Name] Expr
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift, Eq)
|
||||||
|
|
||||||
type Name = String
|
type Name = String
|
||||||
|
|
||||||
data ScDef = ScDef Name [Name] Expr
|
data ScDef = ScDef Name [Name] Expr
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift, Eq)
|
||||||
|
|
||||||
data Module = Module (Maybe (Name, [Name])) Program
|
data Module = Module (Maybe (Name, [Name])) Program
|
||||||
deriving (Show, Lift)
|
deriving (Show, Lift)
|
||||||
|
|||||||
60
src/GM.hs
60
src/GM.hs
@@ -310,6 +310,15 @@ step st = case head (st ^. gmCode) of
|
|||||||
NAp f x -> st
|
NAp f x -> st
|
||||||
-- leave the Unwind instr; continue unwinding
|
-- leave the Unwind instr; continue unwinding
|
||||||
& gmStack %~ (f:)
|
& gmStack %~ (f:)
|
||||||
|
|
||||||
|
NGlobal k c
|
||||||
|
| n < k -> st
|
||||||
|
& gmCode .~ i
|
||||||
|
& gmStack .~ s
|
||||||
|
& gmDump .~ d
|
||||||
|
where
|
||||||
|
((i,s) : d) = st ^. gmDump
|
||||||
|
n = st ^. gmStack & length
|
||||||
-- assumes length s < d (i.e. enough args have been supplied)
|
-- assumes length s < d (i.e. enough args have been supplied)
|
||||||
NGlobal n c -> st
|
NGlobal n c -> st
|
||||||
-- 'jump' to global's code by replacing our current
|
-- 'jump' to global's code by replacing our current
|
||||||
@@ -348,6 +357,7 @@ primitive1 box unbox f st
|
|||||||
& f
|
& f
|
||||||
& box (st & gmStack .~ s)
|
& box (st & gmStack .~ s)
|
||||||
& advanceCode
|
& advanceCode
|
||||||
|
& gmStats . stsPrimReductions %~ succ
|
||||||
where
|
where
|
||||||
putNewStack = gmStack .~ s
|
putNewStack = gmStack .~ s
|
||||||
(a:s) = st ^. gmStack
|
(a:s) = st ^. gmStack
|
||||||
@@ -361,6 +371,7 @@ primitive2 :: (GmState -> b -> GmState) -- boxing function
|
|||||||
primitive2 box unbox f st
|
primitive2 box unbox f st
|
||||||
= st'
|
= st'
|
||||||
& advanceCode
|
& advanceCode
|
||||||
|
& gmStats . stsPrimReductions %~ succ
|
||||||
where
|
where
|
||||||
(ax:ay:s) = st ^. gmStack
|
(ax:ay:s) = st ^. gmStack
|
||||||
putNewStack = gmStack .~ s
|
putNewStack = gmStack .~ s
|
||||||
@@ -434,10 +445,11 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
-- << [ref/compileSc]
|
-- << [ref/compileSc]
|
||||||
|
|
||||||
compileR :: Env -> Expr -> Code
|
compileR :: Env -> Expr -> Code
|
||||||
compileR g e = compileC 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
|
||||||
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]
|
||||||
@@ -483,6 +495,52 @@ buildInitialHeap (Program ss) = mapAccumL allocateSc mempty compiledScs
|
|||||||
compileBinder :: (Binding, Int) -> Code
|
compileBinder :: (Binding, Int) -> Code
|
||||||
compileBinder (k := v, a) = compileC g' v <> [Update a]
|
compileBinder (k := v, a) = compileC g' v <> [Update a]
|
||||||
|
|
||||||
|
-- compile an expression in a strict context such that a pointer to the
|
||||||
|
-- expression is left on top of the stack in WHNF
|
||||||
|
compileE :: Env -> Expr -> Code
|
||||||
|
compileE g (IntE n) = [PushInt n]
|
||||||
|
compileE g (Let NonRec bs e) =
|
||||||
|
-- we use compileE instead of compileC
|
||||||
|
mconcat binders <> compileE g' e <> [Slide d]
|
||||||
|
where
|
||||||
|
d = length bs
|
||||||
|
(g',binders) = mapAccumL compileBinder (argOffset d g) addressed
|
||||||
|
-- kinda gross. revisit this
|
||||||
|
addressed = bs `zip` reverse [0 .. d-1]
|
||||||
|
|
||||||
|
compileBinder :: Env -> (Binding, Int) -> (Env, Code)
|
||||||
|
compileBinder m (k := v, a) = (m',c)
|
||||||
|
where
|
||||||
|
m' = (k,a) : m
|
||||||
|
-- make note that we use m rather than m'!
|
||||||
|
c = compileC m v
|
||||||
|
|
||||||
|
compileE g (Let Rec bs e) =
|
||||||
|
Alloc d : initialisers <> body <> [Slide d]
|
||||||
|
where
|
||||||
|
d = length bs
|
||||||
|
g' = fmap toEnv addressed ++ argOffset d g
|
||||||
|
toEnv (k := _, a) = (k,a)
|
||||||
|
-- kinda gross. revisit this
|
||||||
|
addressed = bs `zip` reverse [0 .. d-1]
|
||||||
|
initialisers = mconcat $ compileBinder <$> addressed
|
||||||
|
|
||||||
|
-- we use compileE instead of compileC
|
||||||
|
body = compileE g' e
|
||||||
|
|
||||||
|
-- we use compileE instead of compileC
|
||||||
|
compileBinder :: (Binding, Int) -> Code
|
||||||
|
compileBinder (k := v, a) = compileC g' v <> [Update a]
|
||||||
|
|
||||||
|
-- special cases for prim functions
|
||||||
|
compileE g ("negate#" :$ a) = compileE g a <> [Neg]
|
||||||
|
compileE g ("+#" :$ a :$ b) = compileE g a <> compileE g b <> [Add]
|
||||||
|
compileE g ("-#" :$ a :$ b) = compileE g a <> compileE g b <> [Sub]
|
||||||
|
compileE g ("*#" :$ a :$ b) = compileE g a <> compileE g b <> [Mul]
|
||||||
|
compileE g ("/#" :$ a :$ b) = compileE g a <> compileE g b <> [Div]
|
||||||
|
|
||||||
|
compileE g e = compileC g e ++ [Eval]
|
||||||
|
|
||||||
-- | offset each address in the environment by n
|
-- | offset each address in the environment by n
|
||||||
argOffset :: Int -> Env -> Env
|
argOffset :: Int -> Env -> Env
|
||||||
argOffset n = each . _2 %~ (+n)
|
argOffset n = each . _2 %~ (+n)
|
||||||
|
|||||||
Reference in New Issue
Block a user