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