Created
December 16, 2019 17:35
-
-
Save pchiusano/ab84be4712b2e07d45564b8d99814837 to your computer and use it in GitHub Desktop.
Unison runtime prototyping (by Dan Doel)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- Code by Dan Doel - https://github.com/unisonweb/unison/issues/1055#issuecomment-565753502 | |
{-# language BangPatterns #-} | |
module POC (C(..), eval0, setup) where | |
import Control.Monad.Primitive | |
import qualified Data.Vector.Generic.Mutable as GM | |
import qualified Data.Vector.Unboxed.Mutable as UM | |
data Args | |
= Arg1 !Int | |
| Arg2 !Int !Int | |
-- | ArgN {-# UNPACK #-} !(U.Vector Int) | |
data C | |
= App !Int !Closure !Args | |
| Lit !Int | |
| Dec !Int | |
| Add !Int !Int | |
| Prn !Int | |
| Let !C !C | |
| Nop | |
| Brn !Int !C !C | |
| Ret !Int !Int | |
| AddThn !Int !Int !C | |
| LitThn !Int !C | |
| DecThn !Int !C | |
data Closure | |
= Ref !Int | |
data K = E | !C :< !K | |
type Stk = UM.MVector (PrimState IO) Int | |
type SP = Int | |
eval0 :: C -> IO () | |
eval0 c = do | |
stk <- GM.new 512 | |
eval stk 512 E c | |
resolve :: Closure -> C | |
resolve (Ref 0) = loop | |
resolve (Ref 1) = fib | |
resolve _ = error "Unknown reference" | |
eval :: Stk -> SP -> K -> C -> IO () | |
eval !stk !sp !k (Dec i) = do | |
x <- GM.unsafeRead stk (sp + i) | |
let sp' = sp-1 | |
GM.unsafeWrite stk sp' (x-1) | |
jump stk sp' k | |
eval !stk !sp !k (Add i j) = do | |
x <- GM.unsafeRead stk (sp + i) | |
y <- GM.unsafeRead stk (sp + j) | |
let sp' = sp-1 | |
GM.unsafeWrite stk sp' (x+y) | |
jump stk sp' k | |
eval !stk !sp !k (Prn i) = do | |
x <- GM.unsafeRead stk (sp + i) | |
print x | |
jump stk sp k | |
eval !stk !sp !k (App lo f args) = do | |
sp' <- moveArgs stk sp lo args | |
eval stk sp' k (resolve f) | |
eval !stk !sp !k (Lit n) = do | |
let sp' = sp-1 | |
GM.unsafeWrite stk sp' n | |
jump stk sp' k | |
eval !stk !sp !k (Let c d) = do | |
eval stk sp (d :< k) c | |
eval !stk !sp !k (Brn i t f) = do | |
b <- GM.unsafeRead stk (sp+i) | |
if b == 0 | |
then eval stk sp k t | |
else eval stk sp k f | |
eval !stk !sp !k (Ret lo i) = do | |
let sp' = sp+lo-1 | |
GM.unsafeRead stk (sp+i) >>= GM.unsafeWrite stk sp' | |
jump stk sp' k | |
eval !stk !sp !k (DecThn i d) = do | |
x <- GM.unsafeRead stk (sp + i) | |
let sp' = sp-1 | |
GM.unsafeWrite stk sp' (x-1) | |
eval stk sp' k d | |
eval !stk !sp !k (AddThn i j d) = do | |
x <- GM.unsafeRead stk (sp + i) | |
y <- GM.unsafeRead stk (sp + j) | |
let sp' = sp-1 | |
GM.unsafeWrite stk sp' (x+y) | |
eval stk sp' k d | |
eval !stk !sp !k (LitThn n d) = do | |
let sp' = sp-1 | |
GM.unsafeWrite stk sp' n | |
eval stk sp' k d | |
eval !stk !sp !k Nop = jump stk sp k | |
jump :: Stk -> SP -> K -> IO () | |
jump _ _ E = return () | |
jump stk sp (d :< k) = eval stk sp k d | |
{-# inline jump #-} | |
moveArgs :: Stk -> SP -> Int -> Args -> IO Int | |
moveArgs !stk !sp !lo (Arg1 i) = do | |
let sp' = sp + lo - 1 | |
GM.unsafeRead stk (sp + i) >>= GM.unsafeWrite stk sp' | |
return sp' | |
moveArgs !stk !sp !lo (Arg2 i j) = do | |
x <- GM.unsafeRead stk (sp + i) | |
y <- GM.unsafeRead stk (sp + j) | |
let sp' = sp + lo - 2 | |
GM.unsafeWrite stk sp' x | |
GM.unsafeWrite stk (sp'+1) y | |
return sp' | |
{-# inline moveArgs #-} | |
loop :: C | |
loop = Brn 0 fls tru | |
where | |
fls = Ret 2 1 | |
tru = Let (Add 0 1) $ Let (Dec 1) $ App 4 (Ref 0) (Arg2 0 1) | |
fib :: C | |
fib = Brn 0 | |
(Let (Lit 0) (Ret 2 0)) $ | |
Let (Dec 0) $ | |
Brn 0 | |
(Let (Lit 1) (Ret 3 0)) $ | |
Let (App 0 (Ref 1) (Arg1 0)) $ | |
Let (Dec 1) $ | |
Let (App 0 (Ref 1) (Arg1 0)) $ | |
Let (Add 0 2) $ | |
Ret 6 0 | |
setup :: C | |
setup = Let (Lit 0) $ Let (Lit 100000000) $ Let (App 2 (Ref 0) (Arg2 0 1)) $ (Prn 0) | |
-- setup = Let (Lit 36) $ Let (App 1 (Ref 1) (Arg1 0)) $ Prn 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment