1use std::collections::HashMap;
7use std::rc::Rc;
8use thiserror::Error;
9
10use crate::ast::FnBody;
11
12#[derive(Debug, Error)]
17pub enum RuntimeError {
18 #[error("Runtime error: {0}")]
19 Error(String),
20 #[error("Error propagation")]
24 ErrProp(Box<Value>),
25 #[error("Tail call")]
28 TailCall(Box<(String, Vec<Value>)>),
29 #[error("Replay mismatch at seq {seq}: expected '{expected}', got '{got}'")]
30 ReplayMismatch {
31 seq: u32,
32 expected: String,
33 got: String,
34 },
35 #[error(
36 "Replay args mismatch at seq {seq} for '{effect_type}': expected {expected}, got {got}"
37 )]
38 ReplayArgsMismatch {
39 seq: u32,
40 effect_type: String,
41 expected: String,
42 got: String,
43 },
44 #[error(
45 "Replay exhausted at position {position}: no recorded effect for call '{effect_type}'"
46 )]
47 ReplayExhausted {
48 effect_type: String,
49 position: usize,
50 },
51 #[error("Replay has {remaining} unconsumed effect(s)")]
52 ReplayUnconsumed { remaining: usize },
53 #[error("Replay serialization error: {0}")]
54 ReplaySerialization(String),
55}
56
57#[derive(Debug, Clone)]
62pub enum Value {
63 Int(i64),
64 Float(f64),
65 Str(String),
66 Bool(bool),
67 Unit,
68 Ok(Box<Value>),
69 Err(Box<Value>),
70 Some(Box<Value>),
71 None,
72 List(Vec<Value>),
73 Tuple(Vec<Value>),
74 Map(HashMap<Value, Value>),
75 ListSlice {
78 items: Rc<Vec<Value>>,
79 start: usize,
80 },
81 Fn {
82 name: String,
83 params: Vec<(String, String)>,
84 effects: Vec<String>,
85 body: Rc<FnBody>,
86 resolution: Option<crate::ast::FnResolution>,
88 memo_eligible: bool,
91 home_globals: Option<Rc<HashMap<String, Rc<Value>>>>,
94 },
95 Builtin(String),
96 Variant {
98 type_name: String,
99 variant: String,
100 fields: Vec<Value>,
101 },
102 Record {
104 type_name: String,
105 fields: Vec<(String, Value)>,
106 },
107 Namespace {
109 name: String,
110 members: HashMap<String, Value>,
111 },
112}
113
114impl PartialEq for Value {
115 fn eq(&self, other: &Self) -> bool {
116 match (list_slice(self), list_slice(other)) {
117 (Some(xs), Some(ys)) => return xs == ys,
118 (Some(_), None) | (None, Some(_)) => return false,
119 (None, None) => {}
120 }
121
122 match (self, other) {
123 (Value::Int(a), Value::Int(b)) => a == b,
124 (Value::Float(a), Value::Float(b)) => {
125 if a.is_nan() || b.is_nan() {
126 a.to_bits() == b.to_bits()
127 } else {
128 a == b
129 }
130 }
131 (Value::Str(a), Value::Str(b)) => a == b,
132 (Value::Bool(a), Value::Bool(b)) => a == b,
133 (Value::Unit, Value::Unit) => true,
134 (Value::Ok(a), Value::Ok(b)) => a == b,
135 (Value::Err(a), Value::Err(b)) => a == b,
136 (Value::Some(a), Value::Some(b)) => a == b,
137 (Value::None, Value::None) => true,
138 (Value::Tuple(a), Value::Tuple(b)) => a == b,
139 (Value::Map(a), Value::Map(b)) => a == b,
140 (
141 Value::Fn {
142 name: n1,
143 params: p1,
144 effects: e1,
145 body: b1,
146 ..
147 },
148 Value::Fn {
149 name: n2,
150 params: p2,
151 effects: e2,
152 body: b2,
153 ..
154 },
155 ) => n1 == n2 && p1 == p2 && 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_slice(self) {
199 8u8.hash(state);
200 items.len().hash(state);
201 for item in items {
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 effects,
264 body,
265 ..
266 } => {
267 11u8.hash(state);
268 name.hash(state);
269 params.hash(state);
270 effects.hash(state);
271 format!("{:?}", body).hash(state);
272 }
273 Value::Builtin(name) => {
274 12u8.hash(state);
275 name.hash(state);
276 }
277 Value::Variant {
278 type_name,
279 variant,
280 fields,
281 } => {
282 13u8.hash(state);
283 type_name.hash(state);
284 variant.hash(state);
285 fields.hash(state);
286 }
287 Value::Record { type_name, fields } => {
288 14u8.hash(state);
289 type_name.hash(state);
290 fields.hash(state);
291 }
292 Value::Namespace { name, members } => {
293 15u8.hash(state);
294 name.hash(state);
295 let mut keys = members.keys().collect::<Vec<_>>();
296 keys.sort();
297 for key in keys {
298 key.hash(state);
299 if let Some(value) = members.get(key) {
300 value.hash(state);
301 }
302 }
303 }
304 Value::List(_) | Value::ListSlice { .. } => unreachable!("list hashed above"),
305 }
306 }
307}
308
309#[derive(Debug, Clone)]
314pub enum EnvFrame {
315 Owned(HashMap<String, Rc<Value>>),
316 Shared(Rc<HashMap<String, Rc<Value>>>),
317 Slots(Vec<Rc<Value>>),
319}
320
321pub type Env = Vec<EnvFrame>;
323
324pub fn list_slice(value: &Value) -> Option<&[Value]> {
329 match value {
330 Value::List(items) => Some(items.as_slice()),
331 Value::ListSlice { items, start } => Some(items.get(*start..).unwrap_or(&[])),
332 _ => None,
333 }
334}
335
336pub fn list_from_vec(items: Vec<Value>) -> Value {
337 Value::ListSlice {
338 items: Rc::new(items),
339 start: 0,
340 }
341}
342
343pub fn list_to_vec(value: &Value) -> Option<Vec<Value>> {
344 list_slice(value).map(|items| items.to_vec())
345}
346
347pub fn list_len(value: &Value) -> Option<usize> {
348 list_slice(value).map(|items| items.len())
349}
350
351pub fn list_head(value: &Value) -> Option<Value> {
352 list_slice(value).and_then(|items| items.first().cloned())
353}
354
355pub fn list_tail_view(value: &Value) -> Option<Value> {
356 match value {
357 Value::List(items) => {
358 if items.is_empty() {
359 None
360 } else {
361 Some(Value::ListSlice {
362 items: Rc::new(items.clone()),
363 start: 1,
364 })
365 }
366 }
367 Value::ListSlice { items, start } => {
368 if *start >= items.len() {
369 None
370 } else {
371 Some(Value::ListSlice {
372 items: Rc::clone(items),
373 start: start + 1,
374 })
375 }
376 }
377 _ => None,
378 }
379}
380
381pub fn aver_repr(val: &Value) -> String {
387 match val {
388 Value::Int(i) => i.to_string(),
389 Value::Float(f) => f.to_string(),
390 Value::Str(s) => s.clone(),
391 Value::Bool(b) => if *b { "true" } else { "false" }.to_string(),
392 Value::Unit => "()".to_string(),
393 Value::Ok(v) => format!("Result.Ok({})", aver_repr_inner(v)),
394 Value::Err(v) => format!("Result.Err({})", aver_repr_inner(v)),
395 Value::Some(v) => format!("Option.Some({})", aver_repr_inner(v)),
396 Value::None => "Option.None".to_string(),
397 Value::List(_) | Value::ListSlice { .. } => {
398 let items = list_slice(val).expect("list variants must have a slice view");
399 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
400 format!("[{}]", parts.join(", "))
401 }
402 Value::Tuple(items) => {
403 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
404 format!("({})", parts.join(", "))
405 }
406 Value::Map(entries) => {
407 let mut pairs = entries
408 .iter()
409 .map(|(k, v)| (aver_repr_inner(k), aver_repr_inner(v)))
410 .collect::<Vec<_>>();
411 pairs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
412 let parts = pairs
413 .into_iter()
414 .map(|(k, v)| format!("{}: {}", k, v))
415 .collect::<Vec<_>>();
416 format!("{{{}}}", parts.join(", "))
417 }
418 Value::Fn { name, .. } => format!("<fn {}>", name),
419 Value::Builtin(name) => format!("<builtin {}>", name),
420 Value::Variant {
421 variant, fields, ..
422 } => {
423 if fields.is_empty() {
424 variant.clone()
425 } else {
426 let parts: Vec<String> = fields.iter().map(aver_repr_inner).collect();
427 format!("{}({})", variant, parts.join(", "))
428 }
429 }
430 Value::Record { type_name, fields } => {
431 let parts: Vec<String> = fields
432 .iter()
433 .map(|(k, v)| format!("{}: {}", k, aver_repr_inner(v)))
434 .collect();
435 format!("{}({})", type_name, parts.join(", "))
436 }
437 Value::Namespace { name, .. } => format!("<type {}>", name),
438 }
439}
440
441fn aver_repr_inner(val: &Value) -> String {
443 match val {
444 Value::Str(s) => format!("\"{}\"", s),
445 Value::Tuple(items) => {
446 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
447 format!("({})", parts.join(", "))
448 }
449 Value::List(_) | Value::ListSlice { .. } => {
450 let items = list_slice(val).expect("list variants must have a slice view");
451 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
452 format!("[{}]", parts.join(", "))
453 }
454 other => aver_repr(other),
455 }
456}
457
458pub fn aver_display(val: &Value) -> Option<String> {
460 match val {
461 Value::Unit => None,
462 other => Some(aver_repr(other)),
463 }
464}
465
466pub fn hash_memo_args(args: &[Value]) -> u64 {
472 use std::hash::Hasher;
473 let mut hasher = std::collections::hash_map::DefaultHasher::new();
474 for arg in args {
475 hash_value(arg, &mut hasher);
476 }
477 hasher.finish()
478}
479
480fn hash_value(val: &Value, hasher: &mut impl std::hash::Hasher) {
481 use std::hash::Hash;
482 match val {
483 Value::Int(i) => {
484 0u8.hash(hasher);
485 i.hash(hasher);
486 }
487 Value::Float(f) => {
488 1u8.hash(hasher);
489 f.to_bits().hash(hasher);
490 }
491 Value::Str(s) => {
492 2u8.hash(hasher);
493 s.hash(hasher);
494 }
495 Value::Bool(b) => {
496 3u8.hash(hasher);
497 b.hash(hasher);
498 }
499 Value::Unit => {
500 4u8.hash(hasher);
501 }
502 Value::Tuple(items) => {
503 7u8.hash(hasher);
504 items.len().hash(hasher);
505 for item in items {
506 hash_value(item, hasher);
507 }
508 }
509 Value::Record { type_name, fields } => {
510 5u8.hash(hasher);
511 type_name.hash(hasher);
512 for (k, v) in fields {
513 k.hash(hasher);
514 hash_value(v, hasher);
515 }
516 }
517 Value::Variant {
518 type_name,
519 variant,
520 fields,
521 } => {
522 6u8.hash(hasher);
523 type_name.hash(hasher);
524 variant.hash(hasher);
525 for v in fields {
526 hash_value(v, hasher);
527 }
528 }
529 _ => {
531 255u8.hash(hasher);
532 }
533 }
534}