Skip to content

Commit

Permalink
wit-encoder: Implement world uses and sort interface and world items,…
Browse files Browse the repository at this point in the history
… uses (#1910)

* wit-encoder: implement world uses and sort interface and world items, uses

* update round trip test
  • Loading branch information
noise64 authored Nov 19, 2024
1 parent 09175fa commit 8f17e78
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 53 deletions.
88 changes: 65 additions & 23 deletions crates/wit-encoder/src/from_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,13 @@ impl<'a> Converter<'a> {
output.item(WorldItem::function_import(func));
}
}
wit_parser::WorldItem::Type(_) => {
todo!();
wit_parser::WorldItem::Type(type_id) => {
let (target, item, rename) = self.convert_world_item_type(package_id, *type_id);
output.use_type(target, item, rename)
}
}
}

for (key, item) in &world.exports {
match item {
wit_parser::WorldItem::Interface { id, .. } => {
Expand All @@ -110,15 +112,42 @@ impl<'a> Converter<'a> {
output.item(WorldItem::function_export(func));
}
}
wit_parser::WorldItem::Type(_) => {
todo!();
wit_parser::WorldItem::Type(type_id) => {
let (target, item, rename) = self.convert_world_item_type(package_id, *type_id);
output.use_type(target, item, rename)
}
}
}

output.uses_mut().sort();
output.items_mut().sort();

output
}

fn convert_world_item_type(
&self,
package_id: PackageId,
type_id: wit_parser::TypeId,
) -> (Ident, Ident, Option<Ident>) {
let type_def = self.resolve.types.get(type_id).unwrap();
let underlying_type_def = self.underlying_type_def(&type_def);
let interface_ident = self
.type_def_owner_interface_ident(package_id, underlying_type_def)
.expect("Type not part of an interface");
let local_type_name = type_def.name.clone().unwrap();
let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
if underlying_local_type_name == local_type_name {
(interface_ident, local_type_name.into(), None)
} else {
(
interface_ident,
underlying_local_type_name.into(),
Some(local_type_name.into()),
)
}
}

fn convert_interface(
&self,
package_id: PackageId,
Expand All @@ -140,31 +169,16 @@ impl<'a> Converter<'a> {
}
for (_, type_id) in &interface.types {
let type_def = self.resolve.types.get(*type_id).unwrap();

let underlying_type_def = match &type_def.kind {
wit_parser::TypeDefKind::Type(type_) => match &type_ {
wit_parser::Type::Id(type_id) => {
let type_def = self.resolve.types.get(*type_id).unwrap();
type_def
}
_ => type_def,
},
_ => type_def,
};
let underlying_type_def = self.underlying_type_def(&type_def);

if underlying_type_def.owner == owner {
if let Some(type_def) = self.convert_type_def(type_def, *type_id) {
output.item(InterfaceItem::TypeDef(type_def));
}
} else {
let interface_ident = match underlying_type_def.owner {
wit_parser::TypeOwner::Interface(id) => self.interface_ident(
package_id,
None,
self.resolve.interfaces.get(id).unwrap(),
),
_ => panic!("Type not part of an interface"),
};
let interface_ident = self
.type_def_owner_interface_ident(package_id, underlying_type_def)
.expect("Type not part of an interface");
let local_type_name = type_def.name.clone().unwrap();
let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
if underlying_local_type_name == local_type_name {
Expand All @@ -179,6 +193,9 @@ impl<'a> Converter<'a> {
}
}

output.uses_mut().sort();
output.items_mut().sort();

output
}

Expand Down Expand Up @@ -521,6 +538,31 @@ impl<'a> Converter<'a> {
},
}
}

fn underlying_type_def(&'a self, type_def: &'a wit_parser::TypeDef) -> &'a wit_parser::TypeDef {
match &type_def.kind {
wit_parser::TypeDefKind::Type(type_) => match &type_ {
wit_parser::Type::Id(type_id) => {
let type_def = self.resolve.types.get(*type_id).unwrap();
type_def
}
_ => type_def,
},
_ => type_def,
}
}

fn type_def_owner_interface_ident(
&self,
package_id: PackageId,
type_def: &wit_parser::TypeDef,
) -> Option<Ident> {
if let wit_parser::TypeOwner::Interface(id) = type_def.owner {
Some(self.interface_ident(package_id, None, self.resolve.interfaces.get(id).unwrap()))
} else {
None
}
}
}

