This commit is contained in:
Graham Kelly 2024-08-11 20:39:53 -04:00
parent 828db2bef3
commit 28760e867e
12 changed files with 1017 additions and 238 deletions

5
Cargo.lock generated
View file

@ -626,6 +626,7 @@ version = "0.1.0"
dependencies = [
"hex",
"pit-core",
"pit-rust-guest",
"proc-macro2",
"quasiquote",
"quote",
@ -970,6 +971,10 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "tpit-rt"
version = "0.1.0"
[[package]]
name = "twox-hash"
version = "1.6.3"

View file

@ -1,5 +1,5 @@
[workspace]
members=[ "pit-basic","pit-core", "pit-patch", "pit-rust-externref", "pit-rust-generator", "pit-rust-guest", "pit-rust-host", "pit-rust-host-lib"]
members=[ "pit-basic","pit-core", "pit-patch", "pit-rust-externref", "pit-rust-generator", "pit-rust-guest", "pit-rust-host", "pit-rust-host-lib", "tpit-rt"]
resolver="2"
[workspace.dependencies]

View file

@ -67,6 +67,28 @@ const _: () = {
125u8,
0u8,
];
fn alloc<T>(m: &mut ::std::collections::BTreeMap<u32, T>, x: T) -> u32 {
let mut u = 0;
while m.contains_key(&u) {
u += 1;
}
m.insert(u, x);
return u;
}
#[derive(Default)]
struct TableCell {
all: std::cell::UnsafeCell<
::std::collections::BTreeMap<
u32,
Box<
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
>,
>,
>,
}
unsafe impl Send for TableCell {}
unsafe impl Sync for TableCell {}
static TABLE: ::std::sync::LazyLock<TableCell> = ::std::sync::LazyLock::new(|| TableCell::default());
impl R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5
for ::externref::Resource<
Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>,
@ -128,42 +150,23 @@ const _: () = {
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e.drop"]
extern "C" fn _drop(
a: *mut Box<
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
>,
) {
unsafe { Box::from_raw(a) };
extern "C" fn _drop(a: u32) {
unsafe { (&mut *(TABLE.all.get())).remove(&a) };
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/read8"]
extern "C" fn read8(
id: *mut Box<
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
>,
p0: u32,
) -> (u32) {
return unsafe { &mut *id }.read8(p0);
extern "C" fn read8(id: u32, p0: u32) -> (u32) {
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().read8(p0);
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/size"]
extern "C" fn size(
id: *mut Box<
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
>,
) -> (u32) {
return unsafe { &mut *id }.size();
extern "C" fn size(id: u32) -> (u32) {
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().size();
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/write8"]
extern "C" fn write8(
id: *mut Box<
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
>,
p0: u32,
p1: u32,
) -> () {
return unsafe { &mut *id }.write8(p0, p1);
extern "C" fn write8(id: u32, p0: u32, p1: u32) -> () {
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().write8(p0, p1);
}
impl From<Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>>
for ::externref::Resource<
@ -179,16 +182,14 @@ const _: () = {
extern "C" {
#[link_name = "~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e"]
fn _push(
a: *mut Box<
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
>,
a: u32,
) -> ::externref::Resource<
Box<
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
>,
>;
}
return unsafe { _push(Box::into_raw(Box::new(a))) };
return unsafe { _push(alloc(&mut *(TABLE.all.get()), a)) };
}
}
};

View file

@ -67,6 +67,28 @@ const _: () = {
125u8,
0u8,
];
fn alloc<T>(m: &mut ::std::collections::BTreeMap<u32, T>, x: T) -> u32 {
let mut u = 0;
while m.contains_key(&u) {
u += 1;
}
m.insert(u, x);
return u;
}
#[derive(Default)]
struct TableCell {
all: std::cell::UnsafeCell<
::std::collections::BTreeMap<
u32,
Box<
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
>,
>,
>,
}
unsafe impl Send for TableCell {}
unsafe impl Sync for TableCell {}
static TABLE: ::std::sync::LazyLock<TableCell> = ::std::sync::LazyLock::new(|| TableCell::default());
impl R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d
for ::externref::Resource<
Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>,
@ -128,42 +150,23 @@ const _: () = {
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9.drop"]
extern "C" fn _drop(
a: *mut Box<
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
>,
) {
unsafe { Box::from_raw(a) };
extern "C" fn _drop(a: u32) {
unsafe { (&mut *(TABLE.all.get())).remove(&a) };
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/read8"]
extern "C" fn read8(
id: *mut Box<
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
>,
p0: u64,
) -> (u32) {
return unsafe { &mut *id }.read8(p0);
extern "C" fn read8(id: u32, p0: u64) -> (u32) {
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().read8(p0);
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/size"]
extern "C" fn size(
id: *mut Box<
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
>,
) -> (u64) {
return unsafe { &mut *id }.size();
extern "C" fn size(id: u32) -> (u64) {
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().size();
}
#[::externref::externref(crate = ":: externref")]
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/write8"]
extern "C" fn write8(
id: *mut Box<
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
>,
p0: u64,
p1: u32,
) -> () {
return unsafe { &mut *id }.write8(p0, p1);
extern "C" fn write8(id: u32, p0: u64, p1: u32) -> () {
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().write8(p0, p1);
}
impl From<Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>>
for ::externref::Resource<
@ -179,16 +182,14 @@ const _: () = {
extern "C" {
#[link_name = "~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9"]
fn _push(
a: *mut Box<
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
>,
a: u32,
) -> ::externref::Resource<
Box<
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
>,
>;
}
return unsafe { _push(Box::into_raw(Box::new(a))) };
return unsafe { _push(alloc(&mut *(TABLE.all.get()), a)) };
}
}
};

View file

@ -1,10 +1,15 @@
use std::collections::BTreeMap;
use waffle::{
util::new_sig, BlockTarget, Func, FunctionBody, Import, ImportKind, Module, Operator,
SignatureData, Table, Type,
use std::{
collections::{BTreeMap, BTreeSet}, iter::once, mem::{replace, take}
};
use waffle_ast::{add_op, Builder, Expr};
use anyhow::Context;
use pit_core::{Arg, ResTy};
use waffle::{
util::new_sig, Block, BlockTarget, Export, ExportKind, Func, FuncDecl, FunctionBody, Import, ImportKind, Module, Operator, SignatureData, Table, TableData, Type, Value
};
use waffle_ast::{add_op, results_ref_2, Builder, Expr};
use crate::get_interfaces;
pub fn talloc(m: &mut Module, t: Table) -> anyhow::Result<Func> {
let e = m.tables[t].ty.clone();
@ -189,3 +194,409 @@ pub fn waffle_funcs(m: &mut Module, i: &pit_core::Interface) -> BTreeMap<String,
})
.collect();
}
pub fn shim(
retref: bool,
f: &mut FunctionBody,
mut k: Block,
r: &Arg,
mut v: Value,
talloc: Func,
tfree: Func,
table: Table,
) -> anyhow::Result<(Value, Block)> {
let Arg::Resource {
ty,
nullable,
take,
ann,
} = r
else {
return Ok((v, k));
};
let end = f.add_block();
let ep = f.add_blockparam(end, if retref { Type::ExternRef } else { Type::I32 });
// if *nullable {
let s = if retref {
let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 0 });
f.append_to_block(k, a);
let a = add_op(f, &[a, v], &[Type::I32], Operator::I32Eq);
f.append_to_block(k, a);
a
} else {
let a = add_op(f, &[v], &[Type::I32], Operator::RefIsNull);
f.append_to_block(k, a);
a
};
let n = f.add_block();
if retref {
let a = add_op(
f,
&[],
&[Type::ExternRef],
Operator::RefNull {
ty: Type::ExternRef,
},
);
f.append_to_block(n, a);
f.set_terminator(
n,
waffle::Terminator::Br {
target: BlockTarget {
block: end,
args: vec![a],
},
},
)
} else {
let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 0 });
f.append_to_block(n, a);
f.set_terminator(
n,
waffle::Terminator::Br {
target: BlockTarget {
block: end,
args: vec![a],
},
},
)
}
let kk = f.add_block();
f.set_terminator(
k,
waffle::Terminator::CondBr {
cond: s,
if_true: BlockTarget {
block: n,
args: vec![],
},
if_false: BlockTarget {
block: kk,
args: vec![],
},
},
);
k = kk;
if retref {
let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 1 });
f.append_to_block(k, a);
let a = add_op(f, &[v, a], &[Type::I32], Operator::I32Sub);
f.append_to_block(k, a);
v = a;
}
// }
match (take, retref) {
(true, true) => {
v = add_op(
f,
&[v],
&[Type::ExternRef],
Operator::Call {
function_index: tfree,
},
);
f.append_to_block(k, v);
}
(_, false) => {
v = add_op(
f,
&[v],
&[Type::I32],
Operator::Call {
function_index: talloc,
},
);
f.append_to_block(k, v);
}
(false, true) => {
v = add_op(
f,
&[v],
&[Type::ExternRef],
Operator::TableGet { table_index: table },
);
f.append_to_block(k, v);
}
}
if !retref {
let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 1 });
f.append_to_block(k, a);
let a = add_op(f, &[v, a], &[Type::I32], Operator::I32Add);
f.append_to_block(k, a);
v = a;
}
f.set_terminator(
k,
waffle::Terminator::Br {
target: BlockTarget {
block: end,
args: vec![v],
},
},
);
Ok((ep, end))
}
pub fn wrap(m: &mut Module) -> anyhow::Result<()> {
let t = m.tables.push(TableData{ty: Type::ExternRef, initial: 0, max: None, func_elements: None});
let talloc = talloc(m, t)?;
let tfree = tfree(m, t)?;
let is = get_interfaces(m)?.into_iter().collect::<BTreeSet<_>>();
for mut import in take(&mut m.imports) {
if import.module == "tpit" && import.name == "void" {
if let ImportKind::Func(f) = &mut import.kind {
let s = m.funcs[*f].sig();
let o = *f;
let mut b = FunctionBody::new(&m, s);
let e = b.entry;
let arg = b.blocks[b.entry].params[0].1;
let arg = add_op(
&mut b,
&[arg],
&[Type::ExternRef],
Operator::Call {
function_index: tfree,
},
);
b.append_to_block(e, arg);
b.set_terminator(e, waffle::Terminator::Return { values: vec![] });
m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b);
}
continue;
}
if import.module == "tpit" && import.name == "clone" {
if let ImportKind::Func(f) = &mut import.kind {
let s = m.funcs[*f].sig();
let o = *f;
let mut b = FunctionBody::new(&m, s);
let e = b.entry;
let arg = b.blocks[b.entry].params[0].1;
let arg = add_op(
&mut b,
&[arg],
&[Type::ExternRef],
Operator::TableGet { table_index: t },
);
b.append_to_block(e, arg);
b.set_terminator(
e,
waffle::Terminator::ReturnCall {
func: talloc,
args: vec![arg],
},
);
m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b);
}
continue;
}
if import.module == "tpit" && import.name == "drop" {
import.module = format!("pit");
let p = new_sig(
m,
SignatureData {
params: vec![Type::I32],
returns: vec![],
},
);
let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit")));
if let ImportKind::Func(f) = &mut import.kind {
let s = m.funcs[*f].sig();
let o = replace(f, p);
let mut b = FunctionBody::new(&m, s);
let e = b.entry;
let arg = b.blocks[b.entry].params[0].1;
let arg = add_op(
&mut b,
&[arg],
&[Type::ExternRef],
Operator::Call {
function_index: tfree,
},
);
b.append_to_block(e, arg);
b.set_terminator(
e,
waffle::Terminator::ReturnCall {
func: p,
args: vec![arg],
},
);
m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b);
}
}
m.imports.push(import);
}
for i in is {
let f = waffle_funcs(m, &i);
for mut import in take(&mut m.imports) {
if import.module == format!("tpit/{}", i.rid_str()) {
match import.name.strip_prefix("~") {
Some(a) => {
let p = new_sig(
m,
SignatureData {
params: vec![Type::I32],
returns: vec![Type::ExternRef],
},
);
let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit")));
if let ImportKind::Func(f) = &mut import.kind {
let s = m.funcs[*f].sig();
let o = replace(f, p);
let mut b = FunctionBody::new(&m, s);
let e = b.entry;
let arg = b.blocks[b.entry].params[0].1;
let arg = add_op(
&mut b,
&[arg],
&[Type::ExternRef],
Operator::Call { function_index: p },
);
b.append_to_block(e, arg);
b.set_terminator(
e,
waffle::Terminator::ReturnCall {
func: talloc,
args: vec![arg],
},
);
m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b);
}
}
None => {
let x = i
.methods
.get(&import.name)
.context("in getting the method")?;
let p = to_waffle_sig(m, x);
let p = m.signatures[p].clone();
let p = new_sig(
m,
SignatureData {
params: vec![Type::I32]
.into_iter()
.chain(p.params.into_iter().map(|a| {
if a == Type::ExternRef {
Type::I32
} else {
a
}
}))
.collect(),
returns: p
.returns
.into_iter()
.map(|a| if a == Type::ExternRef { Type::I32 } else { a })
.collect(),
},
);
let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit")));
if let ImportKind::Func(f) = &mut import.kind {
let s = m.funcs[*f].sig();
let o = replace(f, p);
let mut b = FunctionBody::new(&m, s);
let mut k = b.entry;
let args = b.blocks[b.entry]
.params
.iter()
.map(|a| a.1)
.collect::<Vec<_>>()
.into_iter()
.zip(once(Arg::Resource { ty: ResTy::This, nullable: false, take: false, ann: vec![] }).chain(x.params.iter().cloned()));
let mut v2 = vec![];
for (v, r) in args {
let a;
(a, k) = shim(false, &mut b, k, &r, v, talloc, tfree, t)?;
v2.push(a);
}
let rets = add_op(
&mut b,
&v2,
&m.signatures[m.funcs[p].sig()].returns,
Operator::Call { function_index: p },
);
b.append_to_block(k, rets);
let rets = results_ref_2(&mut b, rets);
let mut r2 = vec![];
for (v, r) in rets.iter().cloned().zip(x.rets.iter()) {
let a;
(a, k) = shim(true, &mut b, k, r, v, talloc, tfree, t)?;
r2.push(a);
}
b.set_terminator(k, waffle::Terminator::Return { values: r2 });
m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b);
}
}
}
import.module = format!("pit/{}", i.rid_str());
}
m.imports.push(import)
}
for mut export in take(&mut m.exports) {
if let Some(a) = export.name.strip_prefix(&format!("tpit/{}/~", i.rid_str())) {
let a = a.to_owned();
export.name = format!("pit/{}/~{a}", i.rid_str());
match a.split_once("/") {
None => {
let b = a.strip_suffix(".drop").context("in egtting the drop")?;
}
Some((a, b)) => {
let x = i.methods.get(b).context("in getting the method")?;
let p = to_waffle_sig(m, x);
let p = m.signatures[p].clone();
let p = new_sig(
m,
SignatureData {
params: vec![Type::I32]
.into_iter()
.chain(p.params.into_iter())
.collect(),
returns: p.returns.into_iter().collect(),
},
);
// let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit")));
if let ExportKind::Func(f) = &mut export.kind {
let s = m.funcs[*f].sig();
let p = *f;
let mut b = FunctionBody::new(&m, s);
let mut k = b.entry;
let args = b.blocks[b.entry]
.params
.iter()
.map(|a| a.1)
.collect::<Vec<_>>()
.into_iter()
.zip(once(Arg::I32).chain(x.params.iter().cloned()));
let mut v2 = vec![];
for (v, r) in args {
let a;
(a, k) = shim(true, &mut b, k, &r, v, talloc, tfree, t)?;
v2.push(a);
}
let rets = add_op(
&mut b,
&v2,
&m.signatures[m.funcs[p].sig()].returns,
Operator::Call { function_index: p },
);
b.append_to_block(k, rets);
let rets = results_ref_2(&mut b, rets);
let mut r2 = vec![];
for (v, r) in rets.iter().cloned().zip(x.rets.iter()) {
let a;
(a, k) = shim(false, &mut b, k, r, v, talloc, tfree, t)?;
r2.push(a);
}
b.set_terminator(k, waffle::Terminator::Return { values: r2 });
*f = m.funcs.push(FuncDecl::Body(s, format!("_pit"), b));
}
}
}
}
m.exports.push(export);
}
}
m.exports.push(Export{name: format!("tpit_alloc"),kind: ExportKind::Func(talloc)});
m.exports.push(Export{name: format!("tpit_free"),kind: ExportKind::Func(tfree)});
m.exports.push(Export{name: format!("tpit_table"),kind: ExportKind::Table(t)});
Ok(())
}

