diff --git a/src/command.rs b/src/command.rs index 067722d..50aa963 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,4 +1,3 @@ -pub mod alt_parser; pub mod parser; mod tokenizer; use std::collections::HashMap; @@ -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; @@ -20,23 +19,22 @@ pub enum Cmd<'a> { name: &'a str, args: Vec>, }, - 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>> { 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, })), @@ -49,17 +47,17 @@ impl<'a> Cmd<'a> { pub fn run( self, runtime: &mut Runtime, - querier: &mut WorldResolver, + resolver: &mut WorldResolver, scope: &mut HashMap, ) -> anyhow::Result { - 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)) } @@ -67,7 +65,7 @@ impl<'a> Cmd<'a> { 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!( "{}", @@ -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()); } } @@ -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 {}", @@ -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"); @@ -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", @@ -188,20 +195,20 @@ 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}'") } @@ -209,8 +216,14 @@ impl<'a> Cmd<'a> { } } } - 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}'") } @@ -236,22 +249,22 @@ 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 { +fn format_world_item(item: &wit_parser::WorldItem, resolver: &WorldResolver) -> Option { 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 { @@ -259,7 +272,7 @@ fn format_interface(interface: &wit_parser::Interface, querier: &WorldResolver) &mut output, " {}: {}", fun.name.bold(), - format_function(fun, querier) + format_function(fun, resolver) ) .unwrap(); } @@ -267,16 +280,16 @@ fn format_interface(interface: &wit_parser::Interface, querier: &WorldResolver) 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(), @@ -284,7 +297,7 @@ fn format_function(f: &wit_parser::Function, querier: &WorldResolver) -> String 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::>() diff --git a/src/command/alt_parser.rs b/src/command/alt_parser.rs deleted file mode 100644 index 25a40b0..0000000 --- a/src/command/alt_parser.rs +++ /dev/null @@ -1,674 +0,0 @@ -use std::collections::VecDeque; - -use crate::command::tokenizer::TokenKind; - -use super::tokenizer::Token; - -#[derive(Debug, PartialEq)] -pub enum Line<'a> { - Expr(Expr<'a>), - BuiltIn(BuiltIn<'a>), - Assignment(&'a str, Expr<'a>), -} - -impl<'a> Line<'a> { - pub fn parse(mut tokens: VecDeque>) -> Result, ParserError<'a>> { - let result = match BuiltIn::try_parse(&mut tokens)? { - Some(builtin) => Ok(Self::BuiltIn(builtin)), - None => match Self::try_parse_assignment(&mut tokens)? { - Some((ident, expr)) => Ok(Self::Assignment(ident, expr)), - None => match Expr::try_parse(&mut tokens)? { - Some(e) => Ok(Self::Expr(e)), - None => todo!(), - }, - }, - }; - if !tokens.is_empty() { - return Err(ParserError::RemainingInput); - } - result - } - - fn try_parse_assignment( - tokens: &mut VecDeque>, - ) -> Result)>, ParserError<'a>> { - let Some(token) = tokens.front() else { - return Ok(None); - }; - println!("0 {tokens:?}"); - let TokenKind::Ident(ident) = token.token() else { - return Ok(None); - }; - println!("1 {tokens:?}"); - let token = *token; - let _ = tokens.pop_front(); - if matches!(tokens.front().map(|t| t.token()), Some(TokenKind::Equal)) { - let _ = tokens.pop_front(); - println!("{tokens:?}"); - match Expr::try_parse(tokens)? { - Some(e) => Ok(Some((ident, e))), - None => Err(ParserError::ExpectedExpr), - } - } else { - tokens.push_front(token); - Ok(None) - } - } -} - -#[derive(Debug, PartialEq)] -pub struct BuiltIn<'a> { - pub name: &'a str, - pub rest: Vec>, -} - -impl<'a> BuiltIn<'a> { - fn try_parse(tokens: &mut VecDeque>) -> Result>, ParserError<'a>> { - let Some(TokenKind::Builtin(ident)) = tokens.front().map(|t| t.token()) else { - return Ok(None); - }; - tokens.pop_front(); - Ok(Some(BuiltIn { - name: ident, - rest: tokens.drain(..).collect(), - })) - } -} - -#[derive(Debug, PartialEq)] -pub enum ParserError<'a> { - UnexpectedToken(Token<'a>), - UnexpectedEndOfInput, - RemainingInput, - ExpectedExpr, -} - -impl std::error::Error for ParserError<'_> {} - -impl std::fmt::Display for ParserError<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ParserError::UnexpectedToken(_) => f.write_str("unexpected token"), - ParserError::UnexpectedEndOfInput => f.write_str("unexpected end of input"), - ParserError::RemainingInput => f.write_str("remaining input"), - ParserError::ExpectedExpr => f.write_str("unexpected expression"), - } - } -} - -#[derive(Debug, PartialEq)] -pub enum Expr<'a> { - FunctionCall(FunctionCall<'a>), - Ident(&'a str), - Literal(Literal<'a>), -} - -impl<'a> Expr<'a> { - fn try_parse(input: &mut VecDeque>) -> Result>, ParserError<'a>> { - let Some(first) = input.front() else { - return Ok(None); - }; - match first.token() { - TokenKind::String(s) => { - input.pop_front(); - Ok(Some(Expr::Literal(Literal::String(s)))) - } - TokenKind::Number(n) => { - input.pop_front(); - Ok(Some(Expr::Literal(Literal::Number(n)))) - } - TokenKind::OpenBracket => { - input.pop_front(); - enum State { - ExpectExpr, - ExpectComma, - } - let mut state = State::ExpectExpr; - let mut items = vec![]; - while let Some(token) = input.front() { - match token.token() { - TokenKind::ClosedBracket => { - input.pop_front(); - return Ok(Some(Expr::Literal(Literal::List(List { items })))); - } - TokenKind::Comma if matches!(state, State::ExpectComma) => { - input.pop_front(); - state = State::ExpectExpr; - } - _ => { - let expr = Expr::try_parse(input)?; - if let Some(expr) = expr { - items.push(expr); - state = State::ExpectComma; - } else { - return Err(ParserError::UnexpectedEndOfInput); - } - } - } - } - return Err(ParserError::UnexpectedEndOfInput); - } - TokenKind::OpenBrace => { - input.pop_front(); - enum State<'a> { - ExpectIdent, - ExpectColon(&'a str), - ExpectExpr(&'a str), - ExpectComma, - } - let mut state = State::ExpectIdent; - let mut fields = vec![]; - while let Some(token) = input.front() { - match (token.token(), state) { - (TokenKind::ClosedBrace, State::ExpectComma | State::ExpectIdent) => { - input.pop_front(); - return Ok(Some(Expr::Literal(Literal::Record(Record { fields })))); - } - (TokenKind::Comma, State::ExpectComma) => { - input.pop_front(); - state = State::ExpectIdent; - } - (TokenKind::Colon, State::ExpectColon(ident)) => { - input.pop_front(); - state = State::ExpectExpr(ident); - } - (_, State::ExpectIdent) => { - let ident = Literal::parse_ident(input)?; - state = State::ExpectColon(ident); - } - (_, State::ExpectExpr(ident)) => { - let expr = Expr::try_parse(input)?; - if let Some(expr) = expr { - fields.push((ident, expr)); - state = State::ExpectComma; - } else { - return Err(ParserError::UnexpectedEndOfInput); - } - } - _ => return Err(ParserError::UnexpectedToken(*token)), - } - } - return Err(ParserError::UnexpectedEndOfInput); - } - TokenKind::Ident(_) => { - let func = FunctionCall::try_parse(input)?; - match func { - Some(f) => Ok(Some(Expr::FunctionCall(f))), - None => Ok(Some(Expr::Ident(Literal::parse_ident(input)?))), - } - } - - _ => return Ok(None), - } - } -} - -#[derive(Debug, PartialEq)] -pub struct FunctionCall<'a> { - pub ident: Ident<'a>, - pub args: Vec>, -} - -impl<'a> FunctionCall<'a> { - fn try_parse(input: &mut VecDeque>) -> Result, ParserError<'a>> { - let original = input.clone(); - let Some(function_ident) = Ident::try_parse(input)? else { - return Ok(None); - }; - let next = input.front(); - if next.map(|t| t.token()) != Some(TokenKind::OpenParen) { - // If we failed to find an open paren then we need to completely bail - // on function parsing which means restoring the input state back to - // its original form. - *input = original; - return Ok(None); - } - expect_token(input, |t| t == TokenKind::OpenParen)?; - let mut args = Vec::new(); - loop { - let Some(expr) = Expr::try_parse(input)? else { - break; - }; - args.push(expr); - if input.front().map(|t| t.token()) != Some(TokenKind::Comma) { - break; - } - } - expect_token(input, |t| t == TokenKind::ClosedParen)?; - Ok(Some(FunctionCall { - ident: function_ident, - args, - })) - } -} - -fn expect_token<'a>( - input: &mut VecDeque>, - pred: impl FnOnce(TokenKind<'a>) -> bool, -) -> Result<(), ParserError<'a>> { - let Some(token) = input.pop_front() else { - return Err(ParserError::UnexpectedEndOfInput); - }; - if !pred(token.token()) { - return Err(ParserError::UnexpectedToken(token)); - } - Ok(()) -} - -// TODO: Rename this to Ident and Ident to ItemIdent -#[derive(Debug, PartialEq, Copy, Clone)] -pub enum ItemIdent<'a> { - Item(Ident<'a>), - Interface(InterfaceIdent<'a>), -} - -impl<'a> ItemIdent<'a> { - pub(crate) fn try_parse( - input: &mut VecDeque>, - ) -> Result>, ParserError<'a>> { - match Ident::try_parse(input)? { - Some(i) => Ok(Some(Self::Item(i))), - None => Ok(InterfaceIdent::try_parse(input)?.map(Self::Interface)), - } - } -} - -#[derive(Debug, PartialEq, Copy, Clone)] -pub struct Ident<'a> { - pub interface: Option>, - pub item: &'a str, -} - -impl<'a> Ident<'a> { - fn try_parse(input: &mut VecDeque>) -> Result, ParserError<'a>> { - let interface = InterfaceIdent::try_parse(input)?; - match interface { - Some(i) if i.package.is_none() => { - if input.front().map(|t| t.token()) == Some(TokenKind::Hash) { - input.pop_front(); - let ident = Literal::parse_ident(input)?; - Ok(Some(Ident { - interface: Some(i), - item: ident, - })) - } else { - // We parsed the function ident as the interface ident - // Map the interface ident to the function ident - Ok(Some(Ident { - interface: None, - item: i.interface, - })) - } - } - Some(i) => { - // if we parse an interface id with a full package, we must - // be expecting a `#` next with the function ident - match input.pop_front() { - Some(t) if t.token() == TokenKind::Hash => { - let ident = Literal::parse_ident(input)?; - Ok(Some(Ident { - interface: Some(i), - item: ident, - })) - } - Some(t) => Err(ParserError::UnexpectedToken(t)), - None => Err(ParserError::UnexpectedEndOfInput), - } - } - - None => Ok(None), - } - } -} - -impl std::fmt::Display for Ident<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(interface) = self.interface { - write!(f, "{interface}#")? - } - write!(f, "{}", self.item) - } -} - -#[derive(Debug, PartialEq, Clone, Copy)] -pub struct InterfaceIdent<'a> { - package: Option<(&'a str, &'a str)>, - interface: &'a str, -} - -impl<'a> InterfaceIdent<'a> { - fn try_parse<'b>(input: &'b mut VecDeque>) -> Result, ParserError<'a>> { - #[derive(Debug)] - enum State<'a> { - ExpectFirst, - ExpectColon(&'a str), - ExpectSecond(&'a str), - ExpectSlash(&'a str, &'a str), - ExpectThird(&'a str, &'a str), - } - let mut state = State::ExpectFirst; - loop { - let token = input.front(); - match (token.map(|t| t.token()), state) { - (Some(TokenKind::Ident(i)), State::ExpectFirst) => { - input.pop_front(); - state = State::ExpectColon(i); - } - (Some(TokenKind::Colon), State::ExpectColon(first)) => { - input.pop_front(); - state = State::ExpectSecond(first); - } - (Some(TokenKind::Ident(second)), State::ExpectSecond(first)) => { - input.pop_front(); - state = State::ExpectSlash(first, second); - } - (Some(TokenKind::Slash), State::ExpectSlash(first, second)) => { - input.pop_front(); - state = State::ExpectThird(first, second); - } - (Some(TokenKind::Ident(third)), State::ExpectThird(first, second)) => { - input.pop_front(); - return Ok(Some(InterfaceIdent { - package: Some((first, second)), - interface: third, - })); - } - (_, State::ExpectColon(first)) => { - return Ok(Some(InterfaceIdent { - package: None, - interface: first, - })); - } - (_, State::ExpectFirst) => return Ok(None), - (Some(_), _) => return Err(ParserError::UnexpectedToken(*token.unwrap())), - _ => return Err(ParserError::UnexpectedEndOfInput), - } - } - } -} - -impl std::fmt::Display for InterfaceIdent<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some((namespace, package)) = self.package { - write!(f, "{namespace}:{package}/")?; - } - write!(f, "{}", self.interface) - } -} - -#[derive(Debug, PartialEq)] -pub enum Literal<'a> { - String(&'a str), - Number(usize), - List(List<'a>), - Record(Record<'a>), -} - -impl<'a> Literal<'a> { - fn parse_ident(input: &mut VecDeque>) -> Result<&'a str, ParserError<'a>> { - let Some(token) = input.front() else { - return Err(ParserError::UnexpectedEndOfInput); - }; - match token.token() { - TokenKind::Ident(i) => { - input.pop_front(); - Ok(i) - } - _ => Err(ParserError::UnexpectedToken(*token)), - } - } -} - -#[derive(Debug, PartialEq)] -pub struct List<'a> { - pub items: Vec>, -} - -impl<'a> From>> for List<'a> { - fn from(items: Vec>) -> Self { - Self { items } - } -} - -#[derive(Debug, PartialEq)] -pub struct Record<'a> { - pub fields: Vec<(&'a str, Expr<'a>)>, -} - -impl<'a> From)>> for Record<'a> { - fn from(fields: Vec<(&'a str, Expr<'a>)>) -> Self { - Self { fields } - } -} - -#[cfg(test)] -mod tests { - use std::vec; - - use crate::command::tokenizer::{SpannedStr, TokenKind}; - - use super::*; - - fn dummy_spanned_str() -> SpannedStr<'static> { - SpannedStr { str: "", offset: 0 } - } - - fn token(kind: TokenKind<'static>) -> Token<'static> { - Token { - input: dummy_spanned_str(), - token: kind, - } - } - - fn tokens(tokens: impl IntoIterator>) -> VecDeque> { - tokens.into_iter().map(token).collect() - } - - fn parse( - ts: impl IntoIterator>, - ) -> Result, ParserError<'static>> { - Line::parse(tokens(ts)) - } - - #[test] - fn parse_string_literals() { - let line = parse([TokenKind::String("hello-world")]).unwrap(); - assert_eq!( - line, - Line::Expr(Expr::Literal(Literal::String("hello-world"))) - ); - } - - #[test] - fn parse_list_literals() { - let list_of_string = Line::Expr(Expr::Literal(Literal::List( - vec![Expr::Literal(Literal::String("hello-world"))].into(), - ))); - let line = parse([ - TokenKind::OpenBracket, - TokenKind::String("hello-world"), - TokenKind::ClosedBracket, - ]) - .unwrap(); - assert_eq!(line, list_of_string); - - let line = parse([ - TokenKind::OpenBracket, - TokenKind::String("hello-world"), - TokenKind::Comma, - TokenKind::ClosedBracket, - ]) - .unwrap(); - assert_eq!(line, list_of_string); - - let err = parse([ - TokenKind::OpenBracket, - TokenKind::String("hello-world"), - TokenKind::Comma, - ]) - .unwrap_err(); - assert_eq!(err, ParserError::UnexpectedEndOfInput); - } - - #[test] - fn parse_record_literals() { - let record = Line::Expr(Expr::Literal(Literal::Record( - vec![("foo", Expr::Literal(Literal::String("bar")))].into(), - ))); - let line = parse([ - TokenKind::OpenBrace, - TokenKind::Ident("foo"), - TokenKind::Colon, - TokenKind::String("bar"), - TokenKind::ClosedBrace, - ]) - .unwrap(); - assert_eq!(line, record); - - let line = parse([ - TokenKind::OpenBrace, - TokenKind::Ident("foo"), - TokenKind::Colon, - TokenKind::String("bar"), - TokenKind::Comma, - TokenKind::ClosedBrace, - ]) - .unwrap(); - assert_eq!(line, record); - - let err = parse([ - TokenKind::OpenBrace, - TokenKind::Ident("foo"), - TokenKind::String("bar"), - TokenKind::ClosedBrace, - ]) - .unwrap_err(); - assert_eq!( - err, - ParserError::UnexpectedToken(token(TokenKind::String("bar"))) - ); - } - - #[test] - fn parse_function_calls() { - let function = Line::Expr(Expr::FunctionCall(FunctionCall { - ident: Ident { - interface: Some(InterfaceIdent { - package: Some(("foo", "bar")), - interface: "baz", - }), - item: "qux", - }, - args: vec![], - })); - let line = parse([ - TokenKind::Ident("foo"), - TokenKind::Colon, - TokenKind::Ident("bar"), - TokenKind::Slash, - TokenKind::Ident("baz"), - TokenKind::Hash, - TokenKind::Ident("qux"), - TokenKind::OpenParen, - TokenKind::ClosedParen, - ]) - .unwrap(); - assert_eq!(line, function); - - let function = Line::Expr(Expr::FunctionCall(FunctionCall { - ident: Ident { - interface: None, - item: "qux", - }, - args: vec![], - })); - let line = parse([ - TokenKind::Ident("qux"), - TokenKind::OpenParen, - TokenKind::ClosedParen, - ]) - .unwrap(); - assert_eq!(line, function); - - let function = Line::Expr(Expr::FunctionCall(FunctionCall { - ident: Ident { - interface: None, - item: "foo", - }, - args: vec![Expr::FunctionCall(FunctionCall { - ident: Ident { - interface: None, - item: "bar", - }, - args: vec![], - })], - })); - let line = parse([ - TokenKind::Ident("foo"), - TokenKind::OpenParen, - TokenKind::Ident("bar"), - TokenKind::OpenParen, - TokenKind::ClosedParen, - TokenKind::ClosedParen, - ]) - .unwrap(); - assert_eq!(line, function); - - let err = parse([ - TokenKind::Ident("foo"), - TokenKind::Colon, - TokenKind::Ident("bar"), - TokenKind::OpenParen, - TokenKind::ClosedParen, - ]) - .unwrap_err(); - assert_eq!( - err, - ParserError::UnexpectedToken(token(TokenKind::OpenParen)) - ); - - let err = parse([ - TokenKind::Ident("foo"), - TokenKind::Colon, - TokenKind::Ident("bar"), - TokenKind::Hash, - TokenKind::Ident("baz"), - TokenKind::OpenParen, - TokenKind::ClosedParen, - ]) - .unwrap_err(); - assert_eq!(err, ParserError::UnexpectedToken(token(TokenKind::Hash))); - } - - #[test] - fn parse_ident_expr() { - let line = parse([TokenKind::Ident("foo")]).unwrap(); - assert_eq!(line, Line::Expr(Expr::Ident("foo"))); - } - - #[test] - fn parse_builtin() { - let line = parse([TokenKind::Builtin("foo"), TokenKind::Ident("foo")]).unwrap(); - assert_eq!( - line, - Line::BuiltIn(BuiltIn { - name: "foo", - rest: vec![token(TokenKind::Ident("foo"))] - }) - ); - } - - #[test] - fn parse_assignment() { - let line = parse([ - TokenKind::Ident("foo"), - TokenKind::Equal, - TokenKind::String("bar"), - ]) - .unwrap(); - assert_eq!( - line, - Line::Assignment("foo", Expr::Literal(Literal::String("bar"))) - ); - } -} diff --git a/src/command/parser.rs b/src/command/parser.rs index 67001ef..cbfa6f2 100644 --- a/src/command/parser.rs +++ b/src/command/parser.rs @@ -1,168 +1,391 @@ -use std::ops::Range; +use std::collections::VecDeque; -use nom::branch::alt; -use nom::bytes::complete::tag; -use nom::character::complete::{alpha1, digit1, multispace0, multispace1}; -use nom::combinator::{cut, map, map_res, recognize}; -use nom::multi::{many0_count, separated_list0}; -use nom::sequence::{delimited, pair, preceded}; -use nom::InputTakeAtPosition; +use crate::command::tokenizer::TokenKind; + +use super::tokenizer::Token; #[derive(Debug, PartialEq)] pub enum Line<'a> { - Builtin(SpannedStr<'a>, Vec>), Expr(Expr<'a>), - Assignment(SpannedStr<'a>, Expr<'a>), + BuiltIn(BuiltIn<'a>), + Assignment(&'a str, Expr<'a>), } impl<'a> Line<'a> { - pub fn parse(input: &'a str) -> nom::IResult<&str, Line> { - let input = Span::new(input); - alt(( - map(builtin, |(name, args)| { - Line::Builtin(name.into(), args.into_iter().map(|s| s.into()).collect()) - }), - map(assignment, |(ident, expr)| { - Line::Assignment(ident.into(), expr) - }), - map(Expr::parse, Line::Expr), - ))(input) - .map_err(|e| e.map(|e| nom::error::Error::new(*e.input.fragment(), e.code))) - .map(|(rest, result)| (*rest.fragment(), result)) + pub fn parse(mut tokens: VecDeque>) -> Result, ParserError<'a>> { + let result = match BuiltIn::try_parse(&mut tokens)? { + Some(builtin) => Ok(Self::BuiltIn(builtin)), + None => match Self::try_parse_assignment(&mut tokens)? { + Some((ident, expr)) => Ok(Self::Assignment(ident, expr)), + None => match Expr::try_parse(&mut tokens)? { + Some(e) => Ok(Self::Expr(e)), + None => { + return match tokens.front() { + Some(t) => Err(ParserError::UnexpectedToken(*t)), + None => Err(ParserError::UnexpectedEndOfInput), + } + } + }, + }, + }; + if !tokens.is_empty() { + return Err(ParserError::RemainingInput); + } + result } -} -/// Used to collect span information during parsing -type Span<'a> = nom_locate::LocatedSpan<&'a str>; - -pub fn builtin(input: Span) -> nom::IResult)> { - alt((builtin_call, special_char))(input) + fn try_parse_assignment( + tokens: &mut VecDeque>, + ) -> Result)>, ParserError<'a>> { + let Some(token) = tokens.front() else { + return Ok(None); + }; + let TokenKind::Ident(ident) = token.token() else { + return Ok(None); + }; + let token = *token; + let _ = tokens.pop_front(); + if matches!(tokens.front().map(|t| t.token()), Some(TokenKind::Equal)) { + let _ = tokens.pop_front(); + match Expr::try_parse(tokens)? { + Some(e) => Ok(Some((ident, e))), + None => Err(ParserError::ExpectedExpr), + } + } else { + tokens.push_front(token); + Ok(None) + } + } } -pub fn builtin_call(input: Span) -> nom::IResult)> { - let (rest, _) = tag(".")(input)?; - let (rest, ident) = ident(rest)?; - if rest.is_empty() { - return Ok((rest, (ident, Vec::new()))); +#[derive(Debug, PartialEq)] +pub struct BuiltIn<'a> { + pub name: &'a str, + pub rest: Vec>, +} + +impl<'a> BuiltIn<'a> { + fn try_parse(tokens: &mut VecDeque>) -> Result>, ParserError<'a>> { + let Some(TokenKind::Builtin(ident)) = tokens.front().map(|t| t.token()) else { + return Ok(None); + }; + tokens.pop_front(); + Ok(Some(BuiltIn { + name: ident, + rest: tokens.drain(..).collect(), + })) } - let (rest, args) = separated_list0(multispace1, builtin_argument)(rest)?; +} - Ok((rest, (ident, args))) +#[derive(Debug, PartialEq)] +pub enum ParserError<'a> { + UnexpectedToken(Token<'a>), + UnexpectedEndOfInput, + RemainingInput, + ExpectedExpr, } -pub fn special_char(input: Span) -> nom::IResult)> { - let (rest, _) = tag("?")(input)?; - let (rest, _) = multispace0(rest)?; - let (rest, args) = separated_list0(multispace1, builtin_argument)(rest)?; - if args.is_empty() { - return Ok((rest, (Span::new("help"), Vec::new()))); +impl std::error::Error for ParserError<'_> {} + +impl std::fmt::Display for ParserError<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ParserError::UnexpectedToken(_) => f.write_str("unexpected token"), + ParserError::UnexpectedEndOfInput => f.write_str("unexpected end of input"), + ParserError::RemainingInput => f.write_str("remaining input"), + ParserError::ExpectedExpr => f.write_str("unexpected expression"), + } } - Ok((rest, (Span::new("inspect"), args))) } #[derive(Debug, PartialEq)] pub enum Expr<'a> { + FunctionCall(FunctionCall<'a>), + Ident(&'a str), Literal(Literal<'a>), - Ident(SpannedStr<'a>), - FunctionCall(FunctionIdent<'a>, Vec>), } impl<'a> Expr<'a> { - pub fn parse(input: Span) -> nom::IResult { - alt(( - map(function_call, |(name, args)| { - Expr::FunctionCall(name.into(), args) - }), - map(ident, |i| Expr::Ident(i.into())), - map(Literal::parse, Expr::Literal), - ))(input) + fn try_parse(input: &mut VecDeque>) -> Result>, ParserError<'a>> { + let Some(first) = input.front() else { + return Ok(None); + }; + match first.token() { + TokenKind::String(s) => { + input.pop_front(); + Ok(Some(Expr::Literal(Literal::String(s)))) + } + TokenKind::Number(n) => { + input.pop_front(); + Ok(Some(Expr::Literal(Literal::Number(n)))) + } + TokenKind::OpenBracket => { + input.pop_front(); + enum State { + ExpectExpr, + ExpectComma, + } + let mut state = State::ExpectExpr; + let mut items = vec![]; + while let Some(token) = input.front() { + match token.token() { + TokenKind::ClosedBracket => { + input.pop_front(); + return Ok(Some(Expr::Literal(Literal::List(List { items })))); + } + TokenKind::Comma if matches!(state, State::ExpectComma) => { + input.pop_front(); + state = State::ExpectExpr; + } + _ => { + let expr = Expr::try_parse(input)?; + if let Some(expr) = expr { + items.push(expr); + state = State::ExpectComma; + } else { + return Err(ParserError::UnexpectedEndOfInput); + } + } + } + } + return Err(ParserError::UnexpectedEndOfInput); + } + TokenKind::OpenBrace => { + input.pop_front(); + enum State<'a> { + ExpectIdent, + ExpectColon(&'a str), + ExpectExpr(&'a str), + ExpectComma, + } + let mut state = State::ExpectIdent; + let mut fields = vec![]; + while let Some(token) = input.front() { + match (token.token(), state) { + (TokenKind::ClosedBrace, State::ExpectComma | State::ExpectIdent) => { + input.pop_front(); + return Ok(Some(Expr::Literal(Literal::Record(Record { fields })))); + } + (TokenKind::Comma, State::ExpectComma) => { + input.pop_front(); + state = State::ExpectIdent; + } + (TokenKind::Colon, State::ExpectColon(ident)) => { + input.pop_front(); + state = State::ExpectExpr(ident); + } + (_, State::ExpectIdent) => { + let ident = Literal::parse_ident(input)?; + state = State::ExpectColon(ident); + } + (_, State::ExpectExpr(ident)) => { + let expr = Expr::try_parse(input)?; + if let Some(expr) = expr { + fields.push((ident, expr)); + state = State::ExpectComma; + } else { + return Err(ParserError::UnexpectedEndOfInput); + } + } + _ => return Err(ParserError::UnexpectedToken(*token)), + } + } + return Err(ParserError::UnexpectedEndOfInput); + } + TokenKind::Ident(_) => { + let func = FunctionCall::try_parse(input)?; + match func { + Some(f) => Ok(Some(Expr::FunctionCall(f))), + None => Ok(Some(Expr::Ident(Literal::parse_ident(input)?))), + } + } + + _ => return Ok(None), + } } } +#[derive(Debug, PartialEq)] +pub struct FunctionCall<'a> { + pub ident: Ident<'a>, + pub args: Vec>, +} + +impl<'a> FunctionCall<'a> { + fn try_parse(input: &mut VecDeque>) -> Result, ParserError<'a>> { + let original = input.clone(); + let Some(function_ident) = Ident::try_parse(input)? else { + return Ok(None); + }; + let next = input.front(); + if next.map(|t| t.token()) != Some(TokenKind::OpenParen) { + // If we failed to find an open paren then we need to completely bail + // on function parsing which means restoring the input state back to + // its original form. + *input = original; + return Ok(None); + } + expect_token(input, |t| t == TokenKind::OpenParen)?; + let mut args = Vec::new(); + loop { + let Some(expr) = Expr::try_parse(input)? else { + break; + }; + args.push(expr); + if input.front().map(|t| t.token()) != Some(TokenKind::Comma) { + break; + } + } + expect_token(input, |t| t == TokenKind::ClosedParen)?; + Ok(Some(FunctionCall { + ident: function_ident, + args, + })) + } +} + +fn expect_token<'a>( + input: &mut VecDeque>, + pred: impl FnOnce(TokenKind<'a>) -> bool, +) -> Result<(), ParserError<'a>> { + let Some(token) = input.pop_front() else { + return Err(ParserError::UnexpectedEndOfInput); + }; + if !pred(token.token()) { + return Err(ParserError::UnexpectedToken(token)); + } + Ok(()) +} + +// TODO: Rename this to Ident and Ident to ItemIdent #[derive(Debug, PartialEq, Copy, Clone)] pub enum ItemIdent<'a> { - Function(FunctionIdent<'a>), + Item(Ident<'a>), Interface(InterfaceIdent<'a>), } impl<'a> ItemIdent<'a> { - pub fn parse(input: Span<'a>) -> nom::IResult, ItemIdent<'a>> { - alt(( - map(FunctionIdent::parse, |f| ItemIdent::Function(f)), - map(InterfaceIdent::parse, |i| ItemIdent::Interface(i)), - ))(input) + pub(crate) fn try_parse( + input: &mut VecDeque>, + ) -> Result>, ParserError<'a>> { + match Ident::try_parse(input)? { + Some(i) => Ok(Some(Self::Item(i))), + None => Ok(InterfaceIdent::try_parse(input)?.map(Self::Interface)), + } } } #[derive(Debug, PartialEq, Copy, Clone)] -pub struct FunctionIdent<'a> { +pub struct Ident<'a> { pub interface: Option>, - pub function: SpannedStr<'a>, -} - -impl<'a> FunctionIdent<'a> { - pub fn parse(input: Span<'a>) -> nom::IResult, FunctionIdent<'a>> { - fn with_interface(input: Span<'_>) -> nom::IResult, FunctionIdent<'_>> { - let (rest, interface) = InterfaceIdent::parse(input)?; - let (rest, _) = tag("#")(rest)?; - let (rest, function) = cut(ident)(rest)?; - Ok(( - rest, - FunctionIdent { - interface: Some(interface), - function: function.into(), - }, - )) + pub item: &'a str, +} + +impl<'a> Ident<'a> { + fn try_parse(input: &mut VecDeque>) -> Result, ParserError<'a>> { + let interface = InterfaceIdent::try_parse(input)?; + match interface { + Some(i) if i.package.is_none() => { + if input.front().map(|t| t.token()) == Some(TokenKind::Hash) { + input.pop_front(); + let ident = Literal::parse_ident(input)?; + Ok(Some(Ident { + interface: Some(i), + item: ident, + })) + } else { + // We parsed the function ident as the interface ident + // Map the interface ident to the function ident + Ok(Some(Ident { + interface: None, + item: i.interface, + })) + } + } + Some(i) => { + // if we parse an interface id with a full package, we must + // be expecting a `#` next with the function ident + match input.pop_front() { + Some(t) if t.token() == TokenKind::Hash => { + let ident = Literal::parse_ident(input)?; + Ok(Some(Ident { + interface: Some(i), + item: ident, + })) + } + Some(t) => Err(ParserError::UnexpectedToken(t)), + None => Err(ParserError::UnexpectedEndOfInput), + } + } + + None => Ok(None), } - alt(( - with_interface, - map(ident, |f| Self { - interface: None, - function: f.into(), - }), - ))(input) } } -impl std::fmt::Display for FunctionIdent<'_> { +impl std::fmt::Display for Ident<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if let Some(interface) = self.interface { write!(f, "{interface}#")? } - write!(f, "{}", self.function) + write!(f, "{}", self.item) } } #[derive(Debug, PartialEq, Clone, Copy)] pub struct InterfaceIdent<'a> { - package: Option<(SpannedStr<'a>, SpannedStr<'a>)>, - interface: SpannedStr<'a>, + package: Option<(&'a str, &'a str)>, + interface: &'a str, } impl<'a> InterfaceIdent<'a> { - fn parse(input: Span<'a>) -> nom::IResult { - fn prefixed<'a>(input: Span<'a>) -> nom::IResult> { - let (rest, namespace) = ident(input)?; - let (rest, _) = tag(":")(rest)?; - let (rest, package) = cut(ident)(rest)?; - let (rest, _) = cut(tag("/"))(rest)?; - let (rest, interface) = cut(ident)(rest)?; - Ok(( - rest, - InterfaceIdent { - package: Some((namespace.into(), package.into())), - interface: interface.into(), - }, - )) + fn try_parse<'b>(input: &'b mut VecDeque>) -> Result, ParserError<'a>> { + #[derive(Debug)] + enum State<'a> { + ExpectFirst, + ExpectColon(&'a str), + ExpectSecond(&'a str), + ExpectSlash(&'a str, &'a str), + ExpectThird(&'a str, &'a str), + } + let mut state = State::ExpectFirst; + loop { + let token = input.front(); + match (token.map(|t| t.token()), state) { + (Some(TokenKind::Ident(i)), State::ExpectFirst) => { + input.pop_front(); + state = State::ExpectColon(i); + } + (Some(TokenKind::Colon), State::ExpectColon(first)) => { + input.pop_front(); + state = State::ExpectSecond(first); + } + (Some(TokenKind::Ident(second)), State::ExpectSecond(first)) => { + input.pop_front(); + state = State::ExpectSlash(first, second); + } + (Some(TokenKind::Slash), State::ExpectSlash(first, second)) => { + input.pop_front(); + state = State::ExpectThird(first, second); + } + (Some(TokenKind::Ident(third)), State::ExpectThird(first, second)) => { + input.pop_front(); + return Ok(Some(InterfaceIdent { + package: Some((first, second)), + interface: third, + })); + } + (_, State::ExpectColon(first)) => { + return Ok(Some(InterfaceIdent { + package: None, + interface: first, + })); + } + (_, State::ExpectFirst) => return Ok(None), + (Some(_), _) => return Err(ParserError::UnexpectedToken(*token.unwrap())), + _ => return Err(ParserError::UnexpectedEndOfInput), + } } - - alt(( - prefixed, - map(ident, |i| Self { - package: None, - interface: i.into(), - }), - ))(input) } } @@ -177,20 +400,24 @@ impl std::fmt::Display for InterfaceIdent<'_> { #[derive(Debug, PartialEq)] pub enum Literal<'a> { - Record(Record<'a>), + String(&'a str), + Number(usize), List(List<'a>), - String(SpannedStr<'a>), - Num(usize), + Record(Record<'a>), } impl<'a> Literal<'a> { - pub fn parse(input: Span) -> nom::IResult { - alt(( - map(number, Literal::Num), - map(Record::parse, Literal::Record), - map(List::parse, Literal::List), - map(string_literal, |s| Literal::String(s.into())), - ))(input) + fn parse_ident(input: &mut VecDeque>) -> Result<&'a str, ParserError<'a>> { + let Some(token) = input.front() else { + return Err(ParserError::UnexpectedEndOfInput); + }; + match token.token() { + TokenKind::Ident(i) => { + input.pop_front(); + Ok(i) + } + _ => Err(ParserError::UnexpectedToken(*token)), + } } } @@ -199,302 +426,251 @@ pub struct List<'a> { pub items: Vec>, } -impl<'a> List<'a> { - fn parse(input: Span<'a>) -> nom::IResult { - fn item(input: Span) -> nom::IResult> { - delimited(multispace0, Expr::parse, multispace0)(input) - } - let (rest, _) = tag("[")(input)?; - let (rest, items) = cut(separated_list0(tag(","), item))(rest)?; - let (rest, _) = cut(tag("]"))(rest)?; - Ok((rest, Self { items })) +impl<'a> From>> for List<'a> { + fn from(items: Vec>) -> Self { + Self { items } } } -fn number(input: Span) -> nom::IResult { - fn parse(input: Span) -> Result { - input.fragment().parse() - } - map_res(digit1, parse)(input) -} - #[derive(Debug, PartialEq)] pub struct Record<'a> { - pub fields: Vec<(SpannedStr<'a>, Expr<'a>)>, -} - -impl<'a> Record<'a> { - fn parse(input: Span<'a>) -> nom::IResult { - fn field(input: Span) -> nom::IResult)> { - let (rest, name) = preceded(multispace0, ident)(input)?; - let (rest, _) = tag(":")(rest)?; - let (rest, expr) = delimited(multispace0, Expr::parse, multispace0)(rest)?; - Ok((rest, (name, expr))) - } - let (rest, _) = tag("{")(input)?; - let (rest, fields) = cut(separated_list0(tag(","), field))(rest)?; - let fields = fields.into_iter().map(|(f, e)| (f.into(), e)).collect(); - let (rest, _) = cut(tag("}"))(rest)?; - Ok((rest, Self { fields })) - } -} - -fn assignment(input: Span) -> nom::IResult)> { - 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(input: Span) -> nom::IResult, Vec>)> { - let (rest, ident) = FunctionIdent::parse(input)?; - let (rest, _) = tag("(")(rest)?; - let (rest, args) = cut(separated_list0(tag(","), Expr::parse))(rest)?; - let (rest, _) = cut(tag(")"))(rest)?; - - Ok((rest, (ident, args))) -} - -fn string_literal(input: Span) -> nom::IResult { - delimited(tag("\""), anything_but_quote, tag("\""))(input) -} - -fn builtin_argument(input: Span) -> nom::IResult { - alt(( - delimited(tag("\""), anything_but_quote, tag("\"")), - anything_but_space, - ))(input) -} - -fn anything_but_quote(input: Span) -> nom::IResult { - input.split_at_position_complete(|c| c == '"') -} - -/// Anything that is not whitespace -fn anything_but_space(input: Span) -> nom::IResult { - input.split_at_position_complete(char::is_whitespace) -} - -pub fn ident(input: Span) -> nom::IResult { - let ident_parser = recognize(pair(alpha1, many0_count(alt((alpha1, tag("-")))))); - delimited(multispace0, ident_parser, multispace0)(input) -} - -/// A view into the input str with span information -#[derive(Debug, PartialEq, Clone, Copy)] -pub struct SpannedStr<'a> { - str: &'a str, - offset: usize, + pub fields: Vec<(&'a str, Expr<'a>)>, } -impl<'a> SpannedStr<'a> { - pub fn as_str(&self) -> &'a str { - self.str - } - - pub fn range(&self) -> Range { - self.offset..(self.offset + self.str.len()) +impl<'a> From)>> for Record<'a> { + fn from(fields: Vec<(&'a str, Expr<'a>)>) -> Self { + Self { fields } } } -impl<'a> PartialEq<&str> for SpannedStr<'a> { - fn eq(&self, other: &&str) -> bool { - self.str == *other - } -} - -impl std::fmt::Display for SpannedStr<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.str) - } -} +#[cfg(test)] +mod tests { + use std::vec; -impl From> for String { - fn from(value: SpannedStr<'_>) -> Self { - value.str.to_owned() - } -} + use crate::command::tokenizer::{SpannedStr, TokenKind}; -impl<'a> std::ops::Deref for SpannedStr<'a> { - type Target = str; + use super::*; - fn deref(&self) -> &Self::Target { - self.str + fn dummy_spanned_str() -> SpannedStr<'static> { + SpannedStr { str: "", offset: 0 } } -} -impl<'a> From> for SpannedStr<'a> { - fn from(span: Span<'a>) -> Self { - Self { - str: span.fragment(), - offset: span.location_offset(), + fn token(kind: TokenKind<'static>) -> Token<'static> { + Token { + input: dummy_spanned_str(), + token: kind, } } -} -impl<'a> From<(&'a str, usize)> for SpannedStr<'a> { - fn from((str, offset): (&'a str, usize)) -> Self { - Self { str, offset } + fn tokens(tokens: impl IntoIterator>) -> VecDeque> { + tokens.into_iter().map(token).collect() } -} -#[cfg(test)] -mod tests { - use super::*; + fn parse( + ts: impl IntoIterator>, + ) -> Result, ParserError<'static>> { + Line::parse(tokens(ts)) + } #[test] - fn function_call() { - let input = r#"my-func(my-other-func("arg"))"#; - let (rest, result) = Line::parse(input).unwrap(); - assert!(rest.is_empty()); + fn parse_string_literals() { + let line = parse([TokenKind::String("hello-world")]).unwrap(); assert_eq!( - result, - Line::Expr(Expr::FunctionCall( - FunctionIdent { - interface: None, - function: ("my-func", 0).into() - }, - vec![Expr::FunctionCall( - FunctionIdent { - interface: None, - function: ("my-other-func", 8).into() - }, - vec![Expr::Literal(Literal::String(("arg", 23).into()))] - )] - )) + line, + Line::Expr(Expr::Literal(Literal::String("hello-world"))) ); } #[test] - fn namespaced_interface_function_call() { - let input = r#"wasi:cli/terminal-stderr#my-func()"#; - let (rest, result) = Line::parse(input).unwrap(); - assert!(rest.is_empty()); - assert_eq!( - result, - Line::Expr(Expr::FunctionCall( - FunctionIdent { - interface: Some(InterfaceIdent { - package: Some((("wasi", 0).into(), ("cli", 5).into())), - interface: ("terminal-stderr", 9).into() - }), - function: ("my-func", 25).into() - }, - vec![] - )) - ); + fn parse_list_literals() { + let list_of_string = Line::Expr(Expr::Literal(Literal::List( + vec![Expr::Literal(Literal::String("hello-world"))].into(), + ))); + let line = parse([ + TokenKind::OpenBracket, + TokenKind::String("hello-world"), + TokenKind::ClosedBracket, + ]) + .unwrap(); + assert_eq!(line, list_of_string); + + let line = parse([ + TokenKind::OpenBracket, + TokenKind::String("hello-world"), + TokenKind::Comma, + TokenKind::ClosedBracket, + ]) + .unwrap(); + assert_eq!(line, list_of_string); + + let err = parse([ + TokenKind::OpenBracket, + TokenKind::String("hello-world"), + TokenKind::Comma, + ]) + .unwrap_err(); + assert_eq!(err, ParserError::UnexpectedEndOfInput); } #[test] - fn interface_function_call() { - let input = r#"terminal-stderr#my-func()"#; - let (rest, result) = Line::parse(input).unwrap(); - assert!(rest.is_empty()); + fn parse_record_literals() { + let record = Line::Expr(Expr::Literal(Literal::Record( + vec![("foo", Expr::Literal(Literal::String("bar")))].into(), + ))); + let line = parse([ + TokenKind::OpenBrace, + TokenKind::Ident("foo"), + TokenKind::Colon, + TokenKind::String("bar"), + TokenKind::ClosedBrace, + ]) + .unwrap(); + assert_eq!(line, record); + + let line = parse([ + TokenKind::OpenBrace, + TokenKind::Ident("foo"), + TokenKind::Colon, + TokenKind::String("bar"), + TokenKind::Comma, + TokenKind::ClosedBrace, + ]) + .unwrap(); + assert_eq!(line, record); + + let err = parse([ + TokenKind::OpenBrace, + TokenKind::Ident("foo"), + TokenKind::String("bar"), + TokenKind::ClosedBrace, + ]) + .unwrap_err(); assert_eq!( - result, - Line::Expr(Expr::FunctionCall( - FunctionIdent { - interface: Some(InterfaceIdent { - package: None, - interface: ("terminal-stderr", 0).into() - }), - function: ("my-func", 16).into() - }, - vec![] - )) + err, + ParserError::UnexpectedToken(token(TokenKind::String("bar"))) ); } #[test] - fn function_call_bad_args() { - let input = r#"my-func(%^&)"#; - let result = Line::parse(input); - assert!(matches!(result, Err(nom::Err::Failure(_)))); - } - - #[test] - fn function_call_with_record() { - let input = r#"my-func({n:1, name: err("string") })"#; - let (rest, result) = Line::parse(input).unwrap(); - assert!(rest.is_empty()); - - assert_eq!( - result, - Line::Expr(Expr::FunctionCall( - FunctionIdent { + fn parse_function_calls() { + let function = Line::Expr(Expr::FunctionCall(FunctionCall { + ident: Ident { + interface: Some(InterfaceIdent { + package: Some(("foo", "bar")), + interface: "baz", + }), + item: "qux", + }, + args: vec![], + })); + let line = parse([ + TokenKind::Ident("foo"), + TokenKind::Colon, + TokenKind::Ident("bar"), + TokenKind::Slash, + TokenKind::Ident("baz"), + TokenKind::Hash, + TokenKind::Ident("qux"), + TokenKind::OpenParen, + TokenKind::ClosedParen, + ]) + .unwrap(); + assert_eq!(line, function); + + let function = Line::Expr(Expr::FunctionCall(FunctionCall { + ident: Ident { + interface: None, + item: "qux", + }, + args: vec![], + })); + let line = parse([ + TokenKind::Ident("qux"), + TokenKind::OpenParen, + TokenKind::ClosedParen, + ]) + .unwrap(); + assert_eq!(line, function); + + let function = Line::Expr(Expr::FunctionCall(FunctionCall { + ident: Ident { + interface: None, + item: "foo", + }, + args: vec![Expr::FunctionCall(FunctionCall { + ident: Ident { interface: None, - function: ("my-func", 0).into() + item: "bar", }, - vec![Expr::Literal(Literal::Record(Record { - fields: vec![ - (("n", 9).into(), Expr::Literal(Literal::Num(1))), - ( - ("name", 15).into(), - Expr::FunctionCall( - FunctionIdent { - interface: None, - function: ("err", 24).into() - }, - vec![Expr::Literal(Literal::String(("string", 29).into()))] - ) - ) - ] - }))] - )) + args: vec![], + })], + })); + let line = parse([ + TokenKind::Ident("foo"), + TokenKind::OpenParen, + TokenKind::Ident("bar"), + TokenKind::OpenParen, + TokenKind::ClosedParen, + TokenKind::ClosedParen, + ]) + .unwrap(); + assert_eq!(line, function); + + let err = parse([ + TokenKind::Ident("foo"), + TokenKind::Colon, + TokenKind::Ident("bar"), + TokenKind::OpenParen, + TokenKind::ClosedParen, + ]) + .unwrap_err(); + assert_eq!( + err, + ParserError::UnexpectedToken(token(TokenKind::OpenParen)) ); + + let err = parse([ + TokenKind::Ident("foo"), + TokenKind::Colon, + TokenKind::Ident("bar"), + TokenKind::Hash, + TokenKind::Ident("baz"), + TokenKind::OpenParen, + TokenKind::ClosedParen, + ]) + .unwrap_err(); + assert_eq!(err, ParserError::UnexpectedToken(token(TokenKind::Hash))); } #[test] - fn builtin() { - let input = r#".foo bar baz"#; - let (rest, result) = Line::parse(input).unwrap(); - assert!(rest.is_empty()); - assert_eq!( - result, - Line::Builtin( - ("foo", 1).into(), - vec![("bar", 5).into(), ("baz", 9).into(),] - ) - ); + fn parse_ident_expr() { + let line = parse([TokenKind::Ident("foo")]).unwrap(); + assert_eq!(line, Line::Expr(Expr::Ident("foo"))); } #[test] - fn builtin_no_args() { - let input = r#".foo"#; - let result = Line::parse(input); + fn parse_builtin() { + let line = parse([TokenKind::Builtin("foo"), TokenKind::Ident("foo")]).unwrap(); assert_eq!( - result, - Ok(("".into(), Line::Builtin(("foo", 1).into(), vec![]))) + line, + Line::BuiltIn(BuiltIn { + name: "foo", + rest: vec![token(TokenKind::Ident("foo"))] + }) ); } #[test] - fn assignment() { - let input = r#"x = "wow""#; - let (rest, result) = Line::parse(input).unwrap(); - assert!(rest.is_empty()); - + fn parse_assignment() { + let line = parse([ + TokenKind::Ident("foo"), + TokenKind::Equal, + TokenKind::String("bar"), + ]) + .unwrap(); assert_eq!( - result, - Line::Assignment( - ("x", 0).into(), - Expr::Literal(Literal::String(("wow", 5).into())) - ) + line, + Line::Assignment("foo", Expr::Literal(Literal::String("bar"))) ); } - - #[test] - fn ident_line() { - let input = r#"hello-world"#; - let (rest, result) = Line::parse(input).unwrap(); - assert!(rest.is_empty()); - assert_eq!(result, Line::Expr(Expr::Ident(("hello-world", 0).into()))); - } - - #[test] - fn nonsense_assignment() { - let input = r#"x = %&*"#; - let result = Line::parse(input); - assert!(matches!(result, Err(nom::Err::Failure(_)))); - } } diff --git a/src/evaluator.rs b/src/evaluator.rs index 58eab1a..60c802f 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -3,11 +3,11 @@ use std::collections::HashMap; use anyhow::{bail, Context}; use wasmtime::component::{self, List, Record, Val}; -use crate::{command::alt_parser, runtime::Runtime, wit::WorldResolver}; +use crate::{command::parser, runtime::Runtime, wit::WorldResolver}; pub struct Evaluator<'a> { runtime: &'a mut Runtime, - querier: &'a WorldResolver, + resolver: &'a WorldResolver, scope: &'a HashMap, } @@ -15,12 +15,12 @@ impl<'a> Evaluator<'a> { /// Create a new evaluator pub fn new( runtime: &'a mut Runtime, - querier: &'a WorldResolver, + resolver: &'a WorldResolver, scope: &'a HashMap, ) -> Self { Self { runtime, - querier, + resolver, scope, } } @@ -28,13 +28,13 @@ impl<'a> Evaluator<'a> { /// Evaluate the expression with the provided type hint pub fn eval( &mut self, - expr: alt_parser::Expr<'_>, + expr: parser::Expr<'_>, type_hint: Option<&component::Type>, ) -> anyhow::Result { match expr { - alt_parser::Expr::Literal(l) => self.eval_literal(l, type_hint), - alt_parser::Expr::Ident(ident) => self.resolve_ident(&*ident, type_hint), - alt_parser::Expr::FunctionCall(func) => { + parser::Expr::Literal(l) => self.eval_literal(l, type_hint), + parser::Expr::Ident(ident) => self.resolve_ident(&*ident, type_hint), + parser::Expr::FunctionCall(func) => { let ident = func.ident; let mut args = func.args; log::debug!( @@ -81,12 +81,12 @@ impl<'a> Evaluator<'a> { /// Call the function pub fn call_func( &mut self, - ident: alt_parser::Ident, - args: Vec>, + ident: parser::Ident, + args: Vec>, ) -> anyhow::Result> { log::debug!("Calling function: {ident} with args: {args:?}"); let func_def = self - .querier + .resolver .exported_function(ident) .with_context(|| format!("no function with name '{ident}'"))?; let mut evaled_args = Vec::with_capacity(func_def.params.len()); @@ -115,11 +115,11 @@ impl<'a> Evaluator<'a> { /// Evaluate a literal using the provided type hint pub fn eval_literal( &mut self, - literal: alt_parser::Literal<'_>, + literal: parser::Literal<'_>, type_hint: Option<&component::Type>, ) -> anyhow::Result { match literal { - alt_parser::Literal::List(list) => { + parser::Literal::List(list) => { match type_hint { Some(component::Type::List(l)) => { let mut values = Vec::new(); @@ -154,7 +154,7 @@ impl<'a> Evaluator<'a> { } } } - alt_parser::Literal::Record(mut r) => { + parser::Literal::Record(mut r) => { let ty = match type_hint { Some(component::Type::Record(r)) => r, Some(t) => bail!( @@ -181,7 +181,7 @@ impl<'a> Evaluator<'a> { } Ok(Val::Record(Record::new(ty, values)?)) } - alt_parser::Literal::String(s) => { + parser::Literal::String(s) => { let val = Val::String(s.to_owned().into()); match type_hint { Some(component::Type::Result(r)) => r.new_val(match (r.ok(), r.err()) { @@ -192,7 +192,7 @@ impl<'a> Evaluator<'a> { _ => Ok(val), } } - alt_parser::Literal::Number(n) => match type_hint { + parser::Literal::Number(n) => match type_hint { Some(component::Type::U8) => Ok(Val::U8(n.try_into()?)), _ => Ok(Val::S32(n.try_into()?)), }, diff --git a/src/main.rs b/src/main.rs index 49fcba3..4ae1969 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,8 +28,8 @@ fn _main() -> anyhow::Result<()> { let cli = Cli::parse(); let component_bytes = std::fs::read(cli.component)?; - let mut querier = wit::WorldResolver::from_bytes(&component_bytes)?; - let mut runtime = runtime::Runtime::init(component_bytes, &querier, |import_name| { + let mut resolver = wit::WorldResolver::from_bytes(&component_bytes)?; + let mut runtime = runtime::Runtime::init(component_bytes, &resolver, |import_name| { print_error_prefix(); eprintln!("unimplemented import: {import_name}"); })?; @@ -38,7 +38,7 @@ fn _main() -> anyhow::Result<()> { if let Some(home) = home::home_dir() { let _ = rl.load_history(&home.join(".weplhistory")); } - let world = querier.world_name(); + let world = resolver.world_name(); println!("{}: {world}", "World".blue().bold()); let mut scope = HashMap::default(); let prompt = "> ".blue().bold().to_string(); @@ -50,7 +50,7 @@ fn _main() -> anyhow::Result<()> { let line = command::Cmd::parse(&line); match line { Ok(Some(cmd)) => { - match cmd.run(&mut runtime, &mut querier, &mut scope) { + match cmd.run(&mut runtime, &mut resolver, &mut scope) { Err(e) => { print_error_prefix(); eprintln!("{e}"); diff --git a/src/runtime.rs b/src/runtime.rs index 3ee552f..c2e0dc2 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -15,7 +15,7 @@ use wasmtime_wasi::preview2::{ }; use crate::{ - command::alt_parser::{self, Ident}, + command::parser::{self, Ident}, wit::WorldResolver, }; @@ -31,7 +31,7 @@ pub struct Runtime { impl Runtime { pub fn init( component_bytes: Vec, - querier: &WorldResolver, + resolver: &WorldResolver, stub_import: impl Fn(&str) + Sync + Send + Clone + 'static, ) -> anyhow::Result { let engine = load_engine()?; @@ -39,13 +39,13 @@ impl Runtime { let mut linker = Linker::::new(&engine); linker.allow_shadowing(true); - let imports_wasi_cli = querier.imports_wasi_cli(); + let imports_wasi_cli = resolver.imports_wasi_cli(); if imports_wasi_cli { log::debug!("Linking with wasi"); wasmtime_wasi::preview2::command::sync::add_to_linker(&mut linker)?; } - for (import_name, import) in querier.imports(!imports_wasi_cli) { - let import_name = querier.world_item_name(import_name); + for (import_name, import) in resolver.imports(!imports_wasi_cli) { + let import_name = resolver.world_item_name(import_name); let stub_import = stub_import.clone(); match import { wit_parser::WorldItem::Function(f) => { @@ -57,7 +57,7 @@ impl Runtime { })?; } wit_parser::WorldItem::Interface(i) => { - let interface = querier.interface_by_id(*i).unwrap(); + let interface = resolver.interface_by_id(*i).unwrap(); let mut root = linker.root(); let mut instance = root.instance(&import_name)?; for (_, f) in interface.functions.iter() { @@ -69,7 +69,7 @@ impl Runtime { })?; } for (name, t) in &interface.types { - let t = querier.type_by_id(*t).unwrap(); + let t = resolver.type_by_id(*t).unwrap(); match &t.kind { wit_parser::TypeDefKind::Resource => { let ty = wasmtime::component::ResourceType::host::<()>(); @@ -137,24 +137,23 @@ impl Runtime { /// export needed. pub fn stub( &mut self, - querier: &WorldResolver, - import_ident: alt_parser::ItemIdent<'_>, - export_ident: alt_parser::ItemIdent<'_>, + resolver: &WorldResolver, + import_ident: parser::ItemIdent<'_>, + export_ident: parser::ItemIdent<'_>, component_bytes: &[u8], ) -> anyhow::Result<()> { match (import_ident, export_ident) { + (parser::ItemIdent::Item(import_ident), parser::ItemIdent::Item(export_ident)) => { + self.stub_function(resolver, import_ident, export_ident, component_bytes) + } ( - alt_parser::ItemIdent::Item(import_ident), - alt_parser::ItemIdent::Item(export_ident), - ) => self.stub_function(querier, import_ident, export_ident, component_bytes), - ( - alt_parser::ItemIdent::Interface(import_ident), - alt_parser::ItemIdent::Interface(export_ident), - ) => self.stub_interface(querier, import_ident, export_ident, component_bytes), - (alt_parser::ItemIdent::Interface(_), alt_parser::ItemIdent::Item(_)) => { + parser::ItemIdent::Interface(import_ident), + parser::ItemIdent::Interface(export_ident), + ) => self.stub_interface(resolver, import_ident, export_ident, component_bytes), + (parser::ItemIdent::Interface(_), parser::ItemIdent::Item(_)) => { anyhow::bail!("cannot satisfy interface import with a function") } - (alt_parser::ItemIdent::Item(_), alt_parser::ItemIdent::Interface(_)) => { + (parser::ItemIdent::Item(_), parser::ItemIdent::Interface(_)) => { anyhow::bail!("cannot satisfy function import with an interface") } } @@ -162,9 +161,9 @@ impl Runtime { pub fn stub_interface( &mut self, - querier: &WorldResolver, - import_ident: alt_parser::InterfaceIdent<'_>, - export_ident: alt_parser::InterfaceIdent<'_>, + resolver: &WorldResolver, + import_ident: parser::InterfaceIdent<'_>, + export_ident: parser::InterfaceIdent<'_>, component_bytes: &[u8], ) -> anyhow::Result<()> { let component = load_component(&self.engine, component_bytes)?; @@ -174,7 +173,7 @@ impl Runtime { let mut import_instance = root .instance(&import_ident.to_string()) .with_context(|| format!("no imported instance named '{import_ident}' found"))?; - let import = querier + let import = resolver .imported_interface(import_ident) .with_context(|| format!("no imported interface named '{import_ident}' found"))?; let other = WorldResolver::from_bytes(component_bytes)?; @@ -197,7 +196,7 @@ impl Runtime { .iter() .zip(&exported_function.params) { - if !types_equal(querier, p1, &other, p2) { + if !types_equal(resolver, p1, &other, p2) { anyhow::bail!( "different types for arg '{arg_name}' in function '{fun_name}'" ) @@ -214,13 +213,13 @@ impl Runtime { .collect::>(); for (name, ty) in is { let e = es.get(name).with_context(|| format!("exported function '{fun_name}' does not have return value '{name}'"))?; - if !types_equal(querier, ty, &other, e) { + if !types_equal(resolver, ty, &other, e) { anyhow::bail!("return value '{name}' has differing types"); } } } (wit_parser::Results::Anon(t1), wit_parser::Results::Anon(t2)) => { - if !types_equal(querier, t1, &other, t2) { + if !types_equal(resolver, t1, &other, t2) { anyhow::bail!("return types did not match for function {fun_name}"); } } @@ -257,13 +256,13 @@ impl Runtime { pub fn stub_function( &mut self, - querier: &WorldResolver, - import_ident: alt_parser::Ident<'_>, - export_ident: alt_parser::Ident<'_>, + resolver: &WorldResolver, + import_ident: parser::Ident<'_>, + export_ident: parser::Ident<'_>, component_bytes: &[u8], ) -> anyhow::Result<()> { // type checking - let import = querier + let import = resolver .imported_function(import_ident) .with_context(|| format!("no import with name '{import_ident}'"))?; let other = WorldResolver::from_bytes(component_bytes)?; @@ -504,29 +503,29 @@ impl WasiView for ImportImplsContext { } fn types_equal( - querier1: &WorldResolver, + resolver1: &WorldResolver, t1: &wit_parser::Type, - querier2: &WorldResolver, + resolver2: &WorldResolver, t2: &wit_parser::Type, ) -> bool { match (t1, t2) { (wit_parser::Type::Id(t1), wit_parser::Type::Id(t2)) => { - let t1 = querier1.type_by_id(*t1).unwrap(); - let t2 = querier2.type_by_id(*t2).unwrap(); - type_defs_equal(querier1, &t1.kind, querier2, &t2.kind) + let t1 = resolver1.type_by_id(*t1).unwrap(); + let t2 = resolver2.type_by_id(*t2).unwrap(); + type_defs_equal(resolver1, &t1.kind, resolver2, &t2.kind) } (wit_parser::Type::Id(t1), t2) => { - let t1 = querier1.type_by_id(*t1).unwrap(); + let t1 = resolver1.type_by_id(*t1).unwrap(); if let wit_parser::TypeDefKind::Type(t1) = &t1.kind { - types_equal(querier1, t1, querier2, t2) + types_equal(resolver1, t1, resolver2, t2) } else { false } } (t1, wit_parser::Type::Id(t2)) => { - let t2 = querier1.type_by_id(*t2).unwrap(); + let t2 = resolver1.type_by_id(*t2).unwrap(); if let wit_parser::TypeDefKind::Type(t2) = &t2.kind { - types_equal(querier1, t1, querier2, t2) + types_equal(resolver1, t1, resolver2, t2) } else { false } @@ -536,27 +535,27 @@ fn types_equal( } fn type_defs_equal( - querier1: &WorldResolver, + resolver1: &WorldResolver, t1: &wit_parser::TypeDefKind, - querier2: &WorldResolver, + resolver2: &WorldResolver, t2: &wit_parser::TypeDefKind, ) -> bool { match (t1, t2) { (wit_parser::TypeDefKind::Result(r1), wit_parser::TypeDefKind::Result(r2)) => { let oks = match (&r1.ok, &r2.ok) { (None, None) => true, - (Some(t1), Some(t2)) => types_equal(querier1, t1, querier2, t2), + (Some(t1), Some(t2)) => types_equal(resolver1, t1, resolver2, t2), _ => false, }; let errs = match (&r1.err, &r2.err) { (None, None) => true, - (Some(t1), Some(t2)) => types_equal(querier1, t1, querier2, t2), + (Some(t1), Some(t2)) => types_equal(resolver1, t1, resolver2, t2), _ => false, }; oks && errs } (wit_parser::TypeDefKind::List(t1), wit_parser::TypeDefKind::List(t2)) => { - types_equal(querier1, t1, querier2, t2) + types_equal(resolver1, t1, resolver2, t2) } (wit_parser::TypeDefKind::Variant(v1), wit_parser::TypeDefKind::Variant(v2)) => { if v1.cases.len() != v2.cases.len() { @@ -564,7 +563,7 @@ fn type_defs_equal( } v1.cases.iter().zip(v2.cases.iter()).all(|(c1, c2)| { let types_equal = match (&c1.ty, &c2.ty) { - (Some(t1), Some(t2)) => types_equal(querier1, t1, querier2, t2), + (Some(t1), Some(t2)) => types_equal(resolver1, t1, resolver2, t2), (None, None) => true, _ => false, }; diff --git a/src/wit.rs b/src/wit.rs index b79b511..fe6307d 100644 --- a/src/wit.rs +++ b/src/wit.rs @@ -7,7 +7,7 @@ use wit_parser::{ WorldKey, }; -use crate::command::alt_parser; +use crate::command::parser; /// A resolver for a wit world. pub struct WorldResolver { @@ -38,7 +38,7 @@ impl WorldResolver { } /// Get the exported function by the given `FunctionIdent`. - pub fn exported_function(&self, ident: alt_parser::Ident) -> Option<&Function> { + pub fn exported_function(&self, ident: parser::Ident) -> Option<&Function> { match ident.interface { Some(i) => { let interface = self.exported_interface(i)?; @@ -55,7 +55,7 @@ impl WorldResolver { } /// Get the imported function by the given `FunctionIdent`. - pub fn imported_function(&self, ident: alt_parser::Ident) -> Option<&Function> { + pub fn imported_function(&self, ident: parser::Ident) -> Option<&Function> { match ident.interface { Some(i) => { let interface = self.imported_interface(i)?; @@ -72,12 +72,12 @@ impl WorldResolver { } /// Get the exported interface by the given `InterfaceIdent`. - pub fn exported_interface(&self, ident: alt_parser::InterfaceIdent) -> Option<&Interface> { + pub fn exported_interface(&self, ident: parser::InterfaceIdent) -> Option<&Interface> { self.interface_in_items(ident, self.world().exports.iter()) } /// Get the imported interface by the given `InterfaceIdent`. - pub fn imported_interface(&self, ident: alt_parser::InterfaceIdent) -> Option<&Interface> { + pub fn imported_interface(&self, ident: parser::InterfaceIdent) -> Option<&Interface> { self.interface_in_items(ident, self.world().imports.iter()) } @@ -342,7 +342,7 @@ impl WorldResolver { /// Get an interface by its ident from a list of world items. fn interface_in_items<'a>( &self, - ident: alt_parser::InterfaceIdent, + ident: parser::InterfaceIdent, items: impl Iterator, ) -> Option<&Interface> { let item = self.get_world_item_by_name(items, &ident.to_string())?;