sim_lib_binding/
let_form.rs1use std::sync::Arc;
16
17use sim_kernel::{
18 Args, Callable, ClassRef, Cx, Env, Error, Expr, Object, ObjectCompat, RawArgs, Result, Symbol,
19 Value,
20};
21
22#[derive(Clone, Copy)]
24pub struct LetForm;
25
26impl LetForm {
27 pub fn symbol() -> Symbol {
29 Symbol::new("let")
30 }
31}
32
33fn parse_clause(clause: Expr) -> Result<(Symbol, Expr)> {
39 let bad = || Error::Eval("let binding must be (name init)".to_owned());
40 match clause {
41 Expr::Call { operator, args } => {
42 let Expr::Symbol(name) = *operator else {
43 return Err(bad());
44 };
45 let mut args = args.into_iter();
46 let (Some(init), None) = (args.next(), args.next()) else {
47 return Err(bad());
48 };
49 Ok((name, init))
50 }
51 Expr::List(items) | Expr::Vector(items) => {
52 let mut items = items.into_iter();
53 match (items.next(), items.next(), items.next()) {
54 (Some(Expr::Symbol(name)), Some(init), None) => Ok((name, init)),
55 _ => Err(bad()),
56 }
57 }
58 _ => Err(bad()),
59 }
60}
61
62fn parse_bindings(bindings: Expr) -> Result<Vec<(Symbol, Expr)>> {
64 let clauses = match bindings {
65 Expr::List(items) | Expr::Vector(items) => items,
66 Expr::Nil => Vec::new(),
67 _ => return Err(Error::Eval("let bindings must be a list".to_owned())),
68 };
69 clauses.into_iter().map(parse_clause).collect()
70}
71
72impl Object for LetForm {
73 fn display(&self, _cx: &mut Cx) -> Result<String> {
74 Ok("#<special-form let>".to_owned())
75 }
76
77 fn as_any(&self) -> &dyn std::any::Any {
78 self
79 }
80}
81
82impl ObjectCompat for LetForm {
83 fn class(&self, cx: &mut Cx) -> Result<ClassRef> {
84 cx.resolve_class(&Symbol::qualified("core", "Function"))
85 }
86
87 fn as_callable(&self) -> Option<&dyn Callable> {
88 Some(self)
89 }
90}
91
92impl Callable for LetForm {
93 fn call(&self, _cx: &mut Cx, _args: Args) -> Result<Value> {
97 Err(Error::Eval(
98 "let is a special form and cannot be applied to evaluated arguments".to_owned(),
99 ))
100 }
101
102 fn call_exprs(&self, cx: &mut Cx, args: RawArgs) -> Result<Value> {
103 let mut exprs = args.into_exprs().into_iter();
104 let Some(bindings) = exprs.next() else {
105 return Err(Error::Eval(
106 "let expects (let (bindings...) body...)".to_owned(),
107 ));
108 };
109 let body: Vec<Expr> = exprs.collect();
110
111 let clauses = parse_bindings(bindings)?;
113 let mut bound = Vec::with_capacity(clauses.len());
114 for (name, init) in clauses {
115 let value = cx.eval_expr(init)?;
116 bound.push((name, value));
117 }
118
119 let child = Env::child(Arc::new(cx.env().clone()));
121 cx.with_env(child, |cx| {
122 for (name, value) in bound {
123 cx.env_mut().define(name, value);
124 }
125 let mut last = cx.factory().nil()?;
126 for expr in body {
127 last = cx.eval_expr(expr)?;
128 }
129 Ok(last)
130 })
131 }
132}