Skip to content

Commit

Permalink
refactor(*): move anonymous type definition to core (#758)
Browse files Browse the repository at this point in the history
* refactor(*): move anonymous type definition to core

Signed-off-by: Jiaxiao Zhou (Mossaka) <duibao55328@gmail.com>

* refactor(*): define a new trait for anonymous types

Signed-off-by: Jiaxiao Zhou (Mossaka) <duibao55328@gmail.com>

* fixed the rebase problem in gen-c

Signed-off-by: Jiaxiao Zhou (Mossaka) <duibao55328@gmail.com>

* removed comments

Signed-off-by: Jiaxiao Zhou (Mossaka) <duibao55328@gmail.com>

---------

Signed-off-by: Jiaxiao Zhou (Mossaka) <duibao55328@gmail.com>
  • Loading branch information
Mossaka committed May 20, 2024
1 parent b342747 commit a955ee4
Show file tree
Hide file tree
Showing 3 changed files with 244 additions and 178 deletions.
190 changes: 105 additions & 85 deletions crates/c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::fmt::Write;
use std::mem;
use wit_bindgen_core::abi::{self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType};
use wit_bindgen_core::{
dealias, uwrite, uwriteln, wit_parser::*, Direction, Files, InterfaceGenerator as _, Ns,
WorldGenerator,
dealias, uwrite, uwriteln, wit_parser::*, AnonymousTypeGenerator, Direction, Files,
InterfaceGenerator as _, Ns, WorldGenerator,
};
use wit_component::StringEncoding;

Expand Down Expand Up @@ -1341,6 +1341,98 @@ void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
}
}

impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> {
fn resolve(&self) -> &'a Resolve {
self.resolve
}

fn anonymous_type_handle(&mut self, id: TypeId, handle: &Handle, docs: &Docs) {
self.src.h_defs("\ntypedef ");
let resource = match handle {
Handle::Borrow(id) | Handle::Own(id) => id,
};
let info = &self.gen.resources[&dealias(self.resolve, *resource)];
match handle {
Handle::Borrow(_) => self.src.h_defs(&info.borrow),
Handle::Own(_) => self.src.h_defs(&info.own),
}
self.src.h_defs(" ");
self.print_typedef_target(id);
}

fn anonymous_type_tuple(&mut self, id: TypeId, ty: &Tuple, docs: &Docs) {
self.src.h_defs("\ntypedef ");
self.src.h_defs("struct {\n");
for (i, t) in ty.types.iter().enumerate() {
let ty = self.gen.type_name(t);
uwriteln!(self.src.h_defs, "{ty} f{i};");
}
self.src.h_defs("}");
self.src.h_defs(" ");
self.print_typedef_target(id);
}

fn anonymous_type_option(&mut self, id: TypeId, ty: &Type, docs: &Docs) {
self.src.h_defs("\ntypedef ");
self.src.h_defs("struct {\n");
self.src.h_defs("bool is_some;\n");
let ty = self.gen.type_name(ty);
uwriteln!(self.src.h_defs, "{ty} val;");
self.src.h_defs("}");
self.src.h_defs(" ");
self.print_typedef_target(id);
}

fn anonymous_type_result(&mut self, id: TypeId, ty: &Result_, docs: &Docs) {
self.src.h_defs("\ntypedef ");
self.src.h_defs(
"struct {
bool is_err;
",
);
let ok_ty = ty.ok.as_ref();
let err_ty = ty.err.as_ref();
if ok_ty.is_some() || err_ty.is_some() {
self.src.h_defs("union {\n");
if let Some(ok) = ok_ty {
let ty = self.gen.type_name(ok);
uwriteln!(self.src.h_defs, "{ty} ok;");
}
if let Some(err) = err_ty {
let ty = self.gen.type_name(err);
uwriteln!(self.src.h_defs, "{ty} err;");
}
self.src.h_defs("} val;\n");
}
self.src.h_defs("}");
self.src.h_defs(" ");
self.print_typedef_target(id);
}

