1use aver_rt::AverList;
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 Tuple(Vec<Value>),
96 Map(HashMap<Value, Value>),
97 Fn(Rc<FunctionValue>),
98 Builtin(String),
99 Variant {
101 type_name: String,
102 variant: String,
103 fields: Rc<[Value]>,
104 },
105 Record {
107 type_name: String,
108 fields: Rc<[(String, Value)]>,
109 },
110 Namespace {
112 name: String,
113 members: HashMap<String, Value>,
114 },
115}
116
117impl PartialEq for Value {
118 fn eq(&self, other: &Self) -> bool {
119 match (list_view(self), list_view(other)) {
120 (Some(xs), Some(ys)) => return xs.iter().eq(ys.iter()),
121 (Some(_), None) | (None, Some(_)) => return false,
122 (None, None) => {}
123 }
124
125 match (self, other) {
126 (Value::Int(a), Value::Int(b)) => a == b,
127 (Value::Float(a), Value::Float(b)) => {
128 if a.is_nan() || b.is_nan() {
129 a.to_bits() == b.to_bits()
130 } else {
131 a == b
132 }
133 }
134 (Value::Str(a), Value::Str(b)) => a == b,
135 (Value::Bool(a), Value::Bool(b)) => a == b,
136 (Value::Unit, Value::Unit) => true,
137 (Value::Ok(a), Value::Ok(b)) => a == b,
138 (Value::Err(a), Value::Err(b)) => a == b,
139 (Value::Some(a), Value::Some(b)) => a == b,
140 (Value::None, Value::None) => true,
141 (Value::Tuple(a), Value::Tuple(b)) => a == b,
142 (Value::Map(a), Value::Map(b)) => a == b,
143 (Value::Fn(a), Value::Fn(b)) => {
144 a.name == b.name
145 && a.params == b.params
146 && a.return_type == b.return_type
147 && a.effects == b.effects
148 && a.body == b.body
149 }
150 (Value::Builtin(a), Value::Builtin(b)) => a == b,
151 (
152 Value::Variant {
153 type_name: t1,
154 variant: v1,
155 fields: f1,
156 },
157 Value::Variant {
158 type_name: t2,
159 variant: v2,
160 fields: f2,
161 },
162 ) => t1 == t2 && v1 == v2 && f1 == f2,
163 (
164 Value::Record {
165 type_name: t1,
166 fields: f1,
167 },
168 Value::Record {
169 type_name: t2,
170 fields: f2,
171 },
172 ) => t1 == t2 && f1 == f2,
173 (
174 Value::Namespace {
175 name: n1,
176 members: m1,
177 },
178 Value::Namespace {
179 name: n2,
180 members: m2,
181 },
182 ) => n1 == n2 && m1 == m2,
183 _ => false,
184 }
185 }
186}
187
188impl Eq for Value {}
189
190impl std::hash::Hash for Value {
191 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
192 if let Some(items) = list_view(self) {
193 8u8.hash(state);
194 items.len().hash(state);
195 for item in items.iter() {
196 item.hash(state);
197 }
198 return;
199 }
200
201 match self {
202 Value::Int(i) => {
203 0u8.hash(state);
204 i.hash(state);
205 }
206 Value::Float(f) => {
207 1u8.hash(state);
208 let bits = if *f == 0.0 {
209 0.0f64.to_bits()
210 } else {
211 f.to_bits()
212 };
213 bits.hash(state);
214 }
215 Value::Str(s) => {
216 2u8.hash(state);
217 s.hash(state);
218 }
219 Value::Bool(b) => {
220 3u8.hash(state);
221 b.hash(state);
222 }
223 Value::Unit => {
224 4u8.hash(state);
225 }
226 Value::Ok(v) => {
227 5u8.hash(state);
228 v.hash(state);
229 }
230 Value::Err(v) => {
231 6u8.hash(state);
232 v.hash(state);
233 }
234 Value::Some(v) => {
235 7u8.hash(state);
236 v.hash(state);
237 }
238 Value::None => {
239 9u8.hash(state);
240 }
241 Value::Map(map) => {
242 10u8.hash(state);
243 let mut entries = map.iter().collect::<Vec<_>>();
244 entries.sort_by(|(k1, _), (k2, _)| aver_repr(k1).cmp(&aver_repr(k2)));
245 for (k, v) in entries {
246 k.hash(state);
247 v.hash(state);
248 }
249 }
250 Value::Tuple(items) => {
251 16u8.hash(state);
252 items.hash(state);
253 }
254 Value::Fn(function) => {
255 11u8.hash(state);
256 function.name.hash(state);
257 function.params.hash(state);
258 function.return_type.hash(state);
259 function.effects.hash(state);
260 format!("{:?}", function.body).hash(state);
261 }
262 Value::Builtin(name) => {
263 12u8.hash(state);
264 name.hash(state);
265 }
266 Value::Variant {
267 type_name,
268 variant,
269 fields,
270 } => {
271 13u8.hash(state);
272 type_name.hash(state);
273 variant.hash(state);
274 fields.hash(state);
275 }
276 Value::Record { type_name, fields } => {
277 14u8.hash(state);
278 type_name.hash(state);
279 fields.hash(state);
280 }
281 Value::Namespace { name, members } => {
282 15u8.hash(state);
283 name.hash(state);
284 let mut keys = members.keys().collect::<Vec<_>>();
285 keys.sort();
286 for key in keys {
287 key.hash(state);
288 if let Some(value) = members.get(key) {
289 value.hash(state);
290 }
291 }
292 }
293 Value::List(_) => unreachable!("list hashed above"),
294 }
295 }
296}
297
298#[derive(Debug, Clone)]
303pub enum EnvFrame {
304 Owned(HashMap<String, NanValue>),
305 Shared(Rc<HashMap<String, NanValue>>),
306 Slots(Vec<NanValue>),
308}
309
310pub type Env = Vec<EnvFrame>;
312
313pub(crate) type ListView<'a> = &'a AverList<Value>;
318
319pub(crate) fn list_view(value: &Value) -> Option<ListView<'_>> {
320 match value {
321 Value::List(items) => Some(items),
322 _ => None,
323 }
324}
325
326pub fn list_slice(value: &Value) -> Option<&[Value]> {
327 list_view(value).and_then(AverList::as_slice)
328}
329
330pub fn list_from_vec(items: Vec<Value>) -> Value {
331 Value::List(AverList::from_vec(items))
332}
333
334pub fn list_to_vec(value: &Value) -> Option<Vec<Value>> {
335 list_view(value).map(AverList::to_vec)
336}
337
338pub fn list_len(value: &Value) -> Option<usize> {
339 list_view(value).map(AverList::len)
340}
341
342pub(crate) fn list_get(value: &Value, index: usize) -> Option<Value> {
343 list_view(value).and_then(|items| items.get(index).cloned())
344}
345
346pub fn list_head(value: &Value) -> Option<Value> {
347 list_view(value).and_then(|items| items.first().cloned())
348}
349
350pub(crate) fn list_append(list: &Value, item: Value) -> Option<Value> {
351 list_view(list).map(|items| Value::List(AverList::append(items, item)))
352}
353
354pub(crate) fn list_prepend(item: Value, list: &Value) -> Option<Value> {
355 list_view(list).map(|items| Value::List(AverList::prepend(item, items)))
356}
357
358pub(crate) fn list_concat(left: &Value, right: &Value) -> Option<Value> {
359 let left = list_view(left)?;
360 let right = list_view(right)?;
361 Some(Value::List(AverList::concat(left, right)))
362}
363
364pub(crate) fn list_reverse(list: &Value) -> Option<Value> {
365 list_view(list).map(|items| Value::List(items.reverse()))
366}
367
368pub fn aver_repr(val: &Value) -> String {
374 if let Some(items) = list_view(val) {
375 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
376 return format!("[{}]", parts.join(", "));
377 }
378
379 match val {
380 Value::Int(i) => i.to_string(),
381 Value::Float(f) => f.to_string(),
382 Value::Str(s) => s.clone(),
383 Value::Bool(b) => if *b { "true" } else { "false" }.to_string(),
384 Value::Unit => "Unit".to_string(),
385 Value::Ok(v) => format!("Result.Ok({})", aver_repr_inner(v)),
386 Value::Err(v) => format!("Result.Err({})", aver_repr_inner(v)),
387 Value::Some(v) => format!("Option.Some({})", aver_repr_inner(v)),
388 Value::None => "Option.None".to_string(),
389 Value::Tuple(items) => {
390 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
391 format!("({})", parts.join(", "))
392 }
393 Value::List(_) => unreachable!("handled via list_view above"),
394 Value::Map(entries) => {
395 let mut pairs = entries
396 .iter()
397 .map(|(k, v)| (aver_repr_inner(k), aver_repr_inner(v)))
398 .collect::<Vec<_>>();
399 pairs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
400 let parts = pairs
401 .into_iter()
402 .map(|(k, v)| format!("{}: {}", k, v))
403 .collect::<Vec<_>>();
404 format!("{{{}}}", parts.join(", "))
405 }
406 Value::Fn(function) => format!("<fn {}>", function.name),
407 Value::Builtin(name) => format!("<builtin {}>", name),
408 Value::Variant {
409 variant, fields, ..
410 } => {
411 if fields.is_empty() {
412 variant.clone()
413 } else {
414 let parts: Vec<String> = fields.iter().map(aver_repr_inner).collect();
415 format!("{}({})", variant, parts.join(", "))
416 }
417 }
418 Value::Record { type_name, fields } => {
419 let parts: Vec<String> = fields
420 .iter()
421 .map(|(k, v)| format!("{}: {}", k, aver_repr_inner(v)))
422 .collect();
423 format!("{}({})", type_name, parts.join(", "))
424 }
425 Value::Namespace { name, .. } => format!("<type {}>", name),
426 }
427}
428
429fn aver_repr_inner(val: &Value) -> String {
431 if let Some(items) = list_view(val) {
432 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
433 return format!("[{}]", parts.join(", "));
434 }
435
436 match val {
437 Value::Str(s) => format!("\"{}\"", s),
438 Value::Tuple(items) => {
439 let parts: Vec<String> = items.iter().map(aver_repr_inner).collect();
440 format!("({})", parts.join(", "))
441 }
442 Value::List(_) => unreachable!("handled via list_view above"),
443 other => aver_repr(other),
444 }
445}
446
447pub fn aver_display(val: &Value) -> Option<String> {
449 match val {
450 Value::Unit => None,
451 other => Some(aver_repr(other)),
452 }
453}