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