fn clean_func_name(resource_name: &str, method_name: &str) -> String {
Expand Down
37 changes: 32 additions & 5 deletions crates/wit-encoder/src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ pub struct World {
/// The WIT identifier name of this world.
name: Ident,

/// Interface uses
uses: Vec<Use>,

/// All imported and exported items into this world.
items: Vec<WorldItem>,

Expand All @@ -21,6 +24,7 @@ impl World {
pub fn new(name: impl Into<Ident>) -> Self {
Self {
name: name.into(),
uses: vec![],
items: vec![],
docs: None,
}
Expand Down Expand Up @@ -69,8 +73,34 @@ impl World {
pub fn include(&mut self, include: Include) {
self.item(WorldItem::Include(include));
}

pub fn uses(&self) -> &[Use] {
&self.uses
}
pub fn uses_mut(&mut self) -> &mut [Use] {
&mut self.uses
}
pub fn use_(&mut self, use_: Use) {
self.item(WorldItem::Use(use_));
self.uses.push(use_);
}
pub fn use_type(
&mut self,
target: impl Into<Ident>,
item: impl Into<Ident>,
rename: Option<Ident>,
) {
let target = target.into();
let use_ = self.uses.iter_mut().find(|u| u.target() == &target);
match use_ {
Some(use_) => use_.item(item, rename),
None => {
self.use_({
let mut use_ = Use::new(target);
use_.item(item, rename);
use_
});
}
}
}

pub fn docs(&self) -> Option<&Docs> {
Expand Down Expand Up @@ -105,6 +135,7 @@ impl Render for World {
}
write!(f, "{}world {} {{\n", opts.spaces(), self.name)?;
let opts = &opts.indent();
self.uses.render(f, opts)?;
for item in &self.items {
match item {
WorldItem::InlineInterfaceImport(interface) => {
Expand Down Expand Up @@ -165,7 +196,6 @@ impl Render for World {
render_function(f, opts, function)?;
}
WorldItem::Include(include) => include.render(f, opts)?,
WorldItem::Use(use_) => use_.render(f, opts)?,
}
}
let opts = &opts.outdent();
Expand Down Expand Up @@ -198,9 +228,6 @@ pub enum WorldItem {

/// Include type
Include(Include),

/// Use
Use(Use),
}

impl WorldItem {
Expand Down
40 changes: 32 additions & 8 deletions crates/wit-encoder/tests/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ const MAIN_PACKAGE_SOURCE: &str = indoc::indoc! {"
use foo:dep-a/dep-a-interface-b.{ ra };
}
interface main-interface-b {}
interface main-interface-b {
record mb {
x: f32,
}
}
interface main-interface-c {}
Expand All @@ -19,14 +23,17 @@ const MAIN_PACKAGE_SOURCE: &str = indoc::indoc! {"
interface main-interface-e {}
world main-world-a {
use foo:dep-c/dep-c-interface-b.{ cb, cb as cbcb };
import foo:dep-c/dep-c-interface-a;
export foo:dep-c/dep-c-interface-b;
include foo:dep-c/dep-c-world-a;
use foo:dep-b/[email protected].{ bb, bb as bbbb };
import foo:dep-b/[email protected];
export foo:dep-b/[email protected];
include foo:dep-b/[email protected];
use main-interface-b.{ mb, mb as mbmb };
import main-interface-b;
export main-interface-a;
include main-world-b;
Expand All @@ -45,7 +52,11 @@ const MAIN_PACKAGE_RESOLVED_ENCODED: &str = indoc::indoc! {"
use foo:dep-a/dep-a-interface-b.{ ra };
}
interface main-interface-b {}
interface main-interface-b {
record mb {
x: f32,
}
}
interface main-interface-c {}
Expand All @@ -59,16 +70,21 @@ const MAIN_PACKAGE_RESOLVED_ENCODED: &str = indoc::indoc! {"
}
world main-world-a {
import foo:dep-c/dep-c-interface-a;
use foo:dep-b/[email protected].{ bb, bb as bbbb };
use foo:dep-c/dep-c-interface-b.{ cb, cb as cbcb };
use main-interface-b.{ mb, mb as mbmb };
import foo:dep-a/dep-a-interface-b;
import foo:dep-b/[email protected];
import main-interface-b;
import foo:dep-b/[email protected];
import foo:dep-c/dep-c-interface-a;
import foo:dep-c/dep-c-interface-b;
import foo:dep-c/dep-c-interface-c;
import main-interface-b;
import main-interface-d;
import foo:dep-a/dep-a-interface-b;
export foo:dep-c/dep-c-interface-b;
export foo:dep-b/[email protected];
export main-interface-a;
export foo:dep-c/dep-c-interface-b;
export foo:dep-c/dep-c-interface-d;
export main-interface-a;
export main-interface-d;
}
"};
Expand Down Expand Up @@ -96,6 +112,10 @@ const DEP_PACKAGE_B: &str = indoc::indoc! {"
interface dep-b-interface-b {
use foo:dep-c/dep-c-interface-a.{a};
record bb {
x: f32,
}
}
world dep-b-world-a {
Expand All @@ -115,7 +135,11 @@ const DEP_PACKAGE_C: &str = indoc::indoc! {"
}
}
interface dep-c-interface-b {}
interface dep-c-interface-b {
record cb {
x: f32,
}
}
interface dep-c-interface-c {}
Expand Down
Loading

0 comments on commit 8f17e78

Please sign in to comment.