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