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