Skip to main content

aver/
value.rs

1/// Core Aver runtime value type and associated utilities.
2///
3/// Lives in its own module so both the interpreter and the service
4/// implementations (`services::*`) can import it without circular
5/// dependencies.
6use aver_rt::AverList;
7use std::collections::HashMap;
8use std::rc::Rc;
9use thiserror::Error;
10
11use crate::ast::FnBody;
12
13mod memo;
14
15pub use memo::hash_memo_args;
16
17// ---------------------------------------------------------------------------
18// RuntimeError
19// ---------------------------------------------------------------------------
20
21#[derive(Debug, Error)]
22pub enum RuntimeError {
23    #[error("Runtime error: {0}")]
24    Error(String),
25    /// Internal signal: `?` operator encountered Err — caught by call_value to
26    /// do early return. Never surfaces to the user (type checker prevents
27    /// top-level use).
28    #[error("Error propagation")]
29    ErrProp(Box<Value>),
30    /// Internal signal: tail-call — caught by the trampoline in call_fn_ref.
31    /// Never surfaces to the user. Boxed to keep RuntimeError small.
32    #[error("Tail call")]
33    TailCall(Box<(String, Vec<Value>)>),
34    #[error("Replay mismatch at seq {seq}: expected '{expected}', got '{got}'")]
35    ReplayMismatch {
36        seq: u32,
37        expected: String,
38        got: String,
39    },
40    #[error(
41        "Replay args mismatch at seq {seq} for '{effect_type}': expected {expected}, got {got}"
42    )]
43    ReplayArgsMismatch {
44        seq: u32,
45        effect_type: String,
46        expected: String,
47        got: String,
48    },
49    #[error("Replay exhausted at position {position}: no recorded effect for call '{effect_type}'")]
50    ReplayExhausted {
51        effect_type: String,
52        position: usize,
53    },
54    #[error("Replay has {remaining} unconsumed effect(s)")]
55    ReplayUnconsumed { remaining: usize },
56    #[error("Replay serialization error: {0}")]
57    ReplaySerialization(String),
58}
59
60// ---------------------------------------------------------------------------
61// Value
62// ---------------------------------------------------------------------------
63
64#[derive(Debug, Clone)]
65pub struct FunctionValue {
66    pub name: Rc<String>,
67    pub params: Rc<Vec<(String, String)>>,
68    pub return_type: Rc<String>,
69    pub effects: Rc<Vec<String>>,
70    pub body: Rc<FnBody>,
71    pub(crate) lowered_body: Rc<crate::interpreter::lowered::LoweredFunctionBody>,
72    /// Compile-time resolution metadata (slot layout for locals).
73    pub resolution: Option<crate::ast::FnResolution>,
74    /// True only for functions selected by `compute_memo_fns` in the
75    /// interpreter that defined them.
76    pub memo_eligible: bool,
77    /// Optional function-specific global scope (used by imported module
78    /// functions so they resolve names in their home module).
79    pub home_globals: Option<Rc<HashMap<String, Value>>>,
80}
81
82#[derive(Debug, Clone)]
83pub enum Value {
84    Int(i64),
85    Float(f64),
86    Str(String),
87    Bool(bool),
88    Unit,
89    Ok(Box<Value>),
90    Err(Box<Value>),
91    Some(Box<Value>),
92    None,
93    List(AverList<Value>),
94    Tuple(Vec<Value>),
95    Map(HashMap<Value, Value>),
96    Fn(Rc<FunctionValue>),
97    Builtin(String),
98    /// User-defined sum type variant, e.g. `Shape.Circle(3.14)`
99    Variant {
100        type_name: String,
101        variant: String,
102        fields: Rc<[Value]>,
103    },
104    /// User-defined product type (record), e.g. `User(name = "Alice", age = 30)`
105    Record {
106        type_name: String,
107        fields: Rc<[(String, Value)]>,
108    },
109    /// Type namespace: `Shape` — provides `Shape.Circle`, `Shape.Rect`, etc.
110    Namespace {
111        name: String,
112        members: HashMap<String, Value>,
113    },
114}
115
116impl PartialEq for Value {
117    fn eq(&self, other: &Self) -> bool {
118        match (list_view(self), list_view(other)) {
119            (Some(xs), Some(ys)) => return xs.iter().eq(ys.iter()),
120            (Some(_), None) | (None, Some(_)) => return false,
121            (None, None) => {}
122        }
123
124        match (self, other) {
125            (Value::Int(a), Value::Int(b)) => a == b,
126            (Value::Float(a), Value::Float(b)) => {
127                if a.is_nan() || b.is_nan() {
128                    a.to_bits() == b.to_bits()
129                } else {
130                    a == b
131                }
132            }
133            (Value::Str(a), Value::Str(b)) => a == b,
134            (Value::Bool(a), Value::Bool(b)) => a == b,
135            (Value::Unit, Value::Unit) => true,
136            (Value::Ok(a), Value::Ok(b)) => a == b,
137            (Value::Err(a), Value::Err(b)) => a == b,
138            (Value::Some(a), Value::Some(b)) => a == b,
139            (Value::None, Value::None) => true,
140            (Value::Tuple(a), Value::Tuple(b)) => a == b,
141            (Value::Map(a), Value::Map(b)) => a == b,
142            (Value::Fn(a), Value::Fn(b)) => {
143                a.name == b.name
144                    && a.params == b.params
145                    && a.return_type == b.return_type
146                    && a.effects == b.effects
147                    && a.body == b.body
148            }
149            (Value::Builtin(a), Value::Builtin(b)) => a == b,
150            (
151                Value::Variant {
152                    type_name: t1,
153                    variant: v1,
154                    fields: f1,
155                },
156                Value::Variant {
157                    type_name: t2,
158                    variant: v2,
159                    fields: f2,
160                },
161            ) => t1 == t2 && v1 == v2 && f1 == f2,
162            (
163                Value::Record {
164                    type_name: t1,
165                    fields: f1,
166                },
167                Value::Record {
168                    type_name: t2,
169                    fields: f2,
170                },
171            ) => t1 == t2 && f1 == f2,
172            (
173                Value::Namespace {
174                    name: n1,
175                    members: m1,
176                },
177                Value::Namespace {
178                    name: n2,
179                    members: m2,
180                },
181            ) => n1 == n2 && m1 == m2,
182            _ => false,
183        }
184    }
185}
186
187impl Eq for Value {}
188
189impl std::hash::Hash for Value {
190    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
191        if let Some(items) = list_view(self) {
192            8u8.hash(state);
193            items.len().hash(state);
194            for item in items.iter() {
195                item.hash(state);
196            }
197            return;
198        }
199
200        match self {
201            Value::Int(i) => {
202                0u8.hash(state);
203                i.hash(state);
204            }
205            Value::Float(f) => {
206                1u8.hash(state);
207                let bits = if *f == 0.0 {
208                    0.0f64.to_bits()
209                } else {
210                    f.to_bits()
211                };
212                bits.hash(state);
213            }
214            Value::Str(s) => {
215                2u8.hash(state);
216                s.hash(state);
217            }
218            Value::Bool(b) => {
219                3u8.hash(state);
220                b.hash(state);
221            }
222            Value::Unit => {
223                4u8.hash(state);
224            }
225            Value::Ok(v) => {
226                5u8.hash(state);
227                v.hash(state);
228            }
229            Value::Err(v) => {
230                6u8.hash(state);
231                v.hash(state);
232            }
233            Value::Some(v) => {
234                7u8.hash(state);
235                v.hash(state);
236            }
237            Value::None => {
238                9u8.hash(state);
239            }
240            Value::Map(map) => {
241                10u8.hash(state);
242                let mut entries = map.iter().collect::<Vec<_>>();
243                entries.sort_by(|(k1, _), (k2, _)| aver_repr(k1).cmp(&aver_repr(k2)));
244                for (k, v) in entries {
245                    k.hash(state);
246                    v.hash(state);
247                }
248            }
249            Value::Tuple(items) => {
250                16u8.hash(state);
251                items.hash(state);
252            }
253            Value::Fn(function) => {
254                11u8.hash(state);
255                function.name.hash(state);
256                function.params.hash(state);
257                function.return_type.hash(state);
258                function.effects.hash(state);
259                format!("{:?}", function.body).hash(state);
260            }
261            Value::Builtin(name) => {
262                12u8.hash(state);
263                name.hash(state);
264            }
265            Value::Variant {
266                type_name,
267                variant,
268                fields,
269            } => {
270                13u8.hash(state);
271                type_name.hash(state);
272                variant.hash(state);
273                fields.hash(state);
274            }
275            Value::Record { type_name, fields } => {
276                14u8.hash(state);
277                type_name.hash(state);
278                fields.hash(state);
279            }
280            Value::Namespace { name, members } => {
281                15u8.hash(state);
282                name.hash(state);
283                let mut keys = members.keys().collect::<Vec<_>>();
284                keys.sort();
285                for key in keys {
286                    key.hash(state);
287                    if let Some(value) = members.get(key) {
288                        value.hash(state);
289                    }
290                }
291            }
292            Value::List(_) => unreachable!("list hashed above"),
293        }
294    }
295}
296
297// ---------------------------------------------------------------------------
298// Environment
299// ---------------------------------------------------------------------------
300
301#[derive(Debug, Clone)]
302pub enum EnvFrame {
303    Owned(HashMap<String, Value>),
304    Shared(Rc<HashMap<String, Value>>),
305    /// Slot-indexed frame for resolved function bodies — O(1) lookup.
306    Slots(Vec<Value>),
307}
308
309/// Scope stack: innermost scope last.
310pub type Env = Vec<EnvFrame>;
311
312// ---------------------------------------------------------------------------
313// List helpers
314// ---------------------------------------------------------------------------
315
316pub(crate) type ListView<'a> = &'a AverList<Value>;
317
318pub(crate) fn list_view(value: &Value) -> Option<ListView<'_>> {
319    match value {
320        Value::List(items) => Some(items),
321        _ => None,
322    }
323}
324
325pub fn list_slice(value: &Value) -> Option<&[Value]> {
326    list_view(value).and_then(AverList::as_slice)
327}
328
329pub fn list_from_vec(items: Vec<Value>) -> Value {
330    Value::List(AverList::from_vec(items))
331}
332
333pub fn list_to_vec(value: &Value) -> Option<Vec<Value>> {
334    list_view(value).map(AverList::to_vec)
335}
336
337pub fn list_len(value: &Value) -> Option<usize> {
338    list_view(value).map(AverList::len)
339}
340
341pub(crate) fn list_get(value: &Value, index: usize) -> Option<Value> {
342    list_view(value).and_then(|items| items.get(index).cloned())
343}
344
345pub fn list_head(value: &Value) -> Option<Value> {
346    list_view(value).and_then(|items| items.first().cloned())
347}
348
349pub(crate) fn list_append(list: &Value, item: Value) -> Option<Value> {
350    list_view(list).map(|items| Value::List(AverList::append(items, item)))
351}
352
353pub(crate) fn list_prepend(item: Value, list: &Value) -> Option<Value> {
354    list_view(list).map(|items| Value::List(AverList::prepend(item, items)))
355}
356
357pub(crate) fn list_concat(left: &Value, right: &Value) -> Option<Value> {
358    let left = list_view(left)?;
359    let right = list_view(right)?;
360    Some(Value::List(AverList::concat(left, right)))
361}
362
363pub(crate) fn list_reverse(list: &Value) -> Option<Value> {
364    list_view(list).map(|items| Value::List(items.reverse()))
365}
366
367// ---------------------------------------------------------------------------
368// Display helpers
369// ---------------------------------------------------------------------------
370
371/// Human-readable representation of a value (used by `str()` and `:env`).
372pub fn aver_repr(val: &Value) -> String {
373    if let Some(items) = list_view(val) {
374        let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
375        return format!("[{}]", parts.join(", "));
376    }
377
378    match val {
379        Value::Int(i) => i.to_string(),
380        Value::Float(f) => f.to_string(),
381        Value::Str(s) => s.clone(),
382        Value::Bool(b) => if *b { "true" } else { "false" }.to_string(),
383        Value::Unit => "Unit".to_string(),
384        Value::Ok(v) => format!("Result.Ok({})", aver_repr_inner(v)),
385        Value::Err(v) => format!("Result.Err({})", aver_repr_inner(v)),
386        Value::Some(v) => format!("Option.Some({})", aver_repr_inner(v)),
387        Value::None => "Option.None".to_string(),
388        Value::Tuple(items) => {
389            let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
390            format!("({})", parts.join(", "))
391        }
392        Value::List(_) => unreachable!("handled via list_view above"),
393        Value::Map(entries) => {
394            let mut pairs = entries
395                .iter()
396                .map(|(k, v)| (aver_repr_inner(k), aver_repr_inner(v)))
397                .collect::<Vec<_>>();
398            pairs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
399            let parts = pairs
400                .into_iter()
401                .map(|(k, v)| format!("{}: {}", k, v))
402                .collect::<Vec<_>>();
403            format!("{{{}}}", parts.join(", "))
404        }
405        Value::Fn(function) => format!("<fn {}>", function.name),
406        Value::Builtin(name) => format!("<builtin {}>", name),
407        Value::Variant {
408            variant, fields, ..
409        } => {
410            if fields.is_empty() {
411                variant.clone()
412            } else {
413                let parts: Vec<String> = fields.iter().map(aver_repr_inner).collect();
414                format!("{}({})", variant, parts.join(", "))
415            }
416        }
417        Value::Record { type_name, fields } => {
418            let parts: Vec<String> = fields
419                .iter()
420                .map(|(k, v)| format!("{}: {}", k, aver_repr_inner(v)))
421                .collect();
422            format!("{}({})", type_name, parts.join(", "))
423        }
424        Value::Namespace { name, .. } => format!("<type {}>", name),
425    }
426}
427
428/// Like `aver_repr` but strings get quoted — used inside constructors and lists.
429fn aver_repr_inner(val: &Value) -> String {
430    if let Some(items) = list_view(val) {
431        let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
432        return format!("[{}]", parts.join(", "));
433    }
434
435    match val {
436        Value::Str(s) => format!("\"{}\"", s),
437        Value::Tuple(items) => {
438            let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
439            format!("({})", parts.join(", "))
440        }
441        Value::List(_) => unreachable!("handled via list_view above"),
442        other => aver_repr(other),
443    }
444}
445
446/// Returns the display string for `print()` — `None` for `Unit` (silent).
447pub fn aver_display(val: &Value) -> Option<String> {
448    match val {
449        Value::Unit => None,
450        other => Some(aver_repr(other)),
451    }
452}