1use crate::builtins::form::{form_to_value, resolve_auto_forms};
4use cljrs_reader::Form;
5use cljrs_reader::form::FormKind;
6use cljrs_types::span::Span;
7use cljrs_value::{Symbol, Value};
8use std::sync::Arc;
9
10use crate::env::env::Env;
11use crate::env::error::{EvalError, EvalResult};
12
13pub fn macroexpand_1(form: &Form, env: &mut Env) -> EvalResult<Form> {
15 if let FormKind::List(parts) = &form.kind
17 && let Some(FormKind::Symbol(s)) = parts.first().map(|f| &f.kind)
18 && let Some(macro_fn) = resolve_macro(s, env)
19 {
20 let resolved = resolve_auto_forms(form, env)?;
25 let parts = if let FormKind::List(p) = &resolved.kind {
26 p
27 } else {
28 unreachable!()
29 };
30
31 let form_val = form_to_value(&resolved)?;
33 let env_val = {
35 let (names, vals) = env.all_local_bindings();
36 let mut m = cljrs_value::MapValue::empty();
37 for (name, val) in names.iter().zip(vals.iter()) {
38 m = m.assoc(Value::symbol(Symbol::simple(name.as_ref())), val.clone());
39 }
40 Value::Map(m)
41 };
42 let mut args = vec![form_val, env_val];
43 for p in &parts[1..] {
44 args.push(form_to_value(p)?);
45 }
46 let expanded = crate::interp::apply::call_cljrs_fn(¯o_fn, &args, env)?;
47 let dummy = Span::new(Arc::new("<macro>".to_string()), 0, 0, 1, 1);
48 return value_to_form(&expanded, dummy);
49 }
50 Ok(form.clone())
51}
52
53pub fn macroexpand(form: &Form, env: &mut Env) -> EvalResult<Form> {
55 let mut current = form.clone();
56 loop {
57 let is_macro_call = matches!(
62 ¤t.kind,
63 FormKind::List(parts)
64 if matches!(parts.first().map(|f| &f.kind), Some(FormKind::Symbol(s)) if resolve_macro(s, env).is_some())
65 );
66 if !is_macro_call {
67 return Ok(current);
68 }
69
70 let expanded = macroexpand_1(¤t, env)?;
71 if expanded == current {
72 return Ok(current);
73 }
74 current = expanded;
75 }
76}
77
78pub fn macroexpand_all(form: &Form, env: &mut Env) -> EvalResult<Form> {
83 let expanded = macroexpand(form, env)?;
85
86 let span = expanded.span.clone();
87 let kind = match &expanded.kind {
88 FormKind::List(parts) if !parts.is_empty() => {
89 let head_name = match &parts[0].kind {
91 FormKind::Symbol(s) => Some(s.as_str()),
92 _ => None,
93 };
94 match head_name {
95 Some("quote") => return Ok(expanded),
97 Some("fn*") => {
99 let mut new_parts = vec![parts[0].clone()];
100 if parts.len() > 1 {
103 if let FormKind::Vector(_) = &parts[1].kind {
104 new_parts.push(parts[1].clone()); for p in &parts[2..] {
107 new_parts.push(macroexpand_all(p, env)?);
108 }
109 } else {
110 for arity in &parts[1..] {
112 if let FormKind::List(arity_parts) = &arity.kind {
113 let mut new_arity = Vec::new();
114 if let Some(params) = arity_parts.first() {
115 new_arity.push(params.clone()); }
117 for p in arity_parts.iter().skip(1) {
118 new_arity.push(macroexpand_all(p, env)?);
119 }
120 new_parts.push(Form::new(
121 FormKind::List(new_arity),
122 arity.span.clone(),
123 ));
124 } else {
125 new_parts.push(arity.clone());
127 }
128 }
129 }
130 }
131 FormKind::List(new_parts)
132 }
133 Some("let*") | Some("loop*") => {
135 let mut new_parts = vec![parts[0].clone()];
136 if parts.len() > 1 {
137 if let FormKind::Vector(bindings) = &parts[1].kind {
139 let mut new_bindings = Vec::new();
140 for (i, b) in bindings.iter().enumerate() {
141 if i % 2 == 0 {
142 new_bindings.push(b.clone()); } else {
144 new_bindings.push(macroexpand_all(b, env)?);
145 }
146 }
147 new_parts.push(Form::new(
148 FormKind::Vector(new_bindings),
149 parts[1].span.clone(),
150 ));
151 } else {
152 new_parts.push(parts[1].clone());
153 }
154 for p in &parts[2..] {
155 new_parts.push(macroexpand_all(p, env)?);
156 }
157 }
158 FormKind::List(new_parts)
159 }
160 _ => {
162 let new_parts = parts
164 .iter()
165 .map(|p| macroexpand_all(p, env))
166 .collect::<EvalResult<Vec<_>>>()?;
167 FormKind::List(new_parts)
168 }
169 }
170 }
171 FormKind::Vector(items) => {
172 let new_items = items
173 .iter()
174 .map(|i| macroexpand_all(i, env))
175 .collect::<EvalResult<Vec<_>>>()?;
176 FormKind::Vector(new_items)
177 }
178 FormKind::Map(items) => {
179 let new_items = items
180 .iter()
181 .map(|i| macroexpand_all(i, env))
182 .collect::<EvalResult<Vec<_>>>()?;
183 FormKind::Map(new_items)
184 }
185 FormKind::Set(items) => {
186 let new_items = items
187 .iter()
188 .map(|i| macroexpand_all(i, env))
189 .collect::<EvalResult<Vec<_>>>()?;
190 FormKind::Set(new_items)
191 }
192 _ => return Ok(expanded),
194 };
195 Ok(Form::new(kind, span))
196}
197
198fn resolve_macro(sym: &str, env: &Env) -> Option<cljrs_value::CljxFn> {
200 let parsed = Symbol::parse(sym);
201 let ns: Arc<str> = match parsed.namespace.as_deref() {
205 Some(ns_part) => env
206 .globals
207 .resolve_alias(&env.current_ns, ns_part)
208 .unwrap_or_else(|| Arc::from(ns_part)),
209 None => env.current_ns.clone(),
210 };
211 let name = parsed.name.as_ref();
212
213 let v = env.globals.lookup_in_ns(&ns, name)?;
214 if let Value::Macro(f) = v {
215 Some(f.get().clone())
216 } else {
217 None
218 }
219}
220
221pub fn value_to_form(val: &Value, span: Span) -> EvalResult<Form> {
225 let kind = match val {
226 Value::Nil => FormKind::Nil,
227 Value::Bool(b) => FormKind::Bool(*b),
228 Value::Long(n) => FormKind::Int(*n),
229 Value::Double(f) => FormKind::Float(*f),
230 Value::Str(s) => FormKind::Str(s.get().clone()),
231 Value::Char(c) => FormKind::Char(*c),
232 Value::BigInt(b) => FormKind::BigInt(b.get().to_string()),
233 Value::BigDecimal(d) => FormKind::BigDecimal(d.get().to_string()),
234 Value::Ratio(r) => FormKind::Ratio(format!("{}/{}", r.get().numer(), r.get().denom())),
235
236 Value::Symbol(s) => FormKind::Symbol(s.get().full_name()),
237 Value::Keyword(k) => FormKind::Keyword(k.get().full_name()),
238
239 Value::List(l) => {
240 let items = l.get();
241 let head_sym = items.iter().next().and_then(|v| {
243 if let Value::Symbol(s) = v {
244 Some(s.get().name.clone())
245 } else {
246 None
247 }
248 });
249 match (head_sym.as_deref(), items.count()) {
250 (Some("syntax-quote"), 2) => {
251 let inner = value_to_form(items.iter().nth(1).unwrap(), span.clone())?;
252 FormKind::SyntaxQuote(Box::new(inner))
253 }
254 (Some("unquote"), 2) => {
255 let inner = value_to_form(items.iter().nth(1).unwrap(), span.clone())?;
256 FormKind::Unquote(Box::new(inner))
257 }
258 (Some("unquote-splicing"), 2) => {
259 let inner = value_to_form(items.iter().nth(1).unwrap(), span.clone())?;
260 FormKind::UnquoteSplice(Box::new(inner))
261 }
262 _ => {
263 let forms: Vec<Form> = items
264 .iter()
265 .map(|v| value_to_form(v, span.clone()))
266 .collect::<EvalResult<_>>()?;
267 FormKind::List(forms)
268 }
269 }
270 }
271 Value::Vector(v) => {
272 let forms: Vec<Form> = v
273 .get()
274 .iter()
275 .map(|v| value_to_form(v, span.clone()))
276 .collect::<EvalResult<_>>()?;
277 FormKind::Vector(forms)
278 }
279 Value::Map(m) => {
280 let mut forms = Vec::new();
281 let mut err: Option<EvalError> = None;
282 let sc = span.clone();
283 m.for_each(|k, v| {
284 if err.is_none() {
285 match (value_to_form(k, sc.clone()), value_to_form(v, sc.clone())) {
286 (Ok(kf), Ok(vf)) => {
287 forms.push(kf);
288 forms.push(vf);
289 }
290 (Err(e), _) | (_, Err(e)) => err = Some(e),
291 }
292 }
293 });
294 if let Some(e) = err {
295 return Err(e);
296 }
297 FormKind::Map(forms)
298 }
299 Value::Set(s) => {
300 let forms: Vec<Form> = s
301 .iter()
302 .map(|v| value_to_form(v, span.clone()))
303 .collect::<EvalResult<_>>()?;
304 FormKind::Set(forms)
305 }
306
307 Value::LazySeq(ls) => {
310 return value_to_form(&ls.get().realize(), span);
311 }
312 Value::Cons(c) => {
313 let mut items: Vec<Form> = Vec::new();
314 let mut cur = Value::Cons(c.clone());
315 loop {
316 match cur {
317 Value::Cons(cell) => {
318 items.push(value_to_form(&cell.get().head, span.clone())?);
319 cur = cell.get().tail.clone();
320 }
321 Value::LazySeq(ls) => cur = ls.get().realize(),
322 Value::List(l) => {
323 for v in l.get().iter() {
324 items.push(value_to_form(v, span.clone())?);
325 }
326 break;
327 }
328 Value::Nil => break,
329 _ => break,
330 }
331 }
332 FormKind::List(items)
333 }
334
335 Value::Uuid(u) => {
336 let uuid_str = uuid::Uuid::from_u128(*u).to_string();
337 FormKind::TaggedLiteral(
338 "uuid".to_string(),
339 Box::new(Form::new(FormKind::Str(uuid_str), span.clone())),
340 )
341 }
342
343 Value::WithMeta(inner, _) => {
345 return value_to_form(inner, span);
346 }
347
348 Value::Pattern(p) => FormKind::Regex(p.get().as_str().to_string()),
349
350 other => FormKind::Symbol(format!("#<{}>", other.type_name())),
352 };
353 Ok(Form::new(kind, span))
354}