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, Default, PartialEq)]
299pub struct CapturedScope(Rc<HashMap<String, Value>>);
300
301impl CapturedScope {
302 pub fn new(map: HashMap<String, Value>) -> Self {
303 Self(Rc::new(map))
304 }
305
306 pub fn is_empty(&self) -> bool {
307 self.0.is_empty()
308 }
309
310 pub fn len(&self) -> usize {
311 self.0.len()
312 }
313
314 pub fn contains_key(&self, key: &str) -> bool {
315 self.0.contains_key(key)
316 }
317
318 pub fn get(&self, key: &str) -> Option<Value> {
319 self.0.get(key).copied()
320 }
321
322 pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)> {
323 self.0.iter()
324 }
325
326 pub fn as_rc(&self) -> Rc<HashMap<String, Value>> {
327 Rc::clone(&self.0)
328 }
329}
330
331#[derive(Debug, Clone, PartialEq)]
332pub struct LambdaDef {
333 pub name: Option<String>,
334 pub args: Vec<LambdaArg>,
335 pub body: SpannedExpr,
336 pub scope: CapturedScope,
337 pub source: Rc<str>,
339}
340
341impl LambdaDef {
342 pub fn set_name(&mut self, name: String, _value: Value) {
343 self.name = Some(name.clone());
344 }
345
346 pub fn get_arity(&self) -> FunctionArity {
347 let has_rest = self.args.iter().any(|arg| arg.is_rest());
348 let min = self.args.iter().filter(|arg| arg.is_required()).count();
349 let max = self.args.len();
350
351 if has_rest {
352 FunctionArity::AtLeast(min)
353 } else if min == max {
354 FunctionArity::Exact(min)
355 } else {
356 FunctionArity::Between(min, max)
357 }
358 }
359}
360
361impl PartialOrd for LambdaDef {
362 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
363 if self.args > other.args {
364 Some(std::cmp::Ordering::Greater)
365 } else if self.args < other.args {
366 Some(std::cmp::Ordering::Less)
367 } else {
368 Some(std::cmp::Ordering::Equal)
369 }
370 }
371}
372
373#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
374pub struct SerializableLambdaDef {
375 pub name: Option<String>,
376 pub args: Vec<LambdaArg>,
377 pub body: String,
378 pub scope: Option<IndexMap<String, SerializableValue>>,
379}
380
381pub struct WithHeap<'h, T> {
382 pub value: &'h T,
383 pub heap: Rc<RefCell<Heap>>,
384}
385
386#[derive(Debug, Copy, Clone, PartialEq)]
387pub enum ReifiedIterableValue<'h> {
388 List(&'h Vec<Value>),
389 String(&'h String),
390 Record(&'h IndexMap<String, Value>),
391}
392
393#[derive(Debug, Clone, PartialEq)]
394pub enum ReifiedIterableValueType {
395 List,
396 String,
397 Record,
398}
399
400impl<'h> ReifiedIterableValue<'h> {
401 pub fn with_heap(&'h self, heap: Rc<RefCell<Heap>>) -> WithHeap<'h, ReifiedIterableValue<'h>> {
402 WithHeap { value: self, heap }
403 }
404
405 pub fn get_type(&self) -> ReifiedIterableValueType {
406 match self {
407 ReifiedIterableValue::List(_) => ReifiedIterableValueType::List,
408 ReifiedIterableValue::String(_) => ReifiedIterableValueType::String,
409 ReifiedIterableValue::Record(_) => ReifiedIterableValueType::Record,
410 }
411 }
412}
413
414impl<'h> IntoIterator for WithHeap<'h, ReifiedIterableValue<'h>> {
415 type Item = Value;
416 type IntoIter = std::vec::IntoIter<Self::Item>;
417
418 fn into_iter(self) -> Self::IntoIter {
419 match self.value {
420 ReifiedIterableValue::List(l) => (*l).clone().into_iter(),
422 ReifiedIterableValue::String(s) => s
424 .chars()
425 .map(|c| self.heap.borrow_mut().insert_string(c.to_string()))
426 .collect::<Vec<Value>>()
427 .into_iter(),
428 ReifiedIterableValue::Record(r) => r
430 .into_iter()
431 .map(|(k, v)| {
432 let list = vec![self.heap.borrow_mut().insert_string(k.to_string()), *v];
433 self.heap.borrow_mut().insert_list(list)
434 })
435 .collect::<Vec<Value>>()
436 .into_iter(),
437 }
438 }
439}
440
441impl<'h> IntoIterator for WithHeap<'h, ReifiedValue<'h>> {
442 type Item = Value;
443 type IntoIter = std::vec::IntoIter<Self::Item>;
444
445 fn into_iter(self) -> Self::IntoIter {
446 match self.value {
447 ReifiedValue::Spread(iterable, _) => iterable.with_heap(self.heap).into_iter(),
448 _ => vec![(*self.value).into()].into_iter(),
449 }
450 }
451}
452
453#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
454pub enum ValueType {
455 Number,
456 List,
457 Spread,
458 Bool,
459 Lambda,
460 BuiltIn,
461 String,
462 Record,
463 Null,
464}
465
466impl Display for ValueType {
467 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
468 match self {
469 ValueType::Number => write!(f, "number"),
470 ValueType::List => write!(f, "list"),
471 ValueType::Spread => write!(f, "spread"),
472 ValueType::Bool => write!(f, "boolean"),
473 ValueType::Lambda => write!(f, "function"),
474 ValueType::BuiltIn => write!(f, "built-in function"),
475 ValueType::String => write!(f, "string"),
476 ValueType::Record => write!(f, "record"),
477 ValueType::Null => write!(f, "null"),
478 }
479 }
480}
481
482#[derive(Debug, Copy, Clone, PartialEq)]
484pub enum ReifiedValue<'h> {
485 Number(f64),
487 Bool(bool),
489 Null,
491 List(&'h Vec<Value>, ListPointer),
493 String(&'h str, StringPointer),
495 Record(&'h IndexMap<String, Value>, RecordPointer),
497 Lambda(&'h LambdaDef, LambdaPointer),
499 Spread(ReifiedIterableValue<'h>, IterablePointer),
501 BuiltIn(BuiltInFunction),
503}
504
505impl<'h> ReifiedValue<'h> {
506 pub fn with_heap(&'h self, heap: Rc<RefCell<Heap>>) -> WithHeap<'h, ReifiedValue<'h>> {
507 WithHeap { value: self, heap }
508 }
509}
510
511impl From<ReifiedValue<'_>> for Value {
512 fn from(value: ReifiedValue) -> Self {
513 match value {
514 ReifiedValue::Number(n) => Value::Number(n),
515 ReifiedValue::Bool(b) => Value::Bool(b),
516 ReifiedValue::Null => Value::Null,
517 ReifiedValue::List(_, p) => Value::List(p),
518 ReifiedValue::String(_, p) => Value::String(p),
519 ReifiedValue::Record(_, p) => Value::Record(p),
520 ReifiedValue::Lambda(_, p) => Value::Lambda(p),
521 ReifiedValue::Spread(_, p) => Value::Spread(p),
522 ReifiedValue::BuiltIn(id) => Value::BuiltIn(id),
523 }
524 }
525}
526
527#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
528pub enum SerializableIterableValue {
529 List(Vec<SerializableValue>),
530 String(String),
531 Record(IndexMap<String, SerializableValue>),
532}
533
534#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
535pub enum SerializableValue {
536 Number(f64),
537 Bool(bool),
538 Null,
539 List(Vec<SerializableValue>),
540 String(String),
541 Record(IndexMap<String, SerializableValue>),
542 Lambda(SerializableLambdaDef),
543 BuiltIn(String),
544}
545
546impl SerializableValue {
547 pub fn from_json(value: &serde_json::Value) -> SerializableValue {
549 match value {
550 serde_json::Value::Number(n) => SerializableValue::Number(n.as_f64().unwrap_or(0.0)),
551 serde_json::Value::Bool(b) => SerializableValue::Bool(*b),
552 serde_json::Value::Null => SerializableValue::Null,
553 serde_json::Value::String(s) => SerializableValue::String(s.clone()),
554 serde_json::Value::Array(arr) => {
555 SerializableValue::List(arr.iter().map(Self::from_json).collect())
556 }
557 serde_json::Value::Object(obj) => {
558 if let Some(func_value) = obj.get("__blots_function")
560 && let Some(func_str) = func_value.as_str()
561 {
562 if crate::functions::BuiltInFunction::from_ident(func_str).is_some() {
564 return SerializableValue::BuiltIn(func_str.to_string());
565 }
566
567 if let Ok(lambda_def) = Self::parse_function_source(func_str) {
570 return SerializableValue::Lambda(lambda_def);
571 }
572 }
573
574 let map: IndexMap<String, SerializableValue> = obj
576 .iter()
577 .map(|(k, v)| (k.clone(), Self::from_json(v)))
578 .collect();
579 SerializableValue::Record(map)
580 }
581 }
582 }
583
584 fn parse_function_source(source: &str) -> Result<SerializableLambdaDef> {
586 use crate::expressions::pairs_to_expr;
587 use crate::parser::get_pairs;
588
589 let pairs = get_pairs(source)?;
591
592 for pair in pairs {
594 if let crate::parser::Rule::statement = pair.as_rule()
595 && let Some(inner_pair) = pair.into_inner().next()
596 && let crate::parser::Rule::expression = inner_pair.as_rule()
597 {
598 let expr = pairs_to_expr(inner_pair.into_inner())?;
600
601 if let crate::ast::Expr::Lambda { args, body } = expr.node {
603 return Ok(SerializableLambdaDef {
606 name: None,
607 args,
608 body: crate::ast_to_source::expr_to_source(&body),
609 scope: None, });
611 }
612 }
613 }
614
615 Err(anyhow!("Failed to parse function source: {}", source))
616 }
617
618 pub fn to_json(&self) -> serde_json::Value {
620 match self {
621 SerializableValue::Number(n) => serde_json::Value::Number(
622 serde_json::Number::from_f64(*n).unwrap_or_else(|| serde_json::Number::from(0)),
623 ),
624 SerializableValue::Bool(b) => serde_json::Value::Bool(*b),
625 SerializableValue::Null => serde_json::Value::Null,
626 SerializableValue::String(s) => serde_json::Value::String(s.clone()),
627 SerializableValue::List(items) => {
628 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
629 }
630 SerializableValue::Record(fields) => {
631 let map: serde_json::Map<String, serde_json::Value> = fields
632 .iter()
633 .map(|(k, v)| (k.clone(), v.to_json()))
634 .collect();
635 serde_json::Value::Object(map)
636 }
637 SerializableValue::Lambda(lambda_def) => {
638 let mut map = serde_json::Map::new();
641
642 let args_str: Vec<String> = lambda_def
644 .args
645 .iter()
646 .map(|arg| match arg {
647 LambdaArg::Required(name) => name.clone(),
648 LambdaArg::Optional(name) => format!("{}?", name),
649 LambdaArg::Rest(name) => format!("...{}", name),
650 })
651 .collect();
652
653 let function_source = format!("({}) => {}", args_str.join(", "), lambda_def.body);
654
655 map.insert(
656 "__blots_function".to_string(),
657 serde_json::Value::String(function_source),
658 );
659 serde_json::Value::Object(map)
660 }
661 SerializableValue::BuiltIn(name) => {
662 let mut map = serde_json::Map::new();
664 map.insert(
665 "__blots_function".to_string(),
666 serde_json::Value::String(name.clone()),
667 );
668 serde_json::Value::Object(map)
669 }
670 }
671 }
672
673 pub fn from_value(value: &Value, heap: &Heap) -> Result<SerializableValue> {
674 match value {
675 Value::Number(n) => Ok(SerializableValue::Number(*n)),
676 Value::Bool(b) => Ok(SerializableValue::Bool(*b)),
677 Value::Null => Ok(SerializableValue::Null),
678 Value::List(p) => {
679 let list = p.reify(heap).as_list()?;
680 let serialized_list = list
681 .iter()
682 .map(|v| SerializableValue::from_value(v, heap))
683 .collect::<Result<Vec<SerializableValue>>>()?;
684 Ok(SerializableValue::List(serialized_list))
685 }
686 Value::String(p) => {
687 let string = p.reify(heap).as_string()?;
688 Ok(SerializableValue::String(string.to_string()))
689 }
690 Value::Record(p) => {
691 let record = p.reify(heap).as_record()?;
692 let serialized_record = record
693 .iter()
694 .map(|(k, v)| Ok((k.to_string(), SerializableValue::from_value(v, heap)?)))
695 .collect::<Result<IndexMap<String, SerializableValue>>>()?;
696 Ok(SerializableValue::Record(serialized_record))
697 }
698 Value::Lambda(p) => {
699 let lambda = p.reify(heap).as_lambda()?;
700
701 let serializable_scope: IndexMap<String, SerializableValue> = lambda
703 .scope
704 .iter()
705 .map(|(k, v)| SerializableValue::from_value(v, heap).map(|sv| (k.clone(), sv)))
706 .collect::<Result<IndexMap<String, SerializableValue>>>()?;
707
708 let body_with_inlined_scope = crate::ast_to_source::expr_to_source_with_scope(
710 &lambda.body,
711 &serializable_scope,
712 );
713
714 Ok(SerializableValue::Lambda(SerializableLambdaDef {
715 name: lambda.name.clone(),
716 args: lambda.args.clone(),
717 body: body_with_inlined_scope,
718 scope: Some(serializable_scope),
719 }))
720 }
721 Value::BuiltIn(built_in) => Ok(SerializableValue::BuiltIn(built_in.name().to_string())),
722 Value::Spread(_) => Err(anyhow!("cannot serialize a spread value")),
723 }
724 }
725
726 pub fn to_value(&self, heap: &mut Heap) -> Result<Value> {
727 match self {
728 SerializableValue::Number(n) => Ok(Value::Number(*n)),
729 SerializableValue::Bool(b) => Ok(Value::Bool(*b)),
730 SerializableValue::Null => Ok(Value::Null),
731 SerializableValue::List(list) => {
732 let deserialized_list = list
733 .iter()
734 .map(|v| SerializableValue::to_value(v, heap))
735 .collect::<Result<Vec<Value>>>()?;
736
737 Ok(heap.insert_list(deserialized_list))
738 }
739 SerializableValue::String(s) => Ok(heap.insert_string(s.to_string())),
740 SerializableValue::Record(record) => {
741 let deserialized_record = record
742 .iter()
743 .map(|(k, v)| Ok((k.to_string(), SerializableValue::to_value(v, heap)?)))
744 .collect::<Result<IndexMap<String, Value>>>()?;
745 Ok(heap.insert_record(deserialized_record))
746 }
747 SerializableValue::Lambda(s_lambda) => {
748 let scope = if let Some(scope) = s_lambda.scope.as_ref() {
749 scope
750 .iter()
751 .map(|(k, v)| Ok((k.to_string(), SerializableValue::to_value(v, heap)?)))
752 .collect::<Result<HashMap<String, Value>>>()?
753 } else {
754 HashMap::new()
755 };
756
757 let body_ast = crate::expressions::pairs_to_expr(
760 crate::parser::get_pairs(&s_lambda.body)?
761 .next()
762 .unwrap()
763 .into_inner(),
764 )?;
765
766 let lambda = LambdaDef {
767 name: s_lambda.name.clone(),
768 args: s_lambda.args.clone(),
769 body: body_ast,
770 scope: CapturedScope::new(scope),
771 source: Rc::from(""), };
773
774 Ok(heap.insert_lambda(lambda))
775 }
776 SerializableValue::BuiltIn(ident) => BuiltInFunction::from_ident(ident)
777 .ok_or(anyhow!("built-in function with ident {} not found", ident))
778 .map(Value::BuiltIn),
779 }
780 }
781}
782
783#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
784pub enum PrimitiveValue {
785 Number(f64),
786 Bool(bool),
787 Null,
788}
789
790impl From<PrimitiveValue> for Value {
791 fn from(val: PrimitiveValue) -> Self {
792 match val {
793 PrimitiveValue::Number(n) => Value::Number(n),
794 PrimitiveValue::Bool(b) => Value::Bool(b),
795 PrimitiveValue::Null => Value::Null,
796 }
797 }
798}
799
800impl From<PrimitiveValue> for SerializableValue {
801 fn from(val: PrimitiveValue) -> Self {
802 match val {
803 PrimitiveValue::Number(n) => SerializableValue::Number(n),
804 PrimitiveValue::Bool(b) => SerializableValue::Bool(b),
805 PrimitiveValue::Null => SerializableValue::Null,
806 }
807 }
808}
809
810#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
811pub enum Value {
812 Number(f64),
814 Bool(bool),
816 Null,
818 List(ListPointer),
820 String(StringPointer),
822 Record(RecordPointer),
824 Lambda(LambdaPointer),
826 Spread(IterablePointer),
828 BuiltIn(BuiltInFunction),
830}
831
832impl Value {
833 pub fn equals(&self, other: &Value, heap: &Heap) -> Result<bool> {
835 match (self, other) {
836 (Value::Number(a), Value::Number(b)) => Ok(a == b),
838 (Value::Bool(a), Value::Bool(b)) => Ok(a == b),
839 (Value::Null, Value::Null) => Ok(true),
840
841 (Value::String(a_ptr), Value::String(b_ptr)) => {
843 let a_str = a_ptr.reify(heap).as_string()?;
844 let b_str = b_ptr.reify(heap).as_string()?;
845 Ok(a_str == b_str)
846 }
847
848 (Value::List(a_ptr), Value::List(b_ptr)) => {
850 let a_list = a_ptr.reify(heap).as_list()?;
851 let b_list = b_ptr.reify(heap).as_list()?;
852
853 if a_list.len() != b_list.len() {
854 return Ok(false);
855 }
856
857 for (a_elem, b_elem) in a_list.iter().zip(b_list.iter()) {
858 if !a_elem.equals(b_elem, heap)? {
859 return Ok(false);
860 }
861 }
862 Ok(true)
863 }
864
865 (Value::Record(a_ptr), Value::Record(b_ptr)) => {
867 let a_record = a_ptr.reify(heap).as_record()?;
868 let b_record = b_ptr.reify(heap).as_record()?;
869
870 if a_record.len() != b_record.len() {
871 return Ok(false);
872 }
873
874 for (key, a_value) in a_record.iter() {
875 match b_record.get(key) {
876 Some(b_value) => {
877 if !a_value.equals(b_value, heap)? {
878 return Ok(false);
879 }
880 }
881 None => return Ok(false),
882 }
883 }
884 Ok(true)
885 }
886
887 (Value::Lambda(a_ptr), Value::Lambda(b_ptr)) => {
889 let a_lambda = a_ptr.reify(heap).as_lambda()?;
890 let b_lambda = b_ptr.reify(heap).as_lambda()?;
891
892 if a_lambda.args != b_lambda.args {
894 return Ok(false);
895 }
896
897 if a_lambda.body != b_lambda.body {
899 return Ok(false);
900 }
901
902 Ok(true)
906 }
907
908 (Value::BuiltIn(a), Value::BuiltIn(b)) => Ok(a == b),
910
911 (Value::Spread(a_ptr), Value::Spread(b_ptr)) => match (a_ptr, b_ptr) {
913 (IterablePointer::List(a), IterablePointer::List(b)) => {
914 Value::List(*a).equals(&Value::List(*b), heap)
915 }
916 (IterablePointer::String(a), IterablePointer::String(b)) => {
917 Value::String(*a).equals(&Value::String(*b), heap)
918 }
919 (IterablePointer::Record(a), IterablePointer::Record(b)) => {
920 Value::Record(*a).equals(&Value::Record(*b), heap)
921 }
922 _ => Ok(false),
923 },
924
925 _ => Ok(false),
927 }
928 }
929
930 pub fn compare(&self, other: &Value, heap: &Heap) -> Result<Option<std::cmp::Ordering>> {
932 match (self, other) {
933 (Value::Number(a), Value::Number(b)) => Ok(a.partial_cmp(b)),
935
936 (Value::Bool(a), Value::Bool(b)) => Ok(a.partial_cmp(b)),
938
939 (Value::String(a_ptr), Value::String(b_ptr)) => {
941 let a_str = a_ptr.reify(heap).as_string()?;
942 let b_str = b_ptr.reify(heap).as_string()?;
943 Ok(a_str.partial_cmp(b_str))
944 }
945
946 (Value::List(a_ptr), Value::List(b_ptr)) => {
948 let a_list = a_ptr.reify(heap).as_list()?;
949 let b_list = b_ptr.reify(heap).as_list()?;
950
951 for (a_elem, b_elem) in a_list.iter().zip(b_list.iter()) {
952 match a_elem.compare(b_elem, heap)? {
953 Some(std::cmp::Ordering::Equal) => continue,
954 other => return Ok(other),
955 }
956 }
957
958 Ok(a_list.len().partial_cmp(&b_list.len()))
960 }
961
962 _ => Ok(None),
964 }
965 }
966
967 pub fn get_type(&self) -> ValueType {
968 match self {
969 Value::Number(_) => ValueType::Number,
970 Value::List(_) => ValueType::List,
971 Value::Spread(_) => ValueType::Spread,
972 Value::Bool(_) => ValueType::Bool,
973 Value::Lambda(_) => ValueType::Lambda,
974 Value::String(_) => ValueType::String,
975 Value::Null => ValueType::Null,
976 Value::BuiltIn(_) => ValueType::BuiltIn,
977 Value::Record(_) => ValueType::Record,
978 }
979 }
980
981 pub fn is_number(&self) -> bool {
982 matches!(self, Value::Number(_))
983 }
984
985 pub fn is_list(&self) -> bool {
986 matches!(self, Value::List(_))
987 }
988
989 pub fn is_spread(&self) -> bool {
990 matches!(self, Value::Spread(_))
991 }
992
993 pub fn is_bool(&self) -> bool {
994 matches!(self, Value::Bool(_))
995 }
996
997 pub fn is_lambda(&self) -> bool {
998 matches!(self, Value::Lambda(_))
999 }
1000
1001 pub fn is_string(&self) -> bool {
1002 matches!(self, Value::String(_))
1003 }
1004
1005 pub fn is_null(&self) -> bool {
1006 matches!(self, Value::Null)
1007 }
1008
1009 pub fn is_built_in(&self) -> bool {
1010 matches!(self, Value::BuiltIn(_))
1011 }
1012
1013 pub fn is_callable(&self) -> bool {
1014 matches!(self, Value::BuiltIn(_) | Value::Lambda(_))
1015 }
1016
1017 pub fn as_number(&self) -> Result<f64> {
1018 match self {
1019 Value::Number(n) => Ok(*n),
1020 _ => Err(anyhow!("expected a number, but got a {}", self.get_type())),
1021 }
1022 }
1023
1024 pub fn as_list<'h>(&self, heap: &'h Heap) -> Result<&'h Vec<Value>> {
1025 match self {
1026 Value::List(l) => l.reify(heap).as_list(),
1027 _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
1028 }
1029 }
1030
1031 pub fn as_spread<'h>(&self, heap: &'h Heap) -> Result<&'h HeapValue> {
1032 match self {
1033 Value::Spread(v) => Ok(v.reify(heap)),
1034 _ => Err(anyhow!("expected a spread, but got a {}", self.get_type())),
1035 }
1036 }
1037
1038 pub fn as_bool(&self) -> Result<bool> {
1039 match self {
1040 Value::Bool(b) => Ok(*b),
1041 _ => Err(anyhow!("expected a boolean, but got a {}", self.get_type())),
1042 }
1043 }
1044
1045 pub fn as_lambda<'h>(&self, heap: &'h Heap) -> Result<&'h LambdaDef> {
1046 match self {
1047 Value::Lambda(l) => l.reify(heap).as_lambda(),
1048 _ => Err(anyhow!("expected a lambda, but got a {}", self.get_type())),
1049 }
1050 }
1051
1052 pub fn as_string<'h>(&self, heap: &'h Heap) -> Result<&'h str> {
1053 match self {
1054 Value::String(p) => p.reify(heap).as_string(),
1055 _ => Err(anyhow!("expected a string, but got a {}", self.get_type())),
1056 }
1057 }
1058
1059 pub fn as_null(&self) -> Result<()> {
1060 match self {
1061 Value::Null => Ok(()),
1062 _ => Err(anyhow!("expected a null, but got a {}", self.get_type())),
1063 }
1064 }
1065
1066 pub fn as_built_in(&self) -> Result<&str> {
1067 match self {
1068 Value::BuiltIn(built_in) => Ok(built_in.name()),
1069 _ => Err(anyhow!(
1070 "expected a built-in function, but got a {}",
1071 self.get_type()
1072 )),
1073 }
1074 }
1075
1076 pub fn as_record<'h>(&self, heap: &'h Heap) -> Result<&'h IndexMap<String, Value>> {
1077 match self {
1078 Value::Record(r) => r.reify(heap).as_record(),
1079 _ => Err(anyhow!("expected a record, but got a {}", self.get_type())),
1080 }
1081 }
1082
1083 pub fn as_list_pointer(&self) -> Result<ListPointer> {
1084 match self {
1085 Value::List(p) => Ok(*p),
1086 _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
1087 }
1088 }
1089
1090 pub fn as_string_pointer(&self) -> Result<StringPointer> {
1091 match self {
1092 Value::String(p) => Ok(*p),
1093 _ => Err(anyhow!("expected a string, but got a {}", self.get_type())),
1094 }
1095 }
1096
1097 pub fn as_record_pointer(&self) -> Result<RecordPointer> {
1098 match self {
1099 Value::Record(p) => Ok(*p),
1100 _ => Err(anyhow!("expected a record, but got a {}", self.get_type())),
1101 }
1102 }
1103
1104 pub fn as_lambda_pointer(&self) -> Result<LambdaPointer> {
1105 match self {
1106 Value::Lambda(p) => Ok(*p),
1107 _ => Err(anyhow!("expected a lambda, but got a {}", self.get_type())),
1108 }
1109 }
1110
1111 pub fn as_iterable_pointer(&self) -> Result<IterablePointer> {
1112 match self {
1113 Value::Spread(p) => Ok(*p),
1114 _ => Err(anyhow!("expected a spread, but got a {}", self.get_type())),
1115 }
1116 }
1117
1118 pub fn to_serializable_value(&self, heap: &Heap) -> Result<SerializableValue> {
1119 SerializableValue::from_value(self, heap)
1120 }
1121
1122 pub fn reify<'h>(&self, heap: &'h Heap) -> Result<ReifiedValue<'h>> {
1123 match self {
1124 Value::Number(n) => Ok(ReifiedValue::Number(*n)),
1125 Value::List(p) => Ok(ReifiedValue::List(p.reify(heap).as_list()?, *p)),
1126 Value::Spread(p) => Ok(ReifiedValue::Spread(p.reify(heap).as_iterable()?, *p)),
1127 Value::Bool(b) => Ok(ReifiedValue::Bool(*b)),
1128 Value::Lambda(p) => Ok(ReifiedValue::Lambda(p.reify(heap).as_lambda()?, *p)),
1129 Value::String(p) => Ok(ReifiedValue::String(p.reify(heap).as_string()?, *p)),
1130 Value::Null => Ok(ReifiedValue::Null),
1131 Value::BuiltIn(id) => Ok(ReifiedValue::BuiltIn(*id)),
1132 Value::Record(p) => Ok(ReifiedValue::Record(p.reify(heap).as_record()?, *p)),
1133 }
1134 }
1135
1136 pub fn stringify_internal(&self, heap: &Heap) -> String {
1140 self.stringify(heap, false, false)
1141 }
1142
1143 pub fn stringify_external(&self, heap: &Heap) -> String {
1144 self.stringify(heap, true, false)
1145 }
1146
1147 pub fn stringify_for_display(&self, heap: &Heap) -> String {
1150 self.stringify(heap, false, true)
1151 }
1152
1153 fn stringify(&self, heap: &Heap, wrap_strings: bool, display_format: bool) -> String {
1154 match self {
1155 Value::String(p) => p
1156 .reify(heap)
1157 .as_string()
1158 .map(|s| {
1159 if wrap_strings {
1160 format!("\"{}\"", s)
1161 } else {
1162 s.to_string()
1163 }
1164 })
1165 .unwrap(),
1166 Value::List(p) => {
1167 let mut result = String::from("[");
1168 let list = p.reify(heap).as_list().unwrap();
1169
1170 for (i, value) in list.iter().enumerate() {
1171 result.push_str(&value.stringify(heap, wrap_strings, display_format));
1172 if i < list.len() - 1 {
1173 result.push_str(", ");
1174 }
1175 }
1176 result.push(']');
1177 result
1178 }
1179 Value::Record(p) => {
1180 let mut result = String::from("{");
1181 let record = p.reify(heap).as_record().unwrap();
1182
1183 for (i, (key, value)) in record.iter().enumerate() {
1184 result.push_str(&format!(
1185 "{}: {}",
1186 key,
1187 value.stringify(heap, wrap_strings, display_format)
1188 ));
1189 if i < record.len() - 1 {
1190 result.push_str(", ");
1191 }
1192 }
1193 result.push('}');
1194 result
1195 }
1196 Value::Lambda(p) => {
1197 let lambda = p.reify(heap).as_lambda().unwrap();
1198 let mut result = String::from("(");
1199 for (i, arg) in lambda.args.iter().enumerate() {
1200 result.push_str(&arg.to_string());
1201 if i < lambda.args.len() - 1 {
1202 result.push_str(", ");
1203 }
1204 }
1205 result.push_str(") => ");
1206
1207 let serializable_scope: IndexMap<String, SerializableValue> = lambda
1209 .scope
1210 .iter()
1211 .filter_map(|(k, v)| {
1212 SerializableValue::from_value(v, heap)
1213 .ok()
1214 .map(|sv| (k.clone(), sv))
1215 })
1216 .collect();
1217
1218 result.push_str(&crate::ast_to_source::expr_to_source_with_scope(
1219 &lambda.body,
1220 &serializable_scope,
1221 ));
1222 result
1223 }
1224 Value::BuiltIn(built_in) => {
1225 format!("{} (built-in)", built_in.name())
1226 }
1227 Value::Spread(p) => match p {
1228 IterablePointer::List(l) => {
1229 let list = l.reify(heap).as_list().unwrap();
1230 let mut result = String::from("...");
1231 result.push_str(
1232 &list
1233 .iter()
1234 .map(|v| v.stringify(heap, wrap_strings, display_format))
1235 .collect::<String>(),
1236 );
1237 result
1238 }
1239 IterablePointer::String(s) => {
1240 let string = s.reify(heap).as_string().unwrap();
1241 format!("...{}", string)
1242 }
1243 IterablePointer::Record(r) => {
1244 let record = r.reify(heap).as_record().unwrap();
1245 let mut result = String::from("...");
1246 result.push('{');
1247 for (i, (key, value)) in record.iter().enumerate() {
1248 result.push_str(&format!(
1249 "{}: {}",
1250 key,
1251 value.stringify(heap, wrap_strings, display_format)
1252 ));
1253 if i < record.len() - 1 {
1254 result.push_str(", ");
1255 }
1256 }
1257 result.push('}');
1258 result
1259 }
1260 },
1261 Value::Number(n) => {
1262 if display_format {
1263 format_display_number(*n)
1264 } else {
1265 n.to_string()
1266 }
1267 }
1268 Value::Bool(b) => b.to_string(),
1269 Value::Null => "null".to_string(),
1270 }
1271 }
1272}
1273
1274impl Display for Value {
1275 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1276 match self {
1277 Value::Number(n) => write!(f, "{}", format_display_number(*n)),
1278 Value::List(p) => write!(f, "{}", p),
1279 Value::Spread(p) => write!(f, "...{}", p),
1280 Value::Bool(b) => write!(f, "{}", b),
1281 Value::Lambda(p) => write!(f, "{}", p),
1282 Value::String(p) => write!(f, "{}", p),
1283 Value::Null => write!(f, "null"),
1284 Value::BuiltIn(built_in) => write!(f, "{} (built-in)", built_in.name()),
1285 Value::Record(p) => write!(f, "{}", p),
1286 }
1287 }
1288}
1289
1290#[cfg(test)]
1291mod tests {
1292 use super::*;
1293
1294 #[test]
1295 fn test_format_display_number_zero() {
1296 assert_eq!(format_display_number(0.0), "0");
1297 assert_eq!(format_display_number(-0.0), "-0"); }
1299
1300 #[test]
1301 fn test_format_display_number_integers() {
1302 assert_eq!(format_display_number(1.0), "1");
1303 assert_eq!(format_display_number(123.0), "123");
1304 assert_eq!(format_display_number(1234.0), "1,234");
1305 assert_eq!(format_display_number(1234567.0), "1,234,567");
1306 assert_eq!(format_display_number(-1234567.0), "-1,234,567");
1307 }
1308
1309 #[test]
1310 fn test_format_display_number_large_integers() {
1311 assert_eq!(
1312 format_display_number(999999999999999.0),
1313 "999,999,999,999,999"
1314 );
1315 assert_eq!(
1316 format_display_number(100000000000000.0),
1317 "100,000,000,000,000"
1318 );
1319 }
1320
1321 #[test]
1322 fn test_format_display_number_decimals() {
1323 assert_eq!(format_display_number(3.7432), "3.7432");
1324 assert_eq!(format_display_number(1234.56), "1,234.56");
1325 assert_eq!(format_display_number(0.5), "0.5");
1326 assert_eq!(format_display_number(0.0001), "0.0001");
1327 }
1328
1329 #[test]
1330 fn test_format_display_number_scientific_small() {
1331 assert_eq!(format_display_number(0.00001), "1e-5");
1333 assert_eq!(format_display_number(0.00001234), "1.234e-5");
1334 assert_eq!(format_display_number(1e-10), "1e-10");
1335 }
1336
1337 #[test]
1338 fn test_format_display_number_scientific_large() {
1339 assert_eq!(format_display_number(1e15), "1e15");
1341 assert_eq!(format_display_number(1.5e15), "1.5e15");
1342 assert_eq!(format_display_number(1e20), "1e20");
1343 }
1344
1345 #[test]
1346 fn test_format_display_number_special_values() {
1347 assert_eq!(format_display_number(f64::NAN), "NaN");
1348 assert_eq!(format_display_number(f64::INFINITY), "Infinity");
1349 assert_eq!(format_display_number(f64::NEG_INFINITY), "-Infinity");
1350 }
1351
1352 #[test]
1353 fn test_format_display_number_negative() {
1354 assert_eq!(format_display_number(-3.7432), "-3.7432");
1355 assert_eq!(format_display_number(-1234.56), "-1,234.56");
1356 assert_eq!(format_display_number(-0.00001), "-1e-5");
1357 assert_eq!(format_display_number(-1e15), "-1e15");
1358 }
1359
1360 #[test]
1361 fn test_stringify_internal_vs_display() {
1362 use crate::heap::Heap;
1363
1364 let heap = Heap::new();
1365 let value = Value::Number(1234567.89);
1366
1367 assert_eq!(value.stringify_internal(&heap), "1234567.89");
1369
1370 assert_eq!(value.stringify_for_display(&heap), "1,234,567.89");
1372 }
1373
1374 #[test]
1375 fn test_stringify_negative_zero() {
1376 use crate::heap::Heap;
1377
1378 let heap = Heap::new();
1379 let neg_zero = Value::Number(-0.0);
1380
1381 assert_eq!(neg_zero.stringify_internal(&heap), "-0");
1383 assert_eq!(neg_zero.stringify_for_display(&heap), "-0");
1384 }
1385}