1use super::*;
2
3impl Interpreter {
4 fn empty_slots(local_count: u16) -> Vec<Rc<Value>> {
5 let unit = Rc::new(Value::Unit);
6 vec![unit; local_count as usize]
7 }
8
9 pub fn eval_expr(&mut self, expr: &Expr) -> Result<Value, RuntimeError> {
10 match expr {
11 Expr::Literal(lit) => Ok(self.eval_literal(lit)),
12 Expr::Resolved(slot) => self.lookup_slot(*slot),
13 Expr::Ident(name) => self.lookup(name),
14 Expr::Attr(obj, field) => {
15 if let Expr::Ident(name) = obj.as_ref() {
17 let rc = self.lookup_rc(name)?;
18 return match rc.as_ref() {
19 Value::Namespace { name, members } => {
20 members.get(field.as_str()).cloned().ok_or_else(|| {
21 RuntimeError::Error(format!("Unknown member '{}.{}'", name, field))
22 })
23 }
24 Value::Record { fields, .. } => fields
25 .iter()
26 .find(|(k, _)| k == field)
27 .map(|(_, v)| Ok(v.clone()))
28 .unwrap_or_else(|| {
29 Err(RuntimeError::Error(format!("Unknown field '{}'", field)))
30 }),
31 _ => Err(RuntimeError::Error(format!(
32 "Field access '{}' is not supported on this value",
33 field
34 ))),
35 };
36 }
37 let obj_val = self.eval_expr(obj)?;
39 match obj_val {
40 Value::Record { fields, .. } => fields
41 .into_iter()
42 .find(|(k, _)| k == field)
43 .map(|(_, v)| Ok(v))
44 .unwrap_or_else(|| {
45 Err(RuntimeError::Error(format!("Unknown field '{}'", field)))
46 }),
47 Value::Namespace { name, members } => {
48 members.get(field).cloned().ok_or_else(|| {
49 RuntimeError::Error(format!("Unknown member '{}.{}'", name, field))
50 })
51 }
52 _ => Err(RuntimeError::Error(format!(
53 "Field access '{}' is not supported on this value",
54 field
55 ))),
56 }
57 }
58 Expr::FnCall(fn_expr, args) => {
59 let fn_val = self.eval_expr(fn_expr)?;
60 let mut arg_vals = Vec::new();
61 for a in args {
62 arg_vals.push(self.eval_expr(a)?);
63 }
64 self.call_value(fn_val, arg_vals)
65 }
66 Expr::BinOp(op, left, right) => {
67 let lv = self.eval_expr(left)?;
68 let rv = self.eval_expr(right)?;
69 self.eval_binop(op, lv, rv)
70 }
71 Expr::Match {
72 subject,
73 arms,
74 line,
75 } => {
76 let sv = self.eval_expr(subject)?;
77 self.eval_match(sv, arms, *line)
78 }
79 Expr::Constructor(name, arg) => {
80 let arg_val = match arg {
81 Some(a) => self.eval_expr(a)?,
82 None => Value::Unit,
83 };
84 match name.as_str() {
85 "Ok" => Ok(Value::Ok(Box::new(arg_val))),
86 "Err" => Ok(Value::Err(Box::new(arg_val))),
87 "Some" => Ok(Value::Some(Box::new(arg_val))),
88 "None" => Ok(Value::None),
89 _ => Err(RuntimeError::Error(format!(
90 "Unknown constructor: {}",
91 name
92 ))),
93 }
94 }
95 Expr::ErrorProp(inner) => {
96 let val = self.eval_expr(inner)?;
97 match val {
98 Value::Ok(v) => Ok(*v),
99 Value::Err(e) => Err(RuntimeError::ErrProp(e)),
100 _ => Err(RuntimeError::Error(
101 "Operator '?' can only be applied to Result".to_string(),
102 )),
103 }
104 }
105 Expr::InterpolatedStr(parts) => {
106 let mut result = String::new();
107 for part in parts {
108 match part {
109 StrPart::Literal(s) => result.push_str(s),
110 StrPart::Parsed(expr) => {
111 let val = self.eval_expr(expr)?;
112 result.push_str(&aver_repr(&val));
113 }
114 }
115 }
116 Ok(Value::Str(result))
117 }
118 Expr::List(elements) => {
119 let mut values = Vec::new();
120 for elem in elements {
121 values.push(self.eval_expr(elem)?);
122 }
123 Ok(list_from_vec(values))
124 }
125 Expr::Tuple(items) => {
126 let mut values = Vec::with_capacity(items.len());
127 for item in items {
128 values.push(self.eval_expr(item)?);
129 }
130 Ok(Value::Tuple(values))
131 }
132 Expr::MapLiteral(entries) => self.eval_map_literal(entries),
133 Expr::RecordCreate { type_name, fields } => self.eval_record_create(type_name, fields),
134 Expr::RecordUpdate {
135 type_name,
136 base,
137 updates,
138 } => self.eval_record_update(type_name, base, updates),
139 Expr::TailCall(boxed) => self.eval_tail_call(boxed),
140 }
141 }
142
143 #[inline(never)]
145 pub(super) fn eval_tail_call(
146 &mut self,
147 boxed: &(String, Vec<Expr>),
148 ) -> Result<Value, RuntimeError> {
149 let (target, args) = boxed;
150 let mut vals = Vec::with_capacity(args.len());
151 for a in args {
152 vals.push(self.eval_expr(a)?);
153 }
154 Err(RuntimeError::TailCall(Box::new((target.clone(), vals))))
155 }
156
157 #[inline(never)]
160 fn eval_record_create(
161 &mut self,
162 type_name: &str,
163 fields: &[(String, Expr)],
164 ) -> Result<Value, RuntimeError> {
165 let mut field_vals = Vec::with_capacity(fields.len());
166 let mut seen = HashSet::new();
167 for (name, expr) in fields {
168 if !seen.insert(name.clone()) {
169 return Err(RuntimeError::Error(format!(
170 "Record '{}' field '{}' provided more than once",
171 type_name, name
172 )));
173 }
174 let val = self.eval_expr(expr)?;
175 field_vals.push((name.clone(), val));
176 }
177
178 if let Some(schema) = self.record_schemas.get(type_name) {
179 let mut by_name = HashMap::with_capacity(field_vals.len());
180 for (name, val) in field_vals {
181 by_name.insert(name, val);
182 }
183
184 for provided in by_name.keys() {
185 if !schema.iter().any(|f| f == provided) {
186 return Err(RuntimeError::Error(format!(
187 "Record '{}' has no field '{}'",
188 type_name, provided
189 )));
190 }
191 }
192
193 let mut ordered = Vec::with_capacity(schema.len());
194 for required in schema {
195 let val = by_name.remove(required).ok_or_else(|| {
196 RuntimeError::Error(format!(
197 "Record '{}' missing required field '{}'",
198 type_name, required
199 ))
200 })?;
201 ordered.push((required.clone(), val));
202 }
203
204 return Ok(Value::Record {
205 type_name: type_name.to_string(),
206 fields: ordered,
207 });
208 }
209
210 Ok(Value::Record {
211 type_name: type_name.to_string(),
212 fields: field_vals,
213 })
214 }
215
216 #[inline(never)]
218 fn eval_record_update(
219 &mut self,
220 type_name: &str,
221 base: &Expr,
222 updates: &[(String, Expr)],
223 ) -> Result<Value, RuntimeError> {
224 let base_val = self.eval_expr(base)?;
225 let (base_type, base_fields) = match base_val {
226 Value::Record {
227 type_name: t,
228 fields,
229 } => (t, fields),
230 _ => {
231 return Err(RuntimeError::Error(format!(
232 "{}.update: base must be a {} record",
233 type_name, type_name
234 )));
235 }
236 };
237 if base_type != type_name {
238 return Err(RuntimeError::Error(format!(
239 "{}.update: base is a {} record, expected {}",
240 type_name, base_type, type_name
241 )));
242 }
243
244 let mut update_vals = Vec::with_capacity(updates.len());
245 for (name, expr) in updates {
246 let val = self.eval_expr(expr)?;
247 update_vals.push((name.clone(), val));
248 }
249
250 if let Some(schema) = self.record_schemas.get(type_name) {
252 for (field_name, _) in &update_vals {
253 if !schema.iter().any(|f| f == field_name) {
254 return Err(RuntimeError::Error(format!(
255 "Record '{}' has no field '{}'",
256 type_name, field_name
257 )));
258 }
259 }
260 }
261
262 let mut fields: Vec<(String, Value)> = base_fields;
264 for (upd_name, upd_val) in update_vals {
265 if let Some(field) = fields.iter_mut().find(|(k, _)| k == &upd_name) {
266 field.1 = upd_val;
267 } else {
268 return Err(RuntimeError::Error(format!(
269 "Record '{}' has no field '{}'",
270 type_name, upd_name
271 )));
272 }
273 }
274
275 Ok(Value::Record {
276 type_name: type_name.to_string(),
277 fields,
278 })
279 }
280
281 #[inline(never)]
282 fn eval_map_literal(&mut self, entries: &[(Expr, Expr)]) -> Result<Value, RuntimeError> {
283 let mut map = HashMap::with_capacity(entries.len());
284 for (key_expr, value_expr) in entries {
285 let key = self.eval_expr(key_expr)?;
286 if !Self::is_hashable_map_key(&key) {
287 return Err(RuntimeError::Error(
288 "Map literal key must be Int, Float, String, or Bool".to_string(),
289 ));
290 }
291 let value = self.eval_expr(value_expr)?;
292 map.insert(key, value);
293 }
294 Ok(Value::Map(map))
295 }
296
297 fn is_hashable_map_key(value: &Value) -> bool {
298 matches!(
299 value,
300 Value::Int(_) | Value::Float(_) | Value::Str(_) | Value::Bool(_)
301 )
302 }
303
304 pub(super) fn eval_literal(&self, lit: &Literal) -> Value {
305 match lit {
306 Literal::Int(i) => Value::Int(*i),
307 Literal::Float(f) => Value::Float(*f),
308 Literal::Str(s) => Value::Str(s.clone()),
309 Literal::Bool(b) => Value::Bool(*b),
310 }
311 }
312
313 pub(super) fn call_value(
315 &mut self,
316 fn_val: Value,
317 args: Vec<Value>,
318 ) -> Result<Value, RuntimeError> {
319 match &fn_val {
320 Value::Builtin(name) => {
321 self.ensure_effects_allowed(name, Self::builtin_effects(name).iter().copied())?;
322 self.call_builtin(name, &args)
323 }
324 Value::Fn { .. } => self.call_fn_ref(&fn_val, args),
325 _ => Err(RuntimeError::Error(format!(
326 "Cannot call value: {:?}",
327 fn_val
328 ))),
329 }
330 }
331
332 pub(super) fn call_fn_ref(
337 &mut self,
338 fn_val: &Value,
339 args: Vec<Value>,
340 ) -> Result<Value, RuntimeError> {
341 let Value::Fn {
342 name,
343 params,
344 effects,
345 body,
346 resolution,
347 memo_eligible,
348 home_globals,
349 ..
350 } = fn_val
351 else {
352 return Err(RuntimeError::Error(format!(
353 "Cannot call value: {:?}",
354 fn_val
355 )));
356 };
357
358 if args.len() != params.len() {
359 return Err(RuntimeError::Error(format!(
360 "Function '{}' expects {} arguments, got {}",
361 name,
362 params.len(),
363 args.len()
364 )));
365 }
366 self.ensure_effects_allowed(name, effects.iter().map(String::as_str))?;
367
368 let is_memo = *memo_eligible;
370 let memo_key = if is_memo {
371 let key = hash_memo_args(&args);
372 if let Some(cached) = self
373 .memo_cache
374 .entry(name.clone())
375 .or_default()
376 .get(key, &args)
377 {
378 return Ok(cached);
379 }
380 Some((key, args.clone()))
381 } else {
382 None
383 };
384
385 self.call_stack.push(CallFrame {
386 name: name.clone(),
387 effects: effects.clone(),
388 });
389
390 let prev_local_slots = self.active_local_slots.take();
391 let saved_frames: Vec<EnvFrame> = self.env.drain(1..).collect();
392 let prev_global = if let Some(home) = home_globals {
393 let global = self
394 .env
395 .first_mut()
396 .ok_or_else(|| RuntimeError::Error("No global scope".to_string()))?;
397 Some(std::mem::replace(global, EnvFrame::Shared(Rc::clone(home))))
398 } else {
399 None
400 };
401
402 let result = if let Some(res) = resolution {
403 let mut slots = Self::empty_slots(res.local_count);
406 for ((param_name, _), arg_val) in params.iter().zip(args.into_iter()) {
407 if let Some(&slot) = res.local_slots.get(param_name) {
408 slots[slot as usize] = Rc::new(arg_val);
409 }
410 }
411 self.active_local_slots = Some(res.local_slots.clone());
412 self.push_env(EnvFrame::Slots(slots));
413 let r = self.exec_body_resolved(body.stmts(), &res.local_slots);
414 self.pop_env();
415 r
416 } else {
417 let mut params_scope = HashMap::new();
419 for ((param_name, _), arg_val) in params.iter().zip(args.into_iter()) {
420 params_scope.insert(param_name.clone(), Rc::new(arg_val));
421 }
422 self.push_env(EnvFrame::Owned(params_scope));
423 let r = self.exec_body(body.stmts());
424 self.pop_env();
425 r
426 };
427
428 let result = match result {
430 Err(RuntimeError::TailCall(boxed)) => {
431 let (target, new_args) = *boxed;
432 self.tco_trampoline(name, params, body, resolution, target, new_args)
433 }
434 other => other,
435 };
436
437 self.active_local_slots = prev_local_slots;
438 if let Some(prev) = prev_global
439 && let Some(global) = self.env.first_mut()
440 {
441 *global = prev;
442 }
443 self.env.truncate(1);
444 self.env.extend(saved_frames);
445
446 self.call_stack.pop();
447 let final_result = match result {
448 Ok(v) => Ok(v),
449 Err(RuntimeError::ErrProp(e)) => Ok(Value::Err(e)),
450 Err(e) => Err(e),
451 };
452
453 if let (Some((key, memo_args)), Ok(val)) = (memo_key, &final_result) {
455 let fn_name = name.clone();
456 let cache = self.memo_cache.entry(fn_name).or_default();
457 cache.insert(key, memo_args, val.clone(), MEMO_CACHE_CAP_PER_FN);
458 }
459
460 final_result
461 }
462
463 #[inline(never)]
467 pub(super) fn tco_trampoline(
468 &mut self,
469 orig_name: &str,
470 orig_params: &[(String, String)],
471 orig_body: &Rc<FnBody>,
472 orig_resolution: &Option<FnResolution>,
473 first_target: String,
474 first_args: Vec<Value>,
475 ) -> Result<Value, RuntimeError> {
476 let mut cur_name = orig_name.to_string();
477 let mut cur_params: Vec<(String, String)> = orig_params.to_vec();
478 let mut cur_body = Rc::clone(orig_body);
479 let mut cur_resolution = orig_resolution.clone();
480
481 let mut target = first_target;
483 let mut new_args = first_args;
484
485 loop {
486 if target != cur_name {
488 let target_fn = self.lookup(&target)?;
489 match target_fn {
490 Value::Fn {
491 name: tn,
492 params: tp,
493 effects: te,
494 body: tb,
495 resolution: tr,
496 ..
497 } => {
498 cur_name = tn;
499 cur_params = tp;
500 cur_body = tb;
501 cur_resolution = tr;
502 if let Some(frame) = self.call_stack.last_mut() {
503 frame.name = cur_name.clone();
504 frame.effects = te;
505 }
506 }
507 _ => {
508 return Err(RuntimeError::Error(format!(
509 "TCO target '{}' is not a function",
510 target
511 )));
512 }
513 }
514 }
515
516 let exec_result = if let Some(ref res) = cur_resolution {
518 let mut slots = Self::empty_slots(res.local_count);
519 for ((param_name, _), arg_val) in cur_params.iter().zip(new_args.into_iter()) {
520 if let Some(&slot) = res.local_slots.get(param_name) {
521 slots[slot as usize] = Rc::new(arg_val);
522 }
523 }
524 self.active_local_slots = Some(res.local_slots.clone());
525 self.push_env(EnvFrame::Slots(slots));
526 let r = self.exec_body_resolved(cur_body.stmts(), &res.local_slots);
527 self.pop_env();
528 r
529 } else {
530 let mut params_scope = HashMap::new();
531 for ((param_name, _), arg_val) in cur_params.iter().zip(new_args.into_iter()) {
532 params_scope.insert(param_name.clone(), Rc::new(arg_val));
533 }
534 let saved_frames: Vec<EnvFrame> = self.env.drain(1..).collect();
535 self.push_env(EnvFrame::Owned(params_scope));
536 let r = self.exec_body(cur_body.stmts());
537 self.pop_env();
538 self.env.extend(saved_frames);
539 r
540 };
541
542 match exec_result {
543 Err(RuntimeError::TailCall(boxed)) => {
544 let (next_target, next_args) = *boxed;
545 target = next_target;
546 new_args = next_args;
547 continue;
548 }
549 other => return other,
550 }
551 }
552 }
553}