Skip to content

Commit 2f9a7ff

Browse files
Implement resource exports + stubs
1 parent 3738327 commit 2f9a7ff

2 files changed

Lines changed: 83 additions & 45 deletions

File tree

crates/d/src/lib.rs

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -541,12 +541,15 @@ impl WorldGenerator for D {
541541
self.interface_exports.push(fqn.clone());
542542

543543
let wasm_import_module = resolve.name_world_key(name);
544+
let emit_exports_stubs = self.opts.emit_export_stubs;
545+
544546
let mut r#gen = self.interface(
545547
resolve,
546548
Some(Direction::Export),
547549
Some(name),
548550
Some(&wasm_import_module),
549551
);
552+
r#gen.fqn = &fqn;
550553
r#gen.interface = Some(id);
551554
r#gen.prologue();
552555

@@ -596,6 +599,16 @@ impl WorldGenerator for D {
596599
wasm_import_module, type_name
597600
));
598601

602+
if emit_exports_stubs {
603+
r#gen.stub_src.push_str(&format!(
604+
"@witExport(\"{}\", \"{}\")\nstruct {escaped_name}_STUB {{\n",
605+
wasm_import_module,
606+
ty.name.as_ref().unwrap()
607+
));
608+
609+
r#gen.stubs.push(escaped_name.to_owned() + "_STUB");
610+
}
611+
599612
for (_, func) in &resolve.interfaces[id].functions {
600613
match func.kind {
601614
FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {}
@@ -611,6 +624,10 @@ impl WorldGenerator for D {
611624
}
612625
}
613626
r#gen.src.push_str("}\n");
627+
628+
if emit_exports_stubs {
629+
r#gen.stub_src.push_str("}\n");
630+
}
614631
}
615632
_ => {}
616633
}
@@ -697,6 +714,7 @@ impl WorldGenerator for D {
697714
let wasm_import_module = resolve.name_world_key(&name);
698715
let mut r#gen =
699716
self.interface(resolve, None, Some(&name), Some(&wasm_import_module));
717+
r#gen.fqn = &fqn;
700718
r#gen.interface = Some(id);
701719
r#gen.prologue();
702720
r#gen.types(id);
@@ -941,16 +959,14 @@ impl<'a> DInterfaceGenerator<'a> {
941959
fn prologue(&mut self) {
942960
let id = self.interface.unwrap();
943961

944-
let fqn = self.r#gen.lookup_interface_fqn(id, self.direction).unwrap();
945-
946962
let interface = &self.resolve.interfaces[self.interface.unwrap()];
947963

948964
self.src.push_str(&format!(
949965
"/++\n{}\n+/\n",
950966
interface.docs.contents.as_deref().unwrap_or_default()
951967
));
952968

953-
self.src.push_str(&format!("module {};\n\n", fqn));
969+
self.src.push_str(&format!("module {};\n\n", self.fqn));
954970

955971
self.src.push_str("import wit.common;\n\n");
956972
if self.direction.is_some()
@@ -1226,14 +1242,9 @@ impl<'a> DInterfaceGenerator<'a> {
12261242
));
12271243

12281244
self.src.push_str(&format!(
1229-
"alias {}_Sig = {} {}({});\n",
1245+
"alias {}_Sig = {} function({});\n",
12301246
d_sig.name,
12311247
d_sig.result,
1232-
if d_sig.implicit_self {
1233-
"delegate"
1234-
} else {
1235-
"function"
1236-
},
12371248
d_sig
12381249
.arguments
12391250
.iter()
@@ -1243,10 +1254,11 @@ impl<'a> DInterfaceGenerator<'a> {
12431254
));
12441255

12451256
self.src.push_str(&format!(
1246-
"/// ditto\nalias {}_Impl = findWitExportFunc!(\"{}\", \"{}\", {0}_Sig, {});\n",
1257+
"/// ditto\nalias {}_Impl = findWitExportFunc!(\"{}\", \"{}\", {0}_Sig, {}, {});\n",
12471258
d_sig.name,
12481259
self.wasm_import_module.unwrap(),
12491260
func.name,
1261+
d_sig.implicit_self,
12501262
match &func.kind {
12511263
FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => "Impl",
12521264
_ => {
@@ -1257,9 +1269,15 @@ impl<'a> DInterfaceGenerator<'a> {
12571269

12581270
if self.r#gen.opts.emit_export_stubs {
12591271
self.stub_src.push_str(&format!(
1260-
"@witExport(\"{}\", \"{}\")\n{} {}_STUB({});\n",
1272+
"@witExport(\"{}\", \"{}\")\n",
12611273
self.wasm_import_module.unwrap(),
1262-
func.name,
1274+
func.name
1275+
));
1276+
if d_sig.static_member {
1277+
self.stub_src.push_str("static ");
1278+
}
1279+
self.stub_src.push_str(&format!(
1280+
"{} {}_STUB({});\n",
12631281
d_sig.result,
12641282
d_sig.name,
12651283
d_sig
@@ -1270,7 +1288,12 @@ impl<'a> DInterfaceGenerator<'a> {
12701288
.join(", ")
12711289
));
12721290

1273-
self.stubs.push(d_sig.name.clone() + "_STUB");
1291+
match func.kind {
1292+
FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
1293+
self.stubs.push(d_sig.name.clone() + "_STUB");
1294+
}
1295+
_ => {}
1296+
}
12741297
}
12751298

12761299
self.src.push_str("/// ditto\n");
@@ -1590,20 +1613,6 @@ impl<'a> InterfaceGenerator<'a> for DInterfaceGenerator<'a> {
15901613
"
15911614
));
15921615

1593-
/*for (_, func) in &self.resolve.interfaces[owner_id].functions {
1594-
if match &func.kind {
1595-
FunctionKind::Freestanding => false,
1596-
FunctionKind::Method(_) => false,
1597-
FunctionKind::Static(mid) => *mid == id,
1598-
FunctionKind::Constructor(mid) => *mid == id,
1599-
FunctionKind::AsyncFreestanding => false,
1600-
FunctionKind::AsyncMethod(_) => false,
1601-
FunctionKind::AsyncStatic(_) => todo!(),
1602-
} {
1603-
self.import_func(func);
1604-
}
1605-
}*/
1606-
16071616
self.src.push_str(&format!(
16081617
"struct Borrow {{
16091618
package(wit) void* __ptr = null;
@@ -1617,20 +1626,6 @@ impl<'a> InterfaceGenerator<'a> for DInterfaceGenerator<'a> {
16171626
"
16181627
));
16191628

1620-
/*for (_, func) in &self.resolve.interfaces[owner_id].functions {
1621-
if match &func.kind {
1622-
FunctionKind::Freestanding => false,
1623-
FunctionKind::Method(mid) => *mid == id,
1624-
FunctionKind::Static(_) => false,
1625-
FunctionKind::Constructor(_) => false,
1626-
FunctionKind::AsyncFreestanding => false,
1627-
FunctionKind::AsyncMethod(_) => todo!(),
1628-
FunctionKind::AsyncStatic(_) => false,
1629-
} {
1630-
self.import_func(func);
1631-
}
1632-
}*/
1633-
16341629
self.src.push_str("}\n");
16351630

16361631
self.src.push_str("}\n");
@@ -2829,7 +2824,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
28292824
}
28302825
FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
28312826
self.src.push_str(&format!(
2832-
"__traits(child, cast(_Resource_Impl*)self, {escaped_name})("
2827+
"__traits(child, cast(_Resource_Impl*)self, {escaped_name}_Impl)("
28332828
));
28342829
true
28352830
}

crates/d/src/wit_common.d

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,13 +255,13 @@ auto mallocSlice(T)(size_t count) {
255255
alias AliasSeq(T...) = T;
256256

257257

258-
template findWitExportFunc(string mod, string name, Sig, Impl...) {
258+
template findWitExportFunc(string mod, string name, Sig, bool implicitSelf, Impl...) {
259259
static foreach(Func; Impl) {
260260
static foreach(uda; __traits(getAttributes, Func)) {
261261
static if (!is(uda) && is(typeof(uda) == witExport) && uda == witExport(mod, name)) {
262262
static assert(
263263
!is(Func) &&
264-
(is(typeof(Func) == function) || is(typeof(Func) == delegate)),
264+
(is(typeof(Func) == function)),
265265
"The implementation of '", mod, "#", name, "' ",
266266
"`", __traits(fullyQualifiedName, findWitExportFunc), "` ",
267267
"must be a function or method."
@@ -284,11 +284,54 @@ template findWitExportFunc(string mod, string name, Sig, Impl...) {
284284
);
285285

286286
static assert(
287-
is(typeof(&findWitExportFunc) : Sig),
287+
is(typeof(&findWitExportFunc) : Sig) && __traits(isStaticFunction, findWitExportFunc) != implicitSelf,
288288
"The implementation of '", mod, "#", name, "' ",
289289
"`", __traits(fullyQualifiedName, findWitExportFunc), "` ",
290290
"must conform to the necessary signature. ",
291291
"Found `", typeof(&findWitExportFunc), "`",
292292
", but expected `", Sig, "`"
293293
);
294294
}
295+
296+
template findWitExportResource(string mod, string name, Impl...) {
297+
static foreach(Resource; Impl) {
298+
static foreach(uda; __traits(getAttributes, Resource)) {
299+
static if (!is(uda) && is(typeof(uda) == witExport) && uda == witExport(mod, name)) {
300+
static assert(
301+
is(Resource == struct),
302+
"The implementation of '", mod, "#", name, "' ",
303+
"`", __traits(fullyQualifiedName, findWitExportResource), "` ",
304+
"must be a struct."
305+
);
306+
307+
static assert(
308+
!is(typeof(findWitExportResource) == void) || __traits(isSame, findWitExportResource, Resource),
309+
"There must be only one implementation of '", mod, "#", name, "'. ",
310+
"Found at least `", __traits(fullyQualifiedName, findWitExportResource),
311+
"` and `", __traits(fullyQualifiedName, Resource), "`."
312+
);
313+
alias findWitExportResource = Resource;
314+
}
315+
}
316+
}
317+
318+
static assert(
319+
!is(typeof(findWitExportResource) == void),
320+
"Could not find implementation for '", mod, "#", name, "'"
321+
);
322+
}
323+
324+
325+
template witExportsIn(T) {
326+
alias witExportsIn = AliasSeq!();
327+
328+
static foreach(M; __traits(allMembers, T)) {
329+
static foreach(Export; __traits(getOverloads, T, M)) {
330+
static foreach(uda; __traits(getAttributes, Export)) {
331+
static if (!is(uda) && is(typeof(uda) == witExport)) {
332+
witExportsIn = AliasSeq!(witExportsIn, Export);
333+
}
334+
}
335+
}
336+
}
337+
}

0 commit comments

Comments
 (0)