Skip to content

Commit

Permalink
Add importize method to Resolve
Browse files Browse the repository at this point in the history
A new method `importize` is added to the Resolve. This is to allow to
mutate the Resolve to state where it would resemble what a consuming
component would expect to see during composition.

Signed-off-by: karthik2804 <[email protected]>
  • Loading branch information
karthik2804 committed Sep 12, 2024
1 parent a21c5d0 commit 60b52a9
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 8 deletions.
50 changes: 50 additions & 0 deletions crates/wit-parser/src/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,56 @@ package {name} is defined in two different locations:\n\
Some(self.id_of_name(interface.package.unwrap(), interface.name.as_ref()?))
}

pub fn importize(&mut self, world_id: WorldId) {
let exports = &self.worlds[world_id].exports.clone();
// Make a copy of the imports as we will wholesale clear the imports in the world being importized
let ref_imports = mem::take(&mut self.worlds[world_id].imports);

let mut temp = Vec::new();

for (key, item) in exports.clone() {
match key {
WorldKey::Name(_) => {
temp.push((key, item));
}
WorldKey::Interface(id) => self.resolve_interface_deps(id, world_id, &ref_imports),
}
}
let world = &mut self.worlds[world_id];
world.imports.append(&mut world.exports);

for (key, item) in ref_imports {
if let WorldItem::Type(_) = item {
world.imports.insert(key, item);
}
}

for (key, item) in temp {
world.imports.insert(key, item);
}

world.exports.clear();
}

fn resolve_interface_deps(
&mut self,
interface_id: InterfaceId,
world_id: WorldId,
ref_imports: &IndexMap<WorldKey, WorldItem>,
) {
let direct_deps = self.interface_direct_deps(interface_id).collect::<Vec<_>>();
for dep_id in direct_deps {
let world_key = WorldKey::Interface(dep_id);
let world_item = ref_imports.get(&world_key).unwrap();

let world = &mut self.worlds[world_id];
if !world.imports.contains_key(&world_key) {
world.imports.insert(world_key, world_item.clone());
self.resolve_interface_deps(dep_id, world_id, ref_imports);
}
}
}

/// Returns the ID of the specified `name` within the `pkg`.
pub fn id_of_name(&self, pkg: PackageId, name: &str) -> String {
let package = &self.packages[pkg];
Expand Down
23 changes: 20 additions & 3 deletions src/bin/wasm-tools/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,16 @@ pub struct WitOpts {
)]
json: bool,

/// Importize the WIT document by removing the imports and
/// moving the exports of a component to be its imports.
#[clap(
long,
conflicts_with = "wasm",
conflicts_with = "wat",
conflicts_with = "json"
)]
importize: bool,

/// Features to enable when parsing the `wit` option.
///
/// This flag enables the `@unstable` feature in WIT documents where the
Expand Down Expand Up @@ -621,7 +631,13 @@ impl WitOpts {
fn emit_wit(&self, decoded: &DecodedWasm) -> Result<()> {
assert!(!self.wasm && !self.wat);

let resolve = decoded.resolve();
let mut resolve = decoded.resolve().clone();

let main = decoded.package();
if self.importize {
let world_id = resolve.select_world(main, None)?;
resolve.importize(world_id)
}

let mut printer = WitPrinter::default();
printer.emit_docs(!self.no_docs);
Expand All @@ -647,7 +663,7 @@ impl WitOpts {
let main = decoded.package();
for (id, pkg) in resolve.packages.iter() {
let is_main = id == main;
let output = printer.print(resolve, id, &[])?;
let output = printer.print(&resolve, id, &[])?;
let out_dir = if is_main {
dir.clone()
} else {
Expand Down Expand Up @@ -685,8 +701,9 @@ impl WitOpts {
self.output.output(
&self.general,
Output::Wit {
wit: &decoded,
printer,
resolve: &resolve,
package: main,
},
)?;
}
Expand Down
14 changes: 9 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ pub struct OutputArg {
pub enum Output<'a> {
#[cfg(feature = "component")]
Wit {
wit: &'a wit_component::DecodedWasm,
resolve: &'a wit_parser::Resolve,
package: wit_parser::PackageId,
printer: wit_component::WitPrinter,
},
Wasm(&'a [u8]),
Expand Down Expand Up @@ -236,15 +237,18 @@ impl OutputArg {
}
Output::Json(s) => self.output_str(s),
#[cfg(feature = "component")]
Output::Wit { wit, mut printer } => {
let resolve = wit.resolve();
Output::Wit {
mut printer,
resolve,
package,
} => {
let ids = resolve
.packages
.iter()
.map(|(id, _)| id)
.filter(|id| *id != wit.package())
.filter(|id| *id != package)
.collect::<Vec<_>>();
let output = printer.print(resolve, wit.package(), &ids)?;
let output = printer.print(resolve, package, &ids)?;
self.output_str(&output)
}
}
Expand Down
37 changes: 37 additions & 0 deletions tests/cli/importize-component.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// RUN: component embed --world foo --dummy % | component wit --importize

package importize:importize;

interface t {
resource r;
}
interface bar {
use t.{r};
record foo {
x: string
}
importize: func(name: r);
}

interface qux {
use bar.{foo};
blah: func(boo: foo);
}

interface something-else-dep {
type t = u32;
}

world foo {
export qux;
export foo: func();
type s = u32;
export bar: func() -> s;
export something: interface {
foo: func();
}
export something-else: interface {
use something-else-dep.{t};
bar: func() -> t;
}
}
60 changes: 60 additions & 0 deletions tests/cli/importize-component.wit.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package root:root;

world root {
import importize:importize/bar;
import importize:importize/t;
import foo: func();
import bar: func() -> s;
import importize:importize/qux;
import something: interface {
foo: func();
}
import something-else: interface {
use something-else-dep.{t};

bar: func() -> t;
}

type s = u32;
}
package importize:importize {
interface t {
resource r;
}
interface bar {
use t.{r};

record foo {
x: string,
}

importize: func(name: r);
}
interface something-else-dep {
type t = u32;
}
interface qux {
use bar.{foo};

blah: func(boo: foo);
}
world foo {
import t;
import bar;
import something-else-dep;

type s = u32;

export foo: func();
export bar: func() -> s;
export qux;
export something: interface {
foo: func();
}
export something-else: interface {
use something-else-dep.{t};

bar: func() -> t;
}
}
}

0 comments on commit 60b52a9

Please sign in to comment.