1use anyhow::{Result, anyhow};
2use indexmap::IndexMap;
3use serde::{Deserialize, Serialize};
4use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc};
5
6use crate::{
7 ast::SpannedExpr,
8 functions::BuiltInFunction,
9 heap::{
10 Heap, HeapPointer, HeapValue, IterablePointer, LambdaPointer, ListPointer, RecordPointer,
11 StringPointer,
12 },
13};
14
15pub fn format_display_number(value: f64) -> String {
19 if value.is_nan() {
21 return "NaN".to_string();
22 }
23 if value.is_infinite() {
24 return if value.is_sign_positive() {
25 "Infinity".to_string()
26 } else {
27 "-Infinity".to_string()
28 };
29 }
30 if value == 0.0 {
32 return value.to_string();
33 }
34
35 let abs_value = value.abs();
36
37 if !(0.0001..1e15).contains(&abs_value) {
39 return format_scientific(value);
40 }
41
42 format_standard(value)
44}
45
46fn format_scientific(value: f64) -> String {
48 let formatted = format!("{:.14e}", value);
50
51 if let Some((mantissa_str, exp_str)) = formatted.split_once('e') {
53 let mantissa: f64 = mantissa_str.parse().unwrap_or(value);
54 let exp: i32 = exp_str.parse().unwrap_or(0);
55
56 let mantissa_formatted = format_mantissa(mantissa);
58
59 format!("{}e{}", mantissa_formatted, exp)
60 } else {
61 formatted
62 }
63}
64
65fn format_mantissa(mantissa: f64) -> String {
67 let s = format!("{:.14}", mantissa);
69
70 let s = s.trim_end_matches('0');
72 let s = s.trim_end_matches('.');
74
75 s.to_string()
76}
77
78fn format_standard(value: f64) -> String {
80 if value.fract() == 0.0 && value.abs() < 9007199254740992.0 {
83 let int_val = value as i64;
85 return format_integer_with_separators(int_val);
86 }
87
88 let rounded = round_to_significant_figures(value, 15);
90
91 let formatted = format_float_significant(rounded, 15);
93
94 add_thousand_separators(&formatted)
96}
97
98fn round_to_significant_figures(value: f64, sig_figs: u32) -> f64 {
100 if value == 0.0 {
101 return 0.0;
102 }
103
104 let magnitude = value.abs().log10().floor() as i32;
105 let scale = 10_f64.powi(sig_figs as i32 - 1 - magnitude);
106 (value * scale).round() / scale
107}
108
109fn format_float_significant(value: f64, max_sig_figs: usize) -> String {
111 let abs_value = value.abs();
113 let magnitude = if abs_value >= 1.0 {
114 abs_value.log10().floor() as i32 + 1
115 } else {
116 -(abs_value.log10().floor() as i32)
118 };
119
120 let decimal_places = if abs_value >= 1.0 {
122 (max_sig_figs as i32 - magnitude).max(0) as usize
123 } else {
124 (max_sig_figs as i32 + magnitude - 1).max(0) as usize
126 };
127
128 let formatted = format!("{:.prec$}", value, prec = decimal_places);
129
130 if formatted.contains('.') {
132 let trimmed = formatted.trim_end_matches('0');
133 if trimmed.ends_with('.') {
134 trimmed.trim_end_matches('.').to_string()
135 } else {
136 trimmed.to_string()
137 }
138 } else {
139 formatted
140 }
141}
142
143fn format_integer_with_separators(value: i64) -> String {
145 let is_negative = value < 0;
146 let abs_str = value.abs().to_string();
147
148 let with_commas: String = abs_str
149 .chars()
150 .rev()
151 .enumerate()
152 .flat_map(|(i, c)| {
153 if i > 0 && i % 3 == 0 {
154 vec![',', c]
155 } else {
156 vec![c]
157 }
158 })
159 .collect::<Vec<_>>()
160 .into_iter()
161 .rev()
162 .collect();
163
164 if is_negative {
165 format!("-{}", with_commas)
166 } else {
167 with_commas
168 }
169}
170
171fn add_thousand_separators(s: &str) -> String {
173 let is_negative = s.starts_with('-');
174 let s = if is_negative { &s[1..] } else { s };
175
176 let (int_part, dec_part) = if let Some(dot_pos) = s.find('.') {
177 (&s[..dot_pos], Some(&s[dot_pos..]))
178 } else {
179 (s, None)
180 };
181
182 let int_with_commas: String = int_part
184 .chars()
185 .rev()
186 .enumerate()
187 .flat_map(|(i, c)| {
188 if i > 0 && i % 3 == 0 {
189 vec![',', c]
190 } else {
191 vec![c]
192 }
193 })
194 .collect::<Vec<_>>()
195 .into_iter()
196 .rev()
197 .collect();
198
199 let result = if let Some(dec) = dec_part {
200 format!("{}{}", int_with_commas, dec)
201 } else {
202 int_with_commas
203 };
204
205 if is_negative {
206 format!("-{}", result)
207 } else {
208 result
209 }
210}
211
212#[derive(Debug)]
213pub enum FunctionArity {
214 Exact(usize),
215 AtLeast(usize),
216 Between(usize, usize),
217}
218
219impl FunctionArity {
220 pub fn can_accept(&self, n: usize) -> bool {
221 match self {
222 FunctionArity::Exact(expected) => n == *expected,
223 FunctionArity::Between(min, max) => n >= *min && n <= *max,
224 FunctionArity::AtLeast(min) => n >= *min,
225 }
226 }
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
230pub enum LambdaArg {
231 Required(String),
232 Optional(String),
233 Rest(String),
234}
235
236impl LambdaArg {
237 pub fn get_name(&self) -> &str {
238 match self {
239 LambdaArg::Required(name) => name,
240 LambdaArg::Optional(name) => name,
241 LambdaArg::Rest(name) => name,
242 }
243 }
244
245 pub fn is_required(&self) -> bool {
246 matches!(self, LambdaArg::Required(_))
247 }
248
249 pub fn is_optional(&self) -> bool {
250 matches!(self, LambdaArg::Optional(_))
251 }
252
253 pub fn is_rest(&self) -> bool {
254 matches!(self, LambdaArg::Rest(_))
255 }
256
257 pub fn as_required(&self) -> Result<&str> {
258 match self {
259 LambdaArg::Required(name) => Ok(name),
260 _ => Err(anyhow!(
261 "expected a required argument, but got a {} one",
262 self.get_name()
263 )),
264 }
265 }
266
267 pub fn as_optional(&self) -> Result<&str> {
268 match self {
269 LambdaArg::Optional(name) => Ok(name),
270 _ => Err(anyhow!(
271 "expected an optional argument, but got a {} one",
272 self.get_name()
273 )),
274 }
275 }
276
277 pub fn as_rest(&self) -> Result<&str> {
278 match self {
279 LambdaArg::Rest(name) => Ok(name),
280 _ => Err(anyhow!(
281 "expected a rest argument, but got a {} one",
282 self.get_name()
283 )),
284 }
285 }
286}
287
288impl Display for LambdaArg {
289 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290 match self {
291 LambdaArg::Required(name) => write!(f, "{}", name),
292 LambdaArg::Optional(name) => write!(f, "{}?", name),
293 LambdaArg::Rest(name) => write!(f, "...{}", name),
294 }
295 }
296}
297
298#[derive(Debug, Clone, PartialEq)]
299pub struct LambdaDef {
300 pub name: Option<String>,
301 pub args: Vec<LambdaArg>,
302 pub body: SpannedExpr,
303 pub scope: HashMap<String, Value>,
304 pub source: Rc<str>,
306}
307
308impl LambdaDef {
309 pub fn set_name(&mut self, name: String, _value: Value) {
310 self.name = Some(name.clone());
311 }
312
313 pub fn get_arity(&self) -> FunctionArity {
314 let has_rest = self.args.iter().any(|arg| arg.is_rest());
315 let min = self.args.iter().filter(|arg| arg.is_required()).count();
316 let max = self.args.len();
317
318 if has_rest {
319 FunctionArity::AtLeast(min)
320 } else if min == max {
321 FunctionArity::Exact(min)
322 } else {
323 FunctionArity::Between(min, max)
324 }
325 }
326}
327
328impl PartialOrd for LambdaDef {
329 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
330 if self.args > other.args {
331 Some(std::cmp::Ordering::Greater)
332 } else if self.args < other.args {
333 Some(std::cmp::Ordering::Less)
334 } else {
335 Some(std::cmp::Ordering::Equal)
336 }
337 }
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
341pub struct SerializableLambdaDef {
342 pub name: Option<String>,
343 pub args: Vec<LambdaArg>,
344 pub body: String,
345 pub scope: Option<IndexMap<String, SerializableValue>>,
346}
347
348pub struct WithHeap<'h, T> {
349 pub value: &'h T,
350 pub heap: Rc<RefCell<Heap>>,
351}
352
353#[derive(Debug, Copy, Clone, PartialEq)]
354pub enum ReifiedIterableValue<'h> {
355 List(&'h Vec<Value>),
356 String(&'h String),
357 Record(&'h IndexMap<String, Value>),
358}
359
360#[derive(Debug, Clone, PartialEq)]
361pub enum ReifiedIterableValueType {
362 List,
363 String,
364 Record,
365}
366
367impl<'h> ReifiedIterableValue<'h> {
368 pub fn with_heap(&'h self, heap: Rc<RefCell<Heap>>) -> WithHeap<'h, ReifiedIterableValue<'h>> {
369 WithHeap { value: self, heap }
370 }
371
372 pub fn get_type(&self) -> ReifiedIterableValueType {
373 match self {
374 ReifiedIterableValue::List(_) => ReifiedIterableValueType::List,
375 ReifiedIterableValue::String(_) => ReifiedIterableValueType::String,
376 ReifiedIterableValue::Record(_) => ReifiedIterableValueType::Record,
377 }
378 }
379}
380
381impl<'h> IntoIterator for WithHeap<'h, ReifiedIterableValue<'h>> {
382 type Item = Value;
383 type IntoIter = std::vec::IntoIter<Self::Item>;
384
385 fn into_iter(self) -> Self::IntoIter {
386 match self.value {
387 ReifiedIterableValue::List(l) => (*l).clone().into_iter(),
389 ReifiedIterableValue::String(s) => s
391 .chars()
392 .map(|c| self.heap.borrow_mut().insert_string(c.to_string()))
393 .collect::<Vec<Value>>()
394 .into_iter(),
395 ReifiedIterableValue::Record(r) => r
397 .into_iter()
398 .map(|(k, v)| {
399 let list = vec![self.heap.borrow_mut().insert_string(k.to_string()), *v];
400 self.heap.borrow_mut().insert_list(list)
401 })
402 .collect::<Vec<Value>>()
403 .into_iter(),
404 }
405 }
406}
407
408impl<'h> IntoIterator for WithHeap<'h, ReifiedValue<'h>> {
409 type Item = Value;
410 type IntoIter = std::vec::IntoIter<Self::Item>;
411
412 fn into_iter(self) -> Self::IntoIter {
413 match self.value {
414 ReifiedValue::Spread(iterable, _) => iterable.with_heap(self.heap).into_iter(),
415 _ => vec![(*self.value).into()].into_iter(),
416 }
417 }
418}
419
420#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
421pub enum ValueType {
422 Number,
423 List,
424 Spread,
425 Bool,
426 Lambda,
427 BuiltIn,
428 String,
429 Record,
430 Null,
431}
432
433impl Display for ValueType {
434 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
435 match self {
436 ValueType::Number => write!(f, "number"),
437 ValueType::List => write!(f, "list"),
438 ValueType::Spread => write!(f, "spread"),
439 ValueType::Bool => write!(f, "boolean"),
440 ValueType::Lambda => write!(f, "function"),
441 ValueType::BuiltIn => write!(f, "built-in function"),
442 ValueType::String => write!(f, "string"),
443 ValueType::Record => write!(f, "record"),
444 ValueType::Null => write!(f, "null"),
445 }
446 }
447}
448
449#[derive(Debug, Copy, Clone, PartialEq)]
451pub enum ReifiedValue<'h> {
452 Number(f64),
454 Bool(bool),
456 Null,
458 List(&'h Vec<Value>, ListPointer),
460 String(&'h str, StringPointer),
462 Record(&'h IndexMap<String, Value>, RecordPointer),
464 Lambda(&'h LambdaDef, LambdaPointer),
466 Spread(ReifiedIterableValue<'h>, IterablePointer),
468 BuiltIn(BuiltInFunction),
470}
471
472impl<'h> ReifiedValue<'h> {
473 pub fn with_heap(&'h self, heap: Rc<RefCell<Heap>>) -> WithHeap<'h, ReifiedValue<'h>> {
474 WithHeap { value: self, heap }
475 }
476}
477
478impl From<ReifiedValue<'_>> for Value {
479 fn from(value: ReifiedValue) -> Self {
480 match value {
481 ReifiedValue::Number(n) => Value::Number(n),
482 ReifiedValue::Bool(b) => Value::Bool(b),
483 ReifiedValue::Null => Value::Null,
484 ReifiedValue::List(_, p) => Value::List(p),
485 ReifiedValue::String(_, p) => Value::String(p),
486 ReifiedValue::Record(_, p) => Value::Record(p),
487 ReifiedValue::Lambda(_, p) => Value::Lambda(p),
488 ReifiedValue::Spread(_, p) => Value::Spread(p),
489 ReifiedValue::BuiltIn(id) => Value::BuiltIn(id),
490 }
491 }
492}
493
494#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
495pub enum SerializableIterableValue {
496 List(Vec<SerializableValue>),
497 String(String),
498 Record(IndexMap<String, SerializableValue>),
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
502pub enum SerializableValue {
503 Number(f64),
504 Bool(bool),
505 Null,
506 List(Vec<SerializableValue>),
507 String(String),
508 Record(IndexMap<String, SerializableValue>),
509 Lambda(SerializableLambdaDef),
510 BuiltIn(String),
511}
512
513impl SerializableValue {
514 pub fn from_json(value: &serde_json::Value) -> SerializableValue {
516 match value {
517 serde_json::Value::Number(n) => SerializableValue::Number(n.as_f64().unwrap_or(0.0)),
518 serde_json::Value::Bool(b) => SerializableValue::Bool(*b),
519 serde_json::Value::Null => SerializableValue::Null,
520 serde_json::Value::String(s) => SerializableValue::String(s.clone()),
521 serde_json::Value::Array(arr) => {
522 SerializableValue::List(arr.iter().map(Self::from_json).collect())
523 }
524 serde_json::Value::Object(obj) => {
525 if let Some(func_value) = obj.get("__blots_function")
527 && let Some(func_str) = func_value.as_str()
528 {
529 if crate::functions::BuiltInFunction::from_ident(func_str).is_some() {
531 return SerializableValue::BuiltIn(func_str.to_string());
532 }
533
534 if let Ok(lambda_def) = Self::parse_function_source(func_str) {
537 return SerializableValue::Lambda(lambda_def);
538 }
539 }
540
541 let map: IndexMap<String, SerializableValue> = obj
543 .iter()
544 .map(|(k, v)| (k.clone(), Self::from_json(v)))
545 .collect();
546 SerializableValue::Record(map)
547 }
548 }
549 }
550
551 fn parse_function_source(source: &str) -> Result<SerializableLambdaDef> {
553 use crate::expressions::pairs_to_expr;
554 use crate::parser::get_pairs;
555
556 let pairs = get_pairs(source)?;
558
559 for pair in pairs {
561 if let crate::parser::Rule::statement = pair.as_rule()
562 && let Some(inner_pair) = pair.into_inner().next()
563 && let crate::parser::Rule::expression = inner_pair.as_rule()
564 {
565 let expr = pairs_to_expr(inner_pair.into_inner())?;
567
568 if let crate::ast::Expr::Lambda { args, body } = expr.node {
570 return Ok(SerializableLambdaDef {
573 name: None,
574 args,
575 body: crate::ast_to_source::expr_to_source(&body),
576 scope: None, });
578 }
579 }
580 }
581
582 Err(anyhow!("Failed to parse function source: {}", source))
583 }
584
585 pub fn to_json(&self) -> serde_json::Value {
587 match self {
588 SerializableValue::Number(n) => serde_json::Value::Number(
589 serde_json::Number::from_f64(*n).unwrap_or_else(|| serde_json::Number::from(0)),
590 ),
591 SerializableValue::Bool(b) => serde_json::Value::Bool(*b),
592 SerializableValue::Null => serde_json::Value::Null,
593 SerializableValue::String(s) => serde_json::Value::String(s.clone()),
594 SerializableValue::List(items) => {
595 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
596 }
597 SerializableValue::Record(fields) => {
598 let map: serde_json::Map<String, serde_json::Value> = fields
599 .iter()
600 .map(|(k, v)| (k.clone(), v.to_json()))
601 .collect();
602 serde_json::Value::Object(map)
603 }
604 SerializableValue::Lambda(lambda_def) => {
605 let mut map = serde_json::Map::new();
608
609 let args_str: Vec<String> = lambda_def
611 .args
612 .iter()
613 .map(|arg| match arg {
614 LambdaArg::Required(name) => name.clone(),
615 LambdaArg::Optional(name) => format!("{}?", name),
616 LambdaArg::Rest(name) => format!("...{}", name),
617 })
618 .collect();
619
620 let function_source = format!("({}) => {}", args_str.join(", "), lambda_def.body);
621
622 map.insert(
623 "__blots_function".to_string(),
624 serde_json::Value::String(function_source),
625 );
626 serde_json::Value::Object(map)
627 }
628 SerializableValue::BuiltIn(name) => {
629 let mut map = serde_json::Map::new();
631 map.insert(
632 "__blots_function".to_string(),
633 serde_json::Value::String(name.clone()),
634 );
635 serde_json::Value::Object(map)
636 }
637 }
638 }
639
640 pub fn from_value(value: &Value, heap: &Heap) -> Result<SerializableValue> {
641 match value {
642 Value::Number(n) => Ok(SerializableValue::Number(*n)),
643 Value::Bool(b) => Ok(SerializableValue::Bool(*b)),
644 Value::Null => Ok(SerializableValue::Null),
645 Value::List(p) => {
646 let list = p.reify(heap).as_list()?;
647 let serialized_list = list
648 .iter()
649 .map(|v| SerializableValue::from_value(v, heap))
650 .collect::<Result<Vec<SerializableValue>>>()?;
651 Ok(SerializableValue::List(serialized_list))
652 }
653 Value::String(p) => {
654 let string = p.reify(heap).as_string()?;
655 Ok(SerializableValue::String(string.to_string()))
656 }
657 Value::Record(p) => {
658 let record = p.reify(heap).as_record()?;
659 let serialized_record = record
660 .iter()
661 .map(|(k, v)| Ok((k.to_string(), SerializableValue::from_value(v, heap)?)))
662 .collect::<Result<IndexMap<String, SerializableValue>>>()?;
663 Ok(SerializableValue::Record(serialized_record))
664 }
665 Value::Lambda(p) => {
666 let lambda = p.reify(heap).as_lambda()?;
667
668 let serializable_scope: IndexMap<String, SerializableValue> = lambda
670 .scope
671 .clone()
672 .into_iter()
673 .map(|(k, v)| SerializableValue::from_value(&v, heap).map(|sv| (k, sv)))
674 .collect::<Result<IndexMap<String, SerializableValue>>>()?;
675
676 let body_with_inlined_scope = crate::ast_to_source::expr_to_source_with_scope(
678 &lambda.body,
679 &serializable_scope,
680 );
681
682 Ok(SerializableValue::Lambda(SerializableLambdaDef {
683 name: lambda.name.clone(),
684 args: lambda.args.clone(),
685 body: body_with_inlined_scope,
686 scope: Some(serializable_scope),
687 }))
688 }
689 Value::BuiltIn(built_in) => Ok(SerializableValue::BuiltIn(built_in.name().to_string())),
690 Value::Spread(_) => Err(anyhow!("cannot serialize a spread value")),
691 }
692 }
693
694 pub fn to_value(&self, heap: &mut Heap) -> Result<Value> {
695 match self {
696 SerializableValue::Number(n) => Ok(Value::Number(*n)),
697 SerializableValue::Bool(b) => Ok(Value::Bool(*b)),
698 SerializableValue::Null => Ok(Value::Null),
699 SerializableValue::List(list) => {
700 let deserialized_list = list
701 .iter()
702 .map(|v| SerializableValue::to_value(v, heap))
703 .collect::<Result<Vec<Value>>>()?;
704
705 Ok(heap.insert_list(deserialized_list))
706 }
707 SerializableValue::String(s) => Ok(heap.insert_string(s.to_string())),
708 SerializableValue::Record(record) => {
709 let deserialized_record = record
710 .iter()
711 .map(|(k, v)| Ok((k.to_string(), SerializableValue::to_value(v, heap)?)))
712 .collect::<Result<IndexMap<String, Value>>>()?;
713 Ok(heap.insert_record(deserialized_record))
714 }
715 SerializableValue::Lambda(s_lambda) => {
716 let scope = if let Some(scope) = s_lambda.scope.clone() {
717 scope
718 .iter()
719 .map(|(k, v)| Ok((k.to_string(), SerializableValue::to_value(v, heap)?)))
720 .collect::<Result<HashMap<String, Value>>>()?
721 } else {
722 HashMap::new()
723 };
724
725 let body_ast = crate::expressions::pairs_to_expr(
728 crate::parser::get_pairs(&s_lambda.body)?
729 .next()
730 .unwrap()
731 .into_inner(),
732 )?;
733
734 let lambda = LambdaDef {
735 name: s_lambda.name.clone(),
736 args: s_lambda.args.clone(),
737 body: body_ast,
738 scope,
739 source: Rc::from(""), };
741
742 Ok(heap.insert_lambda(lambda))
743 }
744 SerializableValue::BuiltIn(ident) => BuiltInFunction::from_ident(ident)
745 .ok_or(anyhow!("built-in function with ident {} not found", ident))
746 .map(Value::BuiltIn),
747 }
748 }
749}
750
751#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
752pub enum PrimitiveValue {
753 Number(f64),
754 Bool(bool),
755 Null,
756}
757
758impl From<PrimitiveValue> for Value {
759 fn from(val: PrimitiveValue) -> Self {
760 match val {
761 PrimitiveValue::Number(n) => Value::Number(n),
762 PrimitiveValue::Bool(b) => Value::Bool(b),
763 PrimitiveValue::Null => Value::Null,
764 }
765 }
766}
767
768impl From<PrimitiveValue> for SerializableValue {
769 fn from(val: PrimitiveValue) -> Self {
770 match val {
771 PrimitiveValue::Number(n) => SerializableValue::Number(n),
772 PrimitiveValue::Bool(b) => SerializableValue::Bool(b),
773 PrimitiveValue::Null => SerializableValue::Null,
774 }
775 }
776}
777
778#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
779pub enum Value {
780 Number(f64),
782 Bool(bool),
784 Null,
786 List(ListPointer),
788 String(StringPointer),
790 Record(RecordPointer),
792 Lambda(LambdaPointer),
794 Spread(IterablePointer),
796 BuiltIn(BuiltInFunction),
798}
799
800impl Value {
801 pub fn equals(&self, other: &Value, heap: &Heap) -> Result<bool> {
803 match (self, other) {
804 (Value::Number(a), Value::Number(b)) => Ok(a == b),
806 (Value::Bool(a), Value::Bool(b)) => Ok(a == b),
807 (Value::Null, Value::Null) => Ok(true),
808
809 (Value::String(a_ptr), Value::String(b_ptr)) => {
811 let a_str = a_ptr.reify(heap).as_string()?;
812 let b_str = b_ptr.reify(heap).as_string()?;
813 Ok(a_str == b_str)
814 }
815
816 (Value::List(a_ptr), Value::List(b_ptr)) => {
818 let a_list = a_ptr.reify(heap).as_list()?;
819 let b_list = b_ptr.reify(heap).as_list()?;
820
821 if a_list.len() != b_list.len() {
822 return Ok(false);
823 }
824
825 for (a_elem, b_elem) in a_list.iter().zip(b_list.iter()) {
826 if !a_elem.equals(b_elem, heap)? {
827 return Ok(false);
828 }
829 }
830 Ok(true)
831 }
832
833 (Value::Record(a_ptr), Value::Record(b_ptr)) => {
835 let a_record = a_ptr.reify(heap).as_record()?;
836 let b_record = b_ptr.reify(heap).as_record()?;
837
838 if a_record.len() != b_record.len() {
839 return Ok(false);
840 }
841
842 for (key, a_value) in a_record.iter() {
843 match b_record.get(key) {
844 Some(b_value) => {
845 if !a_value.equals(b_value, heap)? {
846 return Ok(false);
847 }
848 }
849 None => return Ok(false),
850 }
851 }
852 Ok(true)
853 }
854
855 (Value::Lambda(a_ptr), Value::Lambda(b_ptr)) => {
857 let a_lambda = a_ptr.reify(heap).as_lambda()?;
858 let b_lambda = b_ptr.reify(heap).as_lambda()?;
859
860 if a_lambda.args != b_lambda.args {
862 return Ok(false);
863 }
864
865 if a_lambda.body != b_lambda.body {
867 return Ok(false);
868 }
869
870 Ok(true)
874 }
875
876 (Value::BuiltIn(a), Value::BuiltIn(b)) => Ok(a == b),
878
879 (Value::Spread(a_ptr), Value::Spread(b_ptr)) => match (a_ptr, b_ptr) {
881 (IterablePointer::List(a), IterablePointer::List(b)) => {
882 Value::List(*a).equals(&Value::List(*b), heap)
883 }
884 (IterablePointer::String(a), IterablePointer::String(b)) => {
885 Value::String(*a).equals(&Value::String(*b), heap)
886 }
887 (IterablePointer::Record(a), IterablePointer::Record(b)) => {
888 Value::Record(*a).equals(&Value::Record(*b), heap)
889 }
890 _ => Ok(false),
891 },
892
893 _ => Ok(false),
895 }
896 }
897
898 pub fn compare(&self, other: &Value, heap: &Heap) -> Result<Option<std::cmp::Ordering>> {
900 match (self, other) {
901 (Value::Number(a), Value::Number(b)) => Ok(a.partial_cmp(b)),
903
904 (Value::Bool(a), Value::Bool(b)) => Ok(a.partial_cmp(b)),
906
907 (Value::String(a_ptr), Value::String(b_ptr)) => {
909 let a_str = a_ptr.reify(heap).as_string()?;
910 let b_str = b_ptr.reify(heap).as_string()?;
911 Ok(a_str.partial_cmp(b_str))
912 }
913
914 (Value::List(a_ptr), Value::List(b_ptr)) => {
916 let a_list = a_ptr.reify(heap).as_list()?;
917 let b_list = b_ptr.reify(heap).as_list()?;
918
919 for (a_elem, b_elem) in a_list.iter().zip(b_list.iter()) {
920 match a_elem.compare(b_elem, heap)? {
921 Some(std::cmp::Ordering::Equal) => continue,
922 other => return Ok(other),
923 }
924 }
925
926 Ok(a_list.len().partial_cmp(&b_list.len()))
928 }
929
930 _ => Ok(None),
932 }
933 }
934
935 pub fn get_type(&self) -> ValueType {
936 match self {
937 Value::Number(_) => ValueType::Number,
938 Value::List(_) => ValueType::List,
939 Value::Spread(_) => ValueType::Spread,
940 Value::Bool(_) => ValueType::Bool,
941 Value::Lambda(_) => ValueType::Lambda,
942 Value::String(_) => ValueType::String,
943 Value::Null => ValueType::Null,
944 Value::BuiltIn(_) => ValueType::BuiltIn,
945 Value::Record(_) => ValueType::Record,
946 }
947 }
948
949 pub fn is_number(&self) -> bool {
950 matches!(self, Value::Number(_))
951 }
952
953 pub fn is_list(&self) -> bool {
954 matches!(self, Value::List(_))
955 }
956
957 pub fn is_spread(&self) -> bool {
958 matches!(self, Value::Spread(_))
959 }
960
961 pub fn is_bool(&self) -> bool {
962 matches!(self, Value::Bool(_))
963 }
964
965 pub fn is_lambda(&self) -> bool {
966 matches!(self, Value::Lambda(_))
967 }
968
969 pub fn is_string(&self) -> bool {
970 matches!(self, Value::String(_))
971 }
972
973 pub fn is_null(&self) -> bool {
974 matches!(self, Value::Null)
975 }
976
977 pub fn is_built_in(&self) -> bool {
978 matches!(self, Value::BuiltIn(_))
979 }
980
981 pub fn is_callable(&self) -> bool {
982 matches!(self, Value::BuiltIn(_) | Value::Lambda(_))
983 }
984
985 pub fn as_number(&self) -> Result<f64> {
986 match self {
987 Value::Number(n) => Ok(*n),
988 _ => Err(anyhow!("expected a number, but got a {}", self.get_type())),
989 }
990 }
991
992 pub fn as_list<'h>(&self, heap: &'h Heap) -> Result<&'h Vec<Value>> {
993 match self {
994 Value::List(l) => l.reify(heap).as_list(),
995 _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
996 }
997 }
998
999 pub fn as_spread<'h>(&self, heap: &'h Heap) -> Result<&'h HeapValue> {
1000 match self {
1001 Value::Spread(v) => Ok(v.reify(heap)),
1002 _ => Err(anyhow!("expected a spread, but got a {}", self.get_type())),
1003 }
1004 }
1005
1006 pub fn as_bool(&self) -> Result<bool> {
1007 match self {
1008 Value::Bool(b) => Ok(*b),
1009 _ => Err(anyhow!("expected a boolean, but got a {}", self.get_type())),
1010 }
1011 }
1012
1013 pub fn as_lambda<'h>(&self, heap: &'h Heap) -> Result<&'h LambdaDef> {
1014 match self {
1015 Value::Lambda(l) => l.reify(heap).as_lambda(),
1016 _ => Err(anyhow!("expected a lambda, but got a {}", self.get_type())),
1017 }
1018 }
1019
1020 pub fn as_string<'h>(&self, heap: &'h Heap) -> Result<&'h str> {
1021 match self {
1022 Value::String(p) => p.reify(heap).as_string(),
1023 _ => Err(anyhow!("expected a string, but got a {}", self.get_type())),
1024 }
1025 }
1026
1027 pub fn as_null(&self) -> Result<()> {
1028 match self {
1029 Value::Null => Ok(()),
1030 _ => Err(anyhow!("expected a null, but got a {}", self.get_type())),
1031 }
1032 }
1033
1034 pub fn as_built_in(&self) -> Result<&str> {
1035 match self {
1036 Value::BuiltIn(built_in) => Ok(built_in.name()),
1037 _ => Err(anyhow!(
1038 "expected a built-in function, but got a {}",
1039 self.get_type()
1040 )),
1041 }
1042 }
1043
1044 pub fn as_record<'h>(&self, heap: &'h Heap) -> Result<&'h IndexMap<String, Value>> {
1045 match self {
1046 Value::Record(r) => r.reify(heap).as_record(),
1047 _ => Err(anyhow!("expected a record, but got a {}", self.get_type())),
1048 }
1049 }
1050
1051 pub fn as_list_pointer(&self) -> Result<ListPointer> {
1052 match self {
1053 Value::List(p) => Ok(*p),
1054 _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
1055 }
1056 }
1057
1058 pub fn as_string_pointer(&self) -> Result<StringPointer> {
1059 match self {
1060 Value::String(p) => Ok(*p),
1061 _ => Err(anyhow!("expected a string, but got a {}", self.get_type())),
1062 }
1063 }
1064
1065 pub fn as_record_pointer(&self) -> Result<RecordPointer> {
1066 match self {
1067 Value::Record(p) => Ok(*p),
1068 _ => Err(anyhow!("expected a record, but got a {}", self.get_type())),
1069 }
1070 }
1071
1072 pub fn as_lambda_pointer(&self) -> Result<LambdaPointer> {
1073 match self {
1074 Value::Lambda(p) => Ok(*p),
1075 _ => Err(anyhow!("expected a lambda, but got a {}", self.get_type())),
1076 }
1077 }
1078
1079 pub fn as_iterable_pointer(&self) -> Result<IterablePointer> {
1080 match self {
1081 Value::Spread(p) => Ok(*p),
1082 _ => Err(anyhow!("expected a spread, but got a {}", self.get_type())),
1083 }
1084 }
1085
1086 pub fn to_serializable_value(&self, heap: &Heap) -> Result<SerializableValue> {
1087 SerializableValue::from_value(self, heap)
1088 }
1089
1090 pub fn reify<'h>(&self, heap: &'h Heap) -> Result<ReifiedValue<'h>> {
1091 match self {
1092 Value::Number(n) => Ok(ReifiedValue::Number(*n)),
1093 Value::List(p) => Ok(ReifiedValue::List(p.reify(heap).as_list()?, *p)),
1094 Value::Spread(p) => Ok(ReifiedValue::Spread(p.reify(heap).as_iterable()?, *p)),
1095 Value::Bool(b) => Ok(ReifiedValue::Bool(*b)),
1096 Value::Lambda(p) => Ok(ReifiedValue::Lambda(p.reify(heap).as_lambda()?, *p)),
1097 Value::String(p) => Ok(ReifiedValue::String(p.reify(heap).as_string()?, *p)),
1098 Value::Null => Ok(ReifiedValue::Null),
1099 Value::BuiltIn(id) => Ok(ReifiedValue::BuiltIn(*id)),
1100 Value::Record(p) => Ok(ReifiedValue::Record(p.reify(heap).as_record()?, *p)),
1101 }
1102 }
1103
1104 pub fn stringify_internal(&self, heap: &Heap) -> String {
1108 self.stringify(heap, false, false)
1109 }
1110
1111 pub fn stringify_external(&self, heap: &Heap) -> String {
1112 self.stringify(heap, true, false)
1113 }
1114
1115 pub fn stringify_for_display(&self, heap: &Heap) -> String {
1118 self.stringify(heap, false, true)
1119 }
1120
1121 fn stringify(&self, heap: &Heap, wrap_strings: bool, display_format: bool) -> String {
1122 match self {
1123 Value::String(p) => p
1124 .reify(heap)
1125 .as_string()
1126 .map(|s| {
1127 if wrap_strings {
1128 format!("\"{}\"", s)
1129 } else {
1130 s.to_string()
1131 }
1132 })
1133 .unwrap(),
1134 Value::List(p) => {
1135 let mut result = String::from("[");
1136 let list = p.reify(heap).as_list().unwrap();
1137
1138 for (i, value) in list.iter().enumerate() {
1139 result.push_str(&value.stringify(heap, wrap_strings, display_format));
1140 if i < list.len() - 1 {
1141 result.push_str(", ");
1142 }
1143 }
1144 result.push(']');
1145 result
1146 }
1147 Value::Record(p) => {
1148 let mut result = String::from("{");
1149 let record = p.reify(heap).as_record().unwrap();
1150
1151 for (i, (key, value)) in record.iter().enumerate() {
1152 result.push_str(&format!(
1153 "{}: {}",
1154 key,
1155 value.stringify(heap, wrap_strings, display_format)
1156 ));
1157 if i < record.len() - 1 {
1158 result.push_str(", ");
1159 }
1160 }
1161 result.push('}');
1162 result
1163 }
1164 Value::Lambda(p) => {
1165 let lambda = p.reify(heap).as_lambda().unwrap();
1166 let mut result = String::from("(");
1167 for (i, arg) in lambda.args.iter().enumerate() {
1168 result.push_str(&arg.to_string());
1169 if i < lambda.args.len() - 1 {
1170 result.push_str(", ");
1171 }
1172 }
1173 result.push_str(") => ");
1174
1175 let serializable_scope: IndexMap<String, SerializableValue> = lambda
1177 .scope
1178 .iter()
1179 .filter_map(|(k, v)| {
1180 SerializableValue::from_value(v, heap)
1181 .ok()
1182 .map(|sv| (k.clone(), sv))
1183 })
1184 .collect();
1185
1186 result.push_str(&crate::ast_to_source::expr_to_source_with_scope(
1187 &lambda.body,
1188 &serializable_scope,
1189 ));
1190 result
1191 }
1192 Value::BuiltIn(built_in) => {
1193 format!("{} (built-in)", built_in.name())
1194 }
1195 Value::Spread(p) => match p {
1196 IterablePointer::List(l) => {
1197 let list = l.reify(heap).as_list().unwrap();
1198 let mut result = String::from("...");
1199 result.push_str(
1200 &list
1201 .iter()
1202 .map(|v| v.stringify(heap, wrap_strings, display_format))
1203 .collect::<String>(),
1204 );
1205 result
1206 }
1207 IterablePointer::String(s) => {
1208 let string = s.reify(heap).as_string().unwrap();
1209 format!("...{}", string)
1210 }
1211 IterablePointer::Record(r) => {
1212 let record = r.reify(heap).as_record().unwrap();
1213 let mut result = String::from("...");
1214 result.push('{');
1215 for (i, (key, value)) in record.iter().enumerate() {
1216 result.push_str(&format!(
1217 "{}: {}",
1218 key,
1219 value.stringify(heap, wrap_strings, display_format)
1220 ));
1221 if i < record.len() - 1 {
1222 result.push_str(", ");
1223 }
1224 }
1225 result.push('}');
1226 result
1227 }
1228 },
1229 Value::Number(n) => {
1230 if display_format {
1231 format_display_number(*n)
1232 } else {
1233 n.to_string()
1234 }
1235 }
1236 Value::Bool(b) => b.to_string(),
1237 Value::Null => "null".to_string(),
1238 }
1239 }
1240}
1241
1242impl Display for Value {
1243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1244 match self {
1245 Value::Number(n) => write!(f, "{}", format_display_number(*n)),
1246 Value::List(p) => write!(f, "{}", p),
1247 Value::Spread(p) => write!(f, "...{}", p),
1248 Value::Bool(b) => write!(f, "{}", b),
1249 Value::Lambda(p) => write!(f, "{}", p),
1250 Value::String(p) => write!(f, "{}", p),
1251 Value::Null => write!(f, "null"),
1252 Value::BuiltIn(built_in) => write!(f, "{} (built-in)", built_in.name()),
1253 Value::Record(p) => write!(f, "{}", p),
1254 }
1255 }
1256}
1257
1258#[cfg(test)]
1259mod tests {
1260 use super::*;
1261
1262 #[test]
1263 fn test_format_display_number_zero() {
1264 assert_eq!(format_display_number(0.0), "0");
1265 assert_eq!(format_display_number(-0.0), "-0"); }
1267
1268 #[test]
1269 fn test_format_display_number_integers() {
1270 assert_eq!(format_display_number(1.0), "1");
1271 assert_eq!(format_display_number(123.0), "123");
1272 assert_eq!(format_display_number(1234.0), "1,234");
1273 assert_eq!(format_display_number(1234567.0), "1,234,567");
1274 assert_eq!(format_display_number(-1234567.0), "-1,234,567");
1275 }
1276
1277 #[test]
1278 fn test_format_display_number_large_integers() {
1279 assert_eq!(
1280 format_display_number(999999999999999.0),
1281 "999,999,999,999,999"
1282 );
1283 assert_eq!(
1284 format_display_number(100000000000000.0),
1285 "100,000,000,000,000"
1286 );
1287 }
1288
1289 #[test]
1290 fn test_format_display_number_decimals() {
1291 assert_eq!(format_display_number(3.14159), "3.14159");
1292 assert_eq!(format_display_number(1234.56), "1,234.56");
1293 assert_eq!(format_display_number(0.5), "0.5");
1294 assert_eq!(format_display_number(0.0001), "0.0001");
1295 }
1296
1297 #[test]
1298 fn test_format_display_number_scientific_small() {
1299 assert_eq!(format_display_number(0.00001), "1e-5");
1301 assert_eq!(format_display_number(0.00001234), "1.234e-5");
1302 assert_eq!(format_display_number(1e-10), "1e-10");
1303 }
1304
1305 #[test]
1306 fn test_format_display_number_scientific_large() {
1307 assert_eq!(format_display_number(1e15), "1e15");
1309 assert_eq!(format_display_number(1.5e15), "1.5e15");
1310 assert_eq!(format_display_number(1e20), "1e20");
1311 }
1312
1313 #[test]
1314 fn test_format_display_number_special_values() {
1315 assert_eq!(format_display_number(f64::NAN), "NaN");
1316 assert_eq!(format_display_number(f64::INFINITY), "Infinity");
1317 assert_eq!(format_display_number(f64::NEG_INFINITY), "-Infinity");
1318 }
1319
1320 #[test]
1321 fn test_format_display_number_negative() {
1322 assert_eq!(format_display_number(-3.14), "-3.14");
1323 assert_eq!(format_display_number(-1234.56), "-1,234.56");
1324 assert_eq!(format_display_number(-0.00001), "-1e-5");
1325 assert_eq!(format_display_number(-1e15), "-1e15");
1326 }
1327
1328 #[test]
1329 fn test_stringify_internal_vs_display() {
1330 use crate::heap::Heap;
1331
1332 let heap = Heap::new();
1333 let value = Value::Number(1234567.89);
1334
1335 assert_eq!(value.stringify_internal(&heap), "1234567.89");
1337
1338 assert_eq!(value.stringify_for_display(&heap), "1,234,567.89");
1340 }
1341
1342 #[test]
1343 fn test_stringify_negative_zero() {
1344 use crate::heap::Heap;
1345
1346 let heap = Heap::new();
1347 let neg_zero = Value::Number(-0.0);
1348
1349 assert_eq!(neg_zero.stringify_internal(&heap), "-0");
1351 assert_eq!(neg_zero.stringify_for_display(&heap), "-0");
1352 }
1353}