Compare commits
2
Commits
baa5d248fd
...
b329a42b71
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b329a42b71 | ||
|
|
25ba8c03b8 |
@@ -107,6 +107,7 @@ test-suite test
|
|||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
hs-source-dirs: test
|
hs-source-dirs: test
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
|
build-tool-depends: tasty-discover:tasty-discover
|
||||||
other-modules:
|
other-modules:
|
||||||
Gyehoek.Test.CPS.Eval
|
Gyehoek.Test.CPS.Eval
|
||||||
Gyehoek.Test.CPS.Stackify
|
Gyehoek.Test.CPS.Stackify
|
||||||
@@ -115,6 +116,7 @@ test-suite test
|
|||||||
Gyehoek.Test.Scheme.Syntax
|
Gyehoek.Test.Scheme.Syntax
|
||||||
Gyehoek.Test.Sexp
|
Gyehoek.Test.Sexp
|
||||||
Gyehoek.Test.Stack.VM
|
Gyehoek.Test.Stack.VM
|
||||||
|
Root
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
, base
|
, base
|
||||||
|
|||||||
@@ -13,9 +13,8 @@ close = transformM \case
|
|||||||
ExpLetRec [(f, AbsLambda lam@(MkLambda bs kb m))] e -> do
|
ExpLetRec [(f, AbsLambda lam@(MkLambda bs kb m))] e -> do
|
||||||
f_code <- gensym' @Name $ f ^. _Wrapped'. to (<> "-code")
|
f_code <- gensym' @Name $ f ^. _Wrapped'. to (<> "-code")
|
||||||
-- 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 for the sake of recursive
|
-- but we're reusing the lambda binding so we don't have to
|
||||||
-- reverences.
|
-- explicitly substitute recursive calls.
|
||||||
-- env <- gensym' @Name "env"
|
|
||||||
let frees = freeWithBound' [f] lam
|
let frees = freeWithBound' [f] lam
|
||||||
let m' = ifoldr
|
let m' = ifoldr
|
||||||
(\n x q -> [cps|(prim (env-ref #{f} #{n})
|
(\n x q -> [cps|(prim (env-ref #{f} #{n})
|
||||||
|
|||||||
@@ -23,18 +23,16 @@ telescope f = Cont.runCont . traverse (Cont.cont . f)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
pattern Atomic e <-
|
|
||||||
e@( Scm.ExpLambda _ _
|
|
||||||
; Scm.ExpVar _
|
|
||||||
; Scm.ExpLit _ )
|
|
||||||
|
|
||||||
-- | Transform an expression with a meta-continuation.
|
-- | Transform an expression with a meta-continuation.
|
||||||
convert
|
convert
|
||||||
:: forall es. (GenSym :> es)
|
:: forall es. (GenSym :> es)
|
||||||
=> Scm.Exp -> (Val -> Eff es Exp) -> Eff es Exp
|
=> Scm.Exp -> (Val -> Eff es Exp) -> Eff es Exp
|
||||||
|
|
||||||
convert (Scm.ExpVar x) k = k $ ValVar x
|
convert (Scm.ExpVar x) k = k $ ValVar x
|
||||||
convert (Scm.ExpLit l) k = k $ ValLit l
|
convert (Scm.ExpLit l) k = k . ValImm $ case l of
|
||||||
|
LitInt n -> ImmInt n
|
||||||
|
LitBool b -> ImmBool b
|
||||||
|
_ -> _
|
||||||
|
|
||||||
-- special case: call/cc is desugared during cps-conversion...
|
-- special case: call/cc is desugared during cps-conversion...
|
||||||
convert (Scm.ExpPrim (PrimCallCC withcc)) k = do
|
convert (Scm.ExpPrim (PrimCallCC withcc)) k = do
|
||||||
@@ -112,10 +110,7 @@ convertLambda bs m = do
|
|||||||
|
|
||||||
convertProgram :: forall es. (GenSym :> es) => Scm.Program -> Eff es Program
|
convertProgram :: forall es. (GenSym :> es) => Scm.Program -> Eff es Program
|
||||||
convertProgram p =
|
convertProgram p =
|
||||||
MkProgram <$> telescope (convert @es) (p ^.. each . _Left) \exps ->
|
MkProgram <$> telescope (convert @es) (p ^.. each . _Left) (pure . Halt)
|
||||||
pure . Halt1 $ case NE.nonEmpty exps of
|
|
||||||
Nothing -> ValLit Void
|
|
||||||
Just es -> NE.last es
|
|
||||||
|
|
||||||
convertExp :: forall es. (GenSym :> es) => Scm.Exp -> Eff es Exp
|
convertExp :: forall es. (GenSym :> es) => Scm.Exp -> Eff es Exp
|
||||||
convertExp e = convert e (pure . Halt1)
|
convertExp e = convert e (pure . Halt1)
|
||||||
|
|||||||
@@ -60,13 +60,15 @@ evalVal :: Env -> Val -> Obj
|
|||||||
evalVal g = \case
|
evalVal g = \case
|
||||||
ValVar x -> fromMaybe (error [i|unbound: #{x}|]) $ g ^?! #vars . at x
|
ValVar x -> fromMaybe (error [i|unbound: #{x}|]) $ g ^?! #vars . at x
|
||||||
ValImm x -> ObjImm x
|
ValImm x -> ObjImm x
|
||||||
ValLit l -> ObjImm $ case l of
|
|
||||||
LitInt n -> ImmInt n
|
|
||||||
LitBool b -> ImmBool b
|
|
||||||
|
|
||||||
emptyEnv :: Env
|
emptyEnv :: Env
|
||||||
emptyEnv = MkEnv
|
emptyEnv = MkEnv
|
||||||
{ vars = mempty
|
{ vars = mempty
|
||||||
|
-- a kinda silly hack to make sure `halt` is handled correctly when
|
||||||
|
-- it appears as the tail continuation of an application. the
|
||||||
|
-- special case of `eval` responsible for `halt` only covers terms
|
||||||
|
-- of the form `(continue $halt xs …)`; other terms such as
|
||||||
|
-- `($some-fn xs $halt)` just see an undefined label `$halt`.
|
||||||
, labels = H.singleton "halt"
|
, labels = H.singleton "halt"
|
||||||
( emptyEnv
|
( emptyEnv
|
||||||
, AbsKappa' ["h0"] $ Halt [ValVar "h0"]
|
, AbsKappa' ["h0"] $ Halt [ValVar "h0"]
|
||||||
|
|||||||
@@ -82,13 +82,13 @@ popArg n = [expr|
|
|||||||
|
|
||||||
lowerVal :: (HasCallStack, GenMod :> es) => Env -> Val -> Eff es Wasm.Expr
|
lowerVal :: (HasCallStack, GenMod :> es) => Env -> Val -> Eff es Wasm.Expr
|
||||||
|
|
||||||
lowerVal g (ValLit l) =
|
lowerVal g (ValImm imm) =
|
||||||
pure $ case l of
|
pure $ case imm of
|
||||||
LitInt n -> [expr|
|
ImmInt n -> [expr|
|
||||||
(i32.const #{n})
|
(i32.const #{n})
|
||||||
##{makeSmallFixnum}
|
##{makeSmallFixnum}
|
||||||
|]
|
|]
|
||||||
LitBool b -> [expr|
|
ImmBool b -> [expr|
|
||||||
(i32.const #{b'})
|
(i32.const #{b'})
|
||||||
ref.i31
|
ref.i31
|
||||||
|]
|
|]
|
||||||
|
|||||||
@@ -87,8 +87,6 @@ stackify _ e = error [i|unimplemented exp: #{e}|]
|
|||||||
|
|
||||||
stackifyVal :: Env -> Val -> Stk.Val
|
stackifyVal :: Env -> Val -> Stk.Val
|
||||||
stackifyVal g = \case
|
stackifyVal g = \case
|
||||||
ValLit (LitInt n) -> Stk.ValImm (ImmInt n)
|
|
||||||
ValLit (LitBool b) -> Stk.ValImm (ImmBool b)
|
|
||||||
ValImm imm -> Stk.ValImm imm
|
ValImm imm -> Stk.ValImm imm
|
||||||
ValVar v -> var g v
|
ValVar v -> var g v
|
||||||
v -> error [i|unimplemented val: #{v}|]
|
v -> error [i|unimplemented val: #{v}|]
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ import Gyehoek.Prelude hiding (op)
|
|||||||
|
|
||||||
data Val
|
data Val
|
||||||
= ValImm Imm
|
= ValImm Imm
|
||||||
| ValLit Lit
|
|
||||||
| ValVar Name
|
| ValVar Name
|
||||||
deriving (Show, Generic, Data, Eq)
|
deriving (Show, Generic, Data, Eq)
|
||||||
|
|
||||||
@@ -173,7 +172,6 @@ instance Plated Exp where
|
|||||||
|
|
||||||
instance S.SexpIso Val where
|
instance S.SexpIso Val where
|
||||||
sexpIso = match
|
sexpIso = match
|
||||||
$ With (\lit -> lit . S.sexpIso)
|
|
||||||
$ With (\imm -> imm . S.sexpIso)
|
$ With (\imm -> imm . S.sexpIso)
|
||||||
$ With (\var -> var . S.sexpIso)
|
$ With (\var -> var . S.sexpIso)
|
||||||
$ End
|
$ End
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
module Gyehoek.Prelude
|
module Gyehoek.Prelude
|
||||||
( module Control.Lens
|
( module Control.Lens
|
||||||
, module Effectful
|
, module Effectful
|
||||||
, module Data.Generics.Labels
|
, module Data.Generics.Labels -- exports instances
|
||||||
, module Data.String.Interpolate
|
, module Data.String.Interpolate
|
||||||
, Text
|
, Text
|
||||||
, List
|
, List
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module Gyehoek.Test.CPS.Eval (root) where
|
module Gyehoek.Test.CPS.Eval where
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
@@ -8,9 +8,8 @@ import Gyehoek.CPS.Eval qualified as Sut
|
|||||||
import Data.List (List)
|
import Data.List (List)
|
||||||
|
|
||||||
|
|
||||||
root :: IO TestTree
|
test_cpsInterpreter = testGroup "cps interpreter" $
|
||||||
root = pure . testGroup "cps interpreter" $
|
[ primitives
|
||||||
[ prim
|
|
||||||
, testCase "halt with constant" do
|
, testCase "halt with constant" do
|
||||||
evalsTo [ObjImm (ImmInt 123)] [cps|
|
evalsTo [ObjImm (ImmInt 123)] [cps|
|
||||||
(continue halt 123)
|
(continue halt 123)
|
||||||
@@ -39,7 +38,7 @@ root = pure . testGroup "cps interpreter" $
|
|||||||
evalsTo :: HasCallStack => List Obj -> Sut.Program -> Assertion
|
evalsTo :: HasCallStack => List Obj -> Sut.Program -> Assertion
|
||||||
evalsTo rs p = Sut.evalProgram p @?= rs
|
evalsTo rs p = Sut.evalProgram p @?= rs
|
||||||
|
|
||||||
prim = testGroup "primitives"
|
primitives = testGroup "primitives"
|
||||||
[ testGroup "arith"
|
[ testGroup "arith"
|
||||||
[ testCase "basic 1" do
|
[ testCase "basic 1" do
|
||||||
evalsTo [ObjImm (ImmInt 20)] [cps|
|
evalsTo [ObjImm (ImmInt 20)] [cps|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module Gyehoek.Test.CPS.Stackify (root) where
|
module Gyehoek.Test.CPS.Stackify where
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
@@ -10,8 +10,7 @@ import Gyehoek.GenSym (runGenSym)
|
|||||||
import Effectful
|
import Effectful
|
||||||
|
|
||||||
|
|
||||||
root :: IO TestTree
|
test_stackify =
|
||||||
root = pure . testGroup "stackify" $
|
|
||||||
[ trivialReturn
|
[ trivialReturn
|
||||||
, tailCall
|
, tailCall
|
||||||
, prim
|
, prim
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{-# LANGUAGE OverloadedLists #-}
|
{-# LANGUAGE OverloadedLists #-}
|
||||||
module Gyehoek.Test.CPS.Syntax (root) where
|
module Gyehoek.Test.CPS.Syntax where
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
@@ -8,14 +8,13 @@ import Gyehoek.CPS.Syntax (cps)
|
|||||||
import Gyehoek.CPS.Syntax qualified as Sut
|
import Gyehoek.CPS.Syntax qualified as Sut
|
||||||
|
|
||||||
|
|
||||||
root :: IO TestTree
|
test_root = testGroup "cps syntax"
|
||||||
root = pure . testGroup "cps syntax" $
|
[ free
|
||||||
[ qqTree
|
, qq
|
||||||
, freeTree
|
|
||||||
]
|
]
|
||||||
|
|
||||||
freeTree :: TestTree
|
free :: TestTree
|
||||||
freeTree = testGroup "free"
|
free = testGroup "free"
|
||||||
[ testCase "lambda" do
|
[ testCase "lambda" do
|
||||||
Sut.free' @Sut.Lambda [cps|
|
Sut.free' @Sut.Lambda [cps|
|
||||||
(lambda (x y z k1) (continue k1 x a b c y))
|
(lambda (x y z k1) (continue k1 x a b c y))
|
||||||
@@ -27,8 +26,8 @@ freeTree = testGroup "free"
|
|||||||
(continue x y k3))|] @=? ["k3"]
|
(continue x y k3))|] @=? ["k3"]
|
||||||
]
|
]
|
||||||
|
|
||||||
qqTree :: TestTree
|
qq :: TestTree
|
||||||
qqTree = testGroup "parser"
|
qq = testGroup "parser"
|
||||||
[ testCase "lambda" do
|
[ testCase "lambda" do
|
||||||
assertEqual "" (Sut.MkLambda ["x","y"] "ktail"
|
assertEqual "" (Sut.MkLambda ["x","y"] "ktail"
|
||||||
(Sut.ExpContinue "ktail" [Sut.ValVar "x"]))
|
(Sut.ExpContinue "ktail" [Sut.ValVar "x"]))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module Gyehoek.Test.Golden (root) where
|
module Gyehoek.Test.Golden where
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.Silver
|
import Test.Tasty.Silver
|
||||||
@@ -31,8 +31,8 @@ brokenStackifyTests =
|
|||||||
-- , "callcc-nested1" -- requires closure-conversion
|
-- , "callcc-nested1" -- requires closure-conversion
|
||||||
-- ]
|
-- ]
|
||||||
|
|
||||||
root :: IO TestTree
|
test_root :: IO TestTree
|
||||||
root = do
|
test_root = do
|
||||||
all_cases <- listDirectory "golden"
|
all_cases <- listDirectory "golden"
|
||||||
let tests = all_cases
|
let tests = all_cases
|
||||||
& fmap ("golden"</>)
|
& fmap ("golden"</>)
|
||||||
@@ -43,6 +43,7 @@ root = do
|
|||||||
]
|
]
|
||||||
|
|
||||||
maybeBroken name broken = applyWhen (name `elem` broken) expectFail
|
maybeBroken name broken = applyWhen (name `elem` broken) expectFail
|
||||||
|
|
||||||
wasmTests :: List FilePath -> IO TestTree
|
wasmTests :: List FilePath -> IO TestTree
|
||||||
wasmTests files = do
|
wasmTests files = do
|
||||||
cmd <- getEnvDefault "GYEHOEK_RUNTIME"
|
cmd <- getEnvDefault "GYEHOEK_RUNTIME"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module Gyehoek.Test.Scheme.Syntax (root) where
|
module Gyehoek.Test.Scheme.Syntax where
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
@@ -7,8 +7,7 @@ import Gyehoek.Scheme.Syntax (scm)
|
|||||||
import Gyehoek.Scheme.Syntax qualified as Sut
|
import Gyehoek.Scheme.Syntax qualified as Sut
|
||||||
|
|
||||||
|
|
||||||
root :: IO TestTree
|
test_root = testGroup "scheme syntax" $
|
||||||
root = pure . testGroup "scheme syntax" $
|
|
||||||
[ freeTree
|
[ freeTree
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
module Gyehoek.Test.Sexp
|
module Gyehoek.Test.Sexp where
|
||||||
( root
|
|
||||||
, EquivSexp(..)
|
|
||||||
, assertEquiv
|
|
||||||
, equivto
|
|
||||||
)
|
|
||||||
where
|
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
@@ -14,8 +8,7 @@ import Gyehoek.Sexp (sx, equivalent)
|
|||||||
import Data.Function (on)
|
import Data.Function (on)
|
||||||
|
|
||||||
|
|
||||||
root :: IO TestTree
|
test_root = testGroup "sexp" $
|
||||||
root = pure . testGroup "sexp" $
|
|
||||||
[ sxTree
|
[ sxTree
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module Gyehoek.Test.Stack.VM (root) where
|
module Gyehoek.Test.Stack.VM where
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.HUnit
|
import Test.Tasty.HUnit
|
||||||
@@ -7,8 +7,7 @@ import Gyehoek.Stack.VM qualified as Sut
|
|||||||
import Data.List (List)
|
import Data.List (List)
|
||||||
|
|
||||||
|
|
||||||
root :: IO TestTree
|
test_root = testGroup "stack machine" $
|
||||||
root = pure . testGroup "stack machine" $
|
|
||||||
[ lit_int
|
[ lit_int
|
||||||
, procedure
|
, procedure
|
||||||
, prims
|
, prims
|
||||||
|
|||||||
+12
-21
@@ -1,27 +1,18 @@
|
|||||||
module Main (main) where
|
module Main (main) where
|
||||||
|
|
||||||
import Test.Tasty (TestTree, testGroup)
|
-- import Test.Tasty (TestTree, testGroup)
|
||||||
import Test.Tasty.Silver.Interactive (defaultMain)
|
import Test.Tasty.Silver.Interactive (defaultMain)
|
||||||
import qualified Gyehoek.Test.Golden
|
-- import qualified Gyehoek.Test.Golden
|
||||||
import qualified Gyehoek.Test.Sexp
|
-- import qualified Gyehoek.Test.Sexp
|
||||||
import qualified Gyehoek.Test.CPS.Syntax
|
-- import qualified Gyehoek.Test.CPS.Syntax
|
||||||
import qualified Gyehoek.Test.Scheme.Syntax
|
-- import qualified Gyehoek.Test.Scheme.Syntax
|
||||||
import qualified Gyehoek.Test.Stack.VM
|
-- import qualified Gyehoek.Test.Stack.VM
|
||||||
import qualified Gyehoek.Test.CPS.Stackify
|
-- import qualified Gyehoek.Test.CPS.Stackify
|
||||||
import qualified Gyehoek.Test.CPS.Eval
|
-- import qualified Gyehoek.Test.CPS.Eval
|
||||||
|
import qualified Root
|
||||||
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = defaultMain =<< root
|
main = do
|
||||||
|
discoveredTests <- Root.tests
|
||||||
root :: IO TestTree
|
defaultMain discoveredTests
|
||||||
root = testGroup "test" <$> sequenceA
|
|
||||||
[ Gyehoek.Test.Golden.root
|
|
||||||
, Gyehoek.Test.Sexp.root
|
|
||||||
, Gyehoek.Test.CPS.Syntax.root
|
|
||||||
, Gyehoek.Test.Scheme.Syntax.root
|
|
||||||
, Gyehoek.Test.Stack.VM.root
|
|
||||||
, Gyehoek.Test.CPS.Stackify.root
|
|
||||||
, Gyehoek.Test.CPS.Eval.root
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{-# OPTIONS_GHC
|
||||||
|
-F -pgmF tasty-discover
|
||||||
|
-optF --no-main
|
||||||
|
-optF --generated-module=Root
|
||||||
|
#-}
|
||||||
|
module Root where
|
||||||
Reference in New Issue
Block a user