blots_core/
values.rs

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
15#[derive(Debug)]
16pub enum FunctionArity {
17    Exact(usize),
18    AtLeast(usize),
19    Between(usize, usize),
20}
21
22impl FunctionArity {
23    pub fn can_accept(&self, n: usize) -> bool {
24        match self {
25            FunctionArity::Exact(expected) => n == *expected,
26            FunctionArity::Between(min, max) => n >= *min && n <= *max,
27            FunctionArity::AtLeast(min) => n >= *min,
28        }
29    }
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
33pub enum LambdaArg {
34    Required(String),
35    Optional(String),
36    Rest(String),
37}
38
39impl LambdaArg {
40    pub fn get_name(&self) -> &str {
41        match self {
42            LambdaArg::Required(name) => name,
43            LambdaArg::Optional(name) => name,
44            LambdaArg::Rest(name) => name,
45        }
46    }
47
48    pub fn is_required(&self) -> bool {
49        matches!(self, LambdaArg::Required(_))
50    }
51
52    pub fn is_optional(&self) -> bool {
53        matches!(self, LambdaArg::Optional(_))
54    }
55
56    pub fn is_rest(&self) -> bool {
57        matches!(self, LambdaArg::Rest(_))
58    }
59
60    pub fn as_required(&self) -> Result<&str> {
61        match self {
62            LambdaArg::Required(name) => Ok(name),
63            _ => Err(anyhow!(
64                "expected a required argument, but got a {} one",
65                self.get_name()
66            )),
67        }
68    }
69
70    pub fn as_optional(&self) -> Result<&str> {
71        match self {
72            LambdaArg::Optional(name) => Ok(name),
73            _ => Err(anyhow!(
74                "expected an optional argument, but got a {} one",
75                self.get_name()
76            )),
77        }
78    }
79
80    pub fn as_rest(&self) -> Result<&str> {
81        match self {
82            LambdaArg::Rest(name) => Ok(name),
83            _ => Err(anyhow!(
84                "expected a rest argument, but got a {} one",
85                self.get_name()
86            )),
87        }
88    }
89}
90
91impl Display for LambdaArg {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        match self {
94            LambdaArg::Required(name) => write!(f, "{}", name),
95            LambdaArg::Optional(name) => write!(f, "{}?", name),
96            LambdaArg::Rest(name) => write!(f, "...{}", name),
97        }
98    }
99}
100
101#[derive(Debug, Clone, PartialEq)]
102pub struct LambdaDef {
103    pub name: Option<String>,
104    pub args: Vec<LambdaArg>,
105    pub body: SpannedExpr,
106    pub scope: HashMap<String, Value>,
107    /// The source code string that the body's spans refer to (shared via Rc for efficiency)
108    pub source: Rc<str>,
109}
110
111impl LambdaDef {
112    pub fn set_name(&mut self, name: String, _value: Value) {
113        self.name = Some(name.clone());
114    }
115
116    pub fn get_arity(&self) -> FunctionArity {
117        let has_rest = self.args.iter().any(|arg| arg.is_rest());
118        let min = self.args.iter().filter(|arg| arg.is_required()).count();
119        let max = self.args.len();
120
121        if has_rest {
122            FunctionArity::AtLeast(min)
123        } else if min == max {
124            FunctionArity::Exact(min)
125        } else {
126            FunctionArity::Between(min, max)
127        }
128    }
129}
130
131impl PartialOrd for LambdaDef {
132    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
133        if self.args > other.args {
134            Some(std::cmp::Ordering::Greater)
135        } else if self.args < other.args {
136            Some(std::cmp::Ordering::Less)
137        } else {
138            Some(std::cmp::Ordering::Equal)
139        }
140    }
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
144pub struct SerializableLambdaDef {
145    pub name: Option<String>,
146    pub args: Vec<LambdaArg>,
147    pub body: String,
148    pub scope: Option<IndexMap<String, SerializableValue>>,
149}
150
151pub struct WithHeap<'h, T> {
152    pub value: &'h T,
153    pub heap: Rc<RefCell<Heap>>,
154}
155
156#[derive(Debug, Copy, Clone, PartialEq)]
157pub enum ReifiedIterableValue<'h> {
158    List(&'h Vec<Value>),
159    String(&'h String),
160    Record(&'h IndexMap<String, Value>),
161}
162
163#[derive(Debug, Clone, PartialEq)]
164pub enum ReifiedIterableValueType {
165    List,
166    String,
167    Record,
168}
169
170impl<'h> ReifiedIterableValue<'h> {
171    pub fn with_heap(&'h self, heap: Rc<RefCell<Heap>>) -> WithHeap<'h, ReifiedIterableValue<'h>> {
172        WithHeap { value: self, heap }
173    }
174
175    pub fn get_type(&self) -> ReifiedIterableValueType {
176        match self {
177            ReifiedIterableValue::List(_) => ReifiedIterableValueType::List,
178            ReifiedIterableValue::String(_) => ReifiedIterableValueType::String,
179            ReifiedIterableValue::Record(_) => ReifiedIterableValueType::Record,
180        }
181    }
182}
183
184impl<'h> IntoIterator for WithHeap<'h, ReifiedIterableValue<'h>> {
185    type Item = Value;
186    type IntoIter = std::vec::IntoIter<Self::Item>;
187
188    fn into_iter(self) -> Self::IntoIter {
189        match self.value {
190            // Yields an iterator over the values in the list.
191            ReifiedIterableValue::List(l) => (*l).clone().into_iter(),
192            // Yields an iterator over the characters in the string.
193            ReifiedIterableValue::String(s) => s
194                .chars()
195                .map(|c| self.heap.borrow_mut().insert_string(c.to_string()))
196                .collect::<Vec<Value>>()
197                .into_iter(),
198            // Yields an iterator over the [key, value] pairs of the record.
199            ReifiedIterableValue::Record(r) => r
200                .into_iter()
201                .map(|(k, v)| {
202                    let list = vec![self.heap.borrow_mut().insert_string(k.to_string()), *v];
203                    self.heap.borrow_mut().insert_list(list)
204                })
205                .collect::<Vec<Value>>()
206                .into_iter(),
207        }
208    }
209}
210
211impl<'h> IntoIterator for WithHeap<'h, ReifiedValue<'h>> {
212    type Item = Value;
213    type IntoIter = std::vec::IntoIter<Self::Item>;
214
215    fn into_iter(self) -> Self::IntoIter {
216        match self.value {
217            ReifiedValue::Spread(iterable, _) => iterable.with_heap(self.heap).into_iter(),
218            _ => vec![(*self.value).into()].into_iter(),
219        }
220    }
221}
222
223#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
224pub enum ValueType {
225    Number,
226    List,
227    Spread,
228    Bool,
229    Lambda,
230    BuiltIn,
231    String,
232    Record,
233    Null,
234}
235
236impl Display for ValueType {
237    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238        match self {
239            ValueType::Number => write!(f, "number"),
240            ValueType::List => write!(f, "list"),
241            ValueType::Spread => write!(f, "spread"),
242            ValueType::Bool => write!(f, "boolean"),
243            ValueType::Lambda => write!(f, "function"),
244            ValueType::BuiltIn => write!(f, "built-in function"),
245            ValueType::String => write!(f, "string"),
246            ValueType::Record => write!(f, "record"),
247            ValueType::Null => write!(f, "null"),
248        }
249    }
250}
251
252/// A value, after it has been "reified" (borrowed) from a pointer.
253#[derive(Debug, Copy, Clone, PartialEq)]
254pub enum ReifiedValue<'h> {
255    /// A number is a floating-point value.
256    Number(f64),
257    /// A boolean value is either true or false.
258    Bool(bool),
259    /// A null value represents the absence of a value.
260    Null,
261    /// A list is a sequence of values.
262    List(&'h Vec<Value>, ListPointer),
263    /// A string is a sequence of characters.
264    String(&'h str, StringPointer),
265    /// A record is a collection of key-value pairs.
266    Record(&'h IndexMap<String, Value>, RecordPointer),
267    /// A lambda is a function definition.
268    Lambda(&'h LambdaDef, LambdaPointer),
269    /// A spread value is "spread" into its container when it is used in a list, record, or function call. (internal only)
270    Spread(ReifiedIterableValue<'h>, IterablePointer),
271    /// A built-in function is a function that is implemented in Rust.
272    BuiltIn(BuiltInFunction),
273}
274
275impl<'h> ReifiedValue<'h> {
276    pub fn with_heap(&'h self, heap: Rc<RefCell<Heap>>) -> WithHeap<'h, ReifiedValue<'h>> {
277        WithHeap { value: self, heap }
278    }
279}
280
281impl From<ReifiedValue<'_>> for Value {
282    fn from(value: ReifiedValue) -> Self {
283        match value {
284            ReifiedValue::Number(n) => Value::Number(n),
285            ReifiedValue::Bool(b) => Value::Bool(b),
286            ReifiedValue::Null => Value::Null,
287            ReifiedValue::List(_, p) => Value::List(p),
288            ReifiedValue::String(_, p) => Value::String(p),
289            ReifiedValue::Record(_, p) => Value::Record(p),
290            ReifiedValue::Lambda(_, p) => Value::Lambda(p),
291            ReifiedValue::Spread(_, p) => Value::Spread(p),
292            ReifiedValue::BuiltIn(id) => Value::BuiltIn(id),
293        }
294    }
295}
296
297#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
298pub enum SerializableIterableValue {
299    List(Vec<SerializableValue>),
300    String(String),
301    Record(IndexMap<String, SerializableValue>),
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
305pub enum SerializableValue {
306    Number(f64),
307    Bool(bool),
308    Null,
309    List(Vec<SerializableValue>),
310    String(String),
311    Record(IndexMap<String, SerializableValue>),
312    Lambda(SerializableLambdaDef),
313    BuiltIn(String),
314}
315
316impl SerializableValue {
317    /// Convert from serde_json::Value to SerializableValue
318    pub fn from_json(value: &serde_json::Value) -> SerializableValue {
319        match value {
320            serde_json::Value::Number(n) => SerializableValue::Number(n.as_f64().unwrap_or(0.0)),
321            serde_json::Value::Bool(b) => SerializableValue::Bool(*b),
322            serde_json::Value::Null => SerializableValue::Null,
323            serde_json::Value::String(s) => SerializableValue::String(s.clone()),
324            serde_json::Value::Array(arr) => {
325                SerializableValue::List(arr.iter().map(Self::from_json).collect())
326            }
327            serde_json::Value::Object(obj) => {
328                // Check if this is a function object
329                if let Some(func_value) = obj.get("__blots_function")
330                    && let Some(func_str) = func_value.as_str()
331                {
332                    // Try to parse as a built-in function first (just a name)
333                    if crate::functions::BuiltInFunction::from_ident(func_str).is_some() {
334                        return SerializableValue::BuiltIn(func_str.to_string());
335                    }
336
337                    // Otherwise, parse as a lambda function
338                    // We need to parse the function source and convert it to a SerializableLambdaDef
339                    if let Ok(lambda_def) = Self::parse_function_source(func_str) {
340                        return SerializableValue::Lambda(lambda_def);
341                    }
342                }
343
344                // Regular record
345                let map: IndexMap<String, SerializableValue> = obj
346                    .iter()
347                    .map(|(k, v)| (k.clone(), Self::from_json(v)))
348                    .collect();
349                SerializableValue::Record(map)
350            }
351        }
352    }
353
354    /// Parse a function source string into a SerializableLambdaDef
355    fn parse_function_source(source: &str) -> Result<SerializableLambdaDef> {
356        use crate::expressions::pairs_to_expr;
357        use crate::parser::get_pairs;
358
359        // Parse the source as an expression
360        let pairs = get_pairs(source)?;
361
362        // Extract the lambda expression from the parsed pairs
363        for pair in pairs {
364            if let crate::parser::Rule::statement = pair.as_rule()
365                && let Some(inner_pair) = pair.into_inner().next()
366                && let crate::parser::Rule::expression = inner_pair.as_rule()
367            {
368                // Parse the expression to get an AST
369                let expr = pairs_to_expr(inner_pair.into_inner())?;
370
371                // Check if it's a lambda
372                if let crate::ast::Expr::Lambda { args, body } = expr.node {
373                    // Since the function is already inlined (no scope needed),
374                    // we create a SerializableLambdaDef with the source as the body
375                    return Ok(SerializableLambdaDef {
376                        name: None,
377                        args,
378                        body: crate::ast_to_source::expr_to_source(&body),
379                        scope: None, // Functions from JSON have no scope - they're already inlined
380                    });
381                }
382            }
383        }
384
385        Err(anyhow!("Failed to parse function source: {}", source))
386    }
387
388    /// Convert SerializableValue to clean serde_json::Value
389    pub fn to_json(&self) -> serde_json::Value {
390        match self {
391            SerializableValue::Number(n) => serde_json::Value::Number(
392                serde_json::Number::from_f64(*n).unwrap_or_else(|| serde_json::Number::from(0)),
393            ),
394            SerializableValue::Bool(b) => serde_json::Value::Bool(*b),
395            SerializableValue::Null => serde_json::Value::Null,
396            SerializableValue::String(s) => serde_json::Value::String(s.clone()),
397            SerializableValue::List(items) => {
398                serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
399            }
400            SerializableValue::Record(fields) => {
401                let map: serde_json::Map<String, serde_json::Value> = fields
402                    .iter()
403                    .map(|(k, v)| (k.clone(), v.to_json()))
404                    .collect();
405                serde_json::Value::Object(map)
406            }
407            SerializableValue::Lambda(lambda_def) => {
408                // We can't inline scope values from SerializableLambdaDef because the body is already a string
409                // For now, output the function as a JSON object with the source code
410                let mut map = serde_json::Map::new();
411
412                // Build the function source with arguments
413                let args_str: Vec<String> = lambda_def
414                    .args
415                    .iter()
416                    .map(|arg| match arg {
417                        LambdaArg::Required(name) => name.clone(),
418                        LambdaArg::Optional(name) => format!("{}?", name),
419                        LambdaArg::Rest(name) => format!("...{}", name),
420                    })
421                    .collect();
422
423                let function_source = format!("({}) => {}", args_str.join(", "), lambda_def.body);
424
425                map.insert(
426                    "__blots_function".to_string(),
427                    serde_json::Value::String(function_source),
428                );
429                serde_json::Value::Object(map)
430            }
431            SerializableValue::BuiltIn(name) => {
432                // Output built-in functions in the same format as lambdas
433                let mut map = serde_json::Map::new();
434                map.insert(
435                    "__blots_function".to_string(),
436                    serde_json::Value::String(name.clone()),
437                );
438                serde_json::Value::Object(map)
439            }
440        }
441    }
442
443    pub fn from_value(value: &Value, heap: &Heap) -> Result<SerializableValue> {
444        match value {
445            Value::Number(n) => Ok(SerializableValue::Number(*n)),
446            Value::Bool(b) => Ok(SerializableValue::Bool(*b)),
447            Value::Null => Ok(SerializableValue::Null),
448            Value::List(p) => {
449                let list = p.reify(heap).as_list()?;
450                let serialized_list = list
451                    .iter()
452                    .map(|v| SerializableValue::from_value(v, heap))
453                    .collect::<Result<Vec<SerializableValue>>>()?;
454                Ok(SerializableValue::List(serialized_list))
455            }
456            Value::String(p) => {
457                let string = p.reify(heap).as_string()?;
458                Ok(SerializableValue::String(string.to_string()))
459            }
460            Value::Record(p) => {
461                let record = p.reify(heap).as_record()?;
462                let serialized_record = record
463                    .iter()
464                    .map(|(k, v)| Ok((k.to_string(), SerializableValue::from_value(v, heap)?)))
465                    .collect::<Result<IndexMap<String, SerializableValue>>>()?;
466                Ok(SerializableValue::Record(serialized_record))
467            }
468            Value::Lambda(p) => {
469                let lambda = p.reify(heap).as_lambda()?;
470
471                // Convert the scope to SerializableValues
472                let serializable_scope: IndexMap<String, SerializableValue> = lambda
473                    .scope
474                    .clone()
475                    .into_iter()
476                    .map(|(k, v)| SerializableValue::from_value(&v, heap).map(|sv| (k, sv)))
477                    .collect::<Result<IndexMap<String, SerializableValue>>>()?;
478
479                // Generate the body with inlined scope values
480                let body_with_inlined_scope = crate::ast_to_source::expr_to_source_with_scope(
481                    &lambda.body,
482                    &serializable_scope,
483                );
484
485                Ok(SerializableValue::Lambda(SerializableLambdaDef {
486                    name: lambda.name.clone(),
487                    args: lambda.args.clone(),
488                    body: body_with_inlined_scope,
489                    scope: Some(serializable_scope),
490                }))
491            }
492            Value::BuiltIn(built_in) => Ok(SerializableValue::BuiltIn(built_in.name().to_string())),
493            Value::Spread(_) => Err(anyhow!("cannot serialize a spread value")),
494        }
495    }
496
497    pub fn to_value(&self, heap: &mut Heap) -> Result<Value> {
498        match self {
499            SerializableValue::Number(n) => Ok(Value::Number(*n)),
500            SerializableValue::Bool(b) => Ok(Value::Bool(*b)),
501            SerializableValue::Null => Ok(Value::Null),
502            SerializableValue::List(list) => {
503                let deserialized_list = list
504                    .iter()
505                    .map(|v| SerializableValue::to_value(v, heap))
506                    .collect::<Result<Vec<Value>>>()?;
507
508                Ok(heap.insert_list(deserialized_list))
509            }
510            SerializableValue::String(s) => Ok(heap.insert_string(s.to_string())),
511            SerializableValue::Record(record) => {
512                let deserialized_record = record
513                    .iter()
514                    .map(|(k, v)| Ok((k.to_string(), SerializableValue::to_value(v, heap)?)))
515                    .collect::<Result<IndexMap<String, Value>>>()?;
516                Ok(heap.insert_record(deserialized_record))
517            }
518            SerializableValue::Lambda(s_lambda) => {
519                let scope = if let Some(scope) = s_lambda.scope.clone() {
520                    scope
521                        .iter()
522                        .map(|(k, v)| Ok((k.to_string(), SerializableValue::to_value(v, heap)?)))
523                        .collect::<Result<HashMap<String, Value>>>()?
524                } else {
525                    HashMap::new()
526                };
527
528                // For now, parse the body string back to AST
529                // In a real implementation, we'd want to serialize/deserialize the AST properly
530                let body_ast = crate::expressions::pairs_to_expr(
531                    crate::parser::get_pairs(&s_lambda.body)?
532                        .next()
533                        .unwrap()
534                        .into_inner(),
535                )?;
536
537                let lambda = LambdaDef {
538                    name: s_lambda.name.clone(),
539                    args: s_lambda.args.clone(),
540                    body: body_ast,
541                    scope,
542                    source: Rc::from(""),  // Deserialized lambdas don't have original source
543                };
544
545                Ok(heap.insert_lambda(lambda))
546            }
547            SerializableValue::BuiltIn(ident) => BuiltInFunction::from_ident(ident)
548                .ok_or(anyhow!("built-in function with ident {} not found", ident))
549                .map(Value::BuiltIn),
550        }
551    }
552}
553
554#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
555pub enum PrimitiveValue {
556    Number(f64),
557    Bool(bool),
558    Null,
559}
560
561impl From<PrimitiveValue> for Value {
562    fn from(val: PrimitiveValue) -> Self {
563        match val {
564            PrimitiveValue::Number(n) => Value::Number(n),
565            PrimitiveValue::Bool(b) => Value::Bool(b),
566            PrimitiveValue::Null => Value::Null,
567        }
568    }
569}
570
571impl From<PrimitiveValue> for SerializableValue {
572    fn from(val: PrimitiveValue) -> Self {
573        match val {
574            PrimitiveValue::Number(n) => SerializableValue::Number(n),
575            PrimitiveValue::Bool(b) => SerializableValue::Bool(b),
576            PrimitiveValue::Null => SerializableValue::Null,
577        }
578    }
579}
580
581#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
582pub enum Value {
583    /// A number is a floating-point value.
584    Number(f64),
585    /// A boolean value is either true or false.
586    Bool(bool),
587    /// A null value represents the absence of a value.
588    Null,
589    /// A list is a sequence of values.
590    List(ListPointer),
591    /// A string is a sequence of characters.
592    String(StringPointer),
593    /// A record is a collection of key-value pairs.
594    Record(RecordPointer),
595    /// A lambda is a function definition.
596    Lambda(LambdaPointer),
597    /// A spread value is "spread" into its container when it is used in a list, record, or function call. (internal only)
598    Spread(IterablePointer),
599    /// A built-in function is a function that is implemented in Rust.
600    BuiltIn(BuiltInFunction),
601}
602
603impl Value {
604    /// Compare two values for equality by their actual content, not by reference
605    pub fn equals(&self, other: &Value, heap: &Heap) -> Result<bool> {
606        match (self, other) {
607            // Primitive types - compare directly
608            (Value::Number(a), Value::Number(b)) => Ok(a == b),
609            (Value::Bool(a), Value::Bool(b)) => Ok(a == b),
610            (Value::Null, Value::Null) => Ok(true),
611
612            // String comparison - compare content
613            (Value::String(a_ptr), Value::String(b_ptr)) => {
614                let a_str = a_ptr.reify(heap).as_string()?;
615                let b_str = b_ptr.reify(heap).as_string()?;
616                Ok(a_str == b_str)
617            }
618
619            // List comparison - compare elements recursively
620            (Value::List(a_ptr), Value::List(b_ptr)) => {
621                let a_list = a_ptr.reify(heap).as_list()?;
622                let b_list = b_ptr.reify(heap).as_list()?;
623
624                if a_list.len() != b_list.len() {
625                    return Ok(false);
626                }
627
628                for (a_elem, b_elem) in a_list.iter().zip(b_list.iter()) {
629                    if !a_elem.equals(b_elem, heap)? {
630                        return Ok(false);
631                    }
632                }
633                Ok(true)
634            }
635
636            // Record comparison - compare keys and values
637            (Value::Record(a_ptr), Value::Record(b_ptr)) => {
638                let a_record = a_ptr.reify(heap).as_record()?;
639                let b_record = b_ptr.reify(heap).as_record()?;
640
641                if a_record.len() != b_record.len() {
642                    return Ok(false);
643                }
644
645                for (key, a_value) in a_record.iter() {
646                    match b_record.get(key) {
647                        Some(b_value) => {
648                            if !a_value.equals(b_value, heap)? {
649                                return Ok(false);
650                            }
651                        }
652                        None => return Ok(false),
653                    }
654                }
655                Ok(true)
656            }
657
658            // Lambda comparison - compare by structure (AST equality)
659            (Value::Lambda(a_ptr), Value::Lambda(b_ptr)) => {
660                let a_lambda = a_ptr.reify(heap).as_lambda()?;
661                let b_lambda = b_ptr.reify(heap).as_lambda()?;
662
663                // Compare argument lists
664                if a_lambda.args != b_lambda.args {
665                    return Ok(false);
666                }
667
668                // Compare AST bodies
669                if a_lambda.body != b_lambda.body {
670                    return Ok(false);
671                }
672
673                // Note: We don't compare scopes because two functions with the same
674                // definition but different closures would have different behavior
675                // For now, we only compare structure, not captured variables
676                Ok(true)
677            }
678
679            // Built-in functions - compare by ID
680            (Value::BuiltIn(a), Value::BuiltIn(b)) => Ok(a == b),
681
682            // Spread values - compare the underlying iterable
683            (Value::Spread(a_ptr), Value::Spread(b_ptr)) => match (a_ptr, b_ptr) {
684                (IterablePointer::List(a), IterablePointer::List(b)) => {
685                    Value::List(*a).equals(&Value::List(*b), heap)
686                }
687                (IterablePointer::String(a), IterablePointer::String(b)) => {
688                    Value::String(*a).equals(&Value::String(*b), heap)
689                }
690                (IterablePointer::Record(a), IterablePointer::Record(b)) => {
691                    Value::Record(*a).equals(&Value::Record(*b), heap)
692                }
693                _ => Ok(false),
694            },
695
696            // Different types are never equal
697            _ => Ok(false),
698        }
699    }
700
701    /// Compare two values for ordering
702    pub fn compare(&self, other: &Value, heap: &Heap) -> Result<Option<std::cmp::Ordering>> {
703        match (self, other) {
704            // Numbers have natural ordering
705            (Value::Number(a), Value::Number(b)) => Ok(a.partial_cmp(b)),
706
707            // Booleans: false < true
708            (Value::Bool(a), Value::Bool(b)) => Ok(a.partial_cmp(b)),
709
710            // Strings compare lexicographically
711            (Value::String(a_ptr), Value::String(b_ptr)) => {
712                let a_str = a_ptr.reify(heap).as_string()?;
713                let b_str = b_ptr.reify(heap).as_string()?;
714                Ok(a_str.partial_cmp(b_str))
715            }
716
717            // Lists compare lexicographically
718            (Value::List(a_ptr), Value::List(b_ptr)) => {
719                let a_list = a_ptr.reify(heap).as_list()?;
720                let b_list = b_ptr.reify(heap).as_list()?;
721
722                for (a_elem, b_elem) in a_list.iter().zip(b_list.iter()) {
723                    match a_elem.compare(b_elem, heap)? {
724                        Some(std::cmp::Ordering::Equal) => continue,
725                        other => return Ok(other),
726                    }
727                }
728
729                // If all compared elements are equal, compare lengths
730                Ok(a_list.len().partial_cmp(&b_list.len()))
731            }
732
733            // Other types don't have a natural ordering
734            _ => Ok(None),
735        }
736    }
737
738    pub fn get_type(&self) -> ValueType {
739        match self {
740            Value::Number(_) => ValueType::Number,
741            Value::List(_) => ValueType::List,
742            Value::Spread(_) => ValueType::Spread,
743            Value::Bool(_) => ValueType::Bool,
744            Value::Lambda(_) => ValueType::Lambda,
745            Value::String(_) => ValueType::String,
746            Value::Null => ValueType::Null,
747            Value::BuiltIn(_) => ValueType::BuiltIn,
748            Value::Record(_) => ValueType::Record,
749        }
750    }
751
752    pub fn is_number(&self) -> bool {
753        matches!(self, Value::Number(_))
754    }
755
756    pub fn is_list(&self) -> bool {
757        matches!(self, Value::List(_))
758    }
759
760    pub fn is_spread(&self) -> bool {
761        matches!(self, Value::Spread(_))
762    }
763
764    pub fn is_bool(&self) -> bool {
765        matches!(self, Value::Bool(_))
766    }
767
768    pub fn is_lambda(&self) -> bool {
769        matches!(self, Value::Lambda(_))
770    }
771
772    pub fn is_string(&self) -> bool {
773        matches!(self, Value::String(_))
774    }
775
776    pub fn is_null(&self) -> bool {
777        matches!(self, Value::Null)
778    }
779
780    pub fn is_built_in(&self) -> bool {
781        matches!(self, Value::BuiltIn(_))
782    }
783
784    pub fn is_callable(&self) -> bool {
785        matches!(self, Value::BuiltIn(_) | Value::Lambda(_))
786    }
787
788    pub fn as_number(&self) -> Result<f64> {
789        match self {
790            Value::Number(n) => Ok(*n),
791            _ => Err(anyhow!("expected a number, but got a {}", self.get_type())),
792        }
793    }
794
795    pub fn as_list<'h>(&self, heap: &'h Heap) -> Result<&'h Vec<Value>> {
796        match self {
797            Value::List(l) => l.reify(heap).as_list(),
798            _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
799        }
800    }
801
802    pub fn as_spread<'h>(&self, heap: &'h Heap) -> Result<&'h HeapValue> {
803        match self {
804            Value::Spread(v) => Ok(v.reify(heap)),
805            _ => Err(anyhow!("expected a spread, but got a {}", self.get_type())),
806        }
807    }
808
809    pub fn as_bool(&self) -> Result<bool> {
810        match self {
811            Value::Bool(b) => Ok(*b),
812            _ => Err(anyhow!("expected a boolean, but got a {}", self.get_type())),
813        }
814    }
815
816    pub fn as_lambda<'h>(&self, heap: &'h Heap) -> Result<&'h LambdaDef> {
817        match self {
818            Value::Lambda(l) => l.reify(heap).as_lambda(),
819            _ => Err(anyhow!("expected a lambda, but got a {}", self.get_type())),
820        }
821    }
822
823    pub fn as_string<'h>(&self, heap: &'h Heap) -> Result<&'h str> {
824        match self {
825            Value::String(p) => p.reify(heap).as_string(),
826            _ => Err(anyhow!("expected a string, but got a {}", self.get_type())),
827        }
828    }
829
830    pub fn as_null(&self) -> Result<()> {
831        match self {
832            Value::Null => Ok(()),
833            _ => Err(anyhow!("expected a null, but got a {}", self.get_type())),
834        }
835    }
836
837    pub fn as_built_in(&self) -> Result<&str> {
838        match self {
839            Value::BuiltIn(built_in) => Ok(built_in.name()),
840            _ => Err(anyhow!(
841                "expected a built-in function, but got a {}",
842                self.get_type()
843            )),
844        }
845    }
846
847    pub fn as_record<'h>(&self, heap: &'h Heap) -> Result<&'h IndexMap<String, Value>> {
848        match self {
849            Value::Record(r) => r.reify(heap).as_record(),
850            _ => Err(anyhow!("expected a record, but got a {}", self.get_type())),
851        }
852    }
853
854    pub fn as_list_pointer(&self) -> Result<ListPointer> {
855        match self {
856            Value::List(p) => Ok(*p),
857            _ => Err(anyhow!("expected a list, but got a {}", self.get_type())),
858        }
859    }
860
861    pub fn as_string_pointer(&self) -> Result<StringPointer> {
862        match self {
863            Value::String(p) => Ok(*p),
864            _ => Err(anyhow!("expected a string, but got a {}", self.get_type())),
865        }
866    }
867
868    pub fn as_record_pointer(&self) -> Result<RecordPointer> {
869        match self {
870            Value::Record(p) => Ok(*p),
871            _ => Err(anyhow!("expected a record, but got a {}", self.get_type())),
872        }
873    }
874
875    pub fn as_lambda_pointer(&self) -> Result<LambdaPointer> {
876        match self {
877            Value::Lambda(p) => Ok(*p),
878            _ => Err(anyhow!("expected a lambda, but got a {}", self.get_type())),
879        }
880    }
881
882    pub fn as_iterable_pointer(&self) -> Result<IterablePointer> {
883        match self {
884            Value::Spread(p) => Ok(*p),
885            _ => Err(anyhow!("expected a spread, but got a {}", self.get_type())),
886        }
887    }
888
889    pub fn to_serializable_value(&self, heap: &Heap) -> Result<SerializableValue> {
890        SerializableValue::from_value(self, heap)
891    }
892
893    pub fn reify<'h>(&self, heap: &'h Heap) -> Result<ReifiedValue<'h>> {
894        match self {
895            Value::Number(n) => Ok(ReifiedValue::Number(*n)),
896            Value::List(p) => Ok(ReifiedValue::List(p.reify(heap).as_list()?, *p)),
897            Value::Spread(p) => Ok(ReifiedValue::Spread(p.reify(heap).as_iterable()?, *p)),
898            Value::Bool(b) => Ok(ReifiedValue::Bool(*b)),
899            Value::Lambda(p) => Ok(ReifiedValue::Lambda(p.reify(heap).as_lambda()?, *p)),
900            Value::String(p) => Ok(ReifiedValue::String(p.reify(heap).as_string()?, *p)),
901            Value::Null => Ok(ReifiedValue::Null),
902            Value::BuiltIn(id) => Ok(ReifiedValue::BuiltIn(*id)),
903            Value::Record(p) => Ok(ReifiedValue::Record(p.reify(heap).as_record()?, *p)),
904        }
905    }
906
907    /// Stringify the value. Returns the same thing as stringify, except for
908    /// Value::String, which is returned without wrapping quotes. Use this for string
909    /// concatenation, formatting, etc. Don't use this for displaying values to the user.
910    pub fn stringify_internal(&self, heap: &Heap) -> String {
911        self.stringify(heap, false)
912    }
913
914    pub fn stringify_external(&self, heap: &Heap) -> String {
915        self.stringify(heap, true)
916    }
917
918    fn stringify(&self, heap: &Heap, wrap_strings: bool) -> String {
919        match self {
920            Value::String(p) => p
921                .reify(heap)
922                .as_string()
923                .map(|s| {
924                    if wrap_strings {
925                        format!("\"{}\"", s)
926                    } else {
927                        s.to_string()
928                    }
929                })
930                .unwrap(),
931            Value::List(p) => {
932                let mut result = String::from("[");
933                let list = p.reify(heap).as_list().unwrap();
934
935                for (i, value) in list.iter().enumerate() {
936                    result.push_str(&value.stringify(heap, wrap_strings));
937                    if i < list.len() - 1 {
938                        result.push_str(", ");
939                    }
940                }
941                result.push(']');
942                result
943            }
944            Value::Record(p) => {
945                let mut result = String::from("{");
946                let record = p.reify(heap).as_record().unwrap();
947
948                for (i, (key, value)) in record.iter().enumerate() {
949                    result.push_str(&format!("{}: {}", key, value.stringify(heap, wrap_strings)));
950                    if i < record.len() - 1 {
951                        result.push_str(", ");
952                    }
953                }
954                result.push('}');
955                result
956            }
957            Value::Lambda(p) => {
958                let lambda = p.reify(heap).as_lambda().unwrap();
959                let mut result = String::from("(");
960                for (i, arg) in lambda.args.iter().enumerate() {
961                    result.push_str(&arg.to_string());
962                    if i < lambda.args.len() - 1 {
963                        result.push_str(", ");
964                    }
965                }
966                result.push_str(") => ");
967
968                // Convert scope to SerializableValues and inline them
969                let serializable_scope: IndexMap<String, SerializableValue> = lambda
970                    .scope
971                    .iter()
972                    .filter_map(|(k, v)| {
973                        SerializableValue::from_value(v, heap).ok().map(|sv| (k.clone(), sv))
974                    })
975                    .collect();
976
977                result.push_str(&crate::ast_to_source::expr_to_source_with_scope(
978                    &lambda.body,
979                    &serializable_scope,
980                ));
981                result
982            }
983            Value::BuiltIn(built_in) => {
984                format!("{} (built-in)", built_in.name())
985            }
986            Value::Spread(p) => match p {
987                IterablePointer::List(l) => {
988                    let list = l.reify(heap).as_list().unwrap();
989                    let mut result = String::from("...");
990                    result.push_str(
991                        &list
992                            .iter()
993                            .map(|v| v.stringify(heap, wrap_strings))
994                            .collect::<String>(),
995                    );
996                    result
997                }
998                IterablePointer::String(s) => {
999                    let string = s.reify(heap).as_string().unwrap();
1000                    format!("...{}", string)
1001                }
1002                IterablePointer::Record(r) => {
1003                    let record = r.reify(heap).as_record().unwrap();
1004                    let mut result = String::from("...");
1005                    result.push('{');
1006                    for (i, (key, value)) in record.iter().enumerate() {
1007                        result.push_str(&format!(
1008                            "{}: {}",
1009                            key,
1010                            value.stringify(heap, wrap_strings)
1011                        ));
1012                        if i < record.len() - 1 {
1013                            result.push_str(", ");
1014                        }
1015                    }
1016                    result.push('}');
1017                    result
1018                }
1019            },
1020            Value::Bool(_) | Value::Number(_) | Value::Null => format!("{}", self),
1021        }
1022    }
1023}
1024
1025impl Display for Value {
1026    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1027        match self {
1028            Value::Number(n) => write!(f, "{}", n),
1029            Value::List(p) => write!(f, "{}", p),
1030            Value::Spread(p) => write!(f, "...{}", p),
1031            Value::Bool(b) => write!(f, "{}", b),
1032            Value::Lambda(p) => write!(f, "{}", p),
1033            Value::String(p) => write!(f, "{}", p),
1034            Value::Null => write!(f, "null"),
1035            Value::BuiltIn(built_in) => write!(f, "{} (built-in)", built_in.name()),
1036            Value::Record(p) => write!(f, "{}", p),
1037        }
1038    }
1039}