fn anonymous_type_list(&mut self, id: TypeId, ty: &Type, docs: &Docs) {
self.src.h_defs("\ntypedef ");
self.src.h_defs("struct {\n");
let ty = self.gen.type_name(ty);
uwriteln!(self.src.h_defs, "{ty} *ptr;");
self.src.h_defs("size_t len;\n");
self.src.h_defs("}");
self.src.h_defs(" ");
self.print_typedef_target(id);
}

fn anonymous_type_future(&mut self, id: TypeId, ty: &Option<Type>, docs: &Docs) {
todo!("print_anonymous_type for future");
}

fn anonymous_type_stream(&mut self, id: TypeId, ty: &Stream, docs: &Docs) {
todo!("print_anonymous_type for stream");
}

fn anonymous_typ_type(&mut self, id: TypeId, ty: &Type, docs: &Docs) {
todo!("print_anonymous_type for typ");
}
}

pub enum CTypeNameInfo<'a> {
Named { name: &'a str },
Anonymous { is_prim: bool },
Expand Down Expand Up @@ -1413,6 +1505,17 @@ impl InterfaceGenerator<'_> {
continue;
}

let kind = &self.resolve.types[ty].kind;
if let TypeDefKind::Handle(handle) = kind {
let resource = match handle {
Handle::Borrow(id) | Handle::Own(id) => id,
};
let origin = dealias(self.resolve, *resource);
if origin == *resource {
continue;
}
}

self.define_anonymous_type(ty)
}
}
Expand All @@ -1421,89 +1524,6 @@ impl InterfaceGenerator<'_> {
}
}

fn define_anonymous_type(&mut self, ty: TypeId) {
// skip `typedef handle_x handle_y` where `handle_x` is the same as `handle_y`
let kind = &self.resolve.types[ty].kind;
if let TypeDefKind::Handle(handle) = kind {
let resource = match handle {
Handle::Borrow(id) | Handle::Own(id) => id,
};
let origin = dealias(self.resolve, *resource);
if origin == *resource {
return;
}
}

self.src.h_defs("\ntypedef ");
let name = &self.gen.type_names[&ty];
match kind {
TypeDefKind::Type(_)
| TypeDefKind::Flags(_)
| TypeDefKind::Record(_)
| TypeDefKind::Resource
| TypeDefKind::Enum(_)
| TypeDefKind::Variant(_) => {
unreachable!()
}
TypeDefKind::Handle(handle) => {
let resource = match handle {
Handle::Borrow(id) | Handle::Own(id) => id,
};
let info = &self.gen.resources[&dealias(self.resolve, *resource)];
match handle {
Handle::Borrow(_) => self.src.h_defs(&info.borrow),
Handle::Own(_) => self.src.h_defs(&info.own),
}
}
TypeDefKind::Tuple(t) => {
self.src.h_defs(&format!("struct {name} {{\n"));
for (i, t) in t.types.iter().enumerate() {
let ty = self.gen.type_name(t);
uwriteln!(self.src.h_defs, "{ty} f{i};");
}
self.src.h_defs("}");
}
TypeDefKind::Option(t) => {
self.src.h_defs(&format!("struct {name} {{\n"));
self.src.h_defs("bool is_some;\n");
let ty = self.gen.type_name(t);
uwriteln!(self.src.h_defs, "{ty} val;");
self.src.h_defs("}");
}
TypeDefKind::Result(r) => {
self.src.h_defs(&format!("struct {name} {{\n"));
self.src.h_defs("bool is_err;\n");
let ok_ty = r.ok.as_ref();
let err_ty = r.err.as_ref();
if ok_ty.is_some() || err_ty.is_some() {
self.src.h_defs("union {\n");
if let Some(ok) = ok_ty {
let ty = self.gen.type_name(ok);
uwriteln!(self.src.h_defs, "{ty} ok;");
}
if let Some(err) = err_ty {
let ty = self.gen.type_name(err);
uwriteln!(self.src.h_defs, "{ty} err;");
}
self.src.h_defs("} val;\n");
}
self.src.h_defs("}");
}
TypeDefKind::List(t) => {
self.src.h_defs(&format!("struct {name} {{\n"));
let ty = self.gen.type_name(t);
uwriteln!(self.src.h_defs, "{ty} *ptr;");
self.src.h_defs("size_t len;\n");
self.src.h_defs("}");
}
TypeDefKind::Future(_) => todo!("print_anonymous_type for future"),
TypeDefKind::Stream(_) => todo!("print_anonymous_type for stream"),
TypeDefKind::Unknown => unreachable!(),
}
self.src.h_defs(" ");
self.print_typedef_target(ty);
}

