Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wit-encoder: Implement world uses and sort interface and world items, uses #1910

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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