Compare commits

2 Commits
Author SHA1 Message Date
msyds a97a0ad7bb fix tests }:3
build / build (push) Successful in 4m52s
2026-07-18 02:49:34 -06:00
msyds 9334373f96 "fix stuff lol" 2026-07-18 01:50:43 -06:00
16 changed files with 479 additions and 169 deletions
+6 -10
View File
@@ -16,11 +16,10 @@
"x86_64-darwin" "x86_64-linux" "x86_64-darwin" "x86_64-linux"
]; ];
overlays = [ overlays = [
haskellNix.overlay haskellNix.overlay
(final: prev: { (final: prev: {
gyehoek-wasmtime-wrapper = final.callPackage ./wasmtime.nix {}; shake-wrapper = final.callPackage ./shake-wrapper.nix {};
gyehoek-runtime = final.callPackage ./runtime {}; gyehoek-runtime = final.callPackage ./runtime {};
gyehoek = final.haskell-nix.project' { gyehoek = final.haskell-nix.project' {
src = ./.; src = ./.;
@@ -29,13 +28,10 @@
packages.gyehoek.components.tests.test.preCheck = packages.gyehoek.components.tests.test.preCheck =
let let
bin = [ bin = [
pkgs.gyehoek-wasmtime-wrapper pkgs.git # tasty uses git diff
pkgs.git
]; ];
in '' in ''
# Wasmtime requires a cache in $HOME. This is less export GYEHOEK_RUNTIME=${lib.getExe final.gyehoek-runtime}
# painful than reconfiguring the cache location.
export HOME=$(mktemp -d)
export PATH=${lib.makeBinPath bin}:$PATH export PATH=${lib.makeBinPath bin}:$PATH
''; '';
})]; })];
@@ -50,14 +46,14 @@
}; };
buildInputs = with final; [ buildInputs = with final; [
haskellPackages.cabal-fmt haskellPackages.cabal-fmt
self.packages.${final.stdenv.hostPlatform.system}.shake shake-wrapper
wabt wabt
nodejs nodejs
wasm-tools wasm-tools
wac-cli wac-cli
guile guile
gyehoek-wasmtime-wrapper
rust-analyzer rust-analyzer
wasmtime
]; ];
}; };
}; };
@@ -89,7 +85,7 @@
hf.packages.${system} // lib.fix (packages: { hf.packages.${system} // lib.fix (packages: {
gyehoek = hf.packages.${system}."gyehoek:exe:gyehoek"; gyehoek = hf.packages.${system}."gyehoek:exe:gyehoek";
default = packages.gyehoek; default = packages.gyehoek;
shake = pkgs.callPackage ./shake-wrapper.nix {}; inherit (pkgs) gyehoek-runtime shake-wrapper;
})); }));
devShells = each-system devShells = each-system
-3
View File
@@ -1,5 +1,2 @@
ret > ExitSuccess ret > ExitSuccess
out > 22 out > 22
out >
err > warning: using `--invoke` with a function that returns values is experimental and may break in the future
err >
+80 -32
View File
@@ -1,47 +1,95 @@
(module (module
(type $heap-object (sub (struct (field (mut i32))))) (import
"gyehoek"
"write"
(func $gh-write (param (ref eq))))
(import
"gyehoek"
"to-bool"
(func $gh-to-bool (param (ref eq)) (result i32)))
(type $heap-object (sub (struct (field $hash (mut i32)))))
(type $cont-type (func (param i32)))
(type $cont-stack-type (array (mut (ref null $cont-type))))
(global $cont-stack-top (mut i32) (i32.const 0))
(global
$cont-stack
(ref $cont-stack-type)
(array.new_default $cont-stack-type (i32.const 128)))
(type $arg-array-type (array (mut (ref null eq))))
(global
$arg-array
(ref $arg-array-type)
(array.new_default $arg-array-type (i32.const 32)))
(global $result (mut (ref null eq)) (ref.null eq))
(func (func
(param) $halt
(result (ref eq)) (param i32)
(global.get $arg-array)
(i32.const 0)
(array.get $arg-array-type)
ref.as_non_null
(global.set $result))
(func
$scm-entry
(param i32)
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq)) (local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
(i32.const 3) (i32.const 3)
(i32.const 2) (i32.const 1)
i32.shl i32.shl
ref.i31 ref.i31
(ref.cast (ref i31)) (i31.get_s (ref.cast (ref i31)))
i31.get_s (i32.const 1)
i32.shr_u
(i32.const 4) (i32.const 4)
(i32.const 2) (i32.const 1)
i32.shl i32.shl
ref.i31 ref.i31
(ref.cast (ref i31)) (i31.get_s (ref.cast (ref i31)))
i31.get_s (i32.const 1)
i32.shr_u
i32.mul i32.mul
ref.i31 (i32.const 1)
(local.set 0)
(i32.const 2)
(i32.const 2)
i32.shl i32.shl
ref.i31 ref.i31
(ref.cast (ref i31))
i31.get_s
(i32.const 5)
(i32.const 2)
i32.shl
ref.i31
(ref.cast (ref i31))
i31.get_s
i32.mul
ref.i31
(local.set 1) (local.set 1)
(local.get 0) (i32.const 2)
(ref.cast (ref i31)) (i32.const 1)
i31.get_s i32.shl
(local.get 1) ref.i31
(ref.cast (ref i31)) (i31.get_s (ref.cast (ref i31)))
i31.get_s (i32.const 1)
i32.add i32.shr_u
(i32.const 5)
(i32.const 1)
i32.shl
ref.i31
(i31.get_s (ref.cast (ref i31)))
(i32.const 1)
i32.shr_u
i32.mul
(i32.const 1)
i32.shl
ref.i31 ref.i31
(local.set 2) (local.set 2)
(local.get 2)) (local.get 1)
(export "main" (func 0))) (i31.get_s (ref.cast (ref i31)))
(i32.const 1)
i32.shr_u
(local.get 2)
(i31.get_s (ref.cast (ref i31)))
(i32.const 1)
i32.shr_u
i32.add
(i32.const 1)
i32.shl
ref.i31
(local.set 3)
(global.get $arg-array)
(global.get 0)
(local.get 3)
(array.set $arg-array-type)
(return_call $halt (i32.const 1)))
(func
(export "main")
(call $scm-entry (i32.const 0))
(call $gh-write (ref.as_non_null (global.get $result)))))
-3
View File
@@ -1,5 +1,2 @@
ret > ExitSuccess ret > ExitSuccess
out > 555 out > 555
out >
err > warning: using `--invoke` with a function that returns values is experimental and may break in the future
err >
+56 -8
View File
@@ -1,13 +1,61 @@
(module (module
(type (sub (struct (field (mut i32))))) (import
"gyehoek"
"write"
(func $gh-write (param (ref eq))))
(import
"gyehoek"
"to-bool"
(func $gh-to-bool (param (ref eq)) (result i32)))
(type $heap-object (sub (struct (field $hash (mut i32)))))
(type $cont-type (func (param i32)))
(type $cont-stack-type (array (mut (ref null $cont-type))))
(global $cont-stack-top (mut i32) (i32.const 0))
(global
$cont-stack
(ref $cont-stack-type)
(array.new_default $cont-stack-type (i32.const 128)))
(type $arg-array-type (array (mut (ref null eq))))
(global
$arg-array
(ref $arg-array-type)
(array.new_default $arg-array-type (i32.const 32)))
(global $result (mut (ref null eq)) (ref.null eq))
(func (func
(param) $halt
(result (ref eq)) (param i32)
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq)) (global.get $arg-array)
(i32.const 0) (i32.const 0)
(array.get $arg-array-type)
ref.as_non_null
(global.set $result))
(func
$scm-entry
(param i32)
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
(i32.const 1)
ref.i31 ref.i31
(call $gh-to-bool)
(if (if
(result i32) (then
(then (i32.const 777) ref.i31) (global.get $arg-array)
(else (i32.const 555) ref.i31))) (global.get 0)
(export "main" (func 0))) (i32.const 777)
(i32.const 1)
i32.shl
ref.i31
(array.set $arg-array-type)
(return_call $halt (i32.const 1)))
(else
(global.get $arg-array)
(global.get 0)
(i32.const 555)
(i32.const 1)
i32.shl
ref.i31
(array.set $arg-array-type)
(return_call $halt (i32.const 1)))))
(func
(export "main")
(call $scm-entry (i32.const 0))
(call $gh-write (ref.as_non_null (global.get $result)))))
-3
View File
@@ -1,5 +1,2 @@
ret > ExitSuccess ret > ExitSuccess
out > 777 out > 777
out >
err > warning: using `--invoke` with a function that returns values is experimental and may break in the future
err >
+56 -8
View File
@@ -1,13 +1,61 @@
(module (module
(type (sub (struct (field (mut i32))))) (import
"gyehoek"
"write"
(func $gh-write (param (ref eq))))
(import
"gyehoek"
"to-bool"
(func $gh-to-bool (param (ref eq)) (result i32)))
(type $heap-object (sub (struct (field $hash (mut i32)))))
(type $cont-type (func (param i32)))
(type $cont-stack-type (array (mut (ref null $cont-type))))
(global $cont-stack-top (mut i32) (i32.const 0))
(global
$cont-stack
(ref $cont-stack-type)
(array.new_default $cont-stack-type (i32.const 128)))
(type $arg-array-type (array (mut (ref null eq))))
(global
$arg-array
(ref $arg-array-type)
(array.new_default $arg-array-type (i32.const 32)))
(global $result (mut (ref null eq)) (ref.null eq))
(func (func
(param) $halt
(result (ref eq)) (param i32)
(global.get $arg-array)
(i32.const 0)
(array.get $arg-array-type)
ref.as_non_null
(global.set $result))
(func
$scm-entry
(param i32)
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq)) (local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
(i32.const 1) (i32.const 3)
ref.i31 ref.i31
(call $gh-to-bool)
(if (if
(result i32) (then
(then (i32.const 777) ref.i31) (global.get $arg-array)
(else (i32.const 555) ref.i31))) (global.get 0)
(export "main" (func 0))) (i32.const 777)
(i32.const 1)
i32.shl
ref.i31
(array.set $arg-array-type)
(return_call $halt (i32.const 1)))
(else
(global.get $arg-array)
(global.get 0)
(i32.const 555)
(i32.const 1)
i32.shl
ref.i31
(array.set $arg-array-type)
(return_call $halt (i32.const 1)))))
(func
(export "main")
(call $scm-entry (i32.const 0))
(call $gh-write (ref.as_non_null (global.get $result)))))
+1
View File
@@ -9,4 +9,5 @@ rustPlatform.buildRustPackage (finalAttrs: {
lockFile = ./Cargo.lock; lockFile = ./Cargo.lock;
}; };
doCheck = true; doCheck = true;
meta.mainProgram = "gyehoek-runtime";
}) })
+28 -2
View File
@@ -1,5 +1,31 @@
use wasmtime::*; use wasmtime::*;
use crate::internal as scm;
use crate::internal::{Scm,Immediate};
pub fn say_hi (_caller : Caller<'_, u32>) { // pub fn small_fixnum_p (_)
println! ("hiiii~")
// pub fn immediate_p (caller : Caller<'_, u32>, x : EqRef) -> EqRef {
// x.is_i31 ()
// }
fn write_immediate (_caller : Caller<'_, u32>, imm : Immediate) {
match imm {
Immediate::SmallFixnum (n) => print! ("{}", n),
Immediate::Bool (b) => print! ("{}", if b { "#t" } else { "#f" }),
}
}
pub fn write (caller : Caller<'_, u32>, x : Rooted<EqRef>) {
match scm::interpret (&caller, x).unwrap () {
Scm::Immediate (x) => write_immediate (caller, x)
}
}
pub fn truthy_p (caller : Caller<'_, u32>, x : Rooted<EqRef>,) -> u32 {
let r = scm::interpret (&caller, x).unwrap ();
if let Scm::Immediate (Immediate::Bool (false)) = r {
0
} else {
1
}
} }
+70
View File
@@ -0,0 +1,70 @@
use wasmtime::*;
pub fn immediate_p (store : impl AsContext, x : Rooted<EqRef>) -> bool {
x.is_i31 (store).unwrap ()
}
pub enum Immediate {
SmallFixnum (i32),
Bool (bool),
}
pub enum Scm {
Immediate (Immediate),
}
#[allow(nonstandard_style)]
pub type scm_bits = u32;
#[allow(nonstandard_style)]
pub const scm_false : scm_bits = 0b01;
#[allow(nonstandard_style)]
pub const scm_true : scm_bits = 0b11;
pub fn interpret_immediate (x : scm_bits) -> Option<Immediate> {
if x & 1 == 0 {
Some (Immediate::SmallFixnum ((x >> 1).try_into ().unwrap ()))
} else if x == scm_true {
Some (Immediate::Bool (true))
} else if x == scm_false {
Some (Immediate::Bool (false))
} else {
None
}
}
pub fn interpret (store : impl AsContext, x : Rooted<EqRef>) -> Option<Scm> {
if let Some (imm) = x.as_i31 (store).unwrap () {
Some (Scm::Immediate (interpret_immediate (imm.get_u32 ())?))
} else {
todo! ()
}
}
pub fn encode_immediate (
store : impl AsContext,
imm : Immediate
) -> scm_bits {
use Immediate::*;
match imm {
SmallFixnum (n) => (n << 1).try_into ().unwrap (),
Bool (false) => scm_false,
Bool (true) => scm_true,
}
}
pub fn encode (store : impl AsContextMut, x : Scm) -> Rooted<EqRef> {
match x {
Scm::Immediate (imm) => {
let i31 = I31::new_u32 (encode_immediate (&store, imm))
.unwrap ();
EqRef::from_i31 (store, i31)
}
}
}
pub fn encode_bool (store : impl AsContextMut, b : bool) -> Rooted<EqRef> {
let x = if b { scm_true } else { scm_false };
let i31 = I31::new_u32 (x).unwrap ();
EqRef::from_i31 (store, i31)
}
+19 -2
View File
@@ -1,4 +1,5 @@
mod gyehoek; mod gyehoek;
mod internal;
use std::io; use std::io;
use std::io::Read; use std::io::Read;
@@ -21,12 +22,28 @@ fn read<R : Read> (mut rdr : R) -> io::Result<Vec<u8>> {
Ok (buf) Ok (buf)
} }
fn get_config () -> Config {
let mut cfg = Config::new ();
cfg.wasm_reference_types (true);
cfg.wasm_function_references (true);
cfg.wasm_tail_call (true);
cfg.wasm_gc (true);
cfg
}
fn link_primitives (linker : &mut Linker<u32>) -> wasmtime::Result<()> {
linker.func_wrap ("gyehoek", "write", gyehoek::write)?;
linker.func_wrap ("gyehoek", "to-bool", gyehoek::truthy_p)?;
Ok (())
}
pub fn main () -> wasmtime::Result<()> { pub fn main () -> wasmtime::Result<()> {
let args = Args::parse (); let args = Args::parse ();
let engine = Engine::default (); let wasm_config = get_config ();
let engine = Engine::new (&wasm_config)?;
let module = Module::new (&engine, read (args.wasm)?)?; let module = Module::new (&engine, read (args.wasm)?)?;
let mut linker = Linker::new (&engine); let mut linker = Linker::new (&engine);
linker.func_wrap ("gyehoek", "say-hi", gyehoek::say_hi)?; link_primitives (&mut linker)?;
let mut store : Store<u32> = Store::new (&engine, 4); let mut store : Store<u32> = Store::new (&engine, 4);
let instance = linker.instantiate (&mut store, &module)?; let instance = linker.instantiate (&mut store, &module)?;
let main = instance.get_typed_func::<(),()> (&mut store, "main")?; let main = instance.get_typed_func::<(),()> (&mut store, "main")?;
+45 -5
View File
@@ -39,6 +39,7 @@ import Debug.Pretty.Simple
import Control.Monad.Fix import Control.Monad.Fix
import Language.Sexp.Located (Sexp) import Language.Sexp.Located (Sexp)
import Data.Functor.Foldable (cata) import Data.Functor.Foldable (cata)
import qualified Gyehoek.Sexp
data Env = MkEnv data Env = MkEnv
@@ -121,7 +122,7 @@ lower' :: (GenMod :> es) => Env -> Exp -> Eff es Wasm.Expr
lower' g (Halt [v]) = pure [expr| lower' g (Halt [v]) = pure [expr|
##{arg} ##{arg}
(return_call $halt) (return_call $halt (i32.const 1))
|] |]
where arg = pushArg 0 (lowerVal g v) where arg = pushArg 0 (lowerVal g v)
@@ -132,6 +133,19 @@ lower' g (ExpPrim p rs e) =
where where
r = head rs r = head rs
lower' g (ExpIf c t f) = do
t' <- lower' g t
f' <- lower' g f
let c' = lowerVal g c
pure [expr|
##{c'}
(call $gh-to-bool)
(if (then ##{t'})
(else ##{f'}))
|]
lower' g e = error . show $ e
-- lower' g (ExpIf c t f) = do -- lower' g (ExpIf c t f) = do
-- t' <- lower' g t -- t' <- lower' g t
-- f' <- lower' g f -- f' <- lower' g f
@@ -183,6 +197,7 @@ lowerBinOp
:: (GenMod :> es) :: (GenMod :> es)
=> Text -> Env -> Val -> Val -> Name -> Exp -> Eff es Wasm.Expr => Text -> Env -> Val -> Val -> Name -> Exp -> Eff es Wasm.Expr
lowerBinOp op g x y r e = do lowerBinOp op g x y r e = do
let op' = SL.Symbol op
let g' = g & #vars <>~ [r] let g' = g & #vars <>~ [r]
let n = succ $ length (g ^. #vars) let n = succ $ length (g ^. #vars)
let x' = lowerVal g x let x' = lowerVal g x
@@ -191,9 +206,15 @@ lowerBinOp op g x y r e = do
pure [expr| pure [expr|
##{x'} ##{x'}
(i31.get_s (ref.cast (ref i31))) (i31.get_s (ref.cast (ref i31)))
(i32.const 1)
i32.shr_u
##{y'} ##{y'}
(i31.get_s (ref.cast (ref i31))) (i31.get_s (ref.cast (ref i31)))
(local.set #{n} (ref.i31 #{op})) (i32.const 1)
i32.shr_u
#{op'}
##{makeSmallFixnum}
(local.set #{n})
##{e'} ##{e'}
|] |]
@@ -234,6 +255,11 @@ lowerBinOp op g x y r e = do
emitRuntime :: GenMod :> es => Eff es () emitRuntime :: GenMod :> es => Eff es ()
emitRuntime = mfix \runtime -> do emitRuntime = mfix \runtime -> do
Wasm.emit [wats|
(import "gyehoek" "write" (func $gh-write (param (ref eq))))
(import "gyehoek" "to-bool" (func $gh-to-bool (param (ref eq))
(result i32)))
|]
-- cont stack -- cont stack
Wasm.defineType [wat| Wasm.defineType [wat|
(type $heap-object (sub (struct (field $hash (mut i32))))) (type $heap-object (sub (struct (field $hash (mut i32)))))
@@ -257,7 +283,7 @@ emitRuntime = mfix \runtime -> do
|] |]
Wasm.defineGlobal [wat| Wasm.defineGlobal [wat|
(global $arg-array (ref $arg-array-type) (global $arg-array (ref $arg-array-type)
(array.new_default $arg-array-type) (i32.const 32)) (array.new_default $arg-array-type (i32.const 32)))
|] |]
-- other things 😼 -- other things 😼
Wasm.defineGlobal [wat| Wasm.defineGlobal [wat|
@@ -284,9 +310,9 @@ lower e = fmap Wasm.renderModule . Wasm.execGenMod $ do
##{e'}) ##{e'})
|] |]
Wasm.defineFunction [wat| Wasm.defineFunction [wat|
(func (export "main") (result (ref eq)) (func (export "main")
(call $scm-entry (i32.const 0)) (call $scm-entry (i32.const 0))
(ref.as_non_null (global.get $result))) (call $gh-write (ref.as_non_null (global.get $result))))
|] |]
lowerProgram :: Program -> Eff es Text lowerProgram :: Program -> Eff es Text
@@ -325,3 +351,17 @@ antiquote_splicing_example =
(func $blah (param i32 i64 f64)) (func $blah (param i32 i64 f64))
|] |]
in (metavars, e1, e2, e1 == e2) in (metavars, e1, e2, e1 == e2)
antiquote_both_example =
let
m1 = 123 :: Int
ms = [expr|i32 i64|]
e1 = [expr|
a (b #{m1} c) d ##{ms} e
|]
e2 = [expr|
a (b 123 c) d i32 i64 e
|]
in (e1,e2,e1==e2)
+33 -9
View File
@@ -56,7 +56,7 @@ import Data.List (List, groupBy)
import Data.Text.Encoding import Data.Text.Encoding
import Data.Either (either) import Data.Either (either)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Control.Lens import Control.Lens hiding (para)
import Data.Generics.Labels import Data.Generics.Labels
import System.Process import System.Process
import GHC.IO.Unsafe (unsafePerformIO) import GHC.IO.Unsafe (unsafePerformIO)
@@ -71,9 +71,9 @@ import Language.Haskell.TH (Quote, location, Loc (..), ExpQ, varE, mkName, listE
import qualified Data.Text as T import qualified Data.Text as T
import qualified Control.Category import qualified Control.Category
import Data.Data (Data (..), Typeable, cast) import Data.Data (Data (..), Typeable, cast)
import Language.Haskell.TH.Syntax (lift, Lift) import Language.Haskell.TH.Syntax (lift, Lift, liftData)
import GHC.IsList (fromList) import GHC.IsList (fromList)
import Data.Functor.Foldable (cata) import Data.Functor.Foldable (cata, para, embed)
import Data.Functor.Classes (Show1(..)) import Data.Functor.Classes (Show1(..))
import Data.Vector (Vector) import Data.Vector (Vector)
import Numeric.Natural (Natural) import Numeric.Natural (Natural)
@@ -81,6 +81,7 @@ import Data.Maybe (fromMaybe)
import Control.Applicative (Alternative((<|>))) import Control.Applicative (Alternative((<|>)))
import Debug.Pretty.Simple import Debug.Pretty.Simple
import qualified Data.Vector as V import qualified Data.Vector as V
import qualified Data.Vector.Strict
sexp :: SexpIso a => Iso' a Text sexp :: SexpIso a => Iso' a Text
@@ -295,10 +296,12 @@ instance SexpIso Natural where
| otherwise = Right $ fromIntegral n | otherwise = Right $ fromIntegral n
g n = fromIntegral n g n = fromIntegral n
class SpliceSexp a where class SpliceSexp a where
spliceSexp :: a -> List Sexp spliceSexp :: a -> List Sexp
instance SexpIso a => SpliceSexp (Data.Vector.Strict.Vector a) where
spliceSexp = toSexps
instance SexpIso a => SpliceSexp (Vector a) where instance SexpIso a => SpliceSexp (Vector a) where
spliceSexp = toSexps spliceSexp = toSexps
@@ -329,6 +332,30 @@ unquoteSplicing xs
& listE & listE
unquoteSplicing _ = Nothing unquoteSplicing _ = Nothing
unquoteSplicingRecursive :: List Sexp.Sexp -> ExpQ
unquoteSplicingRecursive xs = [| mconcat $(spans) |]
where
spans = xs
& groupBy \cases
(UnquoteSplicing _) _ -> False
_ (UnquoteSplicing _) -> False
_ _ -> True
& fmap \case
-- [e@(Unquote _)] ->
-- case unquote e of
-- Just x -> [| [$(x)] |]
-- Nothing -> error "unreachable"
[UnquoteSplicing x] ->
[| spliceSexp $(varE (mkName (T.unpack x))) |]
es -> listE $ unquoteRecursive <$> es
& listE
unquoteRecursive :: Sexp.Sexp -> ExpQ
unquoteRecursive = \case
Unquote x -> [| stripLocation (toSexp $(varE (mkName (T.unpack x)))) |]
SL.ParenList xs -> [|SL.ParenList $(unquoteSplicingRecursive xs)|]
e -> liftData e
unquote :: Sexp.Sexp -> Maybe ExpQ unquote :: Sexp.Sexp -> Maybe ExpQ
unquote (Unquote x) = unquote (Unquote x) =
Just [| stripLocation . toSexp $ $(varE (mkName (T.unpack x))) |] Just [| stripLocation . toSexp $ $(varE (mkName (T.unpack x))) |]
@@ -340,13 +367,10 @@ _ParenList = prism' SL.ParenList \case
_ -> Nothing _ -> Nothing
metaSexps :: List Sexp.Sexp -> Maybe ExpQ metaSexps :: List Sexp.Sexp -> Maybe ExpQ
metaSexps = unquoteSplicing metaSexps = Just . unquoteSplicingRecursive
metaSexpsV :: Vector Sexp.Sexp -> Maybe ExpQ
metaSexpsV = unquoteSplicing . V.toList
metaSexp :: Sexp.Sexp -> Maybe ExpQ metaSexp :: Sexp.Sexp -> Maybe ExpQ
metaSexp x = unquote x metaSexp = Just . unquoteRecursive
-- 뻘짓뻘짓뻘짓뻘짓뻘짓 -- 뻘짓뻘짓뻘짓뻘짓뻘짓
class Lift1 f where class Lift1 f where
+13 -8
View File
@@ -28,9 +28,10 @@ module Gyehoek.Wasm
, defineFunction , defineFunction
, defineType , defineType
, defineGlobal , defineGlobal
, declare , emit
, renderModule , renderModule
, wat , wat
, wats
) )
where where
@@ -49,9 +50,9 @@ import Effectful.Dispatch.Dynamic
import Effectful.State.Dynamic import Effectful.State.Dynamic
import Control.Lens import Control.Lens
import Data.Generics.Labels import Data.Generics.Labels
import Data.Vector (Vector) import Data.Vector.Strict (Vector)
import Data.String.Interpolate import Data.String.Interpolate
import qualified Data.Vector as V import qualified Data.Vector.Strict as V
import qualified Data.Text as T import qualified Data.Text as T
import Effectful.Writer.Dynamic import Effectful.Writer.Dynamic
import Control.Applicative (Alternative((<|>))) import Control.Applicative (Alternative((<|>)))
@@ -69,6 +70,7 @@ import Data.Data (Data)
import Data.Functor.Foldable (cata) import Data.Functor.Foldable (cata)
import Gyehoek.Sexp (sx) import Gyehoek.Sexp (sx)
import qualified Language.Sexp as SL import qualified Language.Sexp as SL
import Data.Foldable (traverse_)
newtype Module = MkModule { inner :: Vector Sexp } newtype Module = MkModule { inner :: Vector Sexp }
@@ -124,7 +126,7 @@ data GenMod :: Effect where
DefineFunction :: Sexp -> GenMod m Idx DefineFunction :: Sexp -> GenMod m Idx
DefineType :: Sexp -> GenMod m Idx DefineType :: Sexp -> GenMod m Idx
DefineGlobal :: Sexp -> GenMod m Idx DefineGlobal :: Sexp -> GenMod m Idx
Declare :: Sexp -> GenMod m () Emit :: Sexp -> GenMod m ()
type instance DispatchOf GenMod = Dynamic type instance DispatchOf GenMod = Dynamic
@@ -137,12 +139,12 @@ defineType = send . DefineType
defineGlobal :: GenMod :> es => Sexp -> Eff es Idx defineGlobal :: GenMod :> es => Sexp -> Eff es Idx
defineGlobal = send . DefineGlobal defineGlobal = send . DefineGlobal
declare :: GenMod :> es => Sexp -> Eff es () emit :: GenMod :> es => List Sexp -> Eff es ()
declare = send . Declare emit = traverse_ (send . Emit)
appendAndIncrement appendAndIncrement
:: State GenModState :> es :: State GenModState :> es
=> LensLike' ((,) _) GenModState Natural => LensLike' ((,) Natural) GenModState Natural
-> Sexp -> Sexp
-> Eff es Idx -> Eff es Idx
appendAndIncrement l s = appendAndIncrement l s =
@@ -158,7 +160,7 @@ runGenMod =
_ (DefineFunction s) -> appendAndIncrement #funcs s _ (DefineFunction s) -> appendAndIncrement #funcs s
_ (DefineType s) -> appendAndIncrement #types s _ (DefineType s) -> appendAndIncrement #types s
_ (DefineGlobal s) -> appendAndIncrement #globals s _ (DefineGlobal s) -> appendAndIncrement #globals s
_ (Declare s) -> #mod . #inner <>= V.singleton s _ (Emit s) -> #mod . #inner <>= V.singleton s
execGenMod :: Eff (GenMod : es) a -> Eff es Module execGenMod :: Eff (GenMod : es) a -> Eff es Module
execGenMod = fmap snd . runGenMod execGenMod = fmap snd . runGenMod
@@ -197,3 +199,6 @@ expr = Gyehoek.Sexp.makeSxs
wat :: QuasiQuoter wat :: QuasiQuoter
wat = Gyehoek.Sexp.makeSx [|| id ||] wat = Gyehoek.Sexp.makeSx [|| id ||]
wats :: QuasiQuoter
wats = Gyehoek.Sexp.makeSxs [|| id ||]
+60 -68
View File
@@ -1,69 +1,61 @@
(module (module
(type $heap-object (sub (struct (field (mut i32))))) (import
(type $open-procedure (func (param i32))) "gyehoek"
(type $closure (sub $heap-object "write"
(struct (field (mut i32)) (func $gh-write (param (ref eq))))
(field (ref $open-procedure))))) (import
(type $cont-stack-type (array (mut (ref null $open-procedure)))) "gyehoek"
(type $arg-array-type (array (mut (ref null eq)))) "to-bool"
(global $cont-stack-top (mut i32) (i32.const 0)) (func $gh-to-bool (param (ref eq)) (result i32)))
(global $cont-stack (ref $cont-stack-type) (type $heap-object (sub (struct (field $hash (mut i32)))))
(i32.const 128) (type $cont-type (func (param i32)))
(array.new_default $cont-stack-type)) (type $cont-stack-type (array (mut (ref null $cont-type))))
(global $arg-array (ref $arg-array-type) (global $cont-stack-top (mut i32) (i32.const 0))
(i32.const 32) (global
(array.new_default $arg-array-type)) $cont-stack
(global (mut (ref null eq)) (ref.null eq)) (ref $cont-stack-type)
(elem declare funcref (ref.func 1)) (array.new_default $cont-stack-type (i32.const 128)))
(func (type $arg-array-type (array (mut (ref null eq))))
(param i32) (global
(result) $arg-array
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq)) (ref $arg-array-type)
(global.get 2) (array.new_default $arg-array-type (i32.const 32)))
(i32.const 0) (global $result (mut (ref null eq)) (ref.null eq))
(array.get 3) (func
ref.as_non_null $halt
(global.set 3)) (param i32)
(func (global.get $arg-array)
(param i32) (i32.const 0)
(result) (array.get $arg-array-type)
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq)) ref.as_non_null
(global.get 2) (global.set $result))
(i32.const 0) (func
(array.get 3) $scm-entry
ref.as_non_null (param i32)
(local.set 1) (local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
(global.get 2) (i32.const 3)
(i32.const 0) ref.i31
(local.get 1) (call $gh-to-bool)
(array.set 3) (if
(i32.const 1) (then
(global.get 1) (global.get $arg-array)
(global.get 0) (global.get 0)
(array.get 2) (i32.const 777)
ref.as_non_null (i32.const 1)
(global.get 0) i32.shl
(i32.const 1) ref.i31
i32.sub (array.set $arg-array-type)
(global.set 0) (return_call $halt (i32.const 1)))
(return_call_ref 1)) (else
(func (global.get $arg-array)
(param i32) (global.get 0)
(result) (i32.const 555)
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq)) (i32.const 1)
(ref.func 1) i32.shl
(local.set 1) ref.i31
(global.get 2) (array.set $arg-array-type)
(i32.const 0) (return_call $halt (i32.const 1)))))
(local.get 1) (func
(array.set 3) (export "main")
(return_call 1)) (call $scm-entry (i32.const 0))
(func (call $gh-write (ref.as_non_null (global.get $result)))))
(param)
(result (ref eq))
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
(i32.const 0)
(call 1)
(global.get 3)
ref.as_non_null)
(export "main" (func 3)))
+12 -8
View File
@@ -10,11 +10,13 @@ import Data.List (List)
import Data.Functor ((<&>)) import Data.Functor ((<&>))
import System.Directory import System.Directory
import Data.Function import Data.Function
import System.Environment.Blank (getEnvDefault)
disabled :: List String disabled :: List String
disabled = disabled =
[ "square" [ "square"
, "lambda"
] ]
main :: IO () main :: IO ()
@@ -26,8 +28,8 @@ goldenTests = do
let tests = all_cases let tests = all_cases
& filter (`notElem` disabled) & filter (`notElem` disabled)
& fmap ("golden"</>) & fmap ("golden"</>)
pure $ testGroup "golden" testGroup "golden" <$> sequenceA
[ watTests tests [ pure $ watTests tests
, executionTests tests , executionTests tests
] ]
@@ -43,15 +45,17 @@ watTests files =
(Driver.lower_e2e source) (Driver.lower_e2e source)
id id
executionTests :: List FilePath -> TestTree executionTests :: List FilePath -> IO TestTree
executionTests files = executionTests files = do
testGroup "execution" $ files <&> \test -> cmd <- getEnvDefault "GYEHOEK_RUNTIME"
"runtime/target/debug/gyehoek-runtime"
pure $ testGroup "execution" $ files <&> \test ->
let wat = test </> "out.wat" let wat = test </> "out.wat"
testname = takeFileName test testname = takeFileName test
resultfile = test </> "exec" resultfile = test </> "exec"
in goldenVsProg in goldenVsProg
testname testname
resultfile resultfile
"wasmtime" cmd
["--invoke", "main", wat] [wat]
"" "" -- stdin