Skip to content

Commit

Permalink
Move to new module
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Levick <[email protected]>
  • Loading branch information
rylev committed Mar 12, 2024
1 parent c8f058b commit 4a590ff
Show file tree
Hide file tree
Showing 7 changed files with 689 additions and 1,175 deletions.
143 changes: 78 additions & 65 deletions src/command.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod alt_parser;
pub mod parser;
mod tokenizer;
use std::collections::HashMap;
Expand All @@ -7,7 +6,7 @@ use anyhow::{bail, Context as _};
use colored::Colorize;
use wasmtime::component::Val;

use self::alt_parser::ItemIdent;
use self::parser::ItemIdent;
use self::tokenizer::TokenKind;

use super::runtime::Runtime;
Expand All @@ -20,23 +19,22 @@ pub enum Cmd<'a> {
name: &'a str,
args: Vec<tokenizer::Token<'a>>,
},
Eval(alt_parser::Expr<'a>),
Eval(parser::Expr<'a>),
Assign {
ident: &'a str,
value: alt_parser::Expr<'a>,
value: parser::Expr<'a>,
},
}

impl<'a> Cmd<'a> {
pub fn parse(input: &'a str) -> anyhow::Result<Option<Cmd<'a>>> {
let tokens = tokenizer::Token::tokenize(input)?;
let line = alt_parser::Line::parse(tokens)
.expect("TODO: using ? here leads to borrow checker errors");
let line = parser::Line::parse(tokens).map_err(|e| anyhow::anyhow!("{e}"))?;
log::debug!("Parsed line: {line:?}");
match line {
alt_parser::Line::Expr(expr) => Ok(Some(Cmd::Eval(expr))),
alt_parser::Line::Assignment(ident, value) => Ok(Some(Cmd::Assign { ident, value })),
alt_parser::Line::BuiltIn(builtin) => Ok(Some(Cmd::BuiltIn {
parser::Line::Expr(expr) => Ok(Some(Cmd::Eval(expr))),
parser::Line::Assignment(ident, value) => Ok(Some(Cmd::Assign { ident, value })),
parser::Line::BuiltIn(builtin) => Ok(Some(Cmd::BuiltIn {
name: builtin.name,
args: builtin.rest,
})),
Expand All @@ -49,25 +47,25 @@ impl<'a> Cmd<'a> {
pub fn run(
self,
runtime: &mut Runtime,
querier: &mut WorldResolver,
resolver: &mut WorldResolver,
scope: &mut HashMap<String, Val>,
) -> anyhow::Result<bool> {
let mut eval = Evaluator::new(runtime, querier, scope);
let mut eval = Evaluator::new(runtime, resolver, scope);
match self {
Cmd::Eval(expr) => match expr {
alt_parser::Expr::Literal(l) => {
parser::Expr::Literal(l) => {
let val = eval.eval_literal(l, None)?;
println!("{}: {}", format_val(&val), val_as_type(&val));
}
alt_parser::Expr::Ident(ident) => match scope.get(ident) {
parser::Expr::Ident(ident) => match scope.get(ident) {
Some(val) => {
println!("{}: {}", format_val(val), val_as_type(val))
}
None => {
anyhow::bail!("no identifier '{ident}' in scope")
}
},
alt_parser::Expr::FunctionCall(func) => {
parser::Expr::FunctionCall(func) => {
let results = eval.call_func(func.ident, func.args)?;
println!(
"{}",
Expand All @@ -84,16 +82,19 @@ impl<'a> Cmd<'a> {
println!("{}: {}", ident, val_as_type(&val));
scope.insert(ident.into(), val);
}
Cmd::BuiltIn { name, args } if name == "exports" => {
Cmd::BuiltIn {
name: "exports",
args,
} => {
let &[] = args.as_slice() else {
bail!(
"wrong number of arguments to exports function. Expected 0 got {}",
args.len()
)
};
for (export_name, export) in querier.world().exports.iter() {
let export_name = querier.world_item_name(export_name);
if let Some(ty) = format_world_item(export, querier) {
for (export_name, export) in resolver.world().exports.iter() {
let export_name = resolver.world_item_name(export_name);
if let Some(ty) = format_world_item(export, resolver) {
println!("{}: {ty}", export_name.bold());
}
}
Expand All @@ -118,36 +119,42 @@ impl<'a> Cmd<'a> {
)
}
};
for (import_name, import) in querier.imports(include_wasi) {
let import_name = querier.world_item_name(import_name);
if let Some(ty) = format_world_item(import, querier) {
for (import_name, import) in resolver.imports(include_wasi) {
let import_name = resolver.world_item_name(import_name);
if let Some(ty) = format_world_item(import, resolver) {
println!("{}: {ty}", import_name.bold());
}
}
}
// Cmd::BuiltIn { name: "type", args } => {
// match args.as_slice() {
// &[name] => {
// let types = querier.types_by_name(&*name);
// for (interface, ty) in &types {
// let typ = querier.display_wit_type_def(ty, Expansion::Expanded(1));
// let name = &ty.name;
// let interface = interface.and_then(|i| querier.interface_name(i));
// let ident = match (interface, name) {
// (Some(i), Some(n)) => format!("{i}#{n}: "),
// (None, Some(n)) => format!("{n}: "),
// _ => todo!(),
// };
// println!("{ident}{typ}");
// }
// }
// _ => bail!(
// "wrong number of arguments to inspect function. Expected 1 got {}",
// args.len()
// ),
// };
// }
Cmd::BuiltIn { name, args } if name == "compose" => {
Cmd::BuiltIn { name: "type", args } => {
match args.as_slice() {
&[token] => {
let TokenKind::Ident(name) = token.token() else {
bail!("unrecognized token")
};
let types = resolver.types_by_name(name);
for (interface, ty) in &types {
let typ = resolver.display_wit_type_def(ty, Expansion::Expanded(1));
let name = &ty.name;
let interface = interface.and_then(|i| resolver.interface_name(i));
let ident = match (interface, name) {
(Some(i), Some(n)) => format!("{i}#{n}: "),
(None, Some(n)) => format!("{n}: "),
_ => todo!(),
};
println!("{ident}{typ}");
}
}
_ => bail!(
"wrong number of arguments to inspect function. Expected 1 got {}",
args.len()
),
};
}
Cmd::BuiltIn {
name: "compose",
args,
} => {
let &[token] = args.as_slice() else {
bail!(
"wrong number of arguments to compose function. Expected 1 got {}",
Expand All @@ -160,9 +167,9 @@ impl<'a> Cmd<'a> {
let adapter =
std::fs::read(&*path).context("could not read path to adapter module")?;
runtime.compose(&adapter)?;
*querier = WorldResolver::from_bytes(runtime.component_bytes())?;
*resolver = WorldResolver::from_bytes(runtime.component_bytes())?;
}
Cmd::BuiltIn { name, args } if name == "link" => {
Cmd::BuiltIn { name: "link", args } => {
let mut args = args.into_iter().collect();
let Ok(Some(import_ident)) = ItemIdent::try_parse(&mut args) else {
bail!("import_ident is not a proper item identifier");
Expand All @@ -176,7 +183,7 @@ impl<'a> Cmd<'a> {
};
let component_bytes = std::fs::read(component)
.with_context(|| format!("could not read component '{component}'"))?;
runtime.stub(&querier, import_ident, export_ident, &component_bytes)?;
runtime.stub(&resolver, import_ident, export_ident, &component_bytes)?;
}
Cmd::BuiltIn {
name: "inspect",
Expand All @@ -188,29 +195,35 @@ impl<'a> Cmd<'a> {
};
match ident {
ItemIdent::Item(ident) => {
let f = querier
let f = resolver
.exported_function(ident)
.or_else(|| querier.imported_function(ident));
.or_else(|| resolver.imported_function(ident));
match f {
Some(f) => println!("{}", format_function(f, querier)),
Some(f) => println!("{}", format_function(f, resolver)),
None => bail!("Could not find imported or exported function '{ident}'"),
}
}
ItemIdent::Interface(ident) => {
let i = querier
let i = resolver
.exported_interface(ident)
.or_else(|| querier.imported_interface(ident));
.or_else(|| resolver.imported_interface(ident));
match i {
Some(f) => println!("{}", format_interface(f, querier)),
Some(f) => println!("{}", format_interface(f, resolver)),
None => {
bail!("Could not find imported or exported interface '{ident}'")
}
}
}
}
}
Cmd::BuiltIn { name, args: _ } if name == "help" => print_help(),
Cmd::BuiltIn { name, args: _ } if name == "clear" => return Ok(true),
Cmd::BuiltIn {
name: "help",
args: _,
} => print_help(),
Cmd::BuiltIn {
name: "clear",
args: _,
} => return Ok(true),
Cmd::BuiltIn { name, args: _ } => {
bail!("Unrecognized built-in function '{name}'")
}
Expand All @@ -236,55 +249,55 @@ There are also builtin functions that can be called with a preceding '.'. Suppor
.inspect $item inspect an item `$item` in scope (`?` is alias for this built-in)")
}

fn format_world_item(item: &wit_parser::WorldItem, querier: &WorldResolver) -> Option<String> {
fn format_world_item(item: &wit_parser::WorldItem, resolver: &WorldResolver) -> Option<String> {
match item {
wit_parser::WorldItem::Function(f) => Some(format_function(f, querier)),
wit_parser::WorldItem::Function(f) => Some(format_function(f, resolver)),
wit_parser::WorldItem::Interface(id) => {
let interface = querier.interface_by_id(*id).unwrap();
let interface = resolver.interface_by_id(*id).unwrap();
if interface.functions.is_empty() {
return None;
}
let output = format_interface(interface, querier);
let output = format_interface(interface, resolver);
Some(output)
}
wit_parser::WorldItem::Type(_) => None,
}
}

fn format_interface(interface: &wit_parser::Interface, querier: &WorldResolver) -> String {
fn format_interface(interface: &wit_parser::Interface, resolver: &WorldResolver) -> String {
use std::fmt::Write;
let mut output = String::from("{\n");
for (_, fun) in &interface.functions {
writeln!(
&mut output,
" {}: {}",
fun.name.bold(),
format_function(fun, querier)
format_function(fun, resolver)
)
.unwrap();
}
output.push('}');
output
}

fn format_function(f: &wit_parser::Function, querier: &WorldResolver) -> String {
fn format_function(f: &wit_parser::Function, resolver: &WorldResolver) -> String {
let mut params = Vec::new();
for (param_name, param_type) in &f.params {
let ty = querier.display_wit_type(param_type, Expansion::Collapsed);
let ty = resolver.display_wit_type(param_type, Expansion::Collapsed);
params.push(format!("{param_name}: {}", ty.italic()));
}
let params = params.join(", ");
let rets = match &f.results {
wit_parser::Results::Anon(t) => {
let t = querier.display_wit_type(t, Expansion::Collapsed);
let t = resolver.display_wit_type(t, Expansion::Collapsed);
format!(" -> {}", t.italic())
}
wit_parser::Results::Named(n) if n.is_empty() => String::new(),
wit_parser::Results::Named(params) => {
let params = params
.iter()
.map(|(name, t)| {
let t = querier.display_wit_type(t, Expansion::Collapsed);
let t = resolver.display_wit_type(t, Expansion::Collapsed);
format!("{name}: {t}")
})
.collect::<Vec<_>>()
Expand Down
Loading

0 comments on commit 4a590ff

Please sign in to comment.