This commit is contained in:
@@ -16,12 +16,12 @@ close = transformM \case
|
|||||||
-- it would probably be most sane to generate a symbol for `env`,
|
-- it would probably be most sane to generate a symbol for `env`,
|
||||||
-- but we're reusing the lambda binding so we don't have to
|
-- but we're reusing the lambda binding so we don't have to
|
||||||
-- explicitly substitute recursive calls.
|
-- explicitly substitute recursive calls.
|
||||||
let frees = nub $ freeWithBound' [f] lam
|
let frees = nub $ free' lam
|
||||||
let m' = ifoldr
|
let m' = ifoldr
|
||||||
(\n x q ->
|
(\n x q ->
|
||||||
let n' = if x == f then 0 else n+1
|
let p = if x == f then PrimEnv @Val else PrimEnvRef n
|
||||||
in [cps|
|
in [cps|
|
||||||
(prim (env-ref #{n'})
|
(prim #{p}
|
||||||
(κ (#{x}) #{q}))
|
(κ (#{x}) #{q}))
|
||||||
|])
|
|])
|
||||||
m frees
|
m frees
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ data Prim e
|
|||||||
| PrimZeroP e
|
| PrimZeroP e
|
||||||
| PrimNewline
|
| PrimNewline
|
||||||
| PrimMakeClosure { code :: e, env :: List e }
|
| PrimMakeClosure { code :: e, env :: List e }
|
||||||
|
| PrimEnv
|
||||||
| PrimEnvRef Int
|
| PrimEnvRef Int
|
||||||
| PrimEnvCode e
|
| PrimEnvCode e
|
||||||
| PrimCallCC e
|
| PrimCallCC e
|
||||||
@@ -167,6 +168,7 @@ primDatumIso namefn a = S.match
|
|||||||
$ S.With (. ht1 "zero?")
|
$ S.With (. ht1 "zero?")
|
||||||
$ S.With (. ht0 "newline")
|
$ S.With (. ht0 "newline")
|
||||||
$ S.With (. ht1' "make-closure")
|
$ S.With (. ht1' "make-closure")
|
||||||
|
$ S.With (. ht0 "env")
|
||||||
$ S.With (. S.headTagged1 (namefn "env-ref") S.int)
|
$ S.With (. S.headTagged1 (namefn "env-ref") S.int)
|
||||||
$ S.With (. ht1 "env-code")
|
$ S.With (. ht1 "env-code")
|
||||||
$ S.With (. ht1 "call/cc")
|
$ S.With (. ht1 "call/cc")
|
||||||
|
|||||||
+12
-12
@@ -132,7 +132,7 @@ stepT :: Jalmot :> es => Env -> VM -> Tail -> Eff es VM
|
|||||||
|
|
||||||
stepT g vm tc@(Call nargs) = do
|
stepT g vm tc@(Call nargs) = do
|
||||||
(args,f,ret,frm) <- parseCall nargs (vm ^. activeFrame)
|
(args,f,ret,frm) <- parseCall nargs (vm ^. activeFrame)
|
||||||
& expectOf [i|#{show tc}|] _Just
|
& expectOf [i|bad call: #{show tc}|] _Just
|
||||||
rt <- getRoutine g f
|
rt <- getRoutine g f
|
||||||
let newFrame = MkFrame $ args ++ [f,ret]
|
let newFrame = MkFrame $ args ++ [f,ret]
|
||||||
pure $ vm
|
pure $ vm
|
||||||
@@ -145,7 +145,7 @@ stepT g vm tc@(Call nargs) = do
|
|||||||
|
|
||||||
stepT g vm tc@(Return nret) = do
|
stepT g vm tc@(Return nret) = do
|
||||||
(xs,_) <- splitAtExact nret (vm ^. activeFrame . #locals)
|
(xs,_) <- splitAtExact nret (vm ^. activeFrame . #locals)
|
||||||
& expectOf [i|"#{show tc}"|] _Just
|
& expectOf [i|bad return: #{show tc}|] _Just
|
||||||
expectOf [i|no return addr|] (activeFrame . returnAddress) vm >>= \case
|
expectOf [i|no return addr|] (activeFrame . returnAddress) vm >>= \case
|
||||||
ObjLabel "halt" -> pure $ vm & #result ?~ xs
|
ObjLabel "halt" -> pure $ vm & #result ?~ xs
|
||||||
ra -> do
|
ra -> do
|
||||||
@@ -159,7 +159,7 @@ stepT g vm tc@(Return nret) = do
|
|||||||
|
|
||||||
stepT g vm tc@(TailCall nargs) = do
|
stepT g vm tc@(TailCall nargs) = do
|
||||||
(args,f,ra) <- parseTailCall nargs (vm ^. activeFrame)
|
(args,f,ra) <- parseTailCall nargs (vm ^. activeFrame)
|
||||||
& expectOf [i|#{show tc}|] _Just
|
& expectOf [i|bad call: #{show tc}|] _Just
|
||||||
case f of
|
case f of
|
||||||
ObjLabel "halt" -> pure $ vm & #result ?~ args
|
ObjLabel "halt" -> pure $ vm & #result ?~ args
|
||||||
_ -> do
|
_ -> do
|
||||||
@@ -196,12 +196,14 @@ stepP g vm p = traverse (evalVal g vm) p >>= \case
|
|||||||
case env of
|
case env of
|
||||||
ObjHob (HobClosure l _) -> ret1 . ObjImm . ImmLabel $ l
|
ObjHob (HobClosure l _) -> ret1 . ObjImm . ImmLabel $ l
|
||||||
_ -> vmerror [i|expected closure, got #{env}|]
|
_ -> vmerror [i|expected closure, got #{env}|]
|
||||||
PrimEnvRef n ->
|
PrimEnv -> do
|
||||||
case vm ^? activeFrame . activeProcedure of
|
x <- vm & expectOf "expected closure" (activeFrame . activeProcedure)
|
||||||
Just (ObjHob (HobClosure {label,env})) -> ret1 case n of
|
ret1 x
|
||||||
0 -> ObjLabel label
|
PrimEnvRef n -> do
|
||||||
n -> env ^?! ix (n-1)
|
(label,env) <- vm & expectOf "expected closure"
|
||||||
x -> vmerror [i|expected closure, got #{x}|]
|
(activeFrame . activeProcedure . #_ObjHob . #_HobClosure)
|
||||||
|
x <- env & expectOf "expected upval" (ix n)
|
||||||
|
ret1 x
|
||||||
PrimCons x y -> ret1 $ ObjHob $ HobPair x y
|
PrimCons x y -> ret1 $ ObjHob $ HobPair x y
|
||||||
PrimCar x -> case x of
|
PrimCar x -> case x of
|
||||||
ObjHob (HobPair car _) -> ret1 car
|
ObjHob (HobPair car _) -> ret1 car
|
||||||
@@ -250,9 +252,7 @@ getRoutine g f = do
|
|||||||
expectOf
|
expectOf
|
||||||
:: (HasCallStack, Jalmot :> es)
|
:: (HasCallStack, Jalmot :> es)
|
||||||
=> Text -> Getting (First a) s a -> s -> Eff es a
|
=> Text -> Getting (First a) s a -> s -> Eff es a
|
||||||
expectOf msg l s = case s ^? l of
|
expectOf msg l = maybe (vmerror msg) pure . preview l
|
||||||
Just x -> pure x
|
|
||||||
Nothing -> vmerror [i|bad stack, expecting #{msg}|]
|
|
||||||
|
|
||||||
evalToLabel :: Jalmot :> es => Env -> VM -> Val -> Eff es Label
|
evalToLabel :: Jalmot :> es => Env -> VM -> Val -> Eff es Label
|
||||||
evalToLabel e vm v =
|
evalToLabel e vm v =
|
||||||
|
|||||||
Reference in New Issue
Block a user