Improved bug implementations

This commit is contained in:
2026-05-16 05:32:10 +02:00
parent cbd060149d
commit 1a80fe074b
4 changed files with 41 additions and 31 deletions
+2 -1
View File
@@ -20,7 +20,8 @@ pub struct AstError<'a, T> {
#[derive(Debug, Clone)]
pub enum ErrorCode {
InvalidStatement = 200,
InvalidStatement,
AstGenBug,
}
impl<T> From<pest::error::Error<Rule>> for ParseError<'_, T> {
+16
View File
@@ -32,6 +32,22 @@ pub fn parse<'a>(source: &'a str) -> Result<Vec<TopLevel>, ParseError<'a, Vec<To
}
}
#[macro_export]
macro_rules! ast_ensure {
($pair:expr, $rule:expr => $body:block) => {
if $pair.as_rule() == $rule
$body
else {
Err(AstError {
span: $pair.as_span(),
error_code: crate::error::ErrorCode::AstGenBug,
error_message: format!("Possible bug: expected {:?}, got {}", $rule, $pair),
recovered: None,
})
}
};
}
#[macro_export]
macro_rules! ast_expr {
($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{
+4 -1
View File
@@ -6,6 +6,7 @@ pub mod types;
use crate::{
Rule,
ast::*,
ast_ensure,
error::{AstError, IntoErr, collect_recovered},
parser::consume_rule,
};
@@ -14,7 +15,9 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Identifier {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
Ok(Identifier(pair.as_str().to_string()))
ast_ensure!(pair, Rule::identifier => {
Ok(Identifier(pair.as_str().to_string()))
})
}
}
+19 -29
View File
@@ -1,7 +1,7 @@
use crate::{
Rule,
ast::*,
ast_expr,
ast_ensure, ast_expr,
error::{AstError, AstResult, ErrorCode, IntoErr, collect_recovered},
parser::listen_rule,
};
@@ -10,19 +10,25 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
if pair.as_rule() == Rule::block {
ast_ensure!(pair, Rule::block => {
ast_expr!(Block(collect_recovered(pair.into_inner())))
} else {
Err(AstError {
span: pair.as_span(),
error_code: ErrorCode::InvalidStatement,
error_message: format!(
"BUG: AST requires a block, this isn't a block, it's a {:?}",
pair.as_rule()
),
recovered: None,
})
}
})
}
}
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBranch {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
let mut inner = pair.into_inner();
let condition = inner.next().unwrap().try_into().get()?;
let body = inner.next().unwrap().try_into().get()?;
Ok(StatementBranch {
condition,
body: Box::new(body),
})
}
}
@@ -114,19 +120,3 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
})
}
}
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBranch {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
let mut inner = pair.into_inner();
let condition = inner.next().unwrap().try_into().get()?;
let body = inner.next().unwrap().try_into().get()?;
Ok(StatementBranch {
condition,
body: Box::new(body),
})
}
}