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