View file

@ -12,6 +12,7 @@ fn main() -> anyhow::Result<()>{
},
salt: std::env::var("PIT_SALT").unwrap_or(format!("")).into_bytes(),
tpit: false,
};
let v = pit_rust_guest::render(&x, &src);

View file

@ -2,48 +2,114 @@ use std::iter::once;
use pit_core::{Arg, Interface, ResTy, Sig};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use quasiquote::quasiquote;
use quote::{format_ident, quote};
use sha3::Digest;
use std::io::Write;
pub struct Opts{
pub struct Opts {
pub root: TokenStream,
pub salt: Vec<u8>
pub salt: Vec<u8>,
pub tpit: bool,
}
pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
pub fn render(opts: &Opts, i: &Interface) -> TokenStream {
let root = &opts.root;
let id = i.rid_str();
let mut ha = sha3::Sha3_256::default();
write!(ha,"~{}",id);
write!(ha, "~{}", id);
ha.write(&opts.salt);
let ha = hex::encode(ha.finalize());
let id2 = format_ident!("R{}",i.rid_str());
let internal = format_ident!("R{id}_utils");
let methods = i.methods.iter().map(|(a,b)|quasiquote! {
fn #{format_ident!("{a}")}#{render_sig(root,i,b,&quote! {&mut self})};
let id2 = format_ident!("R{}", i.rid_str());
let methods = i.methods.iter().map(|(a, b)| {
quasiquote! {
fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,&quote! {&mut self},false)};
}
});
let impl_dyns = i.methods.iter().map(|(a,b)|quasiquote! {
fn #{format_ident!("{a}")}#{render_sig(root,i,b,&quote! {&mut self})}{
let xref = if opts.tpit {
quote! {}
} else {
quasiquote!(
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
#[link(wasm_import_module = #{format!("pit/{}",i.rid_str())})]
extern "C"{
#[link_name = #a]
fn go #{render_sig(root, i,b, &quote! {this: &mut #root::externref::Resource<Box<dyn #id2>>})};
}
return unsafe{go(self,#{
let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}"));
quote! {
#(#params),*
)
};
let res = if opts.tpit {
quote! {
#root::tpit_rt::Tpit
}
} else {
quote! {
#root::externref::Resource
}
};
let rx = if opts.tpit {
quote! {
u32
}
} else {
quote! {
&mut #res<Box<dyn #id2>>
}
};
let t = if opts.tpit { "t" } else { "" };
let impl_dyns = i.methods.iter().map(|(a, b)| {
quasiquote! {
fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,&quote! {&mut self},false)}{
#xref
#[link(wasm_import_module = #{format!("{t}pit/{}",i.rid_str())})]
extern "C"{
#[link_name = #a]
fn go #{render_sig(opts,root, i,b, &quote! {this: #rx},true)};
}
})};
return unsafe{go(#{
if opts.tpit{
quote!{self.ptr()}
}else{
quote!{self}
}
},#{
let params = b.params.iter().enumerate().map(|(a,b)|{
let mut c = format_ident!("p{a}");
let mut c = quote!{
#c
};
if let Arg::Resource { ty, nullable, take, ann } = b{
if opts.tpit{
if !*take{
c = quote!{
#root::tpit_rt::Tpit::summon(&mut #c)
}
}
}
}
c
});
quote! {
#(#params),*
}
})};
}
}
});
let chains2 = i.methods.iter().map(|(a,b)|quasiquote! {
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
#[export_name = #{format!("pit/{id}/~{ha}/{a}")}]
extern "C" fn #{format_ident!("{a}")}#{render_sig(root,i,b,&quote! {id: *mut Box<dyn #id2>})}{
return unsafe{&mut *id}.#{format_ident!("{a}")}(#{
let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}"));
#xref
#[export_name = #{format!("{t}pit/{id}/~{ha}/{a}")}]
extern "C" fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,&quote! {id: u32},true)}{
return unsafe{&mut *(TABLE.all.get())}.get_mut(&id).unwrap().#{format_ident!("{a}")}(#{
let params = b.params.iter().enumerate().map(|(a,b)|{
let mut c = format_ident!("p{a}");
let mut c = quote!{
#c
};
if let Arg::Resource { ty, nullable, take, ann } = b{
if opts.tpit{
if !*take{
c = quote!{
#c.ptr()
}
}
}
}
c
});
quote! {
#(#params),*
}
@ -51,8 +117,13 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
}
});
let sb = i.to_string();
let sc = sb.as_bytes().iter().cloned().chain(once(0u8)).collect::<Vec<_>>();
quasiquote!{
let sc = sb
.as_bytes()
.iter()
.cloned()
.chain(once(0u8))
.collect::<Vec<_>>();
quasiquote! {
pub trait #id2{
#(#methods)*
}
@ -63,27 +134,42 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
[#(#sc),*]
}
};
impl #id2 for #root::externref::Resource<Box<dyn #id2>>{
fn alloc<T>(m: &mut ::std::collections::BTreeMap<u32,T>, x: T) -> u32{
let mut u = 0;
while m.contains_key(&u){
u += 1;
};
m.insert(u,x);
return u;
}
#[derive(Default)]
struct TableCell{
all: std::cell::UnsafeCell<::std::collections::BTreeMap<u32,Box<dyn #id2>>>
};
unsafe impl Send for TableCell{}
unsafe impl Sync for TableCell{}
static TABLE: ::std::sync::LazyLock<TableCell> = ::std::sync::LazyLock::new(||TableCell::default());
impl #id2 for #res<Box<dyn #id2>>{
#(#impl_dyns)*
}
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
#[export_name = #{format!("pit/{id}/~{ha}.drop")}]
extern "C" fn _drop(a: *mut Box<dyn #id2>){
#xref
#[export_name = #{format!("{t}pit/{id}/~{ha}.drop")}]
extern "C" fn _drop(a: u32){
unsafe{
Box::from_raw(a)
(&mut *(TABLE.all.get())).remove(&a)
};
}
#(#chains2)*
impl From<Box<dyn #id2>> for #root::externref::Resource<Box<dyn #id2>>{
impl From<Box<dyn #id2>> for #res<Box<dyn #id2>>{
fn from(a: Box<dyn #id2>) -> Self{
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
#xref
#[link(wasm_import_module = #{format!("pit/{}",i.rid_str())})]
extern "C"{
#[link_name = #{format!("~{ha}")}]
fn _push(a: *mut Box<dyn #id2>) -> #root::externref::Resource<Box<dyn #id2>>;
fn _push(a: u32) -> #res<Box<dyn #id2>>;
}
return unsafe{
_push(Box::into_raw(Box::new(a)))
_push(alloc(&mut *(TABLE.all.get()),a))
}
}
}
@ -98,16 +184,34 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
// }
}
}
pub fn render_sig(root: &TokenStream,base: &Interface, s: &Sig, self_: &TokenStream) -> TokenStream{
let params = s.params.iter().map(|a|render_ty(root,base,a)).enumerate().map(|(a,b)|quasiquote!(#{format_ident!("p{a}")} : #b));
pub fn render_sig(
opts: &Opts,
root: &TokenStream,
base: &Interface,
s: &Sig,
self_: &TokenStream,
ffi: bool,
) -> TokenStream {
let params = s
.params
.iter()
.map(|a| render_ty(opts, root, base, a, ffi))
.enumerate()
.map(|(a, b)| quasiquote!(#{format_ident!("p{a}")} : #b));
let params = once(self_).cloned().chain(params);
let rets = s.rets.iter().map(|a|render_ty(root,base,a));
let rets = s.rets.iter().map(|a| render_ty(opts, root, base, a, ffi));
quote! {
(#(#params),*) -> (#(#rets),*)
}
}
pub fn render_ty(root: &TokenStream,base:&Interface, p: &Arg) -> TokenStream{
match p{
pub fn render_ty(
opts: &Opts,
root: &TokenStream,
base: &Interface,
p: &Arg,
ffi: bool,
) -> TokenStream {
match p {
Arg::I32 => quote! {
u32
},
@ -120,30 +224,58 @@ pub fn render_ty(root: &TokenStream,base:&Interface, p: &Arg) -> TokenStream{
Arg::F64 => quote! {
f64
},
Arg::Resource{ty,nullable,take, ann } => {
let ty = match ty{
ResTy::Of(a) => quasiquote!{
#root::externref::Resource<Box<dyn #{format_ident!("R{}",hex::encode(a))}>>
},
ResTy::None => quote! {
#root::externref::Resource<()>
},
ResTy::This => quasiquote! {
#root::externref::Resource<Box<dyn #{format_ident!("R{}",base.rid_str())}>>
Arg::Resource {
ty,
nullable,
take,
ann,
} => {
if !opts.tpit {
let ty = match ty {
ResTy::Of(a) => quasiquote! {
#root::externref::Resource<Box<dyn #{format_ident!("R{}",hex::encode(a))}>>
},
ResTy::None => quote! {
#root::externref::Resource<()>
},
ResTy::This => quasiquote! {
#root::externref::Resource<Box<dyn #{format_ident!("R{}",base.rid_str())}>>
},
};
let ty = if *nullable {
quote! {Option<#ty>}
} else {
ty
};
let ty = if *take {
ty
} else {
quote! {&mut #ty}
};
ty
} else {
let ty = match ty {
ResTy::Of(a) => quasiquote! {
#root::tpit_rt::Tpit<Box<dyn #{format_ident!("R{}",hex::encode(a))}>>
},
ResTy::None => quote! {
#root::tpit_rt::Tpit<()>
},
ResTy::This => quasiquote! {
#root::tpit_rt::Tpit<Box<dyn #{format_ident!("R{}",base.rid_str())}>>
},
};
let mut ty = if *take {
ty
} else {
quote! {&mut #ty}
};
if *take && ffi {
ty = quote! {u32}
}
};
let ty = if *nullable{
quote! {Option<#ty>}
}else{
ty
};
let ty = if *take{
ty
}else{
quote! {&mut #ty}
};
ty
},
}
}
// Arg::Func(_) => todo!()
}
}

View file

@ -8,8 +8,7 @@ use std::{
use pit_core::{Arg, Interface};
use wasm_runtime_layer::{
backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports,
Instance, Module, StoreContext, StoreContextMut, Value, ValueType,
backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports, Instance, Module, Store, StoreContext, StoreContextMut, Value, ValueType
};
pub fn init<U: AsRef<Instance> + 'static, E: WasmEngine>(
l: &mut Imports,
@ -180,3 +179,26 @@ impl<U: 'static, E: wasm_runtime_layer::backend::WasmEngine> Wrapped<U,E> {
pub type RWrapped<U,E> = ::std::sync::Arc<Wrapped<U,E>>;
pub extern crate anyhow;
pub extern crate wasm_runtime_layer;
pub struct W<X,U: 'static,E: WasmEngine>{
pub r: X,
pub store: Arc<StoreCell<U,E>>
}
impl<U: 'static,E: WasmEngine,X: Clone> Clone for W<X,U,E>{
fn clone(&self) -> Self {
Self { r: self.r.clone(), store: self.store.clone() }
}
}
pub struct StoreCell<U,E: WasmEngine>{
pub wrapped: UnsafeCell<Store<U,E>>
}
unsafe impl<U: Send,E: Send + wasm_runtime_layer::backend::WasmEngine + wasm_runtime_layer::backend::WasmEngine> Send for StoreCell<U,E>{}
unsafe impl<U: Sync,E: Sync + wasm_runtime_layer::backend::WasmEngine + wasm_runtime_layer::backend::WasmEngine> Sync for StoreCell<U,E>{}
impl<U,E: WasmEngine> StoreCell<U,E>{
pub unsafe fn get(&self) -> StoreContextMut<'_,U,E>{
unsafe{
&mut *self.wrapped.get()
}.as_context_mut()
}
}

View file

@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
hex = "0.4.3"
pit-core = { version = "0.1.0", path = "../pit-core" }
pit-rust-guest = { version = "0.1.0", path = "../pit-rust-guest" }
proc-macro2 = "1.0.85"
quasiquote = "0.1.1"
quote = "1.0.36"

View file

@ -1,121 +1,247 @@
use std::iter::once;
use pit_core::{Arg, Interface, Sig};
use proc_macro2::TokenStream;
use pit_core::{Arg, Interface, ResTy, Sig};
use proc_macro2::{Span, TokenStream};
use quasiquote::quasiquote;
use quote::{format_ident, quote, ToTokens};
use syn::{spanned::Spanned, Ident, Index};
pub fn render(root: &TokenStream, i: &Interface) -> TokenStream {
let id = format_ident!("R{}", i.rid_str());
let internal = format_ident!("{id}_utils");
pub struct Opts {
pub guest: Option<pit_rust_guest::Opts>,
}
pub fn render(root: &TokenStream, i: &Interface, opts: &Opts) -> TokenStream {
let id = format_ident!("B{}", i.rid_str());
// let internal = format_ident!("{id}_utils");
let methods = i.methods.iter().map(|(a, b)| {
quasiquote! {
fn #{format_ident!("{a}")}#{render_sig(root,b,&quote! {&self})}
fn #{format_ident!("{a}")}#{render_sig(root,b,&quote! {&self},quote!{
ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>
})}
}
});
let impls = i.methods.iter().map(|(a, b)| {
let init = b.params.iter().enumerate().map(|(pi,a)|render_new_val(root, a, quasiquote!{#{format_ident!("p{pi}")}}));
let init = once(quote!{#root::wasm_runtime_layer::Value::I32(self.base as i32)}).chain(init);
let fini = b.rets.iter().enumerate().map(|(ri,r)|{
quasiquote!{
let impls = i.methods.iter().enumerate().map(|(c, (a, b))| {
let init = b
.params
.iter()
.enumerate()
.map(|(pi, a)| render_new_val(root, a, quasiquote! {#{format_ident!("p{pi}")}}));
let init =
once(quote! {#root::wasm_runtime_layer::Value::I32(self.base as i32)}).chain(init);
let fini = b.rets.iter().enumerate().map(|(ri, r)| {
quasiquote! {
#{render_base_val(root, r, quote! {&rets[#ri]})}
}
});
quasiquote! {
fn #{format_ident!("{a}")}#{render_sig(root,b,&quote! {&self})}{
let Some(#root::wasm_runtime_layer::Export::Func(f)) = self.instance.get_export(unsafe{
&*::std::cell::UnsafeCell::raw_get(self.ctx)
},#{format_ident!("pit/{}/{}",i.rid_str(),a)}) else{
panic!("invalid func")
};
fn #{format_ident!("{a}")}#{render_sig(root,b,&quote! {&self},quote!{
ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>
})}{
let a = self.all[#{c+1}].clone();
let args = vec![#(#init),*];
let mut rets = vec![#root::wasm_runtime_layer::Value::I32(0);#{b.rets.len()}];
f.call(unsafe{
&mut *::std::cell::UnsafeCell::raw_get(self.ctx)
},&args,&mut rets)?;
let mut rets = a(ctx,args);
return Ok((#(#fini),*))
}
}
});
let injects = i.methods.iter().map(|(a,b)|{
let init = b.params.iter().enumerate().map(|(pi,a)|quasiquote!{let #{format_ident!("p{pi}")} = #{render_base_val(root, a, quote! {&args[#pi + 1]})}});
let init = b.params.iter().enumerate().map(|(pi,a)|quasiquote!{#{render_base_val(root, a, quote! {&args[#pi + 1]})}});
let fini = b.rets.iter().enumerate().map(|(ri,r)|{
quasiquote!{
rets[#ri] = #{render_new_val(root, r, quasiquote! {r . #{Index{index: ri as u32,span: root.span()}}})}
#{render_new_val(root, r, quasiquote! {r . #{Index{index: ri as u32,span: root.span()}}})}
}
});
quasiquote!{
let f = #root::wasm_runtime_layer::Func::new(ctx,#{render_blit_sig(root, b)},|ctx,args,rets|{
#(#init),*
let #root::wasm_runtime_layer::Value::ExternRef(t) = &args[0] else{
#root::anyhow::bail!("invalid param")
}
let r = match t.downcast::<'_,'_, ::std::sync::Arc<dyn #id<U,E>>,U,E>(ctx){
Ok(t) => {
t.#{format_ident!("{a}")}(#{
let p = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}"));
quote! {
#(#p .clone()),*
}
})?
},
Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped<U,E>>,U,E>(ctx)?{
Ok(t) => {
t.#{format_ident!("{a}")}(#{
let p = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}"));
quote! {
#(#p .clone()),*
}
})?
},
Err(_) => #root::anyhow::bail!("invalid externref")
}
};
#(#fini),*
Ok(())
});
i.define(#{format!("pit/{}",i.rid_str())},#a,f);
}}).chain(once( quasiquote!{
let f = #root::wasm_runtime_layer::Func::new(ctx,#root::wasm_runtime_layer::FuncType::new([#root::wasm_runtime_layer::ValueType::I32],[#root::wasm_runtime_layer::ExternType]),|ctx,args,rets|{
let #root::wasm_runtime_layer::Value::I32(i) = &args[0] else{
unreachable!()
};
let n = ctx.data().as_ref().clone();
let v = #root::Wrapped::new(*i as u32,#{i.rid_str()},ctx.as_context_mut(),n);
// let v: ::std::sync::Arc<dyn #id<U,E>> = ::std::sync::Arc::new(v);
rets[0] = #root::wasm_runtime_layer::Value::ExternRef(#root::wasm_runtime_layer::ExternRef::new(ctx,v));
Ok(())
});
i.define(#{format!("pit/{}",i.rid_str())},"~push",f);
}));
let r = a.clone();
Arc::new(ctx,move|ctx,args|{
let r = r.#{format_ident!("{a}")}(ctx,#(#init),*)
Ok(vec![#(#fini),*])
})
}});
quasiquote! {
pub trait #id<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine>{
fn to_any(&self) -> &dyn ::std::any::Any;
#(#methods)*
unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>;
}
mod #internal{
use super::#id;
const _: () = {
impl<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine> #id<U,E> for #root::RWrapped<U,E>{
fn to_any(&self) -> &dyn ::std::any::Any{
return self;
}
#(#impls)*
unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>{
self.all[0](ctx,vec![])?;
Ok(())
}
}
impl<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine> From<Arc<dyn $id<U,E>> for #root::RWrapped<U,E>{
fn from(a: Arc<dyn $id<U,E>>) -> Self{
Self{
rid: Arc::new(#root::pit_core::Interface::parse_interface(#{i.to_string()}).ok().unwrap()),
all: vec![#{
let all = once(quasiquote!{
let r = a.clone();
unsafe{
Arc::new(move|ctx,args|{r.finalize(ctx);Ok(vec![])})
}
}).chain(injects);
fn inject<U: 'static + AsRef<#root::wasm_runtime_layer::Instance>,E: #root::wasm_runtime_layer::backend::WasmEngine>(ctx: impl #root::wasm_runtime_layer::AsContextMut<UserState = U,Engine = E>, i: &mut #root::wasm_runtime_layer::Imports){
#(#injects)*
quote!{
#(#all),*
}
}]
}
}
}
#{match opts.guest.as_ref(){
None=>quote!{},
Some(g) => proxy(root,i,opts,g),
}}
}
}
}
pub fn proxy(root: &TokenStream, i: &Interface, opts: &Opts, g: &pit_rust_guest::Opts) -> TokenStream{
let id = format_ident!("B{}", i.rid_str());
let pid = format_ident!("R{}", i.rid_str());
let root2 = &g.root;
let res = if g.tpit {
quote! {
#root2::tpit_rt::Tpit
}
} else {
quote! {
#root2::externref::Resource
}
};
let impl_guest = i.methods.iter().map(|(a, b)| {
quasiquote! {
fn #{format_ident!("{a}")}#{pit_rust_guest::render_sig(g,root,i,b,&quote! {&mut self},false)}{
let ctx = unsafe{
self.get()
};
let r = self.r.#{format_ident!("{a}")}(ctx,#{
let params = b.params.iter().enumerate().map(|(a,b)|{
let mut c = format_ident!("p{a}");
let mut c = quote!{
#c
};
if let Arg::Resource { ty, nullable, take, ann } = b{
c = quote!{Box::new(#root::W{
r: #root::RWrapped<U,E>::from(Arc::new(#c)),
store: self.store.clone()
}).into()};
if !take{
c = quote!{&mut #c};
};
}
c
});
quote! {
#(#params),*
}
}).unwrap();
return (#{
let xs = b.rets.iter().enumerate().map(|(a,b)|{
let mut c = Index{
index: a as u32,
span: Span::call_site()
};
let mut c = quote!{
r.#c
};
if let Arg::Resource { ty, nullable, take, ann } = b{
c = quote!{
#root::RWrapped<U,E>::from(Compat(::std::cell::UnsafeCell::new(Some(#c))))
}
}
c
});
quote!{
#(#xs),*
}
})
};
}
});
let impl_host = i.methods.iter().enumerate().map(|(c, (a, b))| {
let params = b.params.iter().enumerate().map(|(a,b)|{
let mut c = format_ident!("p{a}");
let mut c = quote!{
#c
};
if let Arg::Resource { ty, nullable, take, ann } = b{
c = quote!{
#root::RWrapped<U,E>::from(Compat(::std::cell::UnsafeCell::new(Some(#c))))
};
if !take{
c = quote!{&mut #c};
};
}
c
});
let rets = b.rets.iter().enumerate().map(|(a,b)|{
let mut c = Index{
index: a as u32,
span: Span::call_site()
};
let mut c = quote!{
r.#c
};
if let Arg::Resource { ty, nullable, take, ann } = b{
c = quote!{Box::new(#root::W{
r: #root::RWrapped<U,E>::from(Arc::new(#c)),
store: Arc::new(#root::StoreCell{
wrapped: ::std::cell::UnsafeCell::new(#root::wasm_runtime_layer::Store::new(ctx.engine(),ctx.data().clone()))
})
}).into()};
}
c
});
quasiquote! {
fn #{format_ident!("{a}")}#{render_sig(root,b,&quote! {&self},quote!{
ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>
})}{
let x = unsafe{
&mut *(self.0.get())
}.as_mut().unwrap().#{format_ident!("{a}")}(#(#params),*);
Ok((#(#rets),*))
}
}
});
quasiquote!{
struct Compat<T>(::std::cell::UnsafeCell<Option<T>>);
impl<U: 'static + Clone,E: #root::wasm_runtime_layer::backend::WasmEngine> #pid for #root::W<#root::RWrapped<U,E>,U,E>{
#(#impl_guest)*
}
impl<U: 'static + Clone,E: #root::wasm_runtime_layer::backend::WasmEngine, X: #pid> #id<U,E> for Compat<X>{
#(#impl_host)*
unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>{
let x = unsafe{
&mut *(self.0.get())
}.take();
let Some(x) = x else{
return Err(#root::anyhow::anyhow!("double finalized"))
}
Ok(())
}
}
impl From<Box<dyn #pid>> for Arc<dyn #id>{
fn from(p: Box<dyn #pid>) -> Self{
return Arc::new(Compat(::std::cell::UnsafeCell::new(Some(#res::from(p)))))
}
}
}
}
pub fn render_sig(root: &TokenStream, s: &Sig, self_: &TokenStream) -> TokenStream {
pub fn render_sig(
root: &TokenStream,
s: &Sig,
self_: &TokenStream,
s2: TokenStream,
) -> TokenStream {
let params = s
.params
.iter()
.map(|a| render_ty(root, a))
.enumerate()
.map(|(a, b)| quasiquote!(#{format_ident!("p{a}")} : #b));
let params = once(self_).cloned().chain(params);
let params = once(self_).cloned().chain(once(s2)).chain(params);
let rets = s.rets.iter().map(|a| render_ty(root, a));
quote! {
(#(#params),*) -> #root::anyhow::Result<(#(#rets),*)>
@ -168,13 +294,18 @@ pub fn render_ty(root: &TokenStream, p: &Arg) -> TokenStream {
Arg::F64 => quote! {
f64
},
Arg::Resource { ty, nullable } => match ty {
None => quote! {
Arg::Resource {
ty,
nullable,
take,
ann,
} => match ty {
ResTy::None => quote! {
#root::wasm_runtime_layer::ExternRef
},
Some(a) => {
_ => {
let a = quasiquote! {
::std::sync::Arc<dyn #{format_ident!("R{}",hex::encode(a))}<U,E>>
::std::sync::Arc<#root::Wrapped<U,E>>
};
if *nullable {
quote! {Option<#a>}
@ -207,21 +338,24 @@ pub fn render_base_val(root: &TokenStream, p: &Arg, x: TokenStream) -> TokenStre
#root::anyhow::bail!("invalid param")
}
},
Arg::Resource { ty, nullable } => {
Arg::Resource {
ty,
nullable,
take,
ann,
} => {
let mut a = quote! {
let #root::wasm_runtime_layer::Value::ExternRef(t) = #x else{
#root::anyhow::bail!("invalid param")
}
};
if let Some(r) = ty.as_ref() {
if !matches!(ty, ResTy::None) {
quasiquote!{
let t = match t{None => None,Some(t) => Some(match t.downcast::<'_,'_, ::std::sync::Arc<dyn #{format_ident!("R{}",hex::encode(r))}<U,E>>,U,E>(ctx){
Ok(t) => t.clone(),
Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped<U,E>>,U,E>(ctx){
let t = match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped<U,E>>,U,E>(ctx){
Ok(t) => Arc::new(t.clone()),
Err(_) => #root::anyhow::bail!("invalid param")
}
})}
}.to_tokens(&mut a);
}
if !*nullable {
@ -256,33 +390,40 @@ pub fn render_new_val(root: &TokenStream, p: &Arg, t: TokenStream) -> TokenStrea
Arg::F64 => quote! {
#root::wasm_runtime_layer::Value::F64(#t)
},
Arg::Resource { ty, nullable } => {
let tq = |t:TokenStream|quasiquote! {
{
let t = #t;
#{match ty{
None => quote! { #root::wasm_runtime_layer::ExternRef::new(ctx,t)},
Some(_) => quote! {
match t.to_any().downcast_ref::<::std::sync::Arc<#root::Wrapped<U,E>>>(){
None => #root::wasm_runtime_layer::ExternRef::new(ctx,t),
Some(t) => #root::wasm_runtime_layer::ExternRef::new(ctx,t.clone()),
Arg::Resource {
ty,
nullable,
take,
ann,
} => {
let tq = |t: TokenStream| {
quasiquote! {
{
let t = #t;
#{match ty{
ResTy::None => quote! { #root::wasm_runtime_layer::ExternRef::new(ctx,t)},
_ => quote! {
match t.to_any().downcast_ref::<::std::sync::Arc<#root::Wrapped<U,E>>>(){
None => #root::wasm_runtime_layer::ExternRef::new(ctx,t),
Some(t) => #root::wasm_runtime_layer::ExternRef::new(ctx,t.clone()),
}
}
}
}}
}}
}
}
};
if !*nullable {
quasiquote! {
#root::wasm_runtime_layer::Value::ExternRef(Some(#{match ty{
None => t,
Some(_) => tq(t)
ResTy::None => t,
_ => tq(t)
}}))
}
} else {
quasiquote! {
#root::wasm_runtime_layer::Value::ExternRef(#{match ty{
None => t,
Some(_) => quasiquote! {#t.map(|t|#{tq(quote! {t})})}
ResTy::None => t,
_ => quasiquote! {#t.map(|t|#{tq(quote! {t})})}
}})
}
}

6
tpit-rt/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "tpit-rt"
version = "0.1.0"
edition = "2021"
[dependencies]

58
tpit-rt/src/lib.rs Normal file
View file

@ -0,0 +1,58 @@
use std::{
marker::PhantomData,
mem::forget,
num::NonZeroU32,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
};
#[repr(transparent)]
pub struct Tpit<D> {
ptr: Option<NonZeroU32>,
phantom: PhantomData<D>,
}
impl<D> Drop for Tpit<D> {
fn drop(&mut self) {
#[link(wasm_import_module = "tpit")]
extern "C" {
fn drop(a: u32);
fn void(a: u32);
}
if let Some(p) = self.ptr {
unsafe {
drop(p.into());
}
}
}
}
impl<D> Tpit<D> {
pub unsafe fn new(ptr: u32) -> Self {
Self {
ptr: NonZeroU32::new(ptr),
phantom: PhantomData,
}
}
pub fn ptr(&self) -> u32 {
match self.ptr {
Some(a) => {
let a: u32 = a.into();
a
}
None => 0,
}
}
pub unsafe fn cast<U>(self) -> Tpit<U> {
unsafe { Tpit::<U>::new(self.forget_to_ptr()) }
}
pub fn forget_to_ptr(self) -> u32 {
let x = self.ptr();
forget(self);
return x;
}
pub unsafe fn summon(a: &mut u32) -> &mut Self {
unsafe { std::mem::transmute(a) }
}
}