1use std::collections::{HashMap, HashSet};
4use std::sync::Arc;
5
6use crate::builtins::form::{
7 expand_pairs, expand_reader_conds, expand_reader_conds_cow, form_to_value, resolve_auto_forms,
8 select_reader_cond,
9};
10use crate::env::env::{Env, RequireRefer, RequireSpec};
11use crate::env::error::{EvalError, EvalResult};
12use crate::env::loader::load_ns;
13use crate::interp::destructure::bind_pattern;
14use crate::interp::eval::{eval, eval_body, is_special_form};
15use cljrs_gc::GcPtr;
16use cljrs_reader::Form;
17use cljrs_reader::form::FormKind;
18use cljrs_value::error::ExceptionInfo;
19use cljrs_value::{
20 CljxFn, CljxFnArity, CljxFuture, FutureState, Keyword, MapValue, Protocol, ProtocolMethod,
21 ReferClojureFilter, TypeHint, Value, ValueError,
22};
23
24pub fn eval_special(head: &str, args: &[Form], env: &mut Env) -> EvalResult {
26 crate::env::policy::check_special(head)?;
27 match head {
28 "def" => eval_def(args, env),
29 "fn*" | "fn" => eval_fn(args, env),
30 "if" => eval_if(args, env),
31 "do" => eval_body(args, env),
32 "let*" | "let" => eval_let(args, env),
33 "loop*" | "loop" => eval_loop(args, env),
34 "recur" => eval_recur(args, env),
35 "quote" => eval_quote(args, env),
36 "var" => eval_var(args, env),
37 "set!" => eval_set_bang(args, env),
38 "throw" => eval_throw(args, env),
39 "try" => eval_try(args, env),
40 "defn" => eval_defn(args, env, false),
41 "defn-" => eval_defn(args, env, true),
42 "defmacro" => eval_defmacro(args, env),
43 "defonce" => eval_defonce(args, env),
44 "and" => eval_and(args, env),
45 "or" => eval_or(args, env),
46 "." => Err(EvalError::Runtime("interop not yet implemented".into())),
47 "ns" => eval_ns(args, env),
48 "require" => eval_require(args, env),
49 "letfn" => eval_letfn(args, env),
50 "in-ns" => eval_in_ns(args, env),
51 "alias" => eval_alias(args, env),
52 "protocol*" => eval_protocol_star(args, env),
53 "deftype*" => eval_deftype_star(args, env),
54 "load-file" => eval_load_file(args, env),
55 "binding" => eval_binding(args, env),
56 "with-out-str" => eval_with_out_str(args, env),
57 "await" => eval_await(args, env),
58 _ => unreachable!("unknown special form: {head}"),
59 }
60}
61
62fn eval_def(args: &[Form], env: &mut Env) -> EvalResult {
65 let target = parse_def(args, env)?;
66 let val = match target.value_form {
67 Some(form) => {
68 #[cfg(feature = "no-gc")]
71 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
72 eval(form, env)?
73 }
74 None => Value::Nil,
75 };
76 intern_def(target, val, env)
77}
78
79pub struct DefTarget<'a> {
85 pub name: String,
86 pub meta: Option<Value>,
88 pub value_form: Option<&'a Form>,
90}
91
92pub fn parse_def<'a>(args: &'a [Form], env: &mut Env) -> EvalResult<DefTarget<'a>> {
95 if args.is_empty() {
96 return Err(EvalError::Runtime("def requires a name".into()));
97 }
98 let (name, meta_opt) = extract_def_name(&args[0], env)?;
99 let (docstring, val_idx) = if args.len() > 2
101 && let FormKind::Str(s) = &args[1].kind
102 {
103 (Some(s.clone()), 2)
104 } else {
105 (None, 1)
106 };
107 Ok(DefTarget {
108 name,
109 meta: merge_meta(meta_opt, docstring.as_deref().map(doc_meta)),
110 value_form: args.get(val_idx),
111 })
112}
113
114pub fn intern_def(target: DefTarget<'_>, val: Value, env: &mut Env) -> EvalResult {
116 let var = env
117 .globals
118 .intern(&env.current_ns, Arc::from(target.name.as_str()), val);
119 if let Some(meta_val) = target.meta {
120 var.get().set_meta(meta_val);
121 }
122 Ok(Value::Var(var))
123}
124
125pub fn defonce_existing(name: &str, env: &Env) -> Option<Value> {
128 env.globals
129 .lookup_var(&env.current_ns, name)
130 .filter(|var| var.get().is_bound())
131 .map(Value::Var)
132}
133
134fn doc_meta(doc: &str) -> Value {
136 Value::Map(MapValue::empty().assoc(
137 Value::keyword(Keyword::parse("doc")),
138 Value::string(doc.to_string()),
139 ))
140}
141
142fn private_meta() -> Value {
143 Value::Map(
144 MapValue::empty().assoc(Value::keyword(Keyword::parse("private")), Value::Bool(true)),
145 )
146}
147
148fn arglists_meta(fn_val: &Value, skip: usize) -> Option<Value> {
153 let arities = match fn_val {
154 Value::Fn(f) => &f.get().arities,
155 Value::Macro(f) => &f.get().arities,
156 _ => return None,
157 };
158 let lists: Vec<Value> = arities
159 .iter()
160 .map(|a| {
161 let mut syms: Vec<Value> = a
162 .params
163 .iter()
164 .skip(skip)
165 .map(|p| Value::symbol(cljrs_value::Symbol::simple(p.as_ref())))
166 .collect();
167 if let Some(rest) = &a.rest_param {
168 syms.push(Value::symbol(cljrs_value::Symbol::simple("&")));
169 syms.push(Value::symbol(cljrs_value::Symbol::simple(rest.as_ref())));
170 }
171 Value::Vector(GcPtr::new(cljrs_value::PersistentVector::from_iter(syms)))
172 })
173 .collect();
174 Some(Value::Map(MapValue::empty().assoc(
175 Value::keyword(Keyword::parse("arglists")),
176 Value::Vector(GcPtr::new(cljrs_value::PersistentVector::from_iter(lists))),
177 )))
178}
179
180fn extract_def_name(form: &Form, env: &mut Env) -> EvalResult<(String, Option<Value>)> {
182 match &form.kind {
183 FormKind::Symbol(s) => Ok((s.clone(), None)),
184 FormKind::Meta(meta_form, inner) => {
186 let meta_val = compile_meta_form(meta_form, env)?;
187 let (name, inner_meta) = extract_def_name(inner, env)?;
188 Ok((name, merge_meta(inner_meta, Some(meta_val))))
189 }
190 _ => Err(EvalError::Runtime("def name must be a symbol".into())),
191 }
192}
193
194pub fn compile_meta_form(meta: &Form, env: &mut Env) -> EvalResult<Value> {
201 crate::builtins::form::expand_meta_annotation(meta, &mut |f| eval(f, env))
202}
203
204fn eval_fn(args: &[Form], env: &mut Env) -> EvalResult {
207 let mut is_async = false;
210 let peeled: Vec<Form>;
211 let args: &[Form] = if matches!(args.first().map(|f| &f.kind), Some(FormKind::Meta(..))) {
212 let (metas, head) = args[0].peel_meta();
213 is_async |= metas.iter().any(|m| m.requests_async());
214 peeled = std::iter::once(head.clone())
215 .chain(args[1..].iter().cloned())
216 .collect();
217 &peeled
218 } else {
219 args
220 };
221
222 let mut idx = 0;
223 let mut name: Option<Arc<str>> = None;
224
225 if let Some(FormKind::Symbol(s)) = args.first().map(|f| &f.kind)
227 && !is_special_form(s)
228 {
229 name = Some(Arc::from(s.as_str()));
230 idx = 1;
231 }
232
233 let rest = &args[idx..];
234 if rest.is_empty() {
235 return Err(EvalError::Runtime("fn* requires params and body".into()));
236 }
237
238 let arities = match &rest[0].unmeta().kind {
241 FormKind::Vector(_) => {
242 vec![parse_arity(&rest[0], &rest[1..])?]
244 }
245 FormKind::List(_) => {
246 rest.iter()
248 .map(|arity_form| {
249 if let Some(forms) = arity_form.as_list() {
250 if forms.is_empty() {
251 return Err(EvalError::Runtime("arity clause requires params".into()));
252 }
253 parse_arity(&forms[0], &forms[1..])
254 } else {
255 Err(EvalError::Runtime("expected arity clause (list)".into()))
256 }
257 })
258 .collect::<EvalResult<Vec<_>>>()?
259 }
260 _ => {
261 return Err(EvalError::Runtime(
262 "fn* expects vector or arity clauses".into(),
263 ));
264 }
265 };
266
267 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
269
270 let mut cljrs_fn = CljxFn::new(
271 name.clone(),
272 arities,
273 closed_over_names,
274 closed_over_vals,
275 false,
276 Arc::clone(&env.current_ns),
277 );
278 cljrs_fn.is_async = is_async;
279
280 env.on_fn_defined(&cljrs_fn);
281
282 let mut ptr = GcPtr::new(cljrs_fn);
286 if ptr.get().name.is_some() {
290 let self_clone = ptr.clone();
291 ptr.get_mut().self_ptr = Some(self_clone);
292 }
293 Ok(Value::Fn(ptr))
294}
295
296pub fn parse_arity(params_form: &Form, body: &[Form]) -> EvalResult<CljxFnArity> {
298 let Some(param_forms) = params_form.as_vector() else {
299 return Err(EvalError::Runtime(
300 "fn arity params must be a vector".into(),
301 ));
302 };
303
304 let mut params: Vec<Arc<str>> = Vec::new();
305 let mut param_hints: Vec<Option<TypeHint>> = Vec::new();
306 let mut rest_param: Option<Arc<str>> = None;
307 let mut rest_hint: Option<TypeHint> = None;
308 let mut destructure_params: Vec<(usize, Form)> = Vec::new();
309 let mut destructure_rest: Option<Form> = None;
310 let mut saw_amp = false;
311
312 for p in param_forms {
313 let (hint, p) = peel_param_hint(p);
319 match &p.kind {
320 FormKind::Symbol(s) if s == "&" => {
321 saw_amp = true;
322 }
323 FormKind::Symbol(s) => {
324 if saw_amp {
325 rest_param = Some(Arc::from(s.as_str()));
326 rest_hint = hint;
327 break;
328 } else {
329 params.push(Arc::from(s.as_str()));
330 param_hints.push(hint);
331 }
332 }
333 FormKind::Vector(_) | FormKind::Map(_) => {
335 if saw_amp {
336 let gensym = format!("__destructure_rest_{}", params.len());
337 rest_param = Some(Arc::from(gensym.as_str()));
338 destructure_rest = Some(p.clone());
339 break;
340 } else {
341 let idx = params.len();
342 let gensym = format!("__destructure_{idx}");
343 params.push(Arc::from(gensym.as_str()));
344 param_hints.push(None);
346 destructure_params.push((idx, p.clone()));
347 }
348 }
349 _ => {
350 return Err(EvalError::Runtime(
351 "fn params must be symbols, vectors, or maps".into(),
352 ));
353 }
354 }
355 }
356
357 let body = desugar_pre_post_conditions(body);
358
359 Ok(CljxFnArity {
360 params,
361 rest_param,
362 body,
363 destructure_params,
364 destructure_rest,
365 ir_arity_id: crate::interp::arity::fresh_arity_id(),
366 param_hints,
367 rest_hint,
368 })
369}
370
371fn desugar_pre_post_conditions(body: &[Form]) -> Vec<Form> {
389 let first = match body.first() {
390 Some(f) => f,
391 None => return body.to_vec(),
392 };
393
394 let entries = match first.as_map() {
395 Some(entries) => entries,
396 None => return body.to_vec(),
397 };
398
399 let mut pre_conds: Vec<Form> = Vec::new();
400 let mut post_conds: Vec<Form> = Vec::new();
401 let mut has_conditions = false;
402
403 for chunk in entries.chunks(2) {
404 if chunk.len() < 2 {
405 break;
406 }
407 let (key, val) = (&chunk[0], &chunk[1]);
408 match &key.kind {
409 FormKind::Keyword(k) if k == "pre" => {
410 if let FormKind::Vector(conds) = &val.kind {
411 pre_conds.extend_from_slice(conds);
412 has_conditions = true;
413 }
414 }
415 FormKind::Keyword(k) if k == "post" => {
416 if let FormKind::Vector(conds) = &val.kind {
417 post_conds.extend_from_slice(conds);
418 has_conditions = true;
419 }
420 }
421 _ => {}
422 }
423 }
424
425 if !has_conditions {
426 return body.to_vec();
427 }
428
429 let real_body = &body[1..]; let span = first.span.clone();
431 let mut new_body: Vec<Form> = Vec::new();
432
433 for cond in &pre_conds {
435 new_body.push(make_assert_call(cond, &span));
436 }
437
438 if post_conds.is_empty() {
439 new_body.extend_from_slice(real_body);
440 } else {
441 let percent = Form::new(FormKind::Symbol("%".to_string()), span.clone());
444
445 let body_expr = if real_body.len() == 1 {
446 real_body[0].clone()
447 } else {
448 let mut do_forms = vec![Form::new(FormKind::Symbol("do".to_string()), span.clone())];
449 do_forms.extend_from_slice(real_body);
450 Form::new(FormKind::List(do_forms), span.clone())
451 };
452
453 let binding_vec = Form::new(
454 FormKind::Vector(vec![percent.clone(), body_expr]),
455 span.clone(),
456 );
457
458 let mut let_forms = vec![
459 Form::new(FormKind::Symbol("let*".to_string()), span.clone()),
460 binding_vec,
461 ];
462 for cond in &post_conds {
463 let_forms.push(make_assert_call(cond, &span));
464 }
465 let_forms.push(percent);
466
467 new_body.push(Form::new(FormKind::List(let_forms), span));
468 }
469
470 new_body
471}
472
473fn make_assert_call(cond: &Form, span: &cljrs_types::span::Span) -> Form {
475 Form::new(
476 FormKind::List(vec![
477 Form::new(FormKind::Symbol("assert".to_string()), span.clone()),
478 cond.clone(),
479 ]),
480 span.clone(),
481 )
482}
483
484fn peel_param_hint(p: &Form) -> (Option<TypeHint>, &Form) {
488 if let FormKind::Meta(meta, inner) = &p.kind {
489 let hint = tag_name_of_meta(meta).and_then(|n| TypeHint::from_tag(&n));
490 let (inner_hint, inner_form) = peel_param_hint(inner);
492 (hint.or(inner_hint), inner_form)
493 } else {
494 (None, p)
495 }
496}
497
498fn tag_name_of_meta(meta: &Form) -> Option<Arc<str>> {
501 match &meta.kind {
502 FormKind::Symbol(s) => Some(strip_tag_ns(s)),
504 FormKind::Map(entries) => entries.chunks(2).find_map(|kv| {
506 let is_tag = matches!(&kv[0].kind, FormKind::Keyword(k) if k == "tag");
507 if !is_tag {
508 return None;
509 }
510 match kv.get(1).map(|f| &f.kind) {
511 Some(FormKind::Symbol(s)) => Some(strip_tag_ns(s)),
512 Some(FormKind::Str(s)) => Some(strip_tag_ns(s)),
513 _ => None,
514 }
515 }),
516 _ => None,
517 }
518}
519
520fn strip_tag_ns(s: &str) -> Arc<str> {
522 match s.rfind('/') {
523 Some(pos) if pos + 1 < s.len() => Arc::from(&s[pos + 1..]),
524 _ => Arc::from(s),
525 }
526}
527
528fn eval_if(args: &[Form], env: &mut Env) -> EvalResult {
531 if args.is_empty() {
532 return Err(EvalError::Runtime("if requires a test".into()));
533 }
534 let test = eval(&args[0], env)?;
535 let truthy = !matches!(test, Value::Nil | Value::Bool(false));
536 if truthy {
537 if args.len() > 1 {
538 eval(&args[1], env)
539 } else {
540 Ok(Value::Nil)
541 }
542 } else if args.len() > 2 {
543 eval(&args[2], env)
544 } else {
545 Ok(Value::Nil)
546 }
547}
548
549fn eval_let(args: &[Form], env: &mut Env) -> EvalResult {
552 let bindings = match args.first().and_then(|f| f.as_vector()) {
553 Some(v) => expand_pairs(v)
554 .map_err(|_| EvalError::Runtime("let* binding vector must have even length".into()))?
555 .into_owned(),
556 None => return Err(EvalError::Runtime("let* requires a binding vector".into())),
557 };
558
559 let body = &args[1..];
560
561 let chains = crate::interp::virtualize::detect_let_chains(&bindings);
563 let virtualizable_chains = find_virtualizable_chains(&chains, &bindings, body);
564
565 env.push_frame();
566
567 let pairs: Vec<_> = bindings.chunks(2).collect();
568 let mut i = 0;
569 while i < pairs.len() {
570 if let Some(chain) = virtualizable_chains.iter().find(|c| c.start == i) {
572 match eval_virtualized_chain(chain, &pairs, env) {
573 Ok(()) => {
574 i += chain.len;
575 continue;
576 }
577 Err(e) => {
578 env.pop_frame();
579 return Err(e);
580 }
581 }
582 }
583
584 let pair = pairs[i];
586 let val = match eval(&pair[1], env) {
587 Ok(v) => v,
588 Err(e) => {
589 env.pop_frame();
590 return Err(e);
591 }
592 };
593 if let Err(e) = bind_pattern(&pair[0], val, env) {
594 env.pop_frame();
595 return Err(e);
596 }
597 i += 1;
598 }
599
600 let result = eval_body(body, env);
601 env.pop_frame();
602 result
603}
604
605fn find_virtualizable_chains<'a>(
610 chains: &'a [crate::interp::virtualize::LetChain],
611 bindings: &[Form],
612 body: &[Form],
613) -> Vec<&'a crate::interp::virtualize::LetChain> {
614 chains
615 .iter()
616 .filter(|chain| {
617 for j in chain.start..(chain.start + chain.len - 1) {
620 let name = match &bindings[j * 2].kind {
621 FormKind::Symbol(s) => s.as_str(),
622 _ => return false,
623 };
624 if crate::interp::virtualize::binding_used_in_body(name, body) {
625 return false;
626 }
627 if crate::interp::virtualize::binding_used_in_other_bindings(
628 name,
629 bindings,
630 chain.start,
631 chain.len,
632 ) {
633 return false;
634 }
635 }
636 true
637 })
638 .collect()
639}
640
641fn eval_virtualized_chain(
651 chain: &crate::interp::virtualize::LetChain,
652 pairs: &[&[Form]],
653 env: &mut Env,
654) -> Result<(), EvalError> {
655 use crate::builtins::transients::{
656 builtin_assoc_bang, builtin_conj_bang, builtin_persistent_bang, builtin_transient,
657 };
658
659 let first_pair = pairs[chain.start];
661 let first_expr_forms = match &first_pair[1].kind {
662 FormKind::List(forms) => forms,
663 _ => unreachable!("chain detection ensures this is a list"),
664 };
665 let root_collection = eval(&first_expr_forms[1], env)?;
666
667 let mut transient = match builtin_transient(std::slice::from_ref(&root_collection)) {
669 Ok(t) => t,
670 Err(_) => {
671 return eval_chain_normally(chain, pairs, env);
674 }
675 };
676
677 for j in 0..chain.len {
679 let pair_idx = chain.start + j;
680 let pair = pairs[pair_idx];
681 let expr_forms = match &pair[1].kind {
682 FormKind::List(forms) => forms,
683 _ => unreachable!(),
684 };
685
686 let mut args = vec![transient.clone()];
688 for arg_form in expr_forms.iter().skip(2) {
689 args.push(eval(arg_form, env)?);
690 }
691
692 transient = match chain.ops[j] {
694 crate::interp::virtualize::ChainOpKind::Assoc => {
695 builtin_assoc_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
696 }
697 crate::interp::virtualize::ChainOpKind::Conj => {
698 builtin_conj_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
699 }
700 };
701
702 if j < chain.len - 1 {
706 let name = match &pair[0].kind {
707 FormKind::Symbol(s) => s.clone(),
708 _ => unreachable!(),
709 };
710 env.bind(Arc::from(name.as_str()), Value::Nil);
712 }
713 }
714
715 let persistent =
717 builtin_persistent_bang(&[transient]).map_err(|e| EvalError::Runtime(e.to_string()))?;
718
719 let last_pair = pairs[chain.start + chain.len - 1];
721 bind_pattern(&last_pair[0], persistent, env)?;
722
723 Ok(())
724}
725
726fn eval_chain_normally(
728 chain: &crate::interp::virtualize::LetChain,
729 pairs: &[&[Form]],
730 env: &mut Env,
731) -> Result<(), EvalError> {
732 for j in 0..chain.len {
733 let pair_idx = chain.start + j;
734 let pair = pairs[pair_idx];
735 let val = eval(&pair[1], env)?;
736 bind_pattern(&pair[0], val, env)?;
737 }
738 Ok(())
739}
740
741pub fn eval_loop(args: &[Form], env: &mut Env) -> EvalResult {
744 let bindings = match args.first().and_then(|f| f.as_vector()) {
745 Some(v) => expand_pairs(v)
746 .map_err(|_| EvalError::Runtime("loop* binding vector must have even length".into()))?
747 .into_owned(),
748 None => return Err(EvalError::Runtime("loop* requires a binding vector".into())),
749 };
750
751 let body = &args[1..];
752
753 let patterns: Vec<Form> = bindings.iter().step_by(2).cloned().collect();
755 let mut current_vals: Vec<Value> = Vec::new();
756
757 for i in (1..bindings.len()).step_by(2) {
759 current_vals.push(eval(&bindings[i], env)?);
760 }
761
762 loop {
763 let _vals_root = crate::env::gc_roots::root_values(¤t_vals);
765
766 crate::env::gc_roots::gc_safepoint(env);
769
770 #[cfg(feature = "no-gc")]
774 let mut scratch = cljrs_gc::alloc_ctx::ScratchGuard::new();
775
776 #[cfg(not(feature = "no-gc"))]
787 let _iter_frame = cljrs_gc::push_alloc_frame();
788
789 env.push_frame();
790 for (pat, val) in patterns.iter().zip(current_vals.iter()) {
791 if let Err(e) = bind_pattern(pat, val.clone(), env) {
792 env.pop_frame();
793 return Err(e);
794 }
795 }
796
797 #[cfg(not(feature = "no-gc"))]
800 let result = eval_body_recur(body, env);
801 #[cfg(feature = "no-gc")]
802 let result = eval_body_with_scratch_loop(body, &mut scratch, env);
803
804 env.pop_frame();
805 match result {
809 Ok(v) => return Ok(v),
810 Err(EvalError::Recur(new_vals)) => {
811 if new_vals.len() != patterns.len() {
812 return Err(EvalError::Arity {
813 name: "recur".into(),
814 expected: patterns.len().to_string(),
815 got: new_vals.len(),
816 });
817 }
818 current_vals = new_vals;
821 }
822 Err(e) => return Err(e),
823 }
824 }
825}
826
827fn eval_recur(args: &[Form], env: &mut Env) -> EvalResult {
828 let vals: Vec<Value> = args
829 .iter()
830 .map(|f| eval(f, env))
831 .collect::<EvalResult<_>>()?;
832 Err(EvalError::Recur(vals))
833}
834
835pub fn eval_body_recur(body: &[Form], env: &mut Env) -> EvalResult {
837 let mut result = Value::Nil;
838 for form in body {
839 result = eval(form, env)?;
840 }
841 Ok(result)
842}
843
844#[cfg(feature = "no-gc")]
850fn eval_body_with_scratch_loop(
851 body: &[Form],
852 scratch: &mut cljrs_gc::alloc_ctx::ScratchGuard,
853 env: &mut Env,
854) -> EvalResult {
855 if body.is_empty() {
856 scratch.pop_for_return();
857 return Ok(Value::Nil);
858 }
859 for form in &body[..body.len() - 1] {
860 eval(form, env)?;
861 }
862 scratch.pop_for_return();
863 eval(&body[body.len() - 1], env)
864}
865
866fn eval_quote(args: &[Form], env: &Env) -> EvalResult {
869 match args.first() {
870 Some(f) => form_to_value(&resolve_auto_forms(f, env)?),
874 None => Err(EvalError::Runtime("quote requires an argument".into())),
875 }
876}
877
878fn eval_var(args: &[Form], env: &mut Env) -> EvalResult {
881 let sym = match args.first().map(|f| &f.kind) {
882 Some(FormKind::Symbol(s)) => s.clone(),
883 _ => return Err(EvalError::Runtime("var requires a symbol".into())),
884 };
885 let parsed = cljrs_value::Symbol::parse(&sym);
886 let ns: Arc<str> = env.resolve_ns_or_current(parsed.namespace.as_deref());
887 let name = parsed.name.as_ref();
888 env.globals
889 .lookup_var_in_ns(&ns, name)
890 .map(Value::Var)
891 .ok_or_else(|| EvalError::UnboundSymbol(sym))
892}
893
894fn eval_set_bang(args: &[Form], env: &mut Env) -> EvalResult {
897 let target = args
898 .first()
899 .ok_or_else(|| EvalError::Runtime("set! requires a target".into()))?;
900 let val = if args.len() > 1 {
901 eval(&args[1], env)?
902 } else {
903 Value::Nil
904 };
905 match &target.kind {
906 FormKind::Symbol(sym) => set_bang_symbol(sym, val, env),
907 _ => match set_bang_field_target(target) {
908 Some((field, inst_form)) => {
909 let inst = eval(inst_form, env)?;
910 set_type_instance_field(&inst, field, val)
911 }
912 None => Err(set_bang_target_error()),
913 },
914 }
915}
916
917pub fn set_bang_symbol(sym: &str, val: Value, env: &mut Env) -> EvalResult {
920 if !sym.contains('/')
923 && let Some(v) = try_set_mutable_field(env, sym, &val)?
924 {
925 return Ok(v);
926 }
927 let parsed = cljrs_value::Symbol::parse(sym);
928 let ns = parsed.namespace.as_deref().unwrap_or(&env.current_ns);
929 let var = env
930 .globals
931 .lookup_var_in_ns(ns, &parsed.name)
932 .ok_or_else(|| EvalError::UnboundSymbol(sym.to_string()))?;
933 if !crate::env::dynamics::set_thread_local(&var, val.clone()) {
935 var.get().bind(val.clone());
936 }
937 Ok(val)
938}
939
940pub fn set_bang_field_target(target: &Form) -> Option<(&str, &Form)> {
943 match &target.kind {
944 FormKind::List(parts) if parts.len() == 2 => match &parts[0].kind {
945 FormKind::Symbol(op) if op.starts_with(".-") => Some((&op[2..], &parts[1])),
946 _ => None,
947 },
948 _ => None,
949 }
950}
951
952pub fn set_bang_target_error() -> EvalError {
954 EvalError::Runtime("set! requires a symbol or (.-field inst) target".into())
955}
956
957fn try_set_mutable_field(env: &mut Env, sym: &str, val: &Value) -> EvalResult<Option<Value>> {
962 let Some(Value::TypeInstance(ti)) = env.lookup_local_frames(DEFTYPE_SELF) else {
963 return Ok(None);
964 };
965 let Some(atom) = ti.get().mutable.clone() else {
966 return Ok(None);
967 };
968 let key = Value::keyword(cljrs_value::Keyword::simple(sym));
969 let Value::Map(map) = atom.get().deref() else {
970 return Ok(None);
971 };
972 if map.get(&key).is_none() {
973 return Ok(None);
974 }
975 atom.get().reset(Value::Map(map.assoc(key, val.clone())));
976 env.bind(Arc::from(sym), val.clone());
978 Ok(Some(val.clone()))
979}
980
981pub fn set_type_instance_field(inst: &Value, field: &str, val: Value) -> EvalResult {
983 let Value::TypeInstance(ti) = inst else {
984 return Err(EvalError::Runtime(format!(
985 "set! (.-{field} …): target is not a type instance"
986 )));
987 };
988 let atom = ti.get().mutable.clone().ok_or_else(|| {
989 EvalError::Runtime(format!("set! (.-{field} …): type has no mutable fields"))
990 })?;
991 let key = Value::keyword(cljrs_value::Keyword::simple(field));
992 let map = match atom.get().deref() {
993 Value::Map(m) => m,
994 _ => MapValue::empty(),
995 };
996 if map.get(&key).is_none() {
997 return Err(EvalError::Runtime(format!(
998 "set!: {field} is not a mutable field"
999 )));
1000 }
1001 atom.get().reset(Value::Map(map.assoc(key, val.clone())));
1002 Ok(val)
1003}
1004
1005fn eval_throw(args: &[Form], env: &mut Env) -> EvalResult {
1008 let val = match args.first() {
1009 Some(f) => eval(f, env)?,
1010 None => Value::Nil,
1011 };
1012 Err(throw_value(val))
1013}
1014
1015pub fn throw_value(val: Value) -> EvalError {
1020 let val = match val {
1021 Value::Error(_) => val,
1022 other => {
1023 let msg = format!("{}", other);
1024 Value::Error(GcPtr::new(ExceptionInfo::new(
1025 ValueError::Other(msg.clone()),
1026 msg,
1027 None,
1028 None,
1029 )))
1030 }
1031 };
1032 EvalError::Thrown(val)
1033}
1034
1035pub struct CatchClause<'a> {
1042 pub type_sym: &'a str,
1043 pub binding: &'a str,
1044 pub body: &'a [Form],
1045}
1046
1047pub fn eval_error_to_value(err: &EvalError) -> Value {
1052 let msg = err.to_string();
1053 Value::Error(GcPtr::new(ExceptionInfo::new(
1054 ValueError::Other(msg.clone()),
1055 msg,
1056 None,
1057 None,
1058 )))
1059}
1060
1061pub fn catch_type_matches(type_name: &str, val: &Value) -> bool {
1065 let short = type_name.rsplit('.').next().unwrap_or(type_name);
1066 match short {
1067 "Object" | "Exception" | "Throwable" | "Error" | "default" => true,
1071 "ExceptionInfo" => matches!(val, Value::Error(_)),
1073 _ => false,
1074 }
1075}
1076
1077fn eval_try(args: &[Form], env: &mut Env) -> EvalResult {
1078 let (body, catches, fin_body) = parse_try_args(args);
1079
1080 let mut result = eval_body(body, env);
1081
1082 let err_opt = match std::mem::replace(&mut result, Ok(Value::Nil)) {
1084 Ok(v) => {
1085 result = Ok(v);
1086 None
1087 }
1088 Err(EvalError::Recur(args)) => {
1089 result = Err(EvalError::Recur(args));
1090 None
1091 }
1092 Err(EvalError::GasExhausted) => {
1093 result = Err(EvalError::GasExhausted);
1094 None
1095 }
1096 Err(other) => Some(other),
1097 };
1098
1099 if let Some(err) = err_opt {
1100 let thrown_val = match err {
1101 EvalError::Thrown(v) => v,
1102 ref other => eval_error_to_value(other),
1103 };
1104 let mut handled = false;
1105 for c in &catches {
1106 if catch_type_matches(c.type_sym, &thrown_val) {
1107 env.push_frame();
1108 env.bind(Arc::from(c.binding), thrown_val.clone());
1109 result = eval_body(c.body, env);
1110 env.pop_frame();
1111 handled = true;
1112 break;
1113 }
1114 }
1115 if !handled {
1116 result = Err(EvalError::Thrown(thrown_val));
1118 }
1119 }
1120
1121 if !fin_body.is_empty() {
1125 eval_body(fin_body, env)?;
1126 }
1127
1128 result
1129}
1130
1131fn catch_target(f: &Form) -> Option<&str> {
1133 f.as_symbol().or_else(|| f.as_keyword())
1134}
1135
1136pub fn parse_try_args(args: &[Form]) -> (&[Form], Vec<CatchClause<'_>>, &[Form]) {
1140 let mut body_end = args.len();
1141 let mut catches: Vec<CatchClause<'_>> = Vec::new();
1142 let mut fin_body: &[Form] = &[];
1143
1144 for (i, form) in args.iter().enumerate() {
1145 if let Some(parts) = form.as_list()
1146 && let Some(s) = parts.first().and_then(|f| f.as_symbol())
1147 {
1148 if s == "catch" {
1149 if i < body_end {
1150 body_end = i;
1151 }
1152 let type_sym = match parts.get(1) {
1157 Some(f) => match catch_target(f) {
1158 Some(name) => name,
1159 None => match &f.unmeta().kind {
1160 FormKind::ReaderCond {
1161 splicing: false,
1162 clauses,
1163 } => match select_reader_cond(clauses).and_then(catch_target) {
1164 Some(name) => name,
1165 None => continue,
1166 },
1167 _ => continue,
1168 },
1169 },
1170 None => continue,
1171 };
1172 let binding = match parts.get(2).and_then(|f| f.as_symbol()) {
1173 Some(s) => s,
1174 None => continue,
1175 };
1176 catches.push(CatchClause {
1177 type_sym,
1178 binding,
1179 body: &parts[3..],
1180 });
1181 continue;
1182 }
1183 if s == "finally" {
1184 if i < body_end {
1185 body_end = i;
1186 }
1187 fin_body = &parts[1..];
1188 continue;
1189 }
1190 }
1191 }
1192
1193 (&args[..body_end], catches, fin_body)
1194}
1195
1196pub fn eval_defn(args: &[Form], env: &mut Env, private: bool) -> EvalResult {
1199 let name_form = args
1201 .first()
1202 .ok_or_else(|| EvalError::Runtime("defn requires a symbol name".into()))?;
1203 let (name_metas, name_sym) = name_form.peel_meta();
1204 let (name, mut is_async) = match &name_sym.kind {
1205 FormKind::Symbol(s) => (s.clone(), name_metas.iter().any(|m| m.requests_async())),
1206 _ => return Err(EvalError::Runtime("defn name must be a symbol".into())),
1207 };
1208 let mut rest_start = 1;
1212 let mut docstring: Option<String> = None;
1213 if rest_start < args.len()
1214 && let Some(s) = args[rest_start].as_string()
1215 {
1216 docstring = Some(s.to_string());
1217 rest_start += 1;
1218 }
1219 let mut attr_meta: Option<Value> = None;
1220 if rest_start < args.len() && args[rest_start].as_map().is_some() {
1221 is_async |= args[rest_start].requests_async();
1223 attr_meta = Some(eval(&args[rest_start], env)?);
1224 rest_start += 1;
1225 }
1226 let mut fn_args = vec![Form::new(
1228 FormKind::Symbol(name.to_string()),
1229 args[0].span.clone(),
1230 )];
1231 fn_args.extend_from_slice(&args[rest_start..]);
1232 #[cfg(feature = "no-gc")]
1235 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1236 let mut fn_val = eval_fn(&fn_args, env)?;
1237 if is_async && let Value::Fn(ref mut f) = fn_val {
1238 f.get_mut().is_async = true;
1239 }
1240 let var = env
1241 .globals
1242 .intern(&env.current_ns, Arc::from(name.as_str()), fn_val.clone());
1243 let mut meta = attr_meta;
1244 if let Some(doc) = &docstring {
1245 meta = merge_meta(meta, Some(doc_meta(doc)));
1246 }
1247 meta = merge_meta(meta, arglists_meta(&fn_val, 0));
1248 if private {
1249 meta = merge_meta(meta, Some(private_meta()));
1250 }
1251 if let Some(meta_val) = meta {
1252 var.get().set_meta(meta_val);
1253 }
1254 Ok(Value::Var(var))
1255}
1256
1257fn prepend_macro_params(form: &Form) -> Form {
1265 let span = form.span.clone();
1266 match &form.unmeta().kind {
1267 FormKind::Vector(params) => {
1268 let mut new_params = vec![
1269 Form::new(FormKind::Symbol("&form".to_string()), span.clone()),
1270 Form::new(FormKind::Symbol("&env".to_string()), span.clone()),
1271 ];
1272 new_params.extend_from_slice(params);
1273 Form::new(FormKind::Vector(new_params), span)
1274 }
1275 FormKind::List(forms) => {
1276 if let Some(first) = forms.first() {
1278 let new_params_form = prepend_macro_params(first);
1279 let mut new_forms = vec![new_params_form];
1280 new_forms.extend_from_slice(&forms[1..]);
1281 Form::new(FormKind::List(new_forms), span)
1282 } else {
1283 form.clone()
1284 }
1285 }
1286 _ => form.clone(),
1287 }
1288}
1289
1290fn eval_defmacro(args: &[Form], env: &mut Env) -> EvalResult {
1291 let mut current = args
1294 .first()
1295 .ok_or_else(|| EvalError::Runtime("defmacro requires a symbol at position 0".into()))?
1296 .clone();
1297 let mut name_meta: Option<Value> = None;
1298 while let FormKind::Meta(meta_form, inner) = current.kind {
1299 let meta_val = compile_meta_form(&meta_form, env)?;
1300 name_meta = merge_meta(name_meta, Some(meta_val));
1301 current = *inner;
1302 }
1303 let name = match ¤t.kind {
1304 FormKind::Symbol(s) => s.clone(),
1305 _ => {
1306 return Err(EvalError::Runtime(
1307 "defmacro requires a symbol at position 0".into(),
1308 ));
1309 }
1310 };
1311
1312 let mut rest_start = 1;
1313 let mut docstring: Option<String> = None;
1314 if rest_start < args.len()
1315 && let FormKind::Str(s) = &args[rest_start].kind
1316 {
1317 docstring = Some(s.clone());
1318 rest_start += 1;
1319 }
1320 let mut attr_meta = None;
1321 if rest_start < args.len() && matches!(args[rest_start].kind, FormKind::Map(_)) {
1322 attr_meta = Some(eval(&args[rest_start], env)?);
1323 rest_start += 1;
1324 }
1325 let mut fn_args = vec![Form::new(
1327 FormKind::Symbol(name.to_string()),
1328 args[0].span.clone(),
1329 )];
1330 for form in &args[rest_start..] {
1331 fn_args.push(prepend_macro_params(form));
1332 }
1333 #[cfg(feature = "no-gc")]
1336 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1337 let fn_val = eval_fn(&fn_args, env)?;
1338
1339 let macro_val = match fn_val {
1341 Value::Fn(f) => {
1342 let mut mfn = f.get().clone();
1343 mfn.is_macro = true;
1344 Value::Macro(GcPtr::new(mfn))
1345 }
1346 other => other,
1347 };
1348
1349 let var = env
1350 .globals
1351 .intern(&env.current_ns, Arc::from(name.as_str()), macro_val.clone());
1352 let mut meta = merge_meta(name_meta, attr_meta);
1353 if let Some(doc) = &docstring {
1354 meta = merge_meta(meta, Some(doc_meta(doc)));
1355 }
1356 meta = merge_meta(meta, arglists_meta(¯o_val, 2));
1358 if let Some(m) = meta {
1359 var.get().set_meta(m);
1360 }
1361 Ok(Value::Var(var))
1362}
1363
1364fn eval_defonce(args: &[Form], env: &mut Env) -> EvalResult {
1367 if args.is_empty() {
1368 return Err(EvalError::Runtime("defonce requires a name".into()));
1369 }
1370 let (name, _meta) = extract_def_name(&args[0], env)?;
1373 if let Some(var) = defonce_existing(&name, env) {
1375 return Ok(var);
1376 }
1377 eval_def(args, env)
1378}
1379
1380fn eval_and(args: &[Form], env: &mut Env) -> EvalResult {
1383 let mut result = Value::Bool(true);
1384 for form in args {
1385 result = eval(form, env)?;
1386 if matches!(result, Value::Nil | Value::Bool(false)) {
1387 return Ok(result);
1388 }
1389 }
1390 Ok(result)
1391}
1392
1393fn eval_or(args: &[Form], env: &mut Env) -> EvalResult {
1394 let mut last = Value::Nil;
1395 for form in args {
1396 last = eval(form, env)?;
1397 if !matches!(last, Value::Nil | Value::Bool(false)) {
1398 return Ok(last);
1399 }
1400 }
1401 Ok(last)
1402}
1403
1404fn eval_require(args: &[Form], env: &mut Env) -> EvalResult {
1407 for arg in args {
1408 let val = eval(arg, env)?;
1409 let spec = parse_require_spec_val(val).map_err(EvalError::Runtime)?;
1410 load_ns(env.globals.clone(), &spec, &env.current_ns)?;
1411 }
1412 Ok(Value::Nil)
1413}
1414
1415fn parse_require_spec_val(val: Value) -> Result<RequireSpec, String> {
1420 match val {
1421 Value::Symbol(s) => {
1422 let sym = s.get();
1423 Ok(RequireSpec {
1424 ns: sym.name.clone(),
1425 version: sym.version.clone(),
1426 alias: None,
1427 refer: RequireRefer::None,
1428 })
1429 }
1430 Value::Vector(v) => {
1431 let items: Vec<Value> = v.get().iter().cloned().collect();
1432 if items.is_empty() {
1433 return Err("require spec vector must not be empty".into());
1434 }
1435 let (ns, version) = match &items[0] {
1436 Value::Symbol(s) => {
1437 let sym = s.get();
1438 (sym.name.clone(), sym.version.clone())
1439 }
1440 other => {
1441 return Err(format!(
1442 "require spec: first element must be a symbol, got {}",
1443 other.type_name()
1444 ));
1445 }
1446 };
1447 let mut alias = None;
1448 let mut refer = RequireRefer::None;
1449 let mut i = 1;
1450 while i < items.len() {
1451 match &items[i] {
1452 Value::Keyword(k) if k.get().name.as_ref() == "as" => {
1453 i += 1;
1454 alias = Some(match items.get(i) {
1455 Some(Value::Symbol(s)) => s.get().name.clone(),
1456 _ => return Err("require :as expects a symbol".into()),
1457 });
1458 }
1459 Value::Keyword(k) if k.get().name.as_ref() == "refer" => {
1460 i += 1;
1461 refer = match items.get(i) {
1462 Some(Value::Keyword(k2)) if k2.get().name.as_ref() == "all" => {
1463 RequireRefer::All
1464 }
1465 Some(Value::Vector(rv)) => {
1466 let names: Vec<Arc<str>> = rv
1467 .get()
1468 .iter()
1469 .map(|v| match v {
1470 Value::Symbol(s) => Ok(s.get().name.clone()),
1471 other => Err(format!(
1472 "require :refer expects symbols, got {}",
1473 other.type_name()
1474 )),
1475 })
1476 .collect::<Result<_, _>>()?;
1477 RequireRefer::Named(names)
1478 }
1479 _ => {
1480 return Err(
1481 "require :refer expects :all or a vector of symbols".into()
1482 );
1483 }
1484 };
1485 }
1486 other => {
1487 return Err(format!(
1488 "require spec: unexpected option {}",
1489 other.type_name()
1490 ));
1491 }
1492 }
1493 i += 1;
1494 }
1495 Ok(RequireSpec {
1496 ns,
1497 version,
1498 alias,
1499 refer,
1500 })
1501 }
1502 other => Err(format!(
1503 "require expects a symbol or vector, got {}",
1504 other.type_name()
1505 )),
1506 }
1507}
1508
1509fn spec_element(form: &Form) -> Option<&Form> {
1513 match &form.kind {
1514 FormKind::ReaderCond { clauses, .. } => select_reader_cond(clauses),
1515 _ => Some(form),
1516 }
1517}
1518
1519pub fn parse_require_spec_form(form: &Form) -> Result<RequireSpec, String> {
1526 match &form.kind {
1527 FormKind::Symbol(s) => {
1528 let sym = cljrs_value::Symbol::parse(s);
1529 Ok(RequireSpec {
1530 ns: sym.name.clone(),
1531 version: sym.version.clone(),
1532 alias: None,
1533 refer: RequireRefer::None,
1534 })
1535 }
1536 FormKind::Vector(items) => {
1537 if items.is_empty() {
1538 return Err("require spec vector must not be empty".into());
1539 }
1540 let head = spec_element(&items[0]).ok_or_else(|| {
1541 "require spec: no reader-conditional branch matched for the namespace".to_string()
1542 })?;
1543 let (ns, version) = match &head.kind {
1544 FormKind::Symbol(s) => {
1545 let sym = cljrs_value::Symbol::parse(s);
1546 (sym.name.clone(), sym.version.clone())
1547 }
1548 _ => return Err("require spec: first element must be a symbol".into()),
1549 };
1550 let mut alias = None;
1551 let mut refer = RequireRefer::None;
1552 let mut i = 1;
1553 while i < items.len() {
1554 let Some(item) = spec_element(&items[i]) else {
1557 i += 1;
1558 continue;
1559 };
1560 match &item.kind {
1561 FormKind::Keyword(k) if k == "as" => {
1562 i += 1;
1563 alias = Some(match items.get(i).map(|f| &f.kind) {
1564 Some(FormKind::Symbol(s)) => Arc::from(s.as_str()),
1565 _ => return Err("require :as expects a symbol".into()),
1566 });
1567 }
1568 FormKind::Keyword(k) if k == "refer" => {
1569 i += 1;
1570 refer = match items.get(i).map(|f| &f.kind) {
1571 Some(FormKind::Keyword(k2)) if k2 == "all" => RequireRefer::All,
1572 Some(FormKind::Vector(rv)) => {
1573 let names: Vec<Arc<str>> = rv
1574 .iter()
1575 .map(|f| match &f.kind {
1576 FormKind::Symbol(s) => Ok(Arc::from(s.as_str())),
1577 _ => Err("require :refer expects symbols".to_string()),
1578 })
1579 .collect::<Result<_, _>>()?;
1580 RequireRefer::Named(names)
1581 }
1582 _ => return Err("require :refer expects :all or a vector".into()),
1583 };
1584 }
1585 _ => return Err(format!("require spec: unexpected form at position {i}")),
1586 }
1587 i += 1;
1588 }
1589 Ok(RequireSpec {
1590 ns,
1591 version,
1592 alias,
1593 refer,
1594 })
1595 }
1596 _ => Err("require spec must be a symbol or vector".into()),
1597 }
1598}
1599
1600fn extract_ns_name_form(form: Option<&Form>, env: &mut Env) -> EvalResult<(String, Option<Value>)> {
1606 let mut current = form
1607 .ok_or_else(|| EvalError::Runtime("ns requires a symbol at position 0".into()))?
1608 .clone();
1609 let mut meta_acc: Option<Value> = None;
1610 while let FormKind::Meta(meta_form, inner) = current.kind {
1611 let meta_val = compile_meta_form(&meta_form, env)?;
1612 meta_acc = merge_meta(meta_acc, Some(meta_val));
1613 current = *inner;
1614 }
1615 match ¤t.kind {
1616 FormKind::Symbol(s) => Ok((s.clone(), meta_acc)),
1617 _ => Err(EvalError::Runtime(
1618 "ns requires a symbol at position 0".into(),
1619 )),
1620 }
1621}
1622
1623fn merge_meta(base: Option<Value>, overlay: Option<Value>) -> Option<Value> {
1626 match (base, overlay) {
1627 (None, None) => None,
1628 (Some(b), None) => Some(b),
1629 (None, Some(o)) => Some(o),
1630 (Some(Value::Map(b)), Some(Value::Map(o))) => {
1631 let mut merged = b;
1632 for (k, v) in o.iter() {
1633 merged = merged.assoc(k.clone(), v.clone());
1634 }
1635 Some(Value::Map(merged))
1636 }
1637 (_, Some(o)) => Some(o),
1638 }
1639}
1640
1641fn parse_refer_clojure_clause(items: &[Form]) -> Result<ReferClojureFilter, String> {
1645 let mut filter = ReferClojureFilter::default();
1646 let items = expand_reader_conds(items);
1647 let mut i = 0;
1648 while i < items.len() {
1649 let FormKind::Keyword(k) = &items[i].kind else {
1650 return Err(":refer-clojure expects keyword options (:exclude, :only, :rename)".into());
1651 };
1652 let arg = items
1653 .get(i + 1)
1654 .ok_or_else(|| format!(":refer-clojure :{k} expects a value"))?;
1655 match k.as_str() {
1656 "exclude" => filter.exclude = symbol_name_set(arg, "exclude")?,
1657 "only" => filter.only = Some(symbol_name_set(arg, "only")?),
1658 "rename" => {
1659 let FormKind::Map(entries) = &arg.kind else {
1660 return Err(":refer-clojure :rename expects a map".into());
1661 };
1662 if entries.len() % 2 != 0 {
1663 return Err(":refer-clojure :rename expects an even-sized map".into());
1664 }
1665 for pair in entries.chunks(2) {
1666 match (&pair[0].kind, &pair[1].kind) {
1667 (FormKind::Symbol(from), FormKind::Symbol(to)) => {
1668 filter
1669 .rename
1670 .insert(Arc::from(from.as_str()), Arc::from(to.as_str()));
1671 }
1672 _ => {
1673 return Err(
1674 ":refer-clojure :rename expects symbol keys and values".into()
1675 );
1676 }
1677 }
1678 }
1679 }
1680 other => return Err(format!(":refer-clojure does not support :{other}")),
1681 }
1682 i += 2;
1683 }
1684 Ok(filter)
1685}
1686
1687fn symbol_name_set(form: &Form, opt: &str) -> Result<HashSet<Arc<str>>, String> {
1689 let FormKind::Vector(items) = &form.kind else {
1690 return Err(format!(":refer-clojure :{opt} expects a vector of symbols"));
1691 };
1692 expand_reader_conds(items)
1693 .iter()
1694 .map(|f| match &f.kind {
1695 FormKind::Symbol(sym) => Ok(Arc::from(sym.as_str())),
1696 _ => Err(format!(":refer-clojure :{opt} expects symbols")),
1697 })
1698 .collect()
1699}
1700
1701fn eval_ns(args: &[Form], env: &mut Env) -> EvalResult {
1702 let (name, name_meta) = extract_ns_name_form(args.first(), env)?;
1703 env.globals.get_or_create_ns(&name);
1704 env.current_ns = Arc::from(name.as_str());
1705 if name != "clojure.core" {
1707 env.globals.refer_core(&name);
1708 }
1709 sync_star_ns(env);
1710
1711 let mut rest = &args[1..];
1713 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Str(_))) {
1714 rest = &rest[1..];
1715 }
1716 let mut attr_meta = None;
1717 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Map(_))) {
1718 attr_meta = Some(eval(&rest[0], env)?);
1719 rest = &rest[1..];
1720 }
1721
1722 if let Some(m) = merge_meta(name_meta, attr_meta) {
1723 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1724 ns_ptr.get().set_meta(m);
1725 }
1726
1727 let mut refer_clojure = None;
1738 for clause in rest {
1739 if let FormKind::List(items) = &clause.kind
1740 && matches!(items.first().map(|f| &f.kind), Some(FormKind::Keyword(k)) if k == "refer-clojure")
1741 {
1742 refer_clojure =
1743 Some(parse_refer_clojure_clause(&items[1..]).map_err(EvalError::Runtime)?);
1744 }
1745 }
1746 if name != "clojure.core" {
1747 env.globals
1748 .set_refer_clojure_filter(&name, refer_clojure)
1749 .map_err(EvalError::Runtime)?;
1750 }
1751
1752 for clause in rest {
1753 if let FormKind::List(items) = &clause.kind {
1754 match items.first().map(|f| &f.kind) {
1755 Some(FormKind::Keyword(k)) if k == "require" => {
1756 let expanded = expand_reader_conds(&items[1..]);
1758 for spec_form in &expanded {
1759 let spec =
1760 parse_require_spec_form(spec_form).map_err(EvalError::Runtime)?;
1761 load_ns(env.globals.clone(), &spec, &name)?;
1762 }
1763 }
1764 _ => {}
1767 }
1768 }
1769 }
1770
1771 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1772 Ok(Value::Namespace(ns_ptr))
1773}
1774
1775fn eval_load_file(args: &[Form], env: &mut Env) -> EvalResult {
1778 if args.is_empty() {
1779 return Err(EvalError::Runtime(
1780 "load-file requires a path argument".into(),
1781 ));
1782 }
1783 let path_val = eval(&args[0], env)?;
1784 let path = match &path_val {
1785 Value::Str(s) => s.get().clone(),
1786 v => {
1787 return Err(EvalError::Runtime(format!(
1788 "load-file: expected string, got {}",
1789 v.type_name()
1790 )));
1791 }
1792 };
1793 let src = std::fs::read_to_string(&path)
1794 .map_err(|e| EvalError::Runtime(format!("load-file: {e}")))?;
1795 let mut parser = cljrs_reader::Parser::new(src, path.clone());
1796 let forms = parser
1797 .parse_all()
1798 .map_err(|e| EvalError::Runtime(format!("load-file parse error: {e}")))?;
1799 let mut result = Value::Nil;
1800 for form in forms {
1801 let _alloc_frame = cljrs_gc::push_alloc_frame();
1802 result = eval(&form, env)?;
1803 }
1804 Ok(result)
1805}
1806
1807fn eval_letfn(args: &[Form], env: &mut Env) -> EvalResult {
1810 push_letfn_frame(args, env)?;
1811 let result = eval_body(&args[1..], env);
1812 env.pop_frame();
1813 result
1814}
1815
1816pub fn push_letfn_frame(args: &[Form], env: &mut Env) -> EvalResult<()> {
1822 let bindings = match args.first().and_then(|f| f.as_vector()) {
1831 Some(v) => expand_reader_conds_cow(v).into_owned(),
1832 None => return Err(EvalError::Runtime("letfn requires a binding vector".into())),
1833 };
1834
1835 env.push_frame();
1836
1837 for binding in &bindings {
1840 if let Some(parts) = binding.as_list() {
1841 if parts.is_empty() {
1842 continue;
1843 }
1844 let Some(name) = parts[0].as_symbol() else {
1845 env.pop_frame();
1846 return Err(EvalError::Runtime(
1847 "letfn binding name must be a symbol".into(),
1848 ));
1849 };
1850 env.bind(Arc::from(name), Value::Nil);
1851 }
1852 }
1853
1854 let mut built: Vec<(Arc<str>, Value)> = Vec::new();
1857 for binding in &bindings {
1858 if let Some(parts) = binding.as_list() {
1859 if parts.is_empty() {
1860 continue;
1861 }
1862 let fn_val = match eval_fn(parts, env) {
1865 Ok(v) => v,
1866 Err(e) => {
1867 env.pop_frame();
1868 return Err(e);
1869 }
1870 };
1871 let name: Arc<str> = match parts[0].as_symbol() {
1872 Some(s) => Arc::from(s),
1873 None => unreachable!("pass 1 rejected every non-symbol name"),
1874 };
1875 env.bind(Arc::clone(&name), fn_val.clone());
1876 built.push((name, fn_val));
1877 }
1878 }
1879
1880 for (_, fn_val) in &built {
1885 if let Value::Fn(ptr) = fn_val {
1886 let mut ptr = ptr.clone();
1887 let f = ptr.get_mut();
1888 for i in 0..f.closed_over_names.len() {
1889 let captured = f.closed_over_names[i].clone();
1890 if let Some((_, real)) = built.iter().find(|(n, _)| *n == captured) {
1891 f.closed_over_vals[i] = real.clone();
1892 }
1893 }
1894 }
1895 }
1896
1897 Ok(())
1898}
1899
1900fn eval_in_ns(args: &[Form], env: &mut Env) -> EvalResult {
1903 if args.is_empty() {
1905 return Err(EvalError::Runtime("in-ns requires a namespace name".into()));
1906 }
1907 let ns_val = eval(&args[0], env)?;
1908 let ns_name = extract_ns_name(&ns_val)?;
1909 env.globals.get_or_create_ns(&ns_name);
1910 env.globals.refer_core(&ns_name);
1911 env.current_ns = Arc::from(ns_name.as_str());
1912 sync_star_ns(env);
1913 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1914 Ok(Value::Namespace(ns_ptr))
1915}
1916
1917fn eval_alias(args: &[Form], env: &mut Env) -> EvalResult {
1920 if args.len() < 2 {
1922 return Err(EvalError::Runtime(
1923 "alias requires alias-sym and namespace-sym".into(),
1924 ));
1925 }
1926 let alias_val = eval(&args[0], env)?;
1927 let ns_val = eval(&args[1], env)?;
1928
1929 let alias_name = extract_ns_name(&alias_val)?;
1930 let full_ns = extract_ns_name(&ns_val)?;
1931
1932 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1933 let mut aliases = ns_ptr.get().aliases.lock().unwrap();
1934 aliases.insert(Arc::from(alias_name.as_str()), Arc::from(full_ns.as_str()));
1935 Ok(Value::Nil)
1936}
1937
1938fn extract_ns_name(v: &Value) -> EvalResult<String> {
1940 match v {
1941 Value::Symbol(s) => {
1942 Ok(s.get().name.as_ref().to_string())
1944 }
1945 Value::Str(s) => Ok(s.get().clone()),
1946 Value::Keyword(k) => Ok(k.get().name.as_ref().to_string()),
1947 other => Err(EvalError::Runtime(format!(
1948 "expected a symbol or string for namespace name, got {}",
1949 other.type_name()
1950 ))),
1951 }
1952}
1953
1954fn protocol_method_of(spec: &Value) -> EvalResult<ProtocolMethod> {
1958 let Value::Map(m) = spec.unwrap_meta() else {
1959 return Err(EvalError::Runtime(format!(
1960 "protocol* method spec must be a map, got {}",
1961 spec.type_name()
1962 )));
1963 };
1964 let field = |k: &str| m.get(&Value::keyword(Keyword::simple(k)));
1965 let name: Arc<str> = match field("name") {
1966 Some(Value::Str(s)) => Arc::from(s.get().as_str()),
1967 Some(Value::Symbol(s)) => Arc::from(s.get().name.as_ref()),
1968 Some(Value::Keyword(k)) => Arc::from(k.get().name.as_ref()),
1969 _ => {
1970 return Err(EvalError::Runtime(
1971 "protocol* method spec needs a :name".into(),
1972 ));
1973 }
1974 };
1975 let min_arity = match field("min-arity") {
1976 Some(Value::Long(n)) if n >= 0 => n as usize,
1977 _ => 1,
1978 };
1979 let variadic = !matches!(
1980 field("variadic"),
1981 None | Some(Value::Nil) | Some(Value::Bool(false))
1982 );
1983 Ok(ProtocolMethod {
1984 name,
1985 min_arity,
1986 variadic,
1987 })
1988}
1989
1990fn eval_protocol_star(args: &[Form], env: &mut Env) -> EvalResult {
1999 if args.len() < 2 {
2000 return Err(EvalError::Runtime(
2001 "protocol* requires a name and method specs".into(),
2002 ));
2003 }
2004 let (name, _) = require_sym_meta(args, 0, "protocol*", env)?;
2006 let specs = crate::interp::eval::eval(&args[1], env)?;
2007 let specs: Vec<Value> = match specs.unwrap_meta() {
2008 Value::Vector(v) => v.get().iter().cloned().collect(),
2009 Value::Nil => Vec::new(),
2010 v => {
2011 return Err(EvalError::Runtime(format!(
2012 "protocol* method specs must be a vector, got {}",
2013 v.type_name()
2014 )));
2015 }
2016 };
2017 let methods = specs
2018 .iter()
2019 .map(protocol_method_of)
2020 .collect::<EvalResult<Vec<_>>>()?;
2021 let extend_via_metadata = match args.get(2) {
2022 Some(f) => !matches!(
2023 crate::interp::eval::eval(f, env)?,
2024 Value::Nil | Value::Bool(false)
2025 ),
2026 None => false,
2027 };
2028 let proto = Protocol::new(
2029 Arc::from(name.as_str()),
2030 env.current_ns.clone(),
2031 methods,
2032 extend_via_metadata,
2033 );
2034 Ok(Value::Protocol(GcPtr::new(proto)))
2035}
2036
2037fn synth_field_scope(
2055 params_form: &Form,
2056 fields: &[Arc<str>],
2057 mutable_fields: &[Arc<str>],
2058 body: &[Form],
2059) -> Option<Vec<Form>> {
2060 let param_forms = match ¶ms_form.kind {
2061 FormKind::Vector(v) => v,
2062 _ => return None,
2063 };
2064 let this_name = match param_forms.first().map(|f| &f.kind) {
2065 Some(FormKind::Symbol(s)) => s.clone(),
2066 _ => return None,
2067 };
2068 let param_names: Vec<&str> = param_forms
2069 .iter()
2070 .filter_map(|f| match &f.kind {
2071 FormKind::Symbol(s) => Some(s.as_str()),
2072 _ => None,
2073 })
2074 .collect();
2075
2076 let span = params_form.span.clone();
2077 let is_mut = |name: &str| mutable_fields.iter().any(|m| m.as_ref() == name);
2078 let mut bindings: Vec<Form> = Vec::new();
2079 for field in fields {
2080 if param_names.contains(&field.as_ref()) {
2081 continue;
2082 }
2083 bindings.push(Form::new(FormKind::Symbol(field.to_string()), span.clone()));
2084 let accessor = if is_mut(field) {
2088 FormKind::List(vec![
2089 Form::new(FormKind::Symbol(format!(".-{field}")), span.clone()),
2090 Form::new(FormKind::Symbol(this_name.clone()), span.clone()),
2091 ])
2092 } else {
2093 FormKind::List(vec![
2094 Form::new(FormKind::Keyword(field.to_string()), span.clone()),
2095 Form::new(FormKind::Symbol(this_name.clone()), span.clone()),
2096 ])
2097 };
2098 bindings.push(Form::new(accessor, span.clone()));
2099 }
2100 if !mutable_fields.is_empty() {
2103 bindings.push(Form::new(
2104 FormKind::Symbol(DEFTYPE_SELF.to_string()),
2105 span.clone(),
2106 ));
2107 bindings.push(Form::new(FormKind::Symbol(this_name.clone()), span.clone()));
2108 }
2109 if bindings.is_empty() {
2110 return None;
2111 }
2112
2113 let mut let_forms = vec![
2114 Form::new(FormKind::Symbol("let*".to_string()), span.clone()),
2115 Form::new(FormKind::Vector(bindings), span.clone()),
2116 ];
2117 let_forms.extend_from_slice(body);
2118 Some(vec![Form::new(FormKind::List(let_forms), span)])
2119}
2120
2121fn build_impl_fn(
2122 parts: &[Form],
2123 fields: &[Arc<str>],
2124 mutable_fields: &[Arc<str>],
2125 env: &mut Env,
2126) -> EvalResult<Value> {
2127 if parts.len() < 2 {
2128 return Err(EvalError::Runtime(
2129 "protocol method impl requires params and body".into(),
2130 ));
2131 }
2132 let params_form = &parts[1];
2134 let body = &parts[2..];
2135 let scoped;
2136 let body: &[Form] = if fields.is_empty() {
2137 body
2138 } else {
2139 match synth_field_scope(params_form, fields, mutable_fields, body) {
2140 Some(v) => {
2141 scoped = v;
2142 &scoped
2143 }
2144 None => body,
2145 }
2146 };
2147 let arity = parse_arity(params_form, body)?;
2148 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
2149 let fn_name: Option<Arc<str>> = parts[0].as_symbol().map(Arc::from);
2150 let cljrs_fn = CljxFn::new(
2151 fn_name,
2152 vec![arity],
2153 closed_over_names,
2154 closed_over_vals,
2155 false,
2156 Arc::clone(&env.current_ns),
2157 );
2158 Ok(Value::Fn(GcPtr::new(cljrs_fn)))
2159}
2160
2161fn eval_binding(args: &[Form], env: &mut Env) -> EvalResult {
2164 let pairs = match args.first().and_then(|f| f.as_vector()) {
2165 Some(v) => expand_pairs(v)
2166 .map_err(|_| EvalError::Runtime("binding vector must have even count".into()))?
2167 .into_owned(),
2168 None => return Err(EvalError::Runtime("binding requires a vector".into())),
2169 };
2170
2171 let mut frame: HashMap<usize, Value> = HashMap::new();
2172 for pair in pairs.chunks(2) {
2173 let Some(sym_str) = pair[0].as_symbol() else {
2174 return Err(EvalError::Runtime("binding targets must be symbols".into()));
2175 };
2176 let parsed = cljrs_value::Symbol::parse(sym_str);
2177 let ns_part: Arc<str> = env.resolve_ns_or_current(parsed.namespace.as_deref());
2178 let var_ptr = env
2179 .globals
2180 .lookup_var_in_ns(&ns_part, &parsed.name)
2181 .ok_or_else(|| EvalError::UnboundSymbol(sym_str.to_string()))?;
2182 let val = eval(&pair[1], env)?;
2183 frame.insert(crate::env::dynamics::var_key_of(&var_ptr), val);
2184 }
2185
2186 let _guard = crate::env::dynamics::push_frame(frame);
2187 eval_body(&args[1..], env)
2188 }
2190
2191const DEFTYPE_SELF: &str = "__deftype_self__";
2197
2198fn meta_form_is_mutable(meta: &Form) -> bool {
2202 let is_mut_kw = |k: &str| k == "unsynchronized-mutable" || k == "volatile-mutable";
2203 match &meta.kind {
2204 FormKind::Keyword(k) => is_mut_kw(k),
2205 FormKind::Map(entries) => entries.chunks(2).any(|kv| {
2206 matches!(&kv[0].kind, FormKind::Keyword(k) if is_mut_kw(k))
2207 && !matches!(
2208 kv.get(1).map(|f| &f.kind),
2209 None | Some(FormKind::Bool(false)) | Some(FormKind::Nil)
2210 )
2211 }),
2212 FormKind::Quote(inner) => meta_form_is_mutable(inner),
2218 _ => false,
2219 }
2220}
2221
2222fn field_spec_of(form: &Form) -> Option<(Arc<str>, bool)> {
2224 match &form.kind {
2225 FormKind::Symbol(s) => Some((Arc::from(s.as_str()), false)),
2226 FormKind::Meta(meta, inner) => {
2227 let here = meta_form_is_mutable(meta);
2228 field_spec_of(inner).map(|(name, inner_mut)| (name, inner_mut || here))
2229 }
2230 _ => None,
2231 }
2232}
2233
2234fn parse_field_specs(form: &Form, ctx: &str) -> EvalResult<Vec<(Arc<str>, bool)>> {
2236 let Some(fields) = form.as_vector() else {
2239 return Err(EvalError::Runtime(format!(
2240 "{ctx} requires a field vector as second arg"
2241 )));
2242 };
2243 fields
2244 .iter()
2245 .map(|f| {
2246 field_spec_of(f)
2247 .ok_or_else(|| EvalError::Runtime(format!("{ctx} field names must be symbols")))
2248 })
2249 .collect()
2250}
2251
2252fn eval_deftype_star(args: &[Form], env: &mut Env) -> EvalResult {
2260 if args.len() < 2 {
2262 return Err(EvalError::Runtime(
2263 "deftype* requires a name and field vector".into(),
2264 ));
2265 }
2266 let (type_name, _) = require_sym_meta(args, 0, "deftype*", env)?;
2269 let type_tag: Arc<str> = Arc::from(type_name.as_str());
2270
2271 let specs = parse_field_specs(&args[1], "deftype*")?;
2272 let field_names: Vec<Arc<str>> = specs.iter().map(|(n, _)| n.clone()).collect();
2273 let mutable_names: Vec<Arc<str>> = specs
2274 .iter()
2275 .filter(|(_, m)| *m)
2276 .map(|(n, _)| n.clone())
2277 .collect();
2278
2279 register_impls_for_tag(&type_tag, &args[2..], &field_names, &mutable_names, env)?;
2283 Ok(Value::string(type_name))
2287}
2288
2289fn resolve_protocol_sym(env: &Env, s: &str) -> Option<GcPtr<Protocol>> {
2302 let parsed = cljrs_value::Symbol::parse(s);
2303 let val = match parsed.namespace.as_deref() {
2304 Some(ns_part) => {
2305 let ns = env.resolve_ns_part(ns_part);
2306 env.globals.lookup_in_ns(&ns, &parsed.name)
2307 }
2308 None => env.globals.lookup_in_ns(&env.current_ns, s),
2309 };
2310 match val {
2311 Some(Value::Protocol(p)) => Some(p),
2312 _ => None,
2313 }
2314}
2315
2316fn register_impls_for_tag(
2319 type_tag: &Arc<str>,
2320 forms: &[Form],
2321 fields: &[Arc<str>],
2322 mutable_fields: &[Arc<str>],
2323 env: &mut Env,
2324) -> EvalResult<()> {
2325 let mut current_proto: Option<GcPtr<cljrs_value::Protocol>> = None;
2326
2327 for form in forms {
2328 match &form.unmeta().kind {
2329 FormKind::Symbol(s) => match resolve_protocol_sym(env, s) {
2330 Some(p) => current_proto = Some(p),
2331 None => {
2332 return Err(EvalError::Runtime(format!(
2333 "reify/defrecord: {} is not a protocol",
2334 s
2335 )));
2336 }
2337 },
2338 FormKind::List(parts) => {
2339 let proto = current_proto.as_ref().ok_or_else(|| {
2340 EvalError::Runtime("reify/defrecord: method impl before protocol name".into())
2341 })?;
2342 if parts.is_empty() {
2343 continue;
2344 }
2345 let method_name: Arc<str> = match parts[0].as_symbol() {
2346 Some(s) => Arc::from(s),
2347 None => continue,
2348 };
2349 let fn_val = build_impl_fn(parts, fields, mutable_fields, env)?;
2350 let mut impls = proto.get().impls.lock().unwrap();
2351 impls
2352 .entry(type_tag.clone())
2353 .or_default()
2354 .insert(method_name, fn_val);
2355 drop(impls);
2356 cljrs_value::bump_protocol_generation();
2357 }
2358 _ => {}
2359 }
2360 }
2361 Ok(())
2362}
2363
2364pub fn sync_star_ns(env: &mut Env) {
2369 if let Some(star_ns_var) = env.globals.lookup_var("clojure.core", "*ns*") {
2370 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
2371 star_ns_var.get().bind(Value::Namespace(ns_ptr));
2372 }
2373}
2374
2375fn require_sym_meta(
2387 args: &[Form],
2388 idx: usize,
2389 form_name: &str,
2390 env: &mut Env,
2391) -> EvalResult<(String, Option<Value>)> {
2392 fn peel(form: &Form, env: &mut Env) -> EvalResult<Option<(String, Option<Value>)>> {
2393 match &form.kind {
2394 FormKind::Symbol(s) => Ok(Some((s.clone(), None))),
2395 FormKind::Meta(meta_form, inner) => {
2397 let meta_val = compile_meta_form(meta_form, env)?;
2398 match peel(inner, env)? {
2399 Some((name, inner_meta)) => {
2400 Ok(Some((name, merge_meta(inner_meta, Some(meta_val)))))
2401 }
2402 None => Ok(None),
2403 }
2404 }
2405 _ => Ok(None),
2406 }
2407 }
2408 let err = || EvalError::Runtime(format!("{form_name} requires a symbol at position {idx}"));
2409 match args.get(idx) {
2410 Some(form) => peel(form, env)?.ok_or_else(err),
2411 None => Err(err()),
2412 }
2413}
2414
2415fn eval_with_out_str(body: &[Form], env: &mut Env) -> EvalResult {
2418 crate::builtins::builtins::push_output_capture();
2419 let result = eval_body(body, env);
2420 let captured = crate::builtins::builtins::pop_output_capture().unwrap_or_default();
2421 result?;
2423 Ok(Value::string(captured))
2424}
2425
2426fn eval_await(args: &[Form], env: &mut Env) -> EvalResult {
2435 if args.is_empty() {
2436 return Err(EvalError::Runtime("await requires one argument".into()));
2437 }
2438 let val = eval(&args[0], env)?;
2439 match val {
2440 Value::Future(f) => {
2441 let mut guard = f.get().state.lock().unwrap();
2442 loop {
2443 match &*guard {
2444 FutureState::Done(v) => {
2445 f.get().mark_observed();
2446 return Ok(v.clone());
2447 }
2448 FutureState::Failed(v) => {
2449 f.get().mark_observed();
2450 return Err(EvalError::Thrown(v.clone()));
2451 }
2452 FutureState::GasExhausted => {
2453 f.get().mark_observed();
2454 return Err(EvalError::GasExhausted);
2455 }
2456 FutureState::Cancelled => {
2457 return Err(EvalError::Thrown(CljxFuture::cancelled_error()));
2458 }
2459 FutureState::Running => {
2460 guard = f.get().cond.wait(guard).unwrap();
2461 }
2462 }
2463 }
2464 }
2465 Value::Promise(p) => Ok(p.get().deref_blocking()),
2466 other => Ok(other),
2467 }
2468}