fn define_dtor(&mut self, id: TypeId) {
let h_helpers_start = self.src.h_helpers.len();
let c_helpers_start = self.src.c_helpers.len();
Expand Down
36 changes: 35 additions & 1 deletion crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ pub trait InterfaceGenerator<'a> {
fn type_alias(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs);
fn type_list(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs);
fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs);

fn types(&mut self, iface: InterfaceId) {
let iface = &self.resolve().interfaces[iface];
for (name, id) in iface.types.iter() {
Expand Down Expand Up @@ -181,6 +180,41 @@ pub trait InterfaceGenerator<'a> {
}
}

pub trait AnonymousTypeGenerator<'a> {
fn resolve(&self) -> &'a Resolve;

fn anonymous_type_handle(&mut self, id: TypeId, handle: &Handle, docs: &Docs);
fn anonymous_type_tuple(&mut self, id: TypeId, ty: &Tuple, docs: &Docs);
fn anonymous_type_option(&mut self, id: TypeId, ty: &Type, docs: &Docs);
fn anonymous_type_result(&mut self, id: TypeId, ty: &Result_, docs: &Docs);
fn anonymous_type_list(&mut self, id: TypeId, ty: &Type, docs: &Docs);
fn anonymous_type_future(&mut self, id: TypeId, ty: &Option<Type>, docs: &Docs);
fn anonymous_type_stream(&mut self, id: TypeId, ty: &Stream, docs: &Docs);
fn anonymous_typ_type(&mut self, id: TypeId, ty: &Type, docs: &Docs);

fn define_anonymous_type(&mut self, id: TypeId) {
let ty = &self.resolve().types[id];
match &ty.kind {
TypeDefKind::Flags(_)
| TypeDefKind::Record(_)
| TypeDefKind::Resource
| TypeDefKind::Enum(_)
| TypeDefKind::Variant(_) => {
unreachable!()
}
TypeDefKind::Type(t) => self.anonymous_typ_type(id, t, &ty.docs),
TypeDefKind::Tuple(tuple) => self.anonymous_type_tuple(id, tuple, &ty.docs),
TypeDefKind::Option(t) => self.anonymous_type_option(id, t, &ty.docs),
TypeDefKind::Result(r) => self.anonymous_type_result(id, r, &ty.docs),
TypeDefKind::List(t) => self.anonymous_type_list(id, t, &ty.docs),
TypeDefKind::Future(f) => self.anonymous_type_future(id, f, &ty.docs),
TypeDefKind::Stream(s) => self.anonymous_type_stream(id, s, &ty.docs),
TypeDefKind::Handle(handle) => self.anonymous_type_handle(id, handle, &ty.docs),
TypeDefKind::Unknown => unreachable!(),
}
}
}

pub fn generated_preamble(src: &mut Source, version: &str) {
uwriteln!(src, "// Generated by `wit-bindgen` {version}. DO NOT EDIT!")
}
Expand Down

0 comments on commit a955ee4

Please sign in to comment.