Skip to content

Commit

Permalink
Pass interrupt through to Value::compare
Browse files Browse the repository at this point in the history
  • Loading branch information
printfn committed Mar 6, 2024
1 parent fd74661 commit abf50da
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 22 deletions.
47 changes: 43 additions & 4 deletions core/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::serialize::{Deserialize, Serialize};
use crate::value::{built_in_function::BuiltInFunction, ApplyMulHandling, Value};
use crate::Attrs;
use std::sync::Arc;
use std::{fmt, io};
use std::{cmp, fmt, io};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum BitwiseBop {
Expand Down Expand Up @@ -99,7 +99,7 @@ impl fmt::Display for Bop {
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug)]
pub(crate) enum Expr {
Literal(Value),
Ident(Ident),
Expand Down Expand Up @@ -127,6 +127,43 @@ pub(crate) enum Expr {
}

impl Expr {
pub(crate) fn compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<bool> {
Ok(match (self, other) {
(Self::Literal(a), Self::Literal(b)) => {
a.compare(b, int)? == Some(cmp::Ordering::Equal)
}
(Self::Ident(a), Self::Ident(b)) => a == b,
(Self::Parens(a), Self::Parens(b)) => a.compare(b, int)?,
(Self::UnaryMinus(a), Self::UnaryMinus(b)) => a.compare(b, int)?,
(Self::UnaryPlus(a), Self::UnaryPlus(b)) => a.compare(b, int)?,
(Self::UnaryDiv(a), Self::UnaryDiv(b)) => a.compare(b, int)?,
(Self::Factorial(a), Self::Factorial(b)) => a.compare(b, int)?,
(Self::Bop(a1, a2, a3), Self::Bop(b1, b2, b3)) => {
a1 == b1 && a2.compare(b2, int)? && a3.compare(b3, int)?
}
(Self::Apply(a1, a2), Self::Apply(b1, b2)) => {
a1.compare(b1, int)? && a2.compare(b2, int)?
}
(Self::ApplyFunctionCall(a1, a2), Self::ApplyFunctionCall(b1, b2)) => {
a1.compare(b1, int)? && a2.compare(b2, int)?
}
(Self::ApplyMul(a1, a2), Self::ApplyMul(b1, b2)) => {
a1.compare(b1, int)? && a2.compare(b2, int)?
}
(Self::As(a1, a2), Self::As(b1, b2)) => a1.compare(b1, int)? && a2.compare(b2, int)?,
(Self::Fn(a1, a2), Self::Fn(b1, b2)) => a1 == b1 && a2.compare(b2, int)?,
(Self::Of(a1, a2), Self::Of(b1, b2)) => a1 == b1 && a2.compare(b2, int)?,
(Self::Assign(a1, a2), Self::Assign(b1, b2)) => a1 == b1 && a2.compare(b2, int)?,
(Self::Equality(a1, a2, a3), Self::Equality(b1, b2, b3)) => {
a1 == b1 && a2.compare(b2, int)? && a3.compare(b3, int)?
}
(Self::Statements(a1, a2), Self::Statements(b1, b2)) => {
a1.compare(b1, int)? && a2.compare(b2, int)?
}
_ => false,
})
}

pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> {
match self {
Self::Literal(x) => {
Expand Down Expand Up @@ -473,8 +510,10 @@ pub(crate) fn evaluate<I: Interrupt>(
Expr::Equality(is_equals, a, b) => {
let lhs = evaluate(*a, scope.clone(), attrs, context, int)?;
let rhs = evaluate(*b, scope.clone(), attrs, context, int)?;

Value::Bool(if is_equals { lhs == rhs } else { lhs != rhs })
Value::Bool(match lhs.compare(&rhs, int)? {
Some(cmp::Ordering::Equal) => is_equals,
Some(cmp::Ordering::Greater | cmp::Ordering::Less) | None => !is_equals,
})
}
})
}
Expand Down
36 changes: 24 additions & 12 deletions core/src/num/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use crate::scope::Scope;
use crate::serialize::{Deserialize, Serialize};
use crate::units::{lookup_default_unit, query_unit_static};
use crate::{ast, ident::Ident};
use crate::{interrupt::Never, Attrs, Span, SpanKind};
use crate::{Attrs, Span, SpanKind};
use std::borrow::Cow;
use std::collections::HashMap;
use std::ops::Neg;
use std::sync::Arc;
use std::{fmt, io};
use std::{cmp, fmt, io};

pub(crate) mod base_unit;
pub(crate) mod named_unit;
Expand All @@ -37,21 +37,33 @@ pub(crate) struct Value {
simplifiable: bool,
}

impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
impl Value {
pub(crate) fn compare<I: Interrupt>(
&self,
other: &Self,
int: &I,
) -> FResult<Option<cmp::Ordering>> {
if self.value == other.value && self.unit == other.unit {
return true;
return Ok(Some(cmp::Ordering::Equal));
}
match self.clone().sub(other.clone(), &Never) {
Err(_) => false,
Ok(result) => result.is_zero(),
match self.clone().sub(other.clone(), int) {
Err(FendError::Interrupted) => Err(FendError::Interrupted),
Err(_) => Ok(None),
Ok(result) => {
if result.is_zero() {
return Ok(Some(cmp::Ordering::Equal));
}
let Ok(c) = result.value.one_point() else {
return Ok(None);
};
if !c.imag().is_zero() {
return Ok(None);
}
Ok(Some(c.real().cmp(&0.into())))
}
}
}
}

impl Eq for Value {}

impl Value {
pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> {
self.value.serialize(write)?;
self.unit.serialize(write)?;
Expand Down
29 changes: 26 additions & 3 deletions core/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ use crate::{ast::Expr, error::Interrupt};
use std::io;
use std::sync::Arc;

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone)]
enum ScopeValue {
//Variable(Value),
LazyVariable(Expr, Option<Arc<Scope>>),
}

impl ScopeValue {
pub(crate) fn compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<bool> {
let Self::LazyVariable(a1, a2) = self;
let Self::LazyVariable(b1, b2) = other;
Ok(a1.compare(b1, int)? && compare_option_arc_scope(a2, b2, int)?)
}

fn eval<I: Interrupt>(
&self,
attrs: Attrs,
Expand Down Expand Up @@ -55,14 +60,32 @@ impl ScopeValue {
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone)]
pub(crate) struct Scope {
ident: Ident,
value: ScopeValue,
inner: Option<Arc<Scope>>,
}

pub(crate) fn compare_option_arc_scope<I: Interrupt>(
a: &Option<Arc<Scope>>,
b: &Option<Arc<Scope>>,
int: &I,
) -> FResult<bool> {
Ok(match (a, b) {
(None, None) => true,
(Some(a), Some(b)) => a.compare(b, int)?,
_ => false,
})
}

impl Scope {
pub(crate) fn compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<bool> {
Ok(self.ident == other.ident
&& self.value.compare(&other.value, int)?
&& compare_option_arc_scope(&self.inner, &other.inner, int)?)
}

pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> {
self.ident.serialize(write)?;
self.value.serialize(write)?;
Expand Down
51 changes: 48 additions & 3 deletions core/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use crate::date::{Date, DayOfWeek, Month};
use crate::error::{FendError, Interrupt};
use crate::num::{Base, FormattingStyle, Number};
use crate::result::FResult;
use crate::scope::Scope;
use crate::scope::{compare_option_arc_scope, Scope};
use crate::serialize::{Deserialize, Serialize};
use crate::{ast::Expr, ident::Ident};
use crate::{date, Attrs, Span, SpanKind};
use std::borrow::Cow;
use std::io;
use std::{cmp, io};
use std::{
fmt::{self, Write},
sync::Arc,
Expand All @@ -18,7 +18,7 @@ pub(crate) mod built_in_function;

use built_in_function::BuiltInFunction;

#[derive(Clone, PartialEq, Eq)]
#[derive(Clone)]
pub(crate) enum Value {
Num(Box<Number>),
BuiltInFunction(BuiltInFunction),
Expand All @@ -44,6 +44,51 @@ pub(crate) enum ApplyMulHandling {
}

impl Value {
pub(crate) fn compare<I: Interrupt>(
&self,
other: &Self,
int: &I,
) -> FResult<Option<cmp::Ordering>> {
let c = |cmp| {
if cmp {
Some(cmp::Ordering::Equal)
} else {
None
}
};
Ok(match (self, other) {
(Self::Num(a), Self::Num(b)) => a.compare(b, int)?,
(Self::BuiltInFunction(a), Self::BuiltInFunction(b)) => c(a == b),
(Self::Format(a), Self::Format(b)) => c(a == b),
(Self::Dp, Self::Dp) | (Self::Sf, Self::Sf) | (Self::Unit, Self::Unit) => c(true),
(Self::Base(a), Self::Base(b)) => c(a == b),
(Self::Fn(a1, a2, a3), Self::Fn(b1, b2, b3)) => {
c(a1 == b1 && a2.compare(b2, int)? && compare_option_arc_scope(a3, b3, int)?)
}
(Self::Object(a), Self::Object(b)) => {
if a.len() != b.len() {
return Ok(None);
}
for ((a1, a2), (b1, b2)) in a.iter().zip(b.iter()) {
if a1 != b1 {
return Ok(None);
}
match a2.compare(b2, int)? {
Some(cmp::Ordering::Equal) => (),
other => return Ok(other),
}
}
return Ok(Some(cmp::Ordering::Equal));
}
(Self::String(a), Self::String(b)) => c(a == b),
(Self::Bool(a), Self::Bool(b)) => c(a == b),
(Self::Month(a), Self::Month(b)) => c(a == b),
(Self::DayOfWeek(a), Self::DayOfWeek(b)) => c(a == b),
(Self::Date(a), Self::Date(b)) => c(a == b),
_ => None,
})
}

pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> {
match self {
Self::Num(n) => {
Expand Down

0 comments on commit abf50da

Please sign in to comment.