Remember what files error spans come from
This commit is contained in:
parent
7bab866eae
commit
5d191d0edd
6 changed files with 100 additions and 53 deletions
|
|
@ -202,7 +202,10 @@ impl<'a> CommandState<'a> {
|
|||
self.dated.insert(to, entry);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::MoveWithoutSource { span })
|
||||
Err(Error::MoveWithoutSource {
|
||||
file: self.command.source.file(),
|
||||
span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,12 +86,13 @@ impl DateSpec {
|
|||
Some((start, range))
|
||||
}
|
||||
|
||||
fn step(from: NaiveDate, repeat: &Spanned<Delta>) -> Result<NaiveDate> {
|
||||
let to = repeat.value.apply_date(from)?;
|
||||
fn step(file: usize, from: NaiveDate, repeat: &Spanned<Delta>) -> Result<NaiveDate> {
|
||||
let to = repeat.value.apply_date(file, from)?;
|
||||
if to > from {
|
||||
Ok(to)
|
||||
} else {
|
||||
Err(Error::RepeatDidNotMoveForwards {
|
||||
file,
|
||||
span: repeat.span,
|
||||
from,
|
||||
to,
|
||||
|
|
@ -99,13 +100,13 @@ impl DateSpec {
|
|||
}
|
||||
}
|
||||
|
||||
fn dates(&self, start: NaiveDate) -> Result<Dates> {
|
||||
let root = self.start_delta.apply_date(start)?;
|
||||
fn dates(&self, file: usize, start: NaiveDate) -> Result<Dates> {
|
||||
let root = self.start_delta.apply_date(file, start)?;
|
||||
Ok(if let Some(root_time) = self.start_time {
|
||||
let (other, other_time) = self.end_delta.apply_date_time(root, root_time)?;
|
||||
let (other, other_time) = self.end_delta.apply_date_time(file, root, root_time)?;
|
||||
Dates::new_with_time(root, root_time, other, other_time)
|
||||
} else {
|
||||
let other = self.end_delta.apply_date(root)?;
|
||||
let other = self.end_delta.apply_date(file, root)?;
|
||||
Dates::new(root, other)
|
||||
})
|
||||
}
|
||||
|
|
@ -113,19 +114,20 @@ impl DateSpec {
|
|||
|
||||
impl<'a> CommandState<'a> {
|
||||
pub fn eval_date_spec(&mut self, spec: DateSpec) -> Result<()> {
|
||||
let file = self.command.source.file();
|
||||
if let Some(repeat) = &spec.repeat {
|
||||
if let Some((mut start, range)) = spec.start_and_range(self) {
|
||||
while start < range.from() {
|
||||
start = DateSpec::step(start, repeat)?;
|
||||
start = DateSpec::step(file, start, repeat)?;
|
||||
}
|
||||
while start <= range.until() {
|
||||
let dates = spec.dates(start)?;
|
||||
let dates = spec.dates(file, start)?;
|
||||
self.add(self.kind(), Some(dates));
|
||||
start = DateSpec::step(start, repeat)?;
|
||||
start = DateSpec::step(file, start, repeat)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let dates = spec.dates(spec.start)?;
|
||||
let dates = spec.dates(file, spec.start)?;
|
||||
self.add(self.kind(), Some(dates));
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ pub enum Var {
|
|||
}
|
||||
|
||||
impl Var {
|
||||
fn eval(self, date: NaiveDate) -> Result<i64> {
|
||||
fn eval(self, file: usize, date: NaiveDate) -> Result<i64> {
|
||||
Ok(match self {
|
||||
Var::JulianDay => date.num_days_from_ce().into(),
|
||||
Var::Year => date.year().into(),
|
||||
|
|
@ -81,6 +81,7 @@ impl Var {
|
|||
}
|
||||
Var::Easter(span) => {
|
||||
let e = computus::gregorian(date.year()).map_err(|e| Error::Easter {
|
||||
file,
|
||||
span,
|
||||
date,
|
||||
msg: e,
|
||||
|
|
@ -198,38 +199,46 @@ impl From<Weekday> for Expr {
|
|||
}
|
||||
|
||||
impl Expr {
|
||||
fn eval(&self, date: NaiveDate) -> Result<i64> {
|
||||
fn eval(&self, file: usize, date: NaiveDate) -> Result<i64> {
|
||||
Ok(match self {
|
||||
Expr::Lit(l) => *l,
|
||||
Expr::Var(v) => v.eval(date)?,
|
||||
Expr::Neg(e) => -e.eval(date)?,
|
||||
Expr::Add(a, b) => a.eval(date)? + b.eval(date)?,
|
||||
Expr::Sub(a, b) => a.eval(date)? - b.eval(date)?,
|
||||
Expr::Mul(a, b) => a.eval(date)? * b.eval(date)?,
|
||||
Expr::Var(v) => v.eval(file, date)?,
|
||||
Expr::Neg(e) => -e.eval(file, date)?,
|
||||
Expr::Add(a, b) => a.eval(file, date)? + b.eval(file, date)?,
|
||||
Expr::Sub(a, b) => a.eval(file, date)? - b.eval(file, date)?,
|
||||
Expr::Mul(a, b) => a.eval(file, date)? * b.eval(file, date)?,
|
||||
Expr::Div(a, b, span) => {
|
||||
let b = b.eval(date)?;
|
||||
let b = b.eval(file, date)?;
|
||||
if b == 0 {
|
||||
return Err(Error::DivByZero { span: *span, date });
|
||||
return Err(Error::DivByZero {
|
||||
file,
|
||||
span: *span,
|
||||
date,
|
||||
});
|
||||
}
|
||||
a.eval(date)?.div_euclid(b)
|
||||
a.eval(file, date)?.div_euclid(b)
|
||||
}
|
||||
Expr::Mod(a, b, span) => {
|
||||
let b = b.eval(date)?;
|
||||
let b = b.eval(file, date)?;
|
||||
if b == 0 {
|
||||
return Err(Error::ModByZero { span: *span, date });
|
||||
return Err(Error::ModByZero {
|
||||
file,
|
||||
span: *span,
|
||||
date,
|
||||
});
|
||||
}
|
||||
a.eval(date)?.rem_euclid(b)
|
||||
a.eval(file, date)?.rem_euclid(b)
|
||||
}
|
||||
Expr::Eq(a, b) => b2i(a.eval(date)? == b.eval(date)?),
|
||||
Expr::Neq(a, b) => b2i(a.eval(date)? != b.eval(date)?),
|
||||
Expr::Lt(a, b) => b2i(a.eval(date)? < b.eval(date)?),
|
||||
Expr::Lte(a, b) => b2i(a.eval(date)? <= b.eval(date)?),
|
||||
Expr::Gt(a, b) => b2i(a.eval(date)? > b.eval(date)?),
|
||||
Expr::Gte(a, b) => b2i(a.eval(date)? >= b.eval(date)?),
|
||||
Expr::Not(e) => b2i(!i2b(e.eval(date)?)),
|
||||
Expr::And(a, b) => b2i(i2b(a.eval(date)?) && i2b(b.eval(date)?)),
|
||||
Expr::Or(a, b) => b2i(i2b(a.eval(date)?) || i2b(b.eval(date)?)),
|
||||
Expr::Xor(a, b) => b2i(i2b(a.eval(date)?) ^ i2b(b.eval(date)?)),
|
||||
Expr::Eq(a, b) => b2i(a.eval(file, date)? == b.eval(file, date)?),
|
||||
Expr::Neq(a, b) => b2i(a.eval(file, date)? != b.eval(file, date)?),
|
||||
Expr::Lt(a, b) => b2i(a.eval(file, date)? < b.eval(file, date)?),
|
||||
Expr::Lte(a, b) => b2i(a.eval(file, date)? <= b.eval(file, date)?),
|
||||
Expr::Gt(a, b) => b2i(a.eval(file, date)? > b.eval(file, date)?),
|
||||
Expr::Gte(a, b) => b2i(a.eval(file, date)? >= b.eval(file, date)?),
|
||||
Expr::Not(e) => b2i(!i2b(e.eval(file, date)?)),
|
||||
Expr::And(a, b) => b2i(i2b(a.eval(file, date)?) && i2b(b.eval(file, date)?)),
|
||||
Expr::Or(a, b) => b2i(i2b(a.eval(file, date)?) || i2b(b.eval(file, date)?)),
|
||||
Expr::Xor(a, b) => b2i(i2b(a.eval(file, date)?) ^ i2b(b.eval(file, date)?)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -325,28 +334,29 @@ impl FormulaSpec {
|
|||
s.limit_from_until(range)
|
||||
}
|
||||
|
||||
fn dates(&self, start: NaiveDate) -> Result<Dates> {
|
||||
let root = self.start_delta.apply_date(start)?;
|
||||
fn dates(&self, file: usize, start: NaiveDate) -> Result<Dates> {
|
||||
let root = self.start_delta.apply_date(file, start)?;
|
||||
Ok(if let Some(root_time) = self.start_time {
|
||||
let (other, other_time) = self.end_delta.apply_date_time(root, root_time)?;
|
||||
let (other, other_time) = self.end_delta.apply_date_time(file, root, root_time)?;
|
||||
Dates::new_with_time(root, root_time, other, other_time)
|
||||
} else {
|
||||
let other = self.end_delta.apply_date(root)?;
|
||||
let other = self.end_delta.apply_date(file, root)?;
|
||||
Dates::new(root, other)
|
||||
})
|
||||
}
|
||||
|
||||
fn eval(&self, date: NaiveDate) -> Result<bool> {
|
||||
Ok(i2b(self.start.eval(date)?))
|
||||
fn eval(&self, file: usize, date: NaiveDate) -> Result<bool> {
|
||||
Ok(i2b(self.start.eval(file, date)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CommandState<'a> {
|
||||
pub fn eval_formula_spec(&mut self, spec: FormulaSpec) -> Result<()> {
|
||||
if let Some(range) = spec.range(self) {
|
||||
let file = self.command.source.file();
|
||||
for day in range.days() {
|
||||
if spec.eval(day)? {
|
||||
let dates = spec.dates(day)?;
|
||||
if spec.eval(file, day)? {
|
||||
let dates = spec.dates(file, day)?;
|
||||
self.add(self.kind(), Some(dates));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ impl From<&commands::Delta> for Delta {
|
|||
}
|
||||
|
||||
struct DeltaEval {
|
||||
file: usize,
|
||||
start: NaiveDate,
|
||||
start_time: Option<Time>,
|
||||
curr: NaiveDate,
|
||||
|
|
@ -150,8 +151,9 @@ struct DeltaEval {
|
|||
}
|
||||
|
||||
impl DeltaEval {
|
||||
fn new(start: NaiveDate, start_time: Option<Time>) -> Self {
|
||||
fn new(file: usize, start: NaiveDate, start_time: Option<Time>) -> Self {
|
||||
Self {
|
||||
file,
|
||||
start,
|
||||
start_time,
|
||||
curr: start,
|
||||
|
|
@ -161,6 +163,7 @@ impl DeltaEval {
|
|||
|
||||
fn err_step(&self, span: Span) -> Error {
|
||||
Error::DeltaInvalidStep {
|
||||
file: self.file,
|
||||
span,
|
||||
start: self.start,
|
||||
start_time: self.start_time,
|
||||
|
|
@ -171,6 +174,7 @@ impl DeltaEval {
|
|||
|
||||
fn err_time(&self, span: Span) -> Error {
|
||||
Error::DeltaNoTime {
|
||||
file: self.file,
|
||||
span,
|
||||
start: self.start,
|
||||
prev: self.curr,
|
||||
|
|
@ -309,20 +313,29 @@ impl Delta {
|
|||
self.steps.iter().map(|step| step.value.upper_bound()).sum()
|
||||
}
|
||||
|
||||
fn apply(&self, start: (NaiveDate, Option<Time>)) -> Result<(NaiveDate, Option<Time>)> {
|
||||
let mut eval = DeltaEval::new(start.0, start.1);
|
||||
fn apply(
|
||||
&self,
|
||||
file: usize,
|
||||
start: (NaiveDate, Option<Time>),
|
||||
) -> Result<(NaiveDate, Option<Time>)> {
|
||||
let mut eval = DeltaEval::new(file, start.0, start.1);
|
||||
for step in &self.steps {
|
||||
eval.apply(step)?;
|
||||
}
|
||||
Ok((eval.curr, eval.curr_time))
|
||||
}
|
||||
|
||||
pub fn apply_date(&self, date: NaiveDate) -> Result<NaiveDate> {
|
||||
Ok(self.apply((date, None))?.0)
|
||||
pub fn apply_date(&self, file: usize, date: NaiveDate) -> Result<NaiveDate> {
|
||||
Ok(self.apply(file, (date, None))?.0)
|
||||
}
|
||||
|
||||
pub fn apply_date_time(&self, date: NaiveDate, time: Time) -> Result<(NaiveDate, Time)> {
|
||||
let (date, time) = self.apply((date, Some(time)))?;
|
||||
pub fn apply_date_time(
|
||||
&self,
|
||||
file: usize,
|
||||
date: NaiveDate,
|
||||
time: Time,
|
||||
) -> Result<(NaiveDate, Time)> {
|
||||
let (date, time) = self.apply(file, (date, Some(time)))?;
|
||||
Ok((date, time.expect("time was not preserved")))
|
||||
}
|
||||
}
|
||||
|
|
@ -345,7 +358,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn apply_d(step: Step, from: (i32, u32, u32)) -> Result<NaiveDate> {
|
||||
delta(step).apply_date(NaiveDate::from_ymd(from.0, from.1, from.2))
|
||||
delta(step).apply_date(0, NaiveDate::from_ymd(from.0, from.1, from.2))
|
||||
}
|
||||
|
||||
fn test_d(step: Step, from: (i32, u32, u32), expected: (i32, u32, u32)) {
|
||||
|
|
@ -357,6 +370,7 @@ mod tests {
|
|||
|
||||
fn apply_dt(step: Step, from: (i32, u32, u32, u32, u32)) -> Result<(NaiveDate, Time)> {
|
||||
delta(step).apply_date_time(
|
||||
0,
|
||||
NaiveDate::from_ymd(from.0, from.1, from.2),
|
||||
Time::new(from.3, from.4),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ pub enum Error {
|
|||
/// A delta step resulted in an invalid date.
|
||||
#[error("delta step resulted in invalid date")]
|
||||
DeltaInvalidStep {
|
||||
file: usize,
|
||||
span: Span,
|
||||
start: NaiveDate,
|
||||
start_time: Option<Time>,
|
||||
|
|
@ -18,6 +19,7 @@ pub enum Error {
|
|||
/// A time-based delta step was applied to a date without time.
|
||||
#[error("time-based delta step applied to date without time")]
|
||||
DeltaNoTime {
|
||||
file: usize,
|
||||
span: Span,
|
||||
start: NaiveDate,
|
||||
prev: NaiveDate,
|
||||
|
|
@ -27,6 +29,7 @@ pub enum Error {
|
|||
/// in time (`to < from`).
|
||||
#[error("repeat delta did not move forwards")]
|
||||
RepeatDidNotMoveForwards {
|
||||
file: usize,
|
||||
span: Span,
|
||||
from: NaiveDate,
|
||||
to: NaiveDate,
|
||||
|
|
@ -34,16 +37,25 @@ pub enum Error {
|
|||
/// A `MOVE a TO b` statement was executed, but there was no entry at the
|
||||
/// date `a`.
|
||||
#[error("tried to move nonexisting entry")]
|
||||
MoveWithoutSource { span: Span },
|
||||
MoveWithoutSource { file: usize, span: Span },
|
||||
/// A division by zero has occurred.
|
||||
#[error("tried to divide by zero")]
|
||||
DivByZero { span: Span, date: NaiveDate },
|
||||
DivByZero {
|
||||
file: usize,
|
||||
span: Span,
|
||||
date: NaiveDate,
|
||||
},
|
||||
/// A modulo operation by zero has occurred.
|
||||
#[error("tried to modulo by zero")]
|
||||
ModByZero { span: Span, date: NaiveDate },
|
||||
ModByZero {
|
||||
file: usize,
|
||||
span: Span,
|
||||
date: NaiveDate,
|
||||
},
|
||||
/// Easter calculation failed.
|
||||
#[error("easter calculation failed")]
|
||||
Easter {
|
||||
file: usize,
|
||||
span: Span,
|
||||
date: NaiveDate,
|
||||
msg: &'static str,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@ pub struct Source {
|
|||
command: usize,
|
||||
}
|
||||
|
||||
impl Source {
|
||||
pub fn file(&self) -> usize {
|
||||
self.file
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SourcedCommand<'a> {
|
||||
pub source: Source,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue