cljrs_interp/
destructure.rs1use cljrs_builtins::form::form_to_value;
4use cljrs_gc::GcPtr;
5use cljrs_reader::Form;
6use cljrs_reader::form::FormKind;
7use cljrs_value::{Keyword, PersistentList, PersistentVector, Symbol, Value};
8use std::sync::Arc;
9
10use cljrs_env::env::Env;
11use cljrs_env::error::{EvalError, EvalResult};
12
13pub fn bind_pattern(pattern: &Form, val: Value, env: &mut Env) -> EvalResult<()> {
19 match &pattern.kind {
20 FormKind::Symbol(s) => {
21 env.bind(Arc::from(s.as_str()), val);
23 Ok(())
24 }
25 FormKind::Vector(forms) => bind_sequential(forms, &val, env),
26 FormKind::Map(forms) => bind_associative(forms, &val, env),
27 _ => Err(EvalError::Runtime(format!(
28 "unsupported binding pattern: {:?}",
29 pattern.kind
30 ))),
31 }
32}
33
34pub fn bind_sequential(pattern: &[Form], val: &Value, env: &mut Env) -> EvalResult<()> {
41 let items = value_to_seq_vec(val);
42 let mut idx = 0usize;
43 let mut i = 0usize;
44
45 while i < pattern.len() {
46 let p = &pattern[i];
47
48 if matches!(&p.kind, FormKind::Symbol(s) if s == "&") {
50 i += 1;
51 let rest_pat = pattern
52 .get(i)
53 .ok_or_else(|| EvalError::Runtime("& in destructuring requires a name".into()))?;
54 let rest_list = if idx < items.len() {
55 let rest_vals: Vec<Value> = items[idx..].to_vec();
56 Value::List(GcPtr::new(PersistentList::from_iter(rest_vals)))
57 } else {
58 Value::Nil
59 };
60 bind_pattern(rest_pat, rest_list, env)?;
61 i += 1;
62 if i < pattern.len()
64 && let FormKind::Keyword(k) = &pattern[i].kind
65 && k == "as"
66 {
67 i += 1;
68 let alias = pattern
69 .get(i)
70 .ok_or_else(|| EvalError::Runtime(":as requires a name".into()))?;
71 bind_pattern(alias, val.clone(), env)?;
72 }
73 break;
74 }
75
76 if let FormKind::Keyword(k) = &p.kind
78 && k == "as"
79 {
80 i += 1;
81 let alias = pattern
82 .get(i)
83 .ok_or_else(|| EvalError::Runtime(":as requires a name".into()))?;
84 bind_pattern(alias, val.clone(), env)?;
85 break;
86 }
87
88 let item = items.get(idx).cloned().unwrap_or(Value::Nil);
90 bind_pattern(p, item, env)?;
91 idx += 1;
92 i += 1;
93 }
94
95 Ok(())
96}
97
98pub fn value_to_seq_vec(val: &Value) -> Vec<Value> {
100 match val {
101 Value::WithMeta(inner, _) => value_to_seq_vec(inner),
102 Value::Nil => vec![],
103 Value::LazySeq(ls) => value_to_seq_vec(&ls.get().realize()),
104 Value::Cons(c) => {
105 let mut result = vec![c.get().head.clone()];
106 let mut tail = c.get().tail.clone();
107 loop {
108 match tail {
109 Value::Nil => break,
110 Value::List(l) => {
111 result.extend(l.get().iter().cloned());
112 break;
113 }
114 Value::Cons(next_c) => {
115 result.push(next_c.get().head.clone());
116 tail = next_c.get().tail.clone();
117 }
118 Value::LazySeq(ls) => {
119 tail = ls.get().realize();
120 }
121 _ => break,
122 }
123 }
124 result
125 }
126 Value::List(l) => l.get().iter().cloned().collect(),
127 Value::Vector(v) => v.get().iter().cloned().collect(),
128 Value::Set(s) => s.iter().cloned().collect(),
129 Value::Map(m) => {
130 let mut result = Vec::new();
131 m.for_each(|k, v| {
132 result.push(Value::Vector(GcPtr::new(PersistentVector::from_iter([
133 k.clone(),
134 v.clone(),
135 ]))));
136 });
137 result
138 }
139 _ => vec![],
140 }
141}
142
143pub fn bind_associative(pattern: &[Form], val: &Value, env: &mut Env) -> EvalResult<()> {
157 let mut defaults: std::collections::HashMap<String, Value> = std::collections::HashMap::new();
159 let mut i = 0;
160 while i + 1 < pattern.len() {
161 let k = &pattern[i];
162 let v = &pattern[i + 1];
163 if let FormKind::Keyword(kw) = &k.kind
164 && kw == "or"
165 {
166 if let FormKind::Map(or_forms) = &v.kind {
168 let mut j = 0;
169 while j + 1 < or_forms.len() {
170 if let FormKind::Symbol(sym) = &or_forms[j].kind {
171 defaults.insert(sym.clone(), form_to_value(&or_forms[j + 1]));
172 }
173 j += 2;
174 }
175 }
176 }
177 i += 2;
178 }
179
180 let get_val = |key: &Value| -> Value {
181 match val.unwrap_meta() {
182 Value::Map(m) => m.get(key).unwrap_or(Value::Nil),
183 _ => Value::Nil,
184 }
185 };
186
187 let mut i = 0;
188 while i + 1 < pattern.len() {
189 let k = &pattern[i];
190 let v = &pattern[i + 1];
191 i += 2;
192
193 match &k.kind {
194 FormKind::Keyword(kw) if kw == "keys" => {
195 if let FormKind::Vector(syms) = &v.kind {
196 for sym_form in syms {
197 if let FormKind::Symbol(sym) = &sym_form.kind {
198 let key = Value::keyword(Keyword::simple(sym.as_str()));
199 let mut bound_val = get_val(&key);
200 if matches!(bound_val, Value::Nil)
201 && let Some(d) = defaults.get(sym.as_str())
202 {
203 bound_val = d.clone();
204 }
205 env.bind(Arc::from(sym.as_str()), bound_val);
206 }
207 }
208 }
209 }
210 FormKind::Keyword(kw) if kw == "strs" => {
211 if let FormKind::Vector(syms) = &v.kind {
212 for sym_form in syms {
213 if let FormKind::Symbol(sym) = &sym_form.kind {
214 let key = Value::string(sym.clone());
215 let mut bound_val = get_val(&key);
216 if matches!(bound_val, Value::Nil)
217 && let Some(d) = defaults.get(sym.as_str())
218 {
219 bound_val = d.clone();
220 }
221 env.bind(Arc::from(sym.as_str()), bound_val);
222 }
223 }
224 }
225 }
226 FormKind::Keyword(kw) if kw == "syms" => {
227 if let FormKind::Vector(syms) = &v.kind {
228 for sym_form in syms {
229 if let FormKind::Symbol(sym) = &sym_form.kind {
230 let key = Value::symbol(Symbol::simple(sym.as_str()));
231 let mut bound_val = get_val(&key);
232 if matches!(bound_val, Value::Nil)
233 && let Some(d) = defaults.get(sym.as_str())
234 {
235 bound_val = d.clone();
236 }
237 env.bind(Arc::from(sym.as_str()), bound_val);
238 }
239 }
240 }
241 }
242 FormKind::Keyword(kw) if kw == "as" => {
243 if let FormKind::Symbol(sym) = &v.kind {
244 env.bind(Arc::from(sym.as_str()), val.clone());
245 }
246 }
247 FormKind::Keyword(kw) if kw == "or" => {
248 }
250 _ => {
251 let lookup_key = form_to_value(v);
255 let mut bound_val = get_val(&lookup_key);
256 if matches!(bound_val, Value::Nil)
258 && let FormKind::Symbol(sym) = &k.kind
259 && let Some(d) = defaults.get(sym.as_str())
260 {
261 bound_val = d.clone();
262 }
263 bind_pattern(k, bound_val, env)?;
265 }
266 }
267 }
268 Ok(())
269}