1use crate::{
4 error::ErrorKind,
5 interpret::{Match, MatchEnv},
6};
7
8use super::{Callable, ConValue, Environment, Error, IResult, Interpret};
9use cl_ast::{At, Bind, BindOp, Expr, Op, Pat, PatOp, types::Symbol as Sym};
10use cl_structures::{intern::interned::Interned, span::Span};
11use std::{
12 cell::{Ref, RefCell},
13 collections::HashMap,
14 rc::Rc,
15};
16
17type Upvars = HashMap<Sym, ConValue>;
18
19#[derive(Clone, Debug)]
21pub struct Function {
22 decl: Rc<(At<Pat>, At<Expr>)>,
24 upvars: RefCell<Upvars>,
26}
27
28impl Function {
29 pub fn new(decl: &Bind) -> Self {
30 if let Bind(BindOp::Fn, _, pat, exprs) = decl
32 && let [body] = exprs.as_slice()
33 {
34 Self { decl: (pat.clone(), body.clone()).into(), upvars: Default::default() }
35 } else {
36 unimplemented!()
37 }
38 }
39 pub fn decl(&self) -> &(At<Pat>, At<Expr>) {
40 &self.decl
41 }
42 pub fn span(&self) -> Span {
43 self.decl.1.1
44 }
45 pub fn upvars(&self) -> Ref<'_, Upvars> {
46 self.upvars.borrow()
47 }
48 pub fn lift_upvars(&self, env: &Environment) {
49 let upvars = Default::default();
51 if let Ok(mut self_upvars) = self.upvars.try_borrow_mut() {
52 *self_upvars = upvars;
53 }
54 }
55}
56
57impl Callable for Function {
58 fn name(&self) -> Option<Sym> {
59 fn get_name(pat: &Pat) -> Option<Sym> {
60 match pat {
61 Pat::Name(name) => Some(*name),
62 Pat::Op(PatOp::Tuple | PatOp::Slice | PatOp::Fn, _) => None,
63 Pat::Op(_op, pats) => pats.iter().find_map(|At(pat, ..)| get_name(pat)),
64 _ => None,
65 }
66 }
67 get_name(self.decl.0.value())
68 }
69 fn call(&self, env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
70 let args = ConValue::Tuple(args.into());
71 let (pat, body) = self.decl();
72
73 let mut bindings = HashMap::new();
74 pat.matches(args, &mut MatchEnv::new(env, &mut bindings))?;
75
76 let mut scope = env.with_frame("args", bindings);
77 let mut scope = scope.frame(
78 self.name().map(|name| name.to_ref()).unwrap_or("closure"),
79 Some(self.span()),
80 );
81 match body.interpret(&mut scope) {
82 Err(Error { kind: ErrorKind::Panic(e, depth), span }) => {
83 println!("{depth:>4}: {pat} at {}", span.unwrap_or(self.span()));
84 Err(Error { kind: ErrorKind::Panic(e, depth + 1), span: None })
85 }
86 Err(Error { kind: ErrorKind::Return(value), .. }) => Ok(value),
87 other => other,
88 }
89 }
90}
91
92impl std::fmt::Display for Function {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 let (pat, At(expr, ..)) = self.decl();
95 write!(f, "fn {pat}")?;
96 match expr {
97 Expr::Op(Op::Block, ..) => write!(f, " {expr}"),
98 _ => write!(f, " = {expr}"),
99 }
100 }
101}