use wdl_ast::AstNode;
use wdl_ast::AstToken;
use wdl_ast::Diagnostic;
use wdl_ast::Span;
use wdl_ast::v1::Expr;
use wdl_ast::v1::LiteralExpr;
use wdl_ast::v1::Minus;
use crate::Diagnostics;
use crate::VisitReason;
use crate::Visitor;
fn integer_not_in_range(span: Span) -> Diagnostic {
Diagnostic::error(format!(
"literal integer exceeds the range for a 64-bit signed integer ({min}..={max})",
min = i64::MIN,
max = i64::MAX,
))
.with_label("this literal integer is not in range", span)
}
fn float_not_in_range(span: Span) -> Diagnostic {
Diagnostic::error(format!(
"literal float exceeds the range for a 64-bit float ({min:+e}..={max:+e})",
min = f64::MIN,
max = f64::MAX,
))
.with_label("this literal float is not in range", span)
}
#[derive(Debug, Default)]
pub struct NumberVisitor {
negation_start: Option<usize>,
}
impl Visitor for NumberVisitor {
fn reset(&mut self) {
*self = Default::default();
}
fn expr(&mut self, diagnostics: &mut Diagnostics, reason: VisitReason, expr: &Expr) {
if reason == VisitReason::Exit {
self.negation_start = None;
return;
}
match expr {
Expr::Literal(LiteralExpr::Integer(i)) => {
let in_range = if self.negation_start.is_some() {
i.negate().is_some()
} else {
i.value().is_some()
};
if in_range {
return;
}
let start = self
.negation_start
.or_else(|| i.minus().map(|t| t.span().start()));
let span = i.integer().span();
let span = match start {
Some(start) => Span::new(start, span.end() - start),
None => span,
};
diagnostics.add(integer_not_in_range(span));
}
Expr::Literal(LiteralExpr::Float(f)) => {
if f.value().is_some() {
return;
}
let start = self
.negation_start
.or_else(|| f.minus().map(|t| t.span().start()));
let span = f.float().span();
let span = match start {
Some(start) => Span::new(start, span.end() - start),
None => span,
};
diagnostics.add(float_not_in_range(span));
}
Expr::Negation(negation) => {
if matches!(
negation.operand(),
Expr::Literal(LiteralExpr::Integer(_)) | Expr::Literal(LiteralExpr::Float(_))
) {
self.negation_start = Some(
negation
.token::<Minus<_>>()
.expect("should have minus token")
.span()
.start(),
);
}
}
_ => {}
}
}
}