1use 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#[derive(Debug, Error)]
22pub enum RuntimeError {
23 #[error("Runtime error: {0}")]
24 Error(String),
25 #[error("Error propagation")]
29 ErrProp(Box<Value>),
30 #[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#[derive(Debug, Clone)]
65pub enum Value {
66 Int(i64),
67 Float(f64),
68 Str(String),
69 Bool(bool),
70 Unit,
71 Ok(Box<Value>),
72 Err(Box<Value>),
73 Some(Box<Value>),
74 None,
75 List(AverList<Value>),
76 Tuple(Vec<Value>),
77 Map(HashMap<Value, Value>),
78 Fn {
79 name: String,
80 params: Vec<(String, String)>,
81 return_type: String,
82 effects: Vec<String>,
83 body: Rc<FnBody>,
84 resolution: Option<crate::ast::FnResolution>,
86 memo_eligible: bool,
89 home_globals: Option<Rc<HashMap<String, Rc<Value>>>>,
92 },
93 Builtin(String),
94 Variant {
96 type_name: String,
97 variant: String,
98 fields: Vec<Value>,
99 },
100 Record {
102 type_name: String,
103 fields: Vec<(String, Value)>,
104 },
105 Namespace {
107 name: String,
108 members: HashMap<String, Value>,
109 },
110}
111
112impl PartialEq for Value {
113 fn eq(&self, other: &Self) -> bool {
114 match (list_view(self), list_view(other)) {
115 (Some(xs), Some(ys)) => return xs.iter().eq(ys.iter()),
116 (Some(_), None) | (None, Some(_)) => return false,
117 (None, None) => {}
118 }
119
120 match (self, other) {
121 (Value::Int(a), Value::Int(b)) => a == b,
122 (Value::Float(a), Value::Float(b)) => {
123 if a.is_nan() || b.is_nan() {
124 a.to_bits() == b.to_bits()
125 } else {
126 a == b
127 }
128 }
129 (Value::Str(a), Value::Str(b)) => a == b,
130 (Value::Bool(a), Value::Bool(b)) => a == b,
131 (Value::Unit, Value::Unit) => true,
132 (Value::Ok(a), Value::Ok(b)) => a == b,
133 (Value::Err(a), Value::Err(b)) => a == b,
134 (Value::Some(a), Value::Some(b)) => a == b,
135 (Value::None, Value::None) => true,
136 (Value::Tuple(a), Value::Tuple(b)) => a == b,
137 (Value::Map(a), Value::Map(b)) => a == b,
138 (
139 Value::Fn {
140 name: n1,
141 params: p1,
142 return_type: r1,
143 effects: e1,
144 body: b1,
145 ..
146 },
147 Value::Fn {
148 name: n2,
149 params: p2,
150 return_type: r2,
151 effects: e2,
152 body: b2,
153 ..
154 },
155 ) => n1 == n2 && p1 == p2 && r1 == r2 && e1 == e2 && b1 == b2,
156 (Value::Builtin(a), Value::Builtin(b)) => a == b,
157 (
158 Value::Variant {
159 type_name: t1,
160 variant: v1,
161 fields: f1,
162 },
163 Value::Variant {
164 type_name: t2,
165 variant: v2,
166 fields: f2,
167 },
168 ) => t1 == t2 && v1 == v2 && f1 == f2,
169 (
170 Value::Record {
171 type_name: t1,
172 fields: f1,
173 },
174 Value::Record {
175 type_name: t2,
176 fields: f2,
177 },
178 ) => t1 == t2 && f1 == f2,
179 (
180 Value::Namespace {
181 name: n1,
182 members: m1,
183 },
184 Value::Namespace {
185 name: n2,
186 members: m2,
187 },
188 ) => n1 == n2 && m1 == m2,
189 _ => false,
190 }
191 }
192}
193
194impl Eq for Value {}
195
196impl std::hash::Hash for Value {
197 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
198 if let Some(items) = list_view(self) {
199 8u8.hash(state);
200 items.len().hash(state);
201 for item in items.iter() {
202 item.hash(state);
203 }
204 return;
205 }
206
207 match self {
208 Value::Int(i) => {
209 0u8.hash(state);
210 i.hash(state);
211 }
212 Value::Float(f) => {
213 1u8.hash(state);
214 let bits = if *f == 0.0 {
215 0.0f64.to_bits()
216 } else {
217 f.to_bits()
218 };
219 bits.hash(state);
220 }
221 Value::Str(s) => {
222 2u8.hash(state);
223 s.hash(state);
224 }
225 Value::Bool(b) => {
226 3u8.hash(state);
227 b.hash(state);
228 }
229 Value::Unit => {
230 4u8.hash(state);
231 }
232 Value::Ok(v) => {
233 5u8.hash(state);
234 v.hash(state);
235 }
236 Value::Err(v) => {
237 6u8.hash(state);
238 v.hash(state);
239 }
240 Value::Some(v) => {
241 7u8.hash(state);
242 v.hash(state);
243 }
244 Value::None => {
245 9u8.hash(state);
246 }
247 Value::Map(map) => {
248 10u8.hash(state);
249 let mut entries = map.iter().collect::<Vec<_>>();
250 entries.sort_by(|(k1, _), (k2, _)| aver_repr(k1).cmp(&aver_repr(k2)));
251 for (k, v) in entries {
252 k.hash(state);
253 v.hash(state);
254 }
255 }
256 Value::Tuple(items) => {
257 16u8.hash(state);
258 items.hash(state);
259 }
260 Value::Fn {
261 name,
262 params,
263 return_type,
264 effects,
265 body,
266 ..
267 } => {
268 11u8.hash(state);
269 name.hash(state);
270 params.hash(state);
271 return_type.hash(state);
272 effects.hash(state);
273 format!("{:?}", body).hash(state);
274 }
275 Value::Builtin(name) => {
276 12u8.hash(state);
277 name.hash(state);
278 }
279 Value::Variant {
280 type_name,
281 variant,
282 fields,
283 } => {
284 13u8.hash(state);
285 type_name.hash(state);
286 variant.hash(state);
287 fields.hash(state);
288 }
289 Value::Record { type_name, fields } => {
290 14u8.hash(state);
291 type_name.hash(state);
292 fields.hash(state);
293 }
294 Value::Namespace { name, members } => {
295 15u8.hash(state);
296 name.hash(state);
297 let mut keys = members.keys().collect::<Vec<_>>();
298 keys.sort();
299 for key in keys {
300 key.hash(state);
301 if let Some(value) = members.get(key) {
302 value.hash(state);
303 }
304 }
305 }
306 Value::List(_) => unreachable!("list hashed above"),
307 }
308 }
309}
310
311#[derive(Debug, Clone)]
316pub enum EnvFrame {
317 Owned(HashMap<String, Rc<Value>>),
318 Shared(Rc<HashMap<String, Rc<Value>>>),
319 Slots(Vec<Rc<Value>>),
321}
322
323pub type Env = Vec<EnvFrame>;
325
326pub(crate) type ListView<'a> = &'a AverList<Value>;
331
332pub(crate) fn list_view(value: &Value) -> Option<ListView<'_>> {
333 match value {
334 Value::List(items) => Some(items),
335 _ => None,
336 }
337}
338
339pub fn list_slice(value: &Value) -> Option<&[Value]> {
340 list_view(value).and_then(AverList::as_slice)
341}
342
343pub fn list_from_vec(items: Vec<Value>) -> Value {
344 Value::List(AverList::from_vec(items))
345}
346
347pub(crate) fn list_empty() -> Value {
348 Value::List(AverList::empty())
349}
350
351pub fn list_to_vec(value: &Value) -> Option<Vec<Value>> {
352 list_view(value).map(AverList::to_vec)
353}
354
355pub fn list_len(value: &Value) -> Option<usize> {
356 list_view(value).map(AverList::len)
357}
358
359pub(crate) fn list_get(value: &Value, index: usize) -> Option<Value> {
360 list_view(value).and_then(|items| items.get(index).cloned())
361}
362
363pub fn list_head(value: &Value) -> Option<Value> {
364 list_view(value).and_then(|items| items.first().cloned())
365}
366
367pub fn list_tail_view(value: &Value) -> Option<Value> {
368 list_view(value).and_then(AverList::tail).map(Value::List)
369}
370
371pub(crate) fn list_append(list: &Value, item: Value) -> Option<Value> {
372 list_view(list).map(|items| Value::List(AverList::append(items, item)))
373}
374
375pub(crate) fn list_prepend(item: Value, list: &Value) -> Option<Value> {
376 list_view(list).map(|items| Value::List(AverList::prepend(item, items)))
377}
378
379pub(crate) fn list_concat(left: &Value, right: &Value) -> Option<Value> {
380 let left = list_view(left)?;
381 let right = list_view(right)?;
382 Some(Value::List(AverList::concat(left, right)))
383}
384
385pub(crate) fn list_reverse(list: &Value) -> Option<Value> {
386 list_view(list).map(|items| Value::List(items.reverse()))
387}
388
389pub fn aver_repr(val: &Value) -> String {
395 if let Some(items) = list_view(val) {
396 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
397 return format!("[{}]", parts.join(", "));
398 }
399
400 match val {
401 Value::Int(i) => i.to_string(),
402 Value::Float(f) => f.to_string(),
403 Value::Str(s) => s.clone(),
404 Value::Bool(b) => if *b { "true" } else { "false" }.to_string(),
405 Value::Unit => "()".to_string(),
406 Value::Ok(v) => format!("Result.Ok({})", aver_repr_inner(v)),
407 Value::Err(v) => format!("Result.Err({})", aver_repr_inner(v)),
408 Value::Some(v) => format!("Option.Some({})", aver_repr_inner(v)),
409 Value::None => "Option.None".to_string(),
410 Value::Tuple(items) => {
411 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
412 format!("({})", parts.join(", "))
413 }
414 Value::List(_) => unreachable!("handled via list_view above"),
415 Value::Map(entries) => {
416 let mut pairs = entries
417 .iter()
418 .map(|(k, v)| (aver_repr_inner(k), aver_repr_inner(v)))
419 .collect::<Vec<_>>();
420 pairs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
421 let parts = pairs
422 .into_iter()
423 .map(|(k, v)| format!("{}: {}", k, v))
424 .collect::<Vec<_>>();
425 format!("{{{}}}", parts.join(", "))
426 }
427 Value::Fn { name, .. } => format!("<fn {}>", name),
428 Value::Builtin(name) => format!("<builtin {}>", name),
429 Value::Variant {
430 variant, fields, ..
431 } => {
432 if fields.is_empty() {
433 variant.clone()
434 } else {
435 let parts: Vec<String> = fields.iter().map(aver_repr_inner).collect();
436 format!("{}({})", variant, parts.join(", "))
437 }
438 }
439 Value::Record { type_name, fields } => {
440 let parts: Vec<String> = fields
441 .iter()
442 .map(|(k, v)| format!("{}: {}", k, aver_repr_inner(v)))
443 .collect();
444 format!("{}({})", type_name, parts.join(", "))
445 }
446 Value::Namespace { name, .. } => format!("<type {}>", name),
447 }
448}
449
450fn aver_repr_inner(val: &Value) -> String {
452 if let Some(items) = list_view(val) {
453 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
454 return format!("[{}]", parts.join(", "));
455 }
456
457 match val {
458 Value::Str(s) => format!("\"{}\"", s),
459 Value::Tuple(items) => {
460 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
461 format!("({})", parts.join(", "))
462 }
463 Value::List(_) => unreachable!("handled via list_view above"),
464 other => aver_repr(other),
465 }
466}
467
468pub fn aver_display(val: &Value) -> Option<String> {
470 match val {
471 Value::Unit => None,
472 other => Some(aver_repr(other)),
473 }
474}