Skip to content

Commit f0f625e

Browse files
committed
refactor(host): bind capabilities and async execution
1 parent 543f3cf commit f0f625e

33 files changed

Lines changed: 2840 additions & 572 deletions

Cargo.lock

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ name = "vm"
2727
[features]
2828
default = ["runtime", "cli", "cranelift-jit"]
2929
runtime = []
30+
async = ["runtime", "dep:tokio"]
3031
sqlite = ["runtime", "dep:rusqlite"]
3132
edge-abi = [
3233
"dep:edge_abi",
@@ -62,6 +63,7 @@ cranelift-module = { version = "0.129.1", optional = true }
6263
cranelift-native = { version = "0.129.1", optional = true }
6364
pd-host-function = { path = "./pd-host-function", version = "0.1.0" }
6465
rusqlite = { version = "0.32", default-features = false, features = ["bundled", "hooks", "limits"], optional = true }
66+
tokio = { version = "1", features = ["rt-multi-thread", "net", "time", "sync", "fs", "io-util", "process"], optional = true }
6567
edge_abi = { package = "pd-edge-abi", version = "0.1.1", default-features = false, optional = true }
6668
futures-channel = "0.3"
6769
paste = "1"

build.rs

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ struct CallableDecl {
115115
wrapper: Option<WrapperDecl>,
116116
host_binding_kind: HostBindingKind,
117117
host_execution: HostExecutionKind,
118+
runtime_owned_pending: bool,
118119
}
119120

120121
#[derive(Clone, Debug)]
@@ -243,10 +244,21 @@ fn write_generated_file(path: &Path, contents: &str) {
243244
fn builtin_source_specs(namespaces: &[NamespaceDecl]) -> Vec<SourceSpec> {
244245
namespaces
245246
.iter()
246-
.map(|namespace| SourceSpec {
247-
path: format!("src/builtins/runtime/{}.rs", namespace.module),
248-
module: namespace.module.clone(),
249-
category: SourceCategory::NamespacedBuiltin,
247+
.map(|namespace| {
248+
let path = if namespace.module == "io" {
249+
if cfg!(feature = "async") {
250+
"src/builtins/runtime/io/async_io.rs".to_string()
251+
} else {
252+
"src/builtins/runtime/io/blocking.rs".to_string()
253+
}
254+
} else {
255+
format!("src/builtins/runtime/{}.rs", namespace.module)
256+
};
257+
SourceSpec {
258+
path,
259+
module: namespace.module.clone(),
260+
category: SourceCategory::NamespacedBuiltin,
261+
}
250262
})
251263
.collect()
252264
}
@@ -268,6 +280,9 @@ fn parse_sources(
268280
}
269281

270282
pub(crate) fn classify_host_binding(function: &ItemFn) -> HostBindingKind {
283+
if function.sig.asyncness.is_some() {
284+
return HostBindingKind::StaticStack;
285+
}
271286
if function.sig.inputs.iter().any(|input| match input {
272287
FnArg::Typed(pat_type) => is_vm_context_type(&pat_type.ty),
273288
_ => false,
@@ -293,6 +308,9 @@ pub(crate) fn classify_host_binding(function: &ItemFn) -> HostBindingKind {
293308
}
294309

295310
pub(crate) fn infer_host_execution(function: &ItemFn) -> HostExecutionKind {
311+
if function.sig.asyncness.is_some() {
312+
return HostExecutionKind::MaySuspend;
313+
}
296314
let return_type = normalized_return_type(&function.sig.output);
297315
if contains_host_call_result(&return_type) {
298316
HostExecutionKind::MaySuspend
@@ -439,6 +457,8 @@ fn parse_source_file(path: &Path, spec: &SourceSpec, _order_offset: usize) -> Ve
439457
wrapper,
440458
host_binding_kind: classify_host_binding(function),
441459
host_execution: infer_host_execution(function),
460+
runtime_owned_pending: function.sig.asyncness.is_none()
461+
&& contains_host_call_result(&normalized_return_type(&function.sig.output)),
442462
});
443463
}
444464
out
@@ -1090,12 +1110,14 @@ fn render_builtin_runtime_dispatch(
10901110
)
10911111
.unwrap();
10921112
}
1093-
writeln!(
1094-
&mut out,
1095-
" registry.mark_runtime_owned_pending({:?});",
1096-
callable.name
1097-
)
1098-
.unwrap();
1113+
if callable.runtime_owned_pending {
1114+
writeln!(
1115+
&mut out,
1116+
" registry.mark_runtime_owned_pending({:?});",
1117+
callable.name
1118+
)
1119+
.unwrap();
1120+
}
10991121
}
11001122
writeln!(&mut out, "}}").unwrap();
11011123
writeln!(&mut out).unwrap();
@@ -1112,12 +1134,14 @@ fn render_builtin_runtime_dispatch(
11121134
.render_bind_static_call(&callable.name, &host_wrapper_adapter_name(callable));
11131135
writeln!(&mut out, " {:?} => {{", callable.name).unwrap();
11141136
writeln!(&mut out, " {bind_call}").unwrap();
1115-
writeln!(
1116-
&mut out,
1117-
" vm.mark_runtime_owned_pending_binding({:?});",
1118-
callable.name
1119-
)
1120-
.unwrap();
1137+
if callable.runtime_owned_pending {
1138+
writeln!(
1139+
&mut out,
1140+
" vm.mark_runtime_owned_pending_binding({:?});",
1141+
callable.name
1142+
)
1143+
.unwrap();
1144+
}
11211145
writeln!(&mut out, " true").unwrap();
11221146
writeln!(&mut out, " }}").unwrap();
11231147
}
@@ -1886,6 +1910,9 @@ fn host_wrapper_adapter_name(callable: &CallableDecl) -> String {
18861910

18871911
fn generated_wrapper_decl(function: &ItemFn) -> WrapperDecl {
18881912
let mut params = Vec::new();
1913+
if function.sig.asyncness.is_some() {
1914+
params.push(WrapperParamKind::Vm);
1915+
}
18891916
for input in &function.sig.inputs {
18901917
let FnArg::Typed(pat_type) = input else {
18911918
panic!("methods are not supported in #[pd_host_function] declarations");
@@ -1912,6 +1939,13 @@ fn parse_callable_params(function: &ItemFn) -> Vec<CallableParamDecl> {
19121939
let FnArg::Typed(pat_type) = input else {
19131940
panic!("methods are not supported in #[pd_host_function] declarations");
19141941
};
1942+
if pat_type
1943+
.attrs
1944+
.iter()
1945+
.any(|attr| attr.path().is_ident("pd_host_context"))
1946+
{
1947+
return None;
1948+
}
19151949
if is_vm_context_type(&pat_type.ty) {
19161950
return None;
19171951
}
@@ -2078,7 +2112,7 @@ fn type_label(ty: &Type) -> String {
20782112
};
20792113
format!("{} | null", type_label(inner))
20802114
}
2081-
"VmResult" | "HostCallResult" => {
2115+
"VmResult" | "HostCallResult" | "HostFutureOutput" => {
20822116
let syn::PathArguments::AngleBracketed(args) = &segment.arguments else {
20832117
panic!("{ident}<T> requires one generic argument");
20842118
};

crates/rustscript/tests/alias_smoke.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#[cfg(feature = "sqlite")]
2+
use rustscript::SqliteHostExt;
3+
14
/// Verify that the `rustscript` alias crate re-exports the same API as `pd-vm`.
25
#[test]
36
fn alias_exports_compile_source() {

0 commit comments

Comments
 (0)