1 use crate::ast::Bop; 2 use crate::date::{Date, DayOfWeek, Month}; 3 use crate::error::{FendError, Interrupt}; 4 use crate::num::{Base, FormattingStyle, Number}; 5 use crate::result::FResult; 6 use crate::scope::{compare_option_arc_scope, Scope}; 7 use crate::serialize::{Deserialize, Serialize}; 8 use crate::{ast::Expr, ident::Ident}; 9 use crate::{date, Attrs, Span, SpanKind}; 10 use std::borrow::Cow; 11 use std::{cmp, io}; 12 use std::{ 13 fmt::{self, Write}, 14 sync::Arc, 15 }; 16 17 pub(crate) mod built_in_function; 18 19 use built_in_function::BuiltInFunction; 20 21 #[derive(Clone)] 22 pub(crate) enum Value { 23 Num(Box<Number>), 24 BuiltInFunction(BuiltInFunction), 25 Format(FormattingStyle), 26 Dp, 27 Sf, 28 Base(Base), 29 // user-defined function with a named parameter 30 Fn(Ident, Box<Expr>, Option<Arc<Scope>>), 31 Object(Vec<(Cow<'static, str>, Box<Value>)>), 32 String(Cow<'static, str>), 33 Bool(bool), 34 Unit, // unit value `()` 35 Month(date::Month), 36 DayOfWeek(date::DayOfWeek), 37 Date(date::Date), 38 } 39 40 #[derive(Copy, Clone, Eq, PartialEq)] 41 pub(crate) enum ApplyMulHandling { 42 OnlyApply, 43 Both, 44 } 45 46 impl Value { compare<I: Interrupt>( &self, other: &Self, int: &I, ) -> FResult<Option<cmp::Ordering>>47 pub(crate) fn compare<I: Interrupt>( 48 &self, 49 other: &Self, 50 int: &I, 51 ) -> FResult<Option<cmp::Ordering>> { 52 let c = |cmp| { 53 if cmp { 54 Some(cmp::Ordering::Equal) 55 } else { 56 None 57 } 58 }; 59 Ok(match (self, other) { 60 (Self::Num(a), Self::Num(b)) => a.compare(b, int)?, 61 (Self::BuiltInFunction(a), Self::BuiltInFunction(b)) => c(a == b), 62 (Self::Format(a), Self::Format(b)) => c(a == b), 63 (Self::Dp, Self::Dp) | (Self::Sf, Self::Sf) | (Self::Unit, Self::Unit) => c(true), 64 (Self::Base(a), Self::Base(b)) => c(a == b), 65 (Self::Fn(a1, a2, a3), Self::Fn(b1, b2, b3)) => { 66 c(a1 == b1 && a2.compare(b2, int)? && compare_option_arc_scope(a3, b3, int)?) 67 } 68 (Self::Object(a), Self::Object(b)) => { 69 if a.len() != b.len() { 70 return Ok(None); 71 } 72 for ((a1, a2), (b1, b2)) in a.iter().zip(b.iter()) { 73 if a1 != b1 { 74 return Ok(None); 75 } 76 match a2.compare(b2, int)? { 77 Some(cmp::Ordering::Equal) => (), 78 other => return Ok(other), 79 } 80 } 81 return Ok(Some(cmp::Ordering::Equal)); 82 } 83 (Self::String(a), Self::String(b)) => c(a == b), 84 (Self::Bool(a), Self::Bool(b)) => c(a == b), 85 (Self::Month(a), Self::Month(b)) => c(a == b), 86 (Self::DayOfWeek(a), Self::DayOfWeek(b)) => c(a == b), 87 (Self::Date(a), Self::Date(b)) => c(a == b), 88 _ => None, 89 }) 90 } 91 serialize(&self, write: &mut impl io::Write) -> FResult<()>92 pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> { 93 match self { 94 Self::Num(n) => { 95 0u8.serialize(write)?; 96 n.serialize(write)?; 97 } 98 Self::BuiltInFunction(f) => { 99 1u8.serialize(write)?; 100 f.serialize(write)?; 101 } 102 Self::Format(f) => { 103 2u8.serialize(write)?; 104 f.serialize(write)?; 105 } 106 Self::Dp => 3u8.serialize(write)?, 107 Self::Sf => 4u8.serialize(write)?, 108 Self::Base(b) => { 109 5u8.serialize(write)?; 110 b.serialize(write)?; 111 } 112 Self::Fn(i, e, s) => { 113 6u8.serialize(write)?; 114 i.serialize(write)?; 115 e.serialize(write)?; 116 match s { 117 None => false.serialize(write)?, 118 Some(s) => { 119 true.serialize(write)?; 120 s.serialize(write)?; 121 } 122 } 123 } 124 Self::Object(o) => { 125 7u8.serialize(write)?; 126 o.len().serialize(write)?; 127 for (k, v) in o { 128 k.as_ref().serialize(write)?; 129 v.serialize(write)?; 130 } 131 } 132 Self::String(s) => { 133 8u8.serialize(write)?; 134 s.as_ref().serialize(write)?; 135 } 136 Self::Unit => 9u8.serialize(write)?, 137 Self::Bool(b) => { 138 10u8.serialize(write)?; 139 b.serialize(write)?; 140 } 141 Self::Month(m) => { 142 11u8.serialize(write)?; 143 m.serialize(write)?; 144 } 145 Self::DayOfWeek(d) => { 146 12u8.serialize(write)?; 147 d.serialize(write)?; 148 } 149 Self::Date(d) => { 150 13u8.serialize(write)?; 151 d.serialize(write)?; 152 } 153 } 154 Ok(()) 155 } 156 deserialize(read: &mut impl io::Read) -> FResult<Self>157 pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> { 158 Ok(match u8::deserialize(read)? { 159 0 => Self::Num(Box::new(Number::deserialize(read)?)), 160 1 => Self::BuiltInFunction(BuiltInFunction::deserialize(read)?), 161 2 => Self::Format(FormattingStyle::deserialize(read)?), 162 3 => Self::Dp, 163 4 => Self::Sf, 164 5 => Self::Base(Base::deserialize(read)?), 165 6 => Self::Fn( 166 Ident::deserialize(read)?, 167 Box::new(Expr::deserialize(read)?), 168 if bool::deserialize(read)? { 169 Some(Arc::new(Scope::deserialize(read)?)) 170 } else { 171 None 172 }, 173 ), 174 7 => Self::Object({ 175 let len = usize::deserialize(read)?; 176 let mut v = Vec::with_capacity(len); 177 for _ in 0..len { 178 v.push(( 179 Cow::Owned(String::deserialize(read)?), 180 Box::new(Self::deserialize(read)?), 181 )); 182 } 183 v 184 }), 185 8 => Self::String(Cow::Owned(String::deserialize(read)?)), 186 9 => Self::Unit, 187 10 => Self::Bool(bool::deserialize(read)?), 188 11 => Self::Month(Month::deserialize(read)?), 189 12 => Self::DayOfWeek(DayOfWeek::deserialize(read)?), 190 13 => Self::Date(Date::deserialize(read)?), 191 _ => return Err(FendError::DeserializationError), 192 }) 193 } 194 type_name(&self) -> &'static str195 pub(crate) fn type_name(&self) -> &'static str { 196 match self { 197 Self::Num(_) => "number", 198 Self::BuiltInFunction(_) | Self::Fn(_, _, _) => "function", 199 Self::Format(_) => "formatting style", 200 Self::Dp => "decimal places", 201 Self::Sf => "significant figures", 202 Self::Base(_) => "base", 203 Self::Object(_) => "object", 204 Self::String(_) => "string", 205 Self::Bool(_) => "bool", 206 Self::Unit => "()", 207 Self::Month(_) => "month", 208 Self::DayOfWeek(_) => "day of week", 209 Self::Date(_) => "date", 210 } 211 } 212 as_bool(&self) -> FResult<bool>213 fn as_bool(&self) -> FResult<bool> { 214 if let Self::Bool(b) = self { 215 Ok(*b) 216 } else { 217 Err(FendError::ExpectedABool(self.type_name())) 218 } 219 } 220 expect_num(self) -> FResult<Number>221 pub(crate) fn expect_num(self) -> FResult<Number> { 222 match self { 223 Self::Num(bigrat) => Ok(*bigrat), 224 _ => Err(FendError::ExpectedANumber), 225 } 226 } 227 is_unit(&self) -> bool228 pub(crate) fn is_unit(&self) -> bool { 229 matches!(self, Self::Unit) 230 } 231 handle_num( self, eval_fn: impl FnOnce(Number) -> FResult<Number>, lazy_fn: impl FnOnce(Box<Expr>) -> Expr, scope: Option<Arc<Scope>>, ) -> FResult<Self>232 pub(crate) fn handle_num( 233 self, 234 eval_fn: impl FnOnce(Number) -> FResult<Number>, 235 lazy_fn: impl FnOnce(Box<Expr>) -> Expr, 236 scope: Option<Arc<Scope>>, 237 ) -> FResult<Self> { 238 Ok(match self { 239 Self::Num(n) => Self::Num(Box::new(eval_fn(*n)?)), 240 Self::Fn(param, expr, scope) => Self::Fn(param, Box::new(lazy_fn(expr)), scope), 241 Self::BuiltInFunction(f) => f.wrap_with_expr(lazy_fn, scope), 242 _ => return Err(FendError::ExpectedANumber), 243 }) 244 } 245 handle_two_nums<F1: FnOnce(Box<Expr>) -> Expr, F2: FnOnce(Box<Expr>) -> Expr>( self, rhs: Self, eval_fn: impl FnOnce(Number, Number) -> FResult<Number>, lazy_fn_lhs: impl FnOnce(Number) -> F1, lazy_fn_rhs: impl FnOnce(Number) -> F2, scope: Option<Arc<Scope>>, ) -> FResult<Self>246 pub(crate) fn handle_two_nums<F1: FnOnce(Box<Expr>) -> Expr, F2: FnOnce(Box<Expr>) -> Expr>( 247 self, 248 rhs: Self, 249 eval_fn: impl FnOnce(Number, Number) -> FResult<Number>, 250 lazy_fn_lhs: impl FnOnce(Number) -> F1, 251 lazy_fn_rhs: impl FnOnce(Number) -> F2, 252 scope: Option<Arc<Scope>>, 253 ) -> FResult<Self> { 254 Ok(match (self, rhs) { 255 (Self::Num(a), Self::Num(b)) => Self::Num(Box::new(eval_fn(*a, *b)?)), 256 (Self::BuiltInFunction(f), Self::Num(a)) => f.wrap_with_expr(lazy_fn_lhs(*a), scope), 257 (Self::Num(a), Self::BuiltInFunction(f)) => f.wrap_with_expr(lazy_fn_rhs(*a), scope), 258 (Self::Fn(param, expr, scope), Self::Num(a)) => { 259 Self::Fn(param, Box::new(lazy_fn_lhs(*a)(expr)), scope) 260 } 261 (Self::Num(a), Self::Fn(param, expr, scope)) => { 262 Self::Fn(param, Box::new(lazy_fn_rhs(*a)(expr)), scope) 263 } 264 _ => return Err(FendError::ExpectedANumber), 265 }) 266 } 267 apply<I: Interrupt>( self, other: Expr, apply_mul_handling: ApplyMulHandling, scope: Option<Arc<Scope>>, attrs: Attrs, context: &mut crate::Context, int: &I, ) -> FResult<Self>268 pub(crate) fn apply<I: Interrupt>( 269 self, 270 other: Expr, 271 apply_mul_handling: ApplyMulHandling, 272 scope: Option<Arc<Scope>>, 273 attrs: Attrs, 274 context: &mut crate::Context, 275 int: &I, 276 ) -> FResult<Self> { 277 let stringified_self = self.format_to_plain_string(0, attrs, context, int)?; 278 Ok(match self { 279 Self::Num(n) => { 280 let other = crate::ast::evaluate(other, scope.clone(), attrs, context, int)?; 281 if matches!(other, Self::Dp) { 282 let num = Self::Num(n).expect_num()?.try_as_usize(int)?; 283 return Ok(Self::Format(FormattingStyle::DecimalPlaces(num))); 284 } 285 if matches!(other, Self::Sf) { 286 let num = Self::Num(n).expect_num()?.try_as_usize(int)?; 287 if num == 0 { 288 return Err(FendError::CannotFormatWithZeroSf); 289 } 290 return Ok(Self::Format(FormattingStyle::SignificantFigures(num))); 291 } 292 if apply_mul_handling == ApplyMulHandling::OnlyApply { 293 let self_ = Self::Num(n); 294 return Err(FendError::IsNotAFunction( 295 self_.format_to_plain_string(0, attrs, context, int)?, 296 )); 297 } 298 let n2 = n.clone(); 299 other.handle_num( 300 |x| n.mul(x, int), 301 |x| Expr::Bop(Bop::Mul, Box::new(Expr::Literal(Self::Num(n2))), x), 302 scope, 303 )? 304 } 305 Self::BuiltInFunction(func) => { 306 Self::apply_built_in_function(func, other, scope, attrs, context, int)? 307 } 308 Self::Fn(param, expr, custom_scope) => { 309 let new_scope = Scope::with_variable(param, other, scope, custom_scope); 310 return crate::ast::evaluate(*expr, Some(Arc::new(new_scope)), attrs, context, int); 311 } 312 _ => return Err(FendError::IsNotAFunctionOrNumber(stringified_self)), 313 }) 314 } 315 apply_built_in_function<I: Interrupt>( func: BuiltInFunction, arg: Expr, scope: Option<Arc<Scope>>, attrs: Attrs, context: &mut crate::Context, int: &I, ) -> FResult<Self>316 fn apply_built_in_function<I: Interrupt>( 317 func: BuiltInFunction, 318 arg: Expr, 319 scope: Option<Arc<Scope>>, 320 attrs: Attrs, 321 context: &mut crate::Context, 322 int: &I, 323 ) -> FResult<Self> { 324 let arg = crate::ast::evaluate(arg, scope.clone(), attrs, context, int)?; 325 Ok(Self::Num(Box::new(match func { 326 BuiltInFunction::Approximately => arg.expect_num()?.make_approximate(), 327 BuiltInFunction::Abs => arg.expect_num()?.abs(int)?, 328 BuiltInFunction::Sin => arg.expect_num()?.sin(scope, attrs, context, int)?, 329 BuiltInFunction::Cos => arg.expect_num()?.cos(scope, attrs, context, int)?, 330 BuiltInFunction::Tan => arg.expect_num()?.tan(scope, attrs, context, int)?, 331 BuiltInFunction::Asin => arg.expect_num()?.asin(int)?, 332 BuiltInFunction::Acos => arg.expect_num()?.acos(int)?, 333 BuiltInFunction::Atan => arg.expect_num()?.atan(int)?, 334 BuiltInFunction::Sinh => arg.expect_num()?.sinh(int)?, 335 BuiltInFunction::Cosh => arg.expect_num()?.cosh(int)?, 336 BuiltInFunction::Tanh => arg.expect_num()?.tanh(int)?, 337 BuiltInFunction::Asinh => arg.expect_num()?.asinh(int)?, 338 BuiltInFunction::Acosh => arg.expect_num()?.acosh(int)?, 339 BuiltInFunction::Atanh => arg.expect_num()?.atanh(int)?, 340 BuiltInFunction::Ln => arg.expect_num()?.ln(int)?, 341 BuiltInFunction::Log2 => arg.expect_num()?.log2(int)?, 342 BuiltInFunction::Log10 => arg.expect_num()?.log10(int)?, 343 BuiltInFunction::Base => { 344 let n: u8 = arg 345 .expect_num()? 346 .try_as_usize(int)? 347 .try_into() 348 .map_err(|_| FendError::UnableToConvertToBase)?; 349 return Ok(Self::Base(Base::from_plain_base(n)?)); 350 } 351 BuiltInFunction::Sample => arg.expect_num()?.sample(context, int)?, 352 BuiltInFunction::Mean => arg.expect_num()?.mean(int)?, 353 BuiltInFunction::Not => return Ok(Self::Bool(!arg.as_bool()?)), 354 BuiltInFunction::Conjugate => arg.expect_num()?.conjugate()?, 355 BuiltInFunction::Real => arg.expect_num()?.real()?, 356 BuiltInFunction::Imag => arg.expect_num()?.imag()?, 357 BuiltInFunction::Arg => arg.expect_num()?.arg(int)?, 358 BuiltInFunction::Floor => arg.expect_num()?.floor(int)?, 359 BuiltInFunction::Ceil => arg.expect_num()?.ceil(int)?, 360 BuiltInFunction::Round => arg.expect_num()?.round(int)?, 361 }))) 362 } 363 format_to_plain_string<I: Interrupt>( &self, indent: usize, attrs: Attrs, ctx: &mut crate::Context, int: &I, ) -> FResult<String>364 pub(crate) fn format_to_plain_string<I: Interrupt>( 365 &self, 366 indent: usize, 367 attrs: Attrs, 368 ctx: &mut crate::Context, 369 int: &I, 370 ) -> FResult<String> { 371 let mut spans = vec![]; 372 self.format(indent, &mut spans, attrs, ctx, int)?; 373 let mut res = String::new(); 374 for span in spans { 375 res.push_str(&span.string); 376 } 377 Ok(res) 378 } 379 format<I: Interrupt>( &self, indent: usize, spans: &mut Vec<Span>, attrs: Attrs, ctx: &mut crate::Context, int: &I, ) -> FResult<()>380 pub(crate) fn format<I: Interrupt>( 381 &self, 382 indent: usize, 383 spans: &mut Vec<Span>, 384 attrs: Attrs, 385 ctx: &mut crate::Context, 386 int: &I, 387 ) -> FResult<()> { 388 match self { 389 Self::Num(n) => { 390 n.clone() 391 .simplify(attrs, ctx, int)? 392 .format(ctx, int)? 393 .spans(spans, attrs); 394 } 395 Self::BuiltInFunction(name) => { 396 spans.push(Span { 397 string: name.to_string(), 398 kind: SpanKind::BuiltInFunction, 399 }); 400 } 401 Self::Format(fmt) => { 402 spans.push(Span { 403 string: fmt.to_string(), 404 kind: SpanKind::Keyword, 405 }); 406 } 407 Self::Dp => { 408 spans.push(Span { 409 string: "dp".to_string(), 410 kind: SpanKind::Keyword, 411 }); 412 } 413 Self::Sf => { 414 spans.push(Span { 415 string: "sf".to_string(), 416 kind: SpanKind::Keyword, 417 }); 418 } 419 Self::Base(b) => { 420 spans.push(Span { 421 string: "base ".to_string(), 422 kind: SpanKind::Keyword, 423 }); 424 spans.push(Span { 425 string: b.base_as_u8().to_string(), 426 kind: SpanKind::Number, 427 }); 428 } 429 Self::Fn(name, expr, _scope) => { 430 let expr_str = expr.format(attrs, ctx, int)?; 431 let res = if name.as_str().contains('.') { 432 format!("{name}:{expr_str}") 433 } else { 434 format!("\\{name}.{expr_str}") 435 }; 436 spans.push(Span { 437 string: res, 438 kind: SpanKind::Other, 439 }); 440 } 441 Self::Object(kv) => { 442 spans.push(Span::from_string("{".to_string())); 443 for (i, (k, v)) in kv.iter().enumerate() { 444 if i != 0 { 445 spans.push(Span::from_string(",".to_string())); 446 } 447 spans.push(Span::from_string("\n".to_string())); 448 for _ in 0..(indent + 4) { 449 spans.push(Span::from_string(" ".to_string())); 450 } 451 spans.push(Span::from_string(format!("{k}: "))); 452 v.format(indent + 4, spans, attrs, ctx, int)?; 453 } 454 spans.push(Span::from_string("\n}".to_string())); 455 } 456 Self::String(s) => { 457 spans.push(Span { 458 string: s.to_string(), 459 kind: SpanKind::String, 460 }); 461 } 462 Self::Unit => { 463 spans.push(crate::Span { 464 string: "()".to_string(), 465 kind: crate::SpanKind::Ident, 466 }); 467 } 468 Self::Bool(b) => spans.push(crate::Span { 469 string: b.to_string(), 470 kind: crate::SpanKind::Boolean, 471 }), 472 Self::Month(m) => spans.push(crate::Span { 473 string: m.to_string(), 474 kind: crate::SpanKind::Date, 475 }), 476 Self::DayOfWeek(d) => spans.push(crate::Span { 477 string: d.to_string(), 478 kind: crate::SpanKind::Date, 479 }), 480 Self::Date(d) => spans.push(crate::Span { 481 string: d.to_string(), 482 kind: crate::SpanKind::Date, 483 }), 484 } 485 Ok(()) 486 } 487 get_object_member(self, key: &Ident) -> FResult<Self>488 pub(crate) fn get_object_member(self, key: &Ident) -> FResult<Self> { 489 match self { 490 Self::Object(kv) => { 491 for (k, v) in kv { 492 if k == key.as_str() { 493 return Ok(*v); 494 } 495 } 496 Err(FendError::CouldNotFindKeyInObject) 497 } 498 Self::Date(d) => d.get_object_member(key), 499 _ => Err(FendError::ExpectedAnObject), 500 } 501 } 502 } 503 504 impl fmt::Debug for Value { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result505 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 506 match self { 507 Self::Num(n) => write!(f, "{n:?}"), 508 Self::BuiltInFunction(name) => write!(f, "built-in function: {}", name.as_str()), 509 Self::Format(fmt) => write!(f, "format: {fmt:?}"), 510 Self::Dp => write!(f, "dp"), 511 Self::Sf => write!(f, "sf"), 512 Self::Base(b) => write!(f, "base: {b:?}"), 513 Self::Fn(name, expr, scope) => { 514 write!(f, "fn: {name} => {expr:?} (scope: {scope:?})") 515 } 516 Self::Object(kv) => { 517 let mut s = "{".to_string(); 518 for (k, v) in kv { 519 s.push_str(k); 520 s.push(':'); 521 write!(s, "{:?}", *v)?; 522 s.push(','); 523 } 524 s.push('}'); 525 write!(f, "{s}") 526 } 527 Self::String(s) => write!(f, r#""{}""#, s.as_ref()), 528 Self::Unit => write!(f, "()"), 529 Self::Bool(b) => write!(f, "{b}"), 530 Self::Month(m) => write!(f, "{m}"), 531 Self::DayOfWeek(d) => write!(f, "{d}"), 532 Self::Date(d) => write!(f, "{d:?}"), 533 } 534 } 535 } 536