1use crate::value::{Value, Env};
7use synoema_parser::*;
8
9#[derive(Debug, Clone)]
11pub struct EvalError {
12 pub message: String,
13}
14
15impl EvalError {
16 pub fn new(msg: impl Into<String>) -> Self {
17 Self { message: msg.into() }
18 }
19}
20
21impl std::fmt::Display for EvalError {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 write!(f, "Runtime error: {}", self.message)
24 }
25}
26
27type EResult<T> = Result<T, EvalError>;
28
29fn err(msg: impl Into<String>) -> EvalError { EvalError::new(msg) }
30
31pub struct Evaluator {
33 pub output: Vec<String>,
35}
36
37impl Evaluator {
38 pub fn new() -> Self {
39 Evaluator { output: Vec::new() }
40 }
41
42 pub fn eval_program(&mut self, program: &Program) -> EResult<Env> {
44 let mut env = self.builtin_env();
45
46 for decl in &program.decls {
48 if let Decl::TypeDef { variants, .. } = decl {
49 for v in variants {
50 let arity = v.fields.len();
51 if arity == 0 {
52 env.insert(v.name.clone(), Value::Con(v.name.clone(), vec![]));
53 } else {
54 env.insert(v.name.clone(), Value::Builtin(format!("ctor:{}", v.name), arity));
55 }
56 }
57 }
58 }
59
60 let mut impl_eqs: std::collections::HashMap<String, Vec<Equation>> =
62 std::collections::HashMap::new();
63 for decl in &program.decls {
64 if let Decl::ImplDecl { methods, .. } = decl {
65 for (method_name, equations) in methods {
66 impl_eqs.entry(method_name.clone())
67 .or_default()
68 .extend(equations.iter().cloned());
69 }
70 }
71 }
72
73 for decl in &program.decls {
76 if let Decl::Func { name, equations, .. } = decl {
77 let prepend = impl_eqs.remove(name).unwrap_or_default();
78 let mut all_eqs = prepend;
79 all_eqs.extend(equations.iter().cloned());
80 let func = Value::Func {
81 name: name.clone(),
82 equations: all_eqs,
83 env: env.clone(),
84 };
85 env.insert(name.clone(), func);
86 }
87 }
88
89 for (method_name, equations) in impl_eqs {
91 let func = Value::Func {
92 name: method_name.clone(),
93 equations,
94 env: env.clone(),
95 };
96 env.insert(method_name, func);
97 }
98
99 let snapshot = env.clone();
102 for decl in &program.decls {
103 if let Decl::Func { name, .. } = decl {
104 if let Some(Value::Func { equations, .. }) = snapshot.lookup(name) {
105 let equations = equations.clone();
106 let func = Value::Func {
107 name: name.clone(),
108 equations,
109 env: snapshot.clone(),
110 };
111 env.insert(name.clone(), func);
112 }
113 }
114 }
115 for decl in &program.decls {
117 if let Decl::ImplDecl { methods, .. } = decl {
118 for (method_name, _) in methods {
119 if let Some(Value::Func { equations, .. }) = snapshot.lookup(method_name) {
120 let equations = equations.clone();
121 let func = Value::Func {
122 name: method_name.clone(),
123 equations,
124 env: snapshot.clone(),
125 };
126 env.insert(method_name.clone(), func);
127 }
128 }
129 }
130 }
131
132 Ok(env)
133 }
134
135 pub fn eval(&mut self, env: &Env, expr: &Expr) -> EResult<Value> {
137 match &expr.kind {
138 ExprKind::Lit(lit) => Ok(self.eval_lit(lit)),
140
141 ExprKind::Var(name) => {
143 let val = env.lookup(name)
144 .cloned()
145 .ok_or_else(|| err(format!("Undefined variable: {}", name)))?;
146 match &val {
149 Value::Func { equations, env: fenv, name: fname }
150 if equations.len() == 1 && equations[0].pats.is_empty() =>
151 {
152 let mut local = fenv.child();
153 local.insert(fname.clone(), val.clone());
154 self.eval(&local, &equations[0].body)
155 }
156 Value::Builtin(ref bname, 0) => {
158 let n = bname.clone();
159 self.call_builtin(&n, &[])
160 }
161 _ => Ok(val),
162 }
163 }
164
165 ExprKind::Con(name) => {
167 env.lookup(name)
168 .cloned()
169 .ok_or_else(|| err(format!("Undefined constructor: {}", name)))
170 }
171
172 ExprKind::App(func_e, arg_e) => {
174 let func_v = self.eval(env, func_e)?;
175 let arg_v = self.eval(env, arg_e)?;
176 self.apply(func_v, arg_v)
177 }
178
179 ExprKind::Lam(pats, body) => {
181 Ok(Value::Closure {
182 params: pats.clone(),
183 body: *body.clone(),
184 env: env.clone(),
185 })
186 }
187
188 ExprKind::BinOp(op, lhs, rhs) => {
190 match op {
192 BinOp::And => {
193 let l = self.eval(env, lhs)?;
194 return match l {
195 Value::Bool(false) => Ok(Value::Bool(false)),
196 Value::Bool(true) => self.eval(env, rhs),
197 _ => Err(err("&& requires Bool operands")),
198 };
199 }
200 BinOp::Or => {
201 let l = self.eval(env, lhs)?;
202 return match l {
203 Value::Bool(true) => Ok(Value::Bool(true)),
204 Value::Bool(false) => self.eval(env, rhs),
205 _ => Err(err("|| requires Bool operands")),
206 };
207 }
208 BinOp::Pipe => {
209 let x = self.eval(env, lhs)?;
211 let f = self.eval(env, rhs)?;
212 return self.apply(f, x);
213 }
214 BinOp::Compose => {
215 let f_val = self.eval(env, lhs)?;
217 let g_val = self.eval(env, rhs)?;
218 return Ok(Value::PartialBuiltin("compose#".into(), 1, vec![f_val, g_val]));
220 }
221 BinOp::Seq => {
222 self.eval(env, lhs)?;
224 return self.eval(env, rhs);
225 }
226 _ => {}
227 }
228
229 let l = self.eval(env, lhs)?;
230 let r = self.eval(env, rhs)?;
231 self.eval_binop(*op, l, r)
232 }
233
234 ExprKind::Neg(inner) => {
236 match self.eval(env, inner)? {
237 Value::Int(n) => Ok(Value::Int(-n)),
238 Value::Float(n) => Ok(Value::Float(-n)),
239 _ => Err(err("Negation requires a number")),
240 }
241 }
242
243 ExprKind::Cond(guard, then_e, else_e) => {
245 match self.eval(env, guard)? {
246 Value::Bool(true) => self.eval(env, then_e),
247 Value::Bool(false) => self.eval(env, else_e),
248 _ => Err(err("Condition must be Bool")),
249 }
250 }
251
252 ExprKind::List(elems) => {
254 let vals: Vec<Value> = elems.iter()
255 .map(|e| self.eval(env, e))
256 .collect::<EResult<_>>()?;
257 Ok(Value::List(vals))
258 }
259
260 ExprKind::Range(from, to) => {
262 let f = self.eval(env, from)?;
263 let t = self.eval(env, to)?;
264 match (f, t) {
265 (Value::Int(a), Value::Int(b)) => {
266 Ok(Value::List((a..=b).map(Value::Int).collect()))
267 }
268 _ => Err(err("Range requires Int operands")),
269 }
270 }
271
272 ExprKind::ListComp(body_expr, generators) => {
274 self.eval_list_comp(env, body_expr, generators, 0)
275 }
276
277 ExprKind::Block(bindings, result) => {
279 let mut local = env.child();
280 for b in bindings {
281 let val = self.eval(&local, &b.value)?;
282 local.insert(b.name.clone(), val);
283 }
284 self.eval(&local, result)
285 }
286
287 ExprKind::Record(fields) => {
289 let mut pairs = Vec::new();
290 for (name, expr) in fields {
291 let val = self.eval(env, expr)?;
292 pairs.push((name.clone(), val));
293 }
294 Ok(Value::Record(pairs))
295 }
296
297 ExprKind::Field(obj, field) => {
299 let obj_val = self.eval(env, obj)?;
300 match obj_val {
301 Value::Record(fields) => {
302 fields.into_iter()
303 .find(|(name, _)| name == field)
304 .map(|(_, val)| val)
305 .ok_or_else(|| err(format!("Field '{}' not found in record", field)))
306 }
307 _ => Err(err(format!("Field access '{}' requires a record", field))),
308 }
309 }
310
311 ExprKind::Paren(inner) => self.eval(env, inner),
313 }
314 }
315
316 pub fn apply(&mut self, func: Value, arg: Value) -> EResult<Value> {
319 match func {
320 Value::Closure { params, body, env } => {
321 if params.len() == 1 {
322 let mut local = env.child();
323 self.bind_pattern(¶ms[0], &arg, &mut local)?;
324 self.eval(&local, &body)
325 } else {
326 let mut local = env.child();
328 self.bind_pattern(¶ms[0], &arg, &mut local)?;
329 let rest = params[1..].to_vec();
330 Ok(Value::Closure {
331 params: rest,
332 body,
333 env: local,
334 })
335 }
336 }
337
338 Value::Func { name, equations, env } => {
339 if equations.iter().any(|eq| eq.pats.is_empty()) {
342 for eq in &equations {
344 if eq.pats.is_empty() {
345 let mut local = env.child();
346 local.insert(name.clone(), Value::Func {
347 name: name.clone(),
348 equations: equations.clone(),
349 env: env.clone(),
350 });
351 let body_val = self.eval(&local, &eq.body)?;
352 return self.apply(body_val, arg);
353 }
354 }
355 }
356
357 let all_multi = equations.iter().all(|eq| eq.pats.len() > 1);
360
361 if all_multi {
362 let mut local = env.child();
365 if env.lookup(&name).is_none() {
369 local.insert(name.clone(), Value::Func {
370 name: name.clone(),
371 equations: equations.clone(),
372 env: env.clone(),
373 });
374 }
375
376 for eq in &equations {
380 if self.try_bind_pattern(&eq.pats[0], &arg, &mut local) {
381 break;
382 }
383 }
384
385 let remaining: Vec<Equation> = equations.iter().map(|eq| {
387 Equation {
388 pats: eq.pats[1..].to_vec(),
389 body: eq.body.clone(),
390 span: eq.span,
391 }
392 }).collect();
393
394 return Ok(Value::Func {
395 name: name.clone(),
396 equations: remaining,
397 env: local,
398 });
399 }
400
401 for eq in &equations {
403 if eq.pats.is_empty() {
404 continue;
405 }
406 let mut local = env.child();
407 if env.lookup(&name).is_none() {
410 local.insert(name.clone(), Value::Func {
411 name: name.clone(),
412 equations: equations.clone(),
413 env: env.clone(),
414 });
415 }
416
417 if self.try_bind_pattern(&eq.pats[0], &arg, &mut local) {
418 if eq.pats.len() == 1 {
419 return self.eval(&local, &eq.body);
420 } else {
421 let remaining: Vec<Equation> = vec![Equation {
422 pats: eq.pats[1..].to_vec(),
423 body: eq.body.clone(),
424 span: eq.span,
425 }];
426 return Ok(Value::Func {
427 name: name.clone(),
428 equations: remaining,
429 env: local,
430 });
431 }
432 }
433 }
434 Err(err(format!("No matching pattern in function '{}' for argument {}", name, arg)))
435 }
436
437 Value::Builtin(name, arity) => {
438 if arity == 1 {
439 self.call_builtin(&name, &[arg])
440 } else {
441 Ok(Value::PartialBuiltin(name, arity - 1, vec![arg]))
442 }
443 }
444
445 Value::PartialBuiltin(name, remaining, mut args) => {
446 args.push(arg);
447 if remaining == 1 {
448 self.call_builtin(&name, &args)
449 } else {
450 Ok(Value::PartialBuiltin(name, remaining - 1, args))
451 }
452 }
453
454 other => Err(err(format!("Cannot apply non-function: {}", other))),
455 }
456 }
457
458 fn bind_pattern(&self, pat: &Pat, val: &Value, env: &mut Env) -> EResult<()> {
461 if !self.try_bind_pattern(pat, val, env) {
462 Err(err(format!("Pattern match failed: {:?} vs {}", pat, val)))
463 } else {
464 Ok(())
465 }
466 }
467
468 fn try_bind_pattern(&self, pat: &Pat, val: &Value, env: &mut Env) -> bool {
469 match (pat, val) {
470 (Pat::Wildcard, _) => true,
471
472 (Pat::Var(name), _) => {
473 env.insert(name.clone(), val.clone());
474 true
475 }
476
477 (Pat::Lit(lit), val) => {
478 &self.eval_lit(lit) == val
479 }
480
481 (Pat::Con(pname, ppats), Value::Con(vname, vfields)) => {
482 if pname != vname || ppats.len() != vfields.len() {
483 return false;
484 }
485 ppats.iter().zip(vfields.iter())
486 .all(|(p, v)| self.try_bind_pattern(p, v, env))
487 }
488
489 (Pat::Con(name, pats), Value::List(elems)) if name == "[]" || name == "Nil" => {
491 pats.is_empty() && elems.is_empty()
492 }
493
494 (Pat::Cons(head, tail), Value::List(elems)) => {
496 if elems.is_empty() {
497 return false;
498 }
499 let h = &elems[0];
500 let t = Value::List(elems[1..].to_vec());
501 self.try_bind_pattern(head, h, env)
502 && self.try_bind_pattern(tail, &t, env)
503 }
504
505 (Pat::Paren(inner), val) => self.try_bind_pattern(inner, val, env),
506
507 (Pat::Record(pat_fields), Value::Record(val_fields)) => {
508 for (pname, ppat) in pat_fields {
509 if let Some((_, val)) = val_fields.iter().find(|(n, _)| n == pname) {
510 if !self.try_bind_pattern(ppat, val, env) {
511 return false;
512 }
513 } else {
514 return false;
515 }
516 }
517 true
518 }
519
520 _ => false,
521 }
522 }
523
524 fn eval_list_comp(
527 &mut self,
528 env: &Env,
529 body: &Expr,
530 generators: &[Generator],
531 gen_idx: usize,
532 ) -> EResult<Value> {
533 if gen_idx >= generators.len() {
534 let val = self.eval(env, body)?;
536 return Ok(Value::List(vec![val]));
537 }
538
539 match &generators[gen_idx] {
540 Generator::Bind(name, source_expr) => {
541 let source = self.eval(env, source_expr)?;
542 let list = match source {
543 Value::List(elems) => elems,
544 _ => return Err(err("List comprehension source must be a list")),
545 };
546 let mut result = Vec::new();
547 for item in list {
548 let mut local = env.child();
549 local.insert(name.clone(), item);
550 match self.eval_list_comp(&local, body, generators, gen_idx + 1)? {
551 Value::List(vals) => result.extend(vals),
552 _ => unreachable!(),
553 }
554 }
555 Ok(Value::List(result))
556 }
557 Generator::Guard(guard_expr) => {
558 match self.eval(env, guard_expr)? {
559 Value::Bool(true) => self.eval_list_comp(env, body, generators, gen_idx + 1),
560 Value::Bool(false) => Ok(Value::List(vec![])),
561 _ => Err(err("Guard must be Bool")),
562 }
563 }
564 }
565 }
566
567 fn eval_binop(&self, op: BinOp, l: Value, r: Value) -> EResult<Value> {
570 match op {
571 BinOp::Add => num_op(l, r, |a, b| a + b, |a, b| a + b),
573 BinOp::Sub => num_op(l, r, |a, b| a - b, |a, b| a - b),
574 BinOp::Mul => num_op(l, r, |a, b| a * b, |a, b| a * b),
575 BinOp::Div => {
576 let is_zero = matches!(&r, Value::Int(0))
577 || matches!(&r, Value::Float(f) if *f == 0.0);
578 if is_zero {
579 Err(err("Division by zero"))
580 } else {
581 num_op(l, r, |a, b| a / b, |a, b| a / b)
582 }
583 }
584 BinOp::Mod => {
585 match (&l, &r) {
586 (Value::Int(a), Value::Int(b)) if *b != 0 => Ok(Value::Int(a % b)),
587 (Value::Int(_), Value::Int(0)) => Err(err("Modulo by zero")),
588 _ => Err(err("% requires Int operands")),
589 }
590 }
591 BinOp::Pow => {
592 match (&l, &r) {
593 (Value::Int(a), Value::Int(b)) if *b >= 0 => {
594 let exp = u32::try_from(*b)
595 .map_err(|_| err("Exponent too large"))?;
596 a.checked_pow(exp)
597 .map(Value::Int)
598 .ok_or_else(|| err("Integer overflow in **"))
599 }
600 (Value::Int(_), Value::Int(_)) => Err(err("** requires non-negative exponent for Int")),
601 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a.powf(*b))),
602 (Value::Int(a), Value::Float(b)) => Ok(Value::Float((*a as f64).powf(*b))),
603 (Value::Float(a), Value::Int(b)) => {
604 if let Ok(exp) = i32::try_from(*b) {
605 Ok(Value::Float(a.powi(exp)))
606 } else {
607 Ok(Value::Float(a.powf(*b as f64)))
608 }
609 }
610 _ => Err(err("** requires numeric operands")),
611 }
612 }
613
614 BinOp::Eq => Ok(Value::Bool(l == r)),
616 BinOp::Neq => Ok(Value::Bool(l != r)),
617 BinOp::Lt => cmp_op(l, r, |o| o == std::cmp::Ordering::Less),
618 BinOp::Gt => cmp_op(l, r, |o| o == std::cmp::Ordering::Greater),
619 BinOp::Lte => cmp_op(l, r, |o| o != std::cmp::Ordering::Greater),
620 BinOp::Gte => cmp_op(l, r, |o| o != std::cmp::Ordering::Less),
621
622 BinOp::Concat => {
624 match (l, r) {
625 (Value::List(mut a), Value::List(b)) => { a.extend(b); Ok(Value::List(a)) }
626 (Value::Str(a), Value::Str(b)) => Ok(Value::Str(format!("{}{}", a, b))),
627 _ => Err(err("++ requires two lists or two strings")),
628 }
629 }
630 BinOp::Cons => {
631 match r {
632 Value::List(mut elems) => { elems.insert(0, l); Ok(Value::List(elems)) }
633 _ => Err(err(": requires a list on the right")),
634 }
635 }
636
637 BinOp::Compose => Err(err(">> composition should be desugared by parser")),
638 BinOp::Pipe => Err(err("|> pipe should be handled in eval")),
639 BinOp::And | BinOp::Or => Err(err("&&/|| should be short-circuited in eval")),
640 BinOp::Seq => Err(err("; sequence should be short-circuited in eval")),
641 }
642 }
643
644 fn eval_lit(&self, lit: &Lit) -> Value {
647 match lit {
648 Lit::Int(n) => Value::Int(*n),
649 Lit::Float(n) => Value::Float(*n),
650 Lit::Bool(b) => Value::Bool(*b),
651 Lit::Str(s) => Value::Str(s.clone()),
652 Lit::Char(c) => Value::Char(*c),
653 Lit::Unit => Value::Unit,
654 }
655 }
656
657 fn builtin_env(&self) -> Env {
660 let mut env = Env::new();
661 env.insert("readline".to_string(), Value::Builtin("readline".to_string(), 0));
663 for (name, arity) in &[
664 ("print", 1), ("show", 1), ("show_bool", 1), ("length", 1),
665 ("head", 1), ("tail", 1), ("even", 1), ("odd", 1),
666 ("not", 1), ("sum", 1), ("filter", 2), ("map", 2),
667 ("foldl", 3),
668 ("sqrt", 1), ("floor", 1), ("ceil", 1), ("round", 1), ("abs", 1),
670 ] {
671 env.insert(name.to_string(), Value::Builtin(name.to_string(), *arity));
672 }
673 env.insert("Nil".into(), Value::List(vec![]));
675 env.insert("None".into(), Value::Con("None".into(), vec![]));
676 env
677 }
678
679 fn call_builtin(&mut self, name: &str, args: &[Value]) -> EResult<Value> {
680 match name {
681 "readline" => {
682 use std::io::BufRead;
683 let stdin = std::io::stdin();
684 let mut line = String::new();
685 stdin.lock().read_line(&mut line)
686 .map_err(|e| err(format!("readline error: {}", e)))?;
687 if line.ends_with('\n') { line.pop(); }
689 if line.ends_with('\r') { line.pop(); }
690 Ok(Value::Str(line))
691 }
692 "print" => {
693 let s = format!("{}", args[0]);
694 self.output.push(s);
695 Ok(Value::Unit)
696 }
697 "show" => Ok(Value::Str(format!("{}", args[0]))),
698 "show_bool" => {
699 let b = match &args[0] {
700 Value::Bool(b) => *b,
701 Value::Int(0) => false,
702 _ => true,
703 };
704 Ok(Value::Str(if b { "true".into() } else { "false".into() }))
705 }
706 "length" => match &args[0] {
707 Value::List(l) => Ok(Value::Int(l.len() as i64)),
708 Value::Str(s) => Ok(Value::Int(s.len() as i64)),
709 _ => Err(err("length requires a list or string")),
710 },
711 "head" => match &args[0] {
712 Value::List(l) if !l.is_empty() => Ok(l[0].clone()),
713 Value::List(_) => Err(err("head of empty list")),
714 _ => Err(err("head requires a list")),
715 },
716 "tail" => match &args[0] {
717 Value::List(l) if !l.is_empty() => Ok(Value::List(l[1..].to_vec())),
718 Value::List(_) => Err(err("tail of empty list")),
719 _ => Err(err("tail requires a list")),
720 },
721 "even" => match &args[0] {
722 Value::Int(n) => Ok(Value::Bool(n % 2 == 0)),
723 _ => Err(err("even requires Int")),
724 },
725 "odd" => match &args[0] {
726 Value::Int(n) => Ok(Value::Bool(n % 2 != 0)),
727 _ => Err(err("odd requires Int")),
728 },
729 "not" => match &args[0] {
730 Value::Bool(b) => Ok(Value::Bool(!b)),
731 _ => Err(err("not requires Bool")),
732 },
733 "sum" => match &args[0] {
734 Value::List(l) => {
735 let mut total = 0i64;
736 for v in l {
737 match v {
738 Value::Int(n) => total += n,
739 _ => return Err(err("sum requires a list of Int")),
740 }
741 }
742 Ok(Value::Int(total))
743 }
744 _ => Err(err("sum requires a list")),
745 },
746 "filter" => {
747 let func = &args[0];
748 match &args[1] {
749 Value::List(elems) => {
750 let mut result = Vec::new();
751 for e in elems {
752 let r = self.apply(func.clone(), e.clone())?;
753 if r == Value::Bool(true) {
754 result.push(e.clone());
755 }
756 }
757 Ok(Value::List(result))
758 }
759 _ => Err(err("filter requires a list")),
760 }
761 },
762 "map" => {
763 let func = &args[0];
764 match &args[1] {
765 Value::List(elems) => {
766 let mut result = Vec::new();
767 for e in elems {
768 result.push(self.apply(func.clone(), e.clone())?);
769 }
770 Ok(Value::List(result))
771 }
772 _ => Err(err("map requires a list")),
773 }
774 },
775 "foldl" => {
776 let func = &args[0];
777 let acc = &args[1];
778 match &args[2] {
779 Value::List(elems) => {
780 let mut current = acc.clone();
781 for e in elems {
782 let partial = self.apply(func.clone(), current)?;
783 current = self.apply(partial, e.clone())?;
784 }
785 Ok(current)
786 }
787 _ => Err(err("foldl requires a list")),
788 }
789 },
790 "compose#" => {
791 let fx = self.apply(args[0].clone(), args[2].clone())?;
793 self.apply(args[1].clone(), fx)
794 }
795 "sqrt" => match &args[0] {
796 Value::Float(f) => Ok(Value::Float(f.sqrt())),
797 Value::Int(n) => Ok(Value::Float((*n as f64).sqrt())),
798 _ => Err(err("sqrt requires Float")),
799 },
800 "floor" => match &args[0] {
801 Value::Float(f) => Ok(Value::Float(f.floor())),
802 _ => Err(err("floor requires Float")),
803 },
804 "ceil" => match &args[0] {
805 Value::Float(f) => Ok(Value::Float(f.ceil())),
806 _ => Err(err("ceil requires Float")),
807 },
808 "round" => match &args[0] {
809 Value::Float(f) => Ok(Value::Float(f.round())),
810 _ => Err(err("round requires Float")),
811 },
812 "abs" => match &args[0] {
813 Value::Int(n) => Ok(Value::Int(n.abs())),
814 Value::Float(f) => Ok(Value::Float(f.abs())),
815 _ => Err(err("abs requires Int or Float")),
816 },
817 name if name.starts_with("ctor:") => {
818 let ctor_name = &name[5..];
819 Ok(Value::Con(ctor_name.to_string(), args.to_vec()))
820 },
821 _ => Err(err(format!("Unknown builtin: {}", name))),
822 }
823 }
824}
825
826fn num_op(l: Value, r: Value, int_op: fn(i64, i64) -> i64, float_op: fn(f64, f64) -> f64) -> EResult<Value> {
829 match (l, r) {
830 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(int_op(a, b))),
831 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(float_op(a, b))),
832 (Value::Int(a), Value::Float(b)) => Ok(Value::Float(float_op(a as f64, b))),
833 (Value::Float(a), Value::Int(b)) => Ok(Value::Float(float_op(a, b as f64))),
834 _ => Err(err("Arithmetic requires numbers")),
835 }
836}
837
838fn cmp_op(l: Value, r: Value, pred: fn(std::cmp::Ordering) -> bool) -> EResult<Value> {
839 l.partial_cmp(&r)
840 .map(|o| Value::Bool(pred(o)))
841 .ok_or_else(|| err("Cannot compare these values"))
842}