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
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(i64),
123 Float(f64),
124 Str(String),
125 Bool(bool),
126 Unit,
127 Ok(Box<Value>),
128 Err(Box<Value>),
129 Some(Box<Value>),
130 None,
131 List(AverList<Value>),
132 Vector(AverVector<Value>),
133 Tuple(Vec<Value>),
134 Map(HashMap<Value, Value>),
135 Fn(Rc<FunctionValue>),
136 Builtin(String),
137 Variant {
139 type_name: String,
140 variant: String,
141 fields: Rc<[Value]>,
142 },
143 Record {
145 type_name: String,
146 fields: Rc<[(String, Value)]>,
147 },
148 Namespace {
150 name: String,
151 members: HashMap<String, Value>,
152 },
153}
154
155impl PartialEq for Value {
156 fn eq(&self, other: &Self) -> bool {
157 match (list_view(self), list_view(other)) {
158 (Some(xs), Some(ys)) => return xs.iter().eq(ys.iter()),
159 (Some(_), None) | (None, Some(_)) => return false,
160 (None, None) => {}
161 }
162
163 match (self, other) {
164 (Value::Int(a), Value::Int(b)) => a == b,
165 (Value::Float(a), Value::Float(b)) => {
166 if a.is_nan() || b.is_nan() {
167 a.to_bits() == b.to_bits()
168 } else {
169 a == b
170 }
171 }
172 (Value::Str(a), Value::Str(b)) => a == b,
173 (Value::Bool(a), Value::Bool(b)) => a == b,
174 (Value::Unit, Value::Unit) => true,
175 (Value::Ok(a), Value::Ok(b)) => a == b,
176 (Value::Err(a), Value::Err(b)) => a == b,
177 (Value::Some(a), Value::Some(b)) => a == b,
178 (Value::None, Value::None) => true,
179 (Value::Vector(a), Value::Vector(b)) => a == b,
180 (Value::Tuple(a), Value::Tuple(b)) => a == b,
181 (Value::Map(a), Value::Map(b)) => a == b,
182 (Value::Fn(a), Value::Fn(b)) => {
183 a.name == b.name
184 && a.params == b.params
185 && a.return_type == b.return_type
186 && a.effects == b.effects
187 && a.body == b.body
188 }
189 (Value::Builtin(a), Value::Builtin(b)) => a == b,
190 (
191 Value::Variant {
192 type_name: t1,
193 variant: v1,
194 fields: f1,
195 },
196 Value::Variant {
197 type_name: t2,
198 variant: v2,
199 fields: f2,
200 },
201 ) => t1 == t2 && v1 == v2 && f1 == f2,
202 (
203 Value::Record {
204 type_name: t1,
205 fields: f1,
206 },
207 Value::Record {
208 type_name: t2,
209 fields: f2,
210 },
211 ) => t1 == t2 && f1 == f2,
212 (
213 Value::Namespace {
214 name: n1,
215 members: m1,
216 },
217 Value::Namespace {
218 name: n2,
219 members: m2,
220 },
221 ) => n1 == n2 && m1 == m2,
222 _ => false,
223 }
224 }
225}
226
227impl Eq for Value {}
228
229impl std::hash::Hash for Value {
230 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
231 if let Some(items) = list_view(self) {
232 8u8.hash(state);
233 items.len().hash(state);
234 for item in items.iter() {
235 item.hash(state);
236 }
237 return;
238 }
239
240 match self {
241 Value::Int(i) => {
242 0u8.hash(state);
243 i.hash(state);
244 }
245 Value::Float(f) => {
246 1u8.hash(state);
247 let bits = if *f == 0.0 {
248 0.0f64.to_bits()
249 } else {
250 f.to_bits()
251 };
252 bits.hash(state);
253 }
254 Value::Str(s) => {
255 2u8.hash(state);
256 s.hash(state);
257 }
258 Value::Bool(b) => {
259 3u8.hash(state);
260 b.hash(state);
261 }
262 Value::Unit => {
263 4u8.hash(state);
264 }
265 Value::Ok(v) => {
266 5u8.hash(state);
267 v.hash(state);
268 }
269 Value::Err(v) => {
270 6u8.hash(state);
271 v.hash(state);
272 }
273 Value::Some(v) => {
274 7u8.hash(state);
275 v.hash(state);
276 }
277 Value::None => {
278 9u8.hash(state);
279 }
280 Value::Map(map) => {
281 10u8.hash(state);
282 let mut entries = map.iter().collect::<Vec<_>>();
283 entries.sort_by_key(|(k1, _)| aver_repr(k1));
284 for (k, v) in entries {
285 k.hash(state);
286 v.hash(state);
287 }
288 }
289 Value::Vector(vec) => {
290 17u8.hash(state);
291 vec.hash(state);
292 }
293 Value::Tuple(items) => {
294 16u8.hash(state);
295 items.hash(state);
296 }
297 Value::Fn(function) => {
298 11u8.hash(state);
299 function.name.hash(state);
300 function.params.hash(state);
301 function.return_type.hash(state);
302 function.effects.hash(state);
303 format!("{:?}", function.body).hash(state);
304 }
305 Value::Builtin(name) => {
306 12u8.hash(state);
307 name.hash(state);
308 }
309 Value::Variant {
310 type_name,
311 variant,
312 fields,
313 } => {
314 13u8.hash(state);
315 type_name.hash(state);
316 variant.hash(state);
317 fields.hash(state);
318 }
319 Value::Record { type_name, fields } => {
320 14u8.hash(state);
321 type_name.hash(state);
322 fields.hash(state);
323 }
324 Value::Namespace { name, members } => {
325 15u8.hash(state);
326 name.hash(state);
327 let mut keys = members.keys().collect::<Vec<_>>();
328 keys.sort();
329 for key in keys {
330 key.hash(state);
331 if let Some(value) = members.get(key) {
332 value.hash(state);
333 }
334 }
335 }
336 Value::List(_) => unreachable!("list hashed above"),
337 }
338 }
339}
340
341#[derive(Debug, Clone)]
346pub enum EnvFrame {
347 Owned(HashMap<String, NanValue>),
348 Shared(Rc<HashMap<String, NanValue>>),
349 Slots(Vec<NanValue>),
351}
352
353pub type Env = Vec<EnvFrame>;
355
356pub(crate) type ListView<'a> = &'a AverList<Value>;
361
362pub(crate) fn list_view(value: &Value) -> Option<ListView<'_>> {
363 match value {
364 Value::List(items) => Some(items),
365 _ => None,
366 }
367}
368
369#[cfg(feature = "runtime")]
370pub fn list_slice(value: &Value) -> Option<&[Value]> {
371 list_view(value).and_then(AverList::as_slice)
372}
373
374#[cfg(feature = "runtime")]
375pub fn list_from_vec(items: Vec<Value>) -> Value {
376 Value::List(AverList::from_vec(items))
377}
378
379#[cfg(feature = "runtime")]
380pub fn list_to_vec(value: &Value) -> Option<Vec<Value>> {
381 list_view(value).map(AverList::to_vec)
382}
383
384#[cfg(feature = "runtime")]
385pub fn list_len(value: &Value) -> Option<usize> {
386 list_view(value).map(AverList::len)
387}
388
389#[cfg(feature = "runtime")]
390pub fn list_head(value: &Value) -> Option<Value> {
391 list_view(value).and_then(|items| items.first().cloned())
392}
393
394#[cfg(feature = "runtime")]
395pub(crate) fn list_prepend(item: Value, list: &Value) -> Option<Value> {
396 list_view(list).map(|items| Value::List(AverList::prepend(item, items)))
397}
398
399#[cfg(feature = "runtime")]
400pub(crate) fn list_concat(left: &Value, right: &Value) -> Option<Value> {
401 let left = list_view(left)?;
402 let right = list_view(right)?;
403 Some(Value::List(AverList::concat(left, right)))
404}
405
406#[cfg(feature = "runtime")]
407pub(crate) fn list_reverse(list: &Value) -> Option<Value> {
408 list_view(list).map(|items| Value::List(items.reverse()))
409}
410
411pub fn callable_declared_effects(fn_val: &Value) -> Vec<String> {
417 match fn_val {
418 Value::Fn(function) => function.effects.as_ref().clone(),
419 _ => vec![],
420 }
421}
422
423pub fn aver_repr(val: &Value) -> String {
429 if let Some(items) = list_view(val) {
430 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
431 return format!("[{}]", parts.join(", "));
432 }
433
434 match val {
435 Value::Int(i) => i.to_string(),
436 Value::Float(f) => f.to_string(),
437 Value::Str(s) => s.clone(),
438 Value::Bool(b) => if *b { "true" } else { "false" }.to_string(),
439 Value::Unit => "Unit".to_string(),
440 Value::Ok(v) => format!("Result.Ok({})", aver_repr_inner(v)),
441 Value::Err(v) => format!("Result.Err({})", aver_repr_inner(v)),
442 Value::Some(v) => format!("Option.Some({})", aver_repr_inner(v)),
443 Value::None => "Option.None".to_string(),
444 Value::Tuple(items) => {
445 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
446 format!("({})", parts.join(", "))
447 }
448 Value::Vector(vec) => {
449 let parts: Vec<String> = vec.iter().map(aver_repr_inner).collect();
450 format!("Vector[{}]", parts.join(", "))
451 }
452 Value::List(_) => unreachable!("handled via list_view above"),
453 Value::Map(entries) => {
454 let mut pairs = entries
455 .iter()
456 .map(|(k, v)| (aver_repr_inner(k), aver_repr_inner(v)))
457 .collect::<Vec<_>>();
458 pairs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
459 let parts = pairs
460 .into_iter()
461 .map(|(k, v)| format!("{}: {}", k, v))
462 .collect::<Vec<_>>();
463 format!("{{{}}}", parts.join(", "))
464 }
465 Value::Fn(function) => format!("<fn {}>", function.name),
466 Value::Builtin(name) => format!("<builtin {}>", name),
467 Value::Variant {
468 variant, fields, ..
469 } => {
470 if fields.is_empty() {
471 variant.clone()
472 } else {
473 let parts: Vec<String> = fields.iter().map(aver_repr_inner).collect();
474 format!("{}({})", variant, parts.join(", "))
475 }
476 }
477 Value::Record { type_name, fields } => {
478 let parts: Vec<String> = fields
479 .iter()
480 .map(|(k, v)| format!("{}: {}", k, aver_repr_inner(v)))
481 .collect();
482 format!("{}({})", type_name, parts.join(", "))
483 }
484 Value::Namespace { name, .. } => format!("<type {}>", name),
485 }
486}
487
488fn aver_repr_inner(val: &Value) -> String {
490 if let Some(items) = list_view(val) {
491 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
492 return format!("[{}]", parts.join(", "));
493 }
494
495 match val {
496 Value::Str(s) => format!("\"{}\"", s),
497 Value::Tuple(items) => {
498 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
499 format!("({})", parts.join(", "))
500 }
501 Value::Vector(vec) => {
502 let parts: Vec<String> = vec.iter().map(aver_repr_inner).collect();
503 format!("Vector[{}]", parts.join(", "))
504 }
505 Value::List(_) => unreachable!("handled via list_view above"),
506 other => aver_repr(other),
507 }
508}
509
510pub fn aver_display(val: &Value) -> Option<String> {
512 match val {
513 Value::Unit => None,
514 other => Some(aver_repr(other)),
515 }
516}