1use aver_rt::{AverList, AverVector};
7use std::collections::HashMap;
8use std::sync::Arc as Rc;
9use thiserror::Error;
10
11use crate::ast::FnBody;
12use crate::nan_value::NanValue;
13
14mod memo;
15
16pub use memo::hash_memo_args;
17
18#[derive(Debug, Error)]
23pub enum RuntimeError {
24 #[error("Runtime error: {0}")]
25 Error(String),
26 #[error("Runtime error [line {line}]: {msg}")]
27 ErrorAt { msg: String, line: usize },
28 #[error("Error propagation")]
32 ErrProp(NanValue), #[error("Tail call")]
36 TailCall(Box<(String, Vec<NanValue>)>),
37 #[error("Replay mismatch at seq {seq}: expected '{expected}', got '{got}'")]
38 ReplayMismatch {
39 seq: u32,
40 expected: String,
41 got: String,
42 },
43 #[error(
44 "Replay args mismatch at seq {seq} for '{effect_type}': expected {expected}, got {got}"
45 )]
46 ReplayArgsMismatch {
47 seq: u32,
48 effect_type: String,
49 expected: String,
50 got: String,
51 },
52 #[error("Replay exhausted at position {position}: no recorded effect for call '{effect_type}'")]
53 ReplayExhausted {
54 effect_type: String,
55 position: usize,
56 },
57 #[error("Replay has {remaining} unconsumed effect(s)")]
58 ReplayUnconsumed { remaining: usize },
59 #[error("Replay serialization error: {0}")]
60 ReplaySerialization(String),
61}
62
63impl RuntimeError {
64 pub fn at_line(self, line: usize) -> Self {
67 if line == 0 {
68 return self;
69 }
70 match self {
71 RuntimeError::Error(msg) => RuntimeError::ErrorAt { msg, line },
72 other => other,
73 }
74 }
75
76 pub fn message(&self) -> &str {
78 match self {
79 RuntimeError::Error(msg) | RuntimeError::ErrorAt { msg, .. } => msg,
80 other => {
81 match other {
85 RuntimeError::Error(_) | RuntimeError::ErrorAt { .. } => unreachable!(),
86 _ => "",
87 }
88 }
89 }
90 }
91
92 pub fn source_line(&self) -> Option<usize> {
94 match self {
95 RuntimeError::ErrorAt { line, .. } if *line > 0 => Some(*line),
96 _ => None,
97 }
98 }
99}
100
101#[derive(Debug, Clone)]
106pub struct FunctionValue {
107 pub name: Rc<String>,
108 pub params: Rc<Vec<(String, String)>>,
109 pub return_type: Rc<String>,
110 pub effects: Rc<Vec<String>>,
111 pub body: Rc<FnBody>,
112 pub(crate) lowered_body: Rc<crate::interpreter::lowered::LoweredFunctionBody>,
113 pub resolution: Option<crate::ast::FnResolution>,
115 pub memo_eligible: bool,
118 pub home_globals: Option<Rc<HashMap<String, NanValue>>>,
121}
122
123#[derive(Debug, Clone)]
124pub enum Value {
125 Int(i64),
126 Float(f64),
127 Str(String),
128 Bool(bool),
129 Unit,
130 Ok(Box<Value>),
131 Err(Box<Value>),
132 Some(Box<Value>),
133 None,
134 List(AverList<Value>),
135 Vector(AverVector<Value>),
136 Tuple(Vec<Value>),
137 Map(HashMap<Value, Value>),
138 Fn(Rc<FunctionValue>),
139 Builtin(String),
140 Variant {
142 type_name: String,
143 variant: String,
144 fields: Rc<[Value]>,
145 },
146 Record {
148 type_name: String,
149 fields: Rc<[(String, Value)]>,
150 },
151 Namespace {
153 name: String,
154 members: HashMap<String, Value>,
155 },
156}
157
158impl PartialEq for Value {
159 fn eq(&self, other: &Self) -> bool {
160 match (list_view(self), list_view(other)) {
161 (Some(xs), Some(ys)) => return xs.iter().eq(ys.iter()),
162 (Some(_), None) | (None, Some(_)) => return false,
163 (None, None) => {}
164 }
165
166 match (self, other) {
167 (Value::Int(a), Value::Int(b)) => a == b,
168 (Value::Float(a), Value::Float(b)) => {
169 if a.is_nan() || b.is_nan() {
170 a.to_bits() == b.to_bits()
171 } else {
172 a == b
173 }
174 }
175 (Value::Str(a), Value::Str(b)) => a == b,
176 (Value::Bool(a), Value::Bool(b)) => a == b,
177 (Value::Unit, Value::Unit) => true,
178 (Value::Ok(a), Value::Ok(b)) => a == b,
179 (Value::Err(a), Value::Err(b)) => a == b,
180 (Value::Some(a), Value::Some(b)) => a == b,
181 (Value::None, Value::None) => true,
182 (Value::Vector(a), Value::Vector(b)) => a == b,
183 (Value::Tuple(a), Value::Tuple(b)) => a == b,
184 (Value::Map(a), Value::Map(b)) => a == b,
185 (Value::Fn(a), Value::Fn(b)) => {
186 a.name == b.name
187 && a.params == b.params
188 && a.return_type == b.return_type
189 && a.effects == b.effects
190 && a.body == b.body
191 }
192 (Value::Builtin(a), Value::Builtin(b)) => a == b,
193 (
194 Value::Variant {
195 type_name: t1,
196 variant: v1,
197 fields: f1,
198 },
199 Value::Variant {
200 type_name: t2,
201 variant: v2,
202 fields: f2,
203 },
204 ) => t1 == t2 && v1 == v2 && f1 == f2,
205 (
206 Value::Record {
207 type_name: t1,
208 fields: f1,
209 },
210 Value::Record {
211 type_name: t2,
212 fields: f2,
213 },
214 ) => t1 == t2 && f1 == f2,
215 (
216 Value::Namespace {
217 name: n1,
218 members: m1,
219 },
220 Value::Namespace {
221 name: n2,
222 members: m2,
223 },
224 ) => n1 == n2 && m1 == m2,
225 _ => false,
226 }
227 }
228}
229
230impl Eq for Value {}
231
232impl std::hash::Hash for Value {
233 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
234 if let Some(items) = list_view(self) {
235 8u8.hash(state);
236 items.len().hash(state);
237 for item in items.iter() {
238 item.hash(state);
239 }
240 return;
241 }
242
243 match self {
244 Value::Int(i) => {
245 0u8.hash(state);
246 i.hash(state);
247 }
248 Value::Float(f) => {
249 1u8.hash(state);
250 let bits = if *f == 0.0 {
251 0.0f64.to_bits()
252 } else {
253 f.to_bits()
254 };
255 bits.hash(state);
256 }
257 Value::Str(s) => {
258 2u8.hash(state);
259 s.hash(state);
260 }
261 Value::Bool(b) => {
262 3u8.hash(state);
263 b.hash(state);
264 }
265 Value::Unit => {
266 4u8.hash(state);
267 }
268 Value::Ok(v) => {
269 5u8.hash(state);
270 v.hash(state);
271 }
272 Value::Err(v) => {
273 6u8.hash(state);
274 v.hash(state);
275 }
276 Value::Some(v) => {
277 7u8.hash(state);
278 v.hash(state);
279 }
280 Value::None => {
281 9u8.hash(state);
282 }
283 Value::Map(map) => {
284 10u8.hash(state);
285 let mut entries = map.iter().collect::<Vec<_>>();
286 entries.sort_by(|(k1, _), (k2, _)| aver_repr(k1).cmp(&aver_repr(k2)));
287 for (k, v) in entries {
288 k.hash(state);
289 v.hash(state);
290 }
291 }
292 Value::Vector(vec) => {
293 17u8.hash(state);
294 vec.hash(state);
295 }
296 Value::Tuple(items) => {
297 16u8.hash(state);
298 items.hash(state);
299 }
300 Value::Fn(function) => {
301 11u8.hash(state);
302 function.name.hash(state);
303 function.params.hash(state);
304 function.return_type.hash(state);
305 function.effects.hash(state);
306 format!("{:?}", function.body).hash(state);
307 }
308 Value::Builtin(name) => {
309 12u8.hash(state);
310 name.hash(state);
311 }
312 Value::Variant {
313 type_name,
314 variant,
315 fields,
316 } => {
317 13u8.hash(state);
318 type_name.hash(state);
319 variant.hash(state);
320 fields.hash(state);
321 }
322 Value::Record { type_name, fields } => {
323 14u8.hash(state);
324 type_name.hash(state);
325 fields.hash(state);
326 }
327 Value::Namespace { name, members } => {
328 15u8.hash(state);
329 name.hash(state);
330 let mut keys = members.keys().collect::<Vec<_>>();
331 keys.sort();
332 for key in keys {
333 key.hash(state);
334 if let Some(value) = members.get(key) {
335 value.hash(state);
336 }
337 }
338 }
339 Value::List(_) => unreachable!("list hashed above"),
340 }
341 }
342}
343
344#[derive(Debug, Clone)]
349pub enum EnvFrame {
350 Owned(HashMap<String, NanValue>),
351 Shared(Rc<HashMap<String, NanValue>>),
352 Slots(Vec<NanValue>),
354}
355
356pub type Env = Vec<EnvFrame>;
358
359pub(crate) type ListView<'a> = &'a AverList<Value>;
364
365pub(crate) fn list_view(value: &Value) -> Option<ListView<'_>> {
366 match value {
367 Value::List(items) => Some(items),
368 _ => None,
369 }
370}
371
372pub fn list_slice(value: &Value) -> Option<&[Value]> {
373 list_view(value).and_then(AverList::as_slice)
374}
375
376pub fn list_from_vec(items: Vec<Value>) -> Value {
377 Value::List(AverList::from_vec(items))
378}
379
380pub fn list_to_vec(value: &Value) -> Option<Vec<Value>> {
381 list_view(value).map(AverList::to_vec)
382}
383
384pub fn list_len(value: &Value) -> Option<usize> {
385 list_view(value).map(AverList::len)
386}
387
388pub fn list_head(value: &Value) -> Option<Value> {
389 list_view(value).and_then(|items| items.first().cloned())
390}
391
392pub(crate) fn list_prepend(item: Value, list: &Value) -> Option<Value> {
393 list_view(list).map(|items| Value::List(AverList::prepend(item, items)))
394}
395
396pub(crate) fn list_concat(left: &Value, right: &Value) -> Option<Value> {
397 let left = list_view(left)?;
398 let right = list_view(right)?;
399 Some(Value::List(AverList::concat(left, right)))
400}
401
402pub(crate) fn list_reverse(list: &Value) -> Option<Value> {
403 list_view(list).map(|items| Value::List(items.reverse()))
404}
405
406pub fn aver_repr(val: &Value) -> String {
412 if let Some(items) = list_view(val) {
413 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
414 return format!("[{}]", parts.join(", "));
415 }
416
417 match val {
418 Value::Int(i) => i.to_string(),
419 Value::Float(f) => f.to_string(),
420 Value::Str(s) => s.clone(),
421 Value::Bool(b) => if *b { "true" } else { "false" }.to_string(),
422 Value::Unit => "Unit".to_string(),
423 Value::Ok(v) => format!("Result.Ok({})", aver_repr_inner(v)),
424 Value::Err(v) => format!("Result.Err({})", aver_repr_inner(v)),
425 Value::Some(v) => format!("Option.Some({})", aver_repr_inner(v)),
426 Value::None => "Option.None".to_string(),
427 Value::Tuple(items) => {
428 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
429 format!("({})", parts.join(", "))
430 }
431 Value::Vector(vec) => {
432 let parts: Vec<String> = vec.iter().map(aver_repr_inner).collect();
433 format!("Vector[{}]", parts.join(", "))
434 }
435 Value::List(_) => unreachable!("handled via list_view above"),
436 Value::Map(entries) => {
437 let mut pairs = entries
438 .iter()
439 .map(|(k, v)| (aver_repr_inner(k), aver_repr_inner(v)))
440 .collect::<Vec<_>>();
441 pairs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
442 let parts = pairs
443 .into_iter()
444 .map(|(k, v)| format!("{}: {}", k, v))
445 .collect::<Vec<_>>();
446 format!("{{{}}}", parts.join(", "))
447 }
448 Value::Fn(function) => format!("<fn {}>", function.name),
449 Value::Builtin(name) => format!("<builtin {}>", name),
450 Value::Variant {
451 variant, fields, ..
452 } => {
453 if fields.is_empty() {
454 variant.clone()
455 } else {
456 let parts: Vec<String> = fields.iter().map(aver_repr_inner).collect();
457 format!("{}({})", variant, parts.join(", "))
458 }
459 }
460 Value::Record { type_name, fields } => {
461 let parts: Vec<String> = fields
462 .iter()
463 .map(|(k, v)| format!("{}: {}", k, aver_repr_inner(v)))
464 .collect();
465 format!("{}({})", type_name, parts.join(", "))
466 }
467 Value::Namespace { name, .. } => format!("<type {}>", name),
468 }
469}
470
471fn aver_repr_inner(val: &Value) -> String {
473 if let Some(items) = list_view(val) {
474 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
475 return format!("[{}]", parts.join(", "));
476 }
477
478 match val {
479 Value::Str(s) => format!("\"{}\"", s),
480 Value::Tuple(items) => {
481 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
482 format!("({})", parts.join(", "))
483 }
484 Value::Vector(vec) => {
485 let parts: Vec<String> = vec.iter().map(aver_repr_inner).collect();
486 format!("Vector[{}]", parts.join(", "))
487 }
488 Value::List(_) => unreachable!("handled via list_view above"),
489 other => aver_repr(other),
490 }
491}
492
493pub fn aver_display(val: &Value) -> Option<String> {
495 match val {
496 Value::Unit => None,
497 other => Some(aver_repr(other)),
498 }
499}