From 68e4c15a4d7fc755e6ba52f814312f9da66d4007 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Tue, 12 Sep 2023 19:24:49 +0200 Subject: [PATCH] Add github actions Signed-off-by: Ryan Levick --- .github/workflows/main.yml | 28 ++++++++++++++++++++++++++++ src/command.rs | 11 ++++++----- src/command/parser.rs | 4 ++-- src/main.rs | 4 ++-- src/runtime.rs | 19 ++++++++++++++++++- src/wit.rs | 32 +++++++++++++++----------------- 6 files changed, 71 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..0c60602 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,28 @@ +name: Build and Test +on: + push: + branches: + - main + pull_request: {} + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout the source code + uses: actions/checkout@v2 + with: + fetch-depth: 1 + submodules: recursive + + - name: Installs nightly toolchain + run: | + rustup update nightly + rustup default nightly + + - name: Formatting check + run: cargo fmt --all -- --check + + - name: Run tests + run: cargo test --all + diff --git a/src/command.rs b/src/command.rs index 6b267b8..7b3109c 100644 --- a/src/command.rs +++ b/src/command.rs @@ -39,7 +39,7 @@ impl<'a> Cmd<'a> { pub fn run( self, runtime: &mut Runtime, - querier: &Querier, + querier: &mut Querier, scope: &mut HashMap, ) -> anyhow::Result { match self { @@ -143,6 +143,7 @@ impl<'a> Cmd<'a> { let adapter = std::fs::read(path).context("could not read path to adapter module")?; runtime.compose(&adapter)?; + *querier = Querier::from_bytes(runtime.component_bytes())?; } Cmd::BuiltIn { name: "link", args } => { let &[func_name, component] = args.as_slice() else { @@ -166,11 +167,11 @@ impl<'a> Cmd<'a> { } } -fn eval<'a>( +fn eval( runtime: &mut Runtime, querier: &Querier, scope: &HashMap, - expr: parser::Expr<'a>, + expr: parser::Expr<'_>, preferred_type: Option<&wit_parser::Type>, ) -> anyhow::Result { match expr { @@ -196,12 +197,12 @@ fn lookup_in_scope(scope: &HashMap, ident: &str) -> anyhow::Result< .cloned() } -fn call_func<'a>( +fn call_func( runtime: &mut Runtime, querier: &Querier, scope: &HashMap, name: &str, - args: Vec>, + args: Vec>, ) -> anyhow::Result> { log::debug!("Calling function: {name} with args: {args:?}"); let func_def = querier diff --git a/src/command/parser.rs b/src/command/parser.rs index 0001e92..6212092 100644 --- a/src/command/parser.rs +++ b/src/command/parser.rs @@ -75,14 +75,14 @@ impl<'a> Literal<'a> { } } -fn assignment<'a>(input: &'a str) -> nom::IResult<&str, (&str, Expr<'a>)> { +fn assignment(input: &str) -> nom::IResult<&str, (&str, Expr<'_>)> { let (rest, ident) = ident(input)?; let (rest, _) = delimited(multispace0, tag("="), multispace0)(rest)?; let (r, value) = cut(Expr::parse)(rest)?; Ok((r, (ident, value))) } -pub fn function_call<'a>(input: &'a str) -> nom::IResult<&str, (&str, Vec>)> { +pub fn function_call(input: &str) -> nom::IResult<&str, (&str, Vec>)> { let (rest, ident) = ident(input)?; let args = separated_list0(tag(","), Expr::parse); let (rest, args) = delimited(tag("("), args, tag(")"))(rest)?; diff --git a/src/main.rs b/src/main.rs index 43a9225..c8445f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ fn _main() -> anyhow::Result<()> { let cli = Cli::parse(); let component_bytes = std::fs::read(cli.component)?; - let querier = wit::Querier::from_bytes(&component_bytes)?; + let mut querier = wit::Querier::from_bytes(&component_bytes)?; let mut runtime = runtime::Runtime::init(component_bytes, &querier, |import_name| { print_error_prefix(); eprintln!("unimplemented import: {import_name}"); @@ -45,7 +45,7 @@ fn _main() -> anyhow::Result<()> { let line = command::Cmd::parse(&line); match line { Ok(cmd) => { - match cmd.run(&mut runtime, &querier, &mut scope) { + match cmd.run(&mut runtime, &mut querier, &mut scope) { Err(e) => { print_error_prefix(); eprintln!("{e}"); diff --git a/src/runtime.rs b/src/runtime.rs index 9c4bea0..1249b29 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -45,6 +45,19 @@ impl Runtime { Ok(()) })?; } + wit_parser::WorldItem::Interface(i) => { + let interface = querier.interface(*i).unwrap(); + let mut root = linker.root(); + let mut instance = root.instance(&import_name)?; + for (_, f) in interface.functions.iter() { + let stub_import = stub_import.clone(); + let import_name = import_name.clone(); + instance.func_new(&component, &f.name, move |_ctx, _args, _rets| { + stub_import(&import_name); + Ok(()) + })?; + } + } i => todo!("Implement import: {i:?}"), } } @@ -87,7 +100,7 @@ impl Runtime { /// This function does not check that the component in `components_bytes` has the /// export needed and that it doesn't have any non-wasi imports. pub fn stub_function(&mut self, name: String, component_bytes: &[u8]) -> anyhow::Result<()> { - let component = load_component(&self.engine, &component_bytes)?; + let component = load_component(&self.engine, component_bytes)?; let mut linker = Linker::::new(&self.engine); wasmtime_wasi::preview2::command::sync::add_to_linker(&mut linker)?; let instance = @@ -134,6 +147,10 @@ impl Runtime { self.set_component(bytes) } + pub fn component_bytes(&self) -> &[u8] { + &self.component.1 + } + /// Get a new instance pub fn refresh(&mut self) -> anyhow::Result<()> { self.store = build_store(&self.engine); diff --git a/src/wit.rs b/src/wit.rs index 1c72032..c6295d1 100644 --- a/src/wit.rs +++ b/src/wit.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use anyhow::Context; use wit_component::DecodedWasm; -use wit_parser::{Function, Resolve, World, WorldId, WorldItem, WorldKey}; +use wit_parser::{Function, InterfaceId, Resolve, World, WorldId, WorldItem, WorldKey}; pub struct Querier { resolve: Resolve, @@ -21,7 +21,7 @@ impl Querier { } pub fn from_bytes(component_bytes: &[u8]) -> anyhow::Result { - let (resolve, world) = match wit_component::decode(&component_bytes) + let (resolve, world) = match wit_component::decode(component_bytes) .context("could not decode given file as a WebAssembly component")? { DecodedWasm::Component(r, w) => (r, w), @@ -54,6 +54,10 @@ impl Querier { get_world_item_by_name(self.world().imports.iter(), name) } + pub fn interface(&self, id: InterfaceId) -> Option<&wit_parser::Interface> { + self.resolve.interfaces.get(id) + } + pub fn display_wit_type<'a>(&self, param_type: &wit_parser::Type) -> Cow<'a, str> { let str = match param_type { wit_parser::Type::Bool => "bool", @@ -87,7 +91,7 @@ impl Querier { match (ok, err) { (Some(ok), Some(err)) => format!("result<{ok}, {err}>"), (Some(t), _) | (_, Some(t)) => format!("result<{t}>"), - _ => format!("result"), + _ => "result".into(), } } wit_parser::TypeDefKind::Type(t) => return self.display_wit_type(t), @@ -132,22 +136,16 @@ impl Querier { .imports .iter() .filter_map(|(import_name, import)| { - let import_name = match import_name { - WorldKey::Name(n) => n.clone(), - WorldKey::Interface(i) => { - let interface = self.resolve.interfaces.get(*i).unwrap(); - match &interface.package { - Some(package_id) => { - let package = self.resolve.packages.get(*package_id).unwrap(); - if package.name.namespace == "wasi" { - return None; - } - format!("{}", package.name) - } - None => todo!(), + if let WorldKey::Interface(i) = import_name { + let interface = self.resolve.interfaces.get(*i).unwrap(); + if let Some(package_id) = &interface.package { + let package = self.resolve.packages.get(*package_id).unwrap(); + if package.name.namespace == "wasi" { + return None; } } - }; + } + let import_name = self.resolve.name_world_key(import_name); Some((import_name, import)) }) }