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
204pub fn meta_form_is_async(meta: &Form) -> bool {
211 match &meta.kind {
212 FormKind::Keyword(k) => k == "async",
213 FormKind::Map(entries) => entries.chunks(2).any(|kv| {
214 matches!(&kv[0].kind, FormKind::Keyword(k) if k == "async")
215 && !matches!(
216 kv.get(1).map(|f| &f.kind),
217 None | Some(FormKind::Bool(false)) | Some(FormKind::Nil)
218 )
219 }),
220 _ => false,
221 }
222}
223
224fn eval_fn(args: &[Form], env: &mut Env) -> EvalResult {
225 let mut is_async = false;
228 let peeled: Vec<Form>;
229 let args: &[Form] = if matches!(args.first().map(|f| &f.kind), Some(FormKind::Meta(..))) {
230 let (metas, head) = args[0].peel_meta();
231 is_async |= metas.iter().any(|m| meta_form_is_async(m));
232 peeled = std::iter::once(head.clone())
233 .chain(args[1..].iter().cloned())
234 .collect();
235 &peeled
236 } else {
237 args
238 };
239
240 let mut idx = 0;
241 let mut name: Option<Arc<str>> = None;
242
243 if let Some(FormKind::Symbol(s)) = args.first().map(|f| &f.kind)
245 && !is_special_form(s)
246 {
247 name = Some(Arc::from(s.as_str()));
248 idx = 1;
249 }
250
251 let rest = &args[idx..];
252 if rest.is_empty() {
253 return Err(EvalError::Runtime("fn* requires params and body".into()));
254 }
255
256 let arities = match &rest[0].unmeta().kind {
259 FormKind::Vector(_) => {
260 vec![parse_arity(&rest[0], &rest[1..])?]
262 }
263 FormKind::List(_) => {
264 rest.iter()
266 .map(|arity_form| {
267 if let Some(forms) = arity_form.as_list() {
268 if forms.is_empty() {
269 return Err(EvalError::Runtime("arity clause requires params".into()));
270 }
271 parse_arity(&forms[0], &forms[1..])
272 } else {
273 Err(EvalError::Runtime("expected arity clause (list)".into()))
274 }
275 })
276 .collect::<EvalResult<Vec<_>>>()?
277 }
278 _ => {
279 return Err(EvalError::Runtime(
280 "fn* expects vector or arity clauses".into(),
281 ));
282 }
283 };
284
285 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
287
288 let mut cljrs_fn = CljxFn::new(
289 name.clone(),
290 arities,
291 closed_over_names,
292 closed_over_vals,
293 false,
294 Arc::clone(&env.current_ns),
295 );
296 cljrs_fn.is_async = is_async;
297
298 env.on_fn_defined(&cljrs_fn);
299
300 let mut ptr = GcPtr::new(cljrs_fn);
304 if ptr.get().name.is_some() {
308 let self_clone = ptr.clone();
309 ptr.get_mut().self_ptr = Some(self_clone);
310 }
311 Ok(Value::Fn(ptr))
312}
313
314pub fn parse_arity(params_form: &Form, body: &[Form]) -> EvalResult<CljxFnArity> {
316 let Some(param_forms) = params_form.as_vector() else {
317 return Err(EvalError::Runtime(
318 "fn arity params must be a vector".into(),
319 ));
320 };
321
322 let mut params: Vec<Arc<str>> = Vec::new();
323 let mut param_hints: Vec<Option<TypeHint>> = Vec::new();
324 let mut rest_param: Option<Arc<str>> = None;
325 let mut rest_hint: Option<TypeHint> = None;
326 let mut destructure_params: Vec<(usize, Form)> = Vec::new();
327 let mut destructure_rest: Option<Form> = None;
328 let mut saw_amp = false;
329
330 for p in param_forms {
331 let (hint, p) = peel_param_hint(p);
337 match &p.kind {
338 FormKind::Symbol(s) if s == "&" => {
339 saw_amp = true;
340 }
341 FormKind::Symbol(s) => {
342 if saw_amp {
343 rest_param = Some(Arc::from(s.as_str()));
344 rest_hint = hint;
345 break;
346 } else {
347 params.push(Arc::from(s.as_str()));
348 param_hints.push(hint);
349 }
350 }
351 FormKind::Vector(_) | FormKind::Map(_) => {
353 if saw_amp {
354 let gensym = format!("__destructure_rest_{}", params.len());
355 rest_param = Some(Arc::from(gensym.as_str()));
356 destructure_rest = Some(p.clone());
357 break;
358 } else {
359 let idx = params.len();
360 let gensym = format!("__destructure_{idx}");
361 params.push(Arc::from(gensym.as_str()));
362 param_hints.push(None);
364 destructure_params.push((idx, p.clone()));
365 }
366 }
367 _ => {
368 return Err(EvalError::Runtime(
369 "fn params must be symbols, vectors, or maps".into(),
370 ));
371 }
372 }
373 }
374
375 let body = desugar_pre_post_conditions(body);
376
377 Ok(CljxFnArity {
378 params,
379 rest_param,
380 body,
381 destructure_params,
382 destructure_rest,
383 ir_arity_id: crate::interp::arity::fresh_arity_id(),
384 param_hints,
385 rest_hint,
386 })
387}
388
389fn desugar_pre_post_conditions(body: &[Form]) -> Vec<Form> {
407 let first = match body.first() {
408 Some(f) => f,
409 None => return body.to_vec(),
410 };
411
412 let entries = match first.as_map() {
413 Some(entries) => entries,
414 None => return body.to_vec(),
415 };
416
417 let mut pre_conds: Vec<Form> = Vec::new();
418 let mut post_conds: Vec<Form> = Vec::new();
419 let mut has_conditions = false;
420
421 for chunk in entries.chunks(2) {
422 if chunk.len() < 2 {
423 break;
424 }
425 let (key, val) = (&chunk[0], &chunk[1]);
426 match &key.kind {
427 FormKind::Keyword(k) if k == "pre" => {
428 if let FormKind::Vector(conds) = &val.kind {
429 pre_conds.extend_from_slice(conds);
430 has_conditions = true;
431 }
432 }
433 FormKind::Keyword(k) if k == "post" => {
434 if let FormKind::Vector(conds) = &val.kind {
435 post_conds.extend_from_slice(conds);
436 has_conditions = true;
437 }
438 }
439 _ => {}
440 }
441 }
442
443 if !has_conditions {
444 return body.to_vec();
445 }
446
447 let real_body = &body[1..]; let span = first.span.clone();
449 let mut new_body: Vec<Form> = Vec::new();
450
451 for cond in &pre_conds {
453 new_body.push(make_assert_call(cond, &span));
454 }
455
456 if post_conds.is_empty() {
457 new_body.extend_from_slice(real_body);
458 } else {
459 let percent = Form::new(FormKind::Symbol("%".to_string()), span.clone());
462
463 let body_expr = if real_body.len() == 1 {
464 real_body[0].clone()
465 } else {
466 let mut do_forms = vec![Form::new(FormKind::Symbol("do".to_string()), span.clone())];
467 do_forms.extend_from_slice(real_body);
468 Form::new(FormKind::List(do_forms), span.clone())
469 };
470
471 let binding_vec = Form::new(
472 FormKind::Vector(vec![percent.clone(), body_expr]),
473 span.clone(),
474 );
475
476 let mut let_forms = vec![
477 Form::new(FormKind::Symbol("let*".to_string()), span.clone()),
478 binding_vec,
479 ];
480 for cond in &post_conds {
481 let_forms.push(make_assert_call(cond, &span));
482 }
483 let_forms.push(percent);
484
485 new_body.push(Form::new(FormKind::List(let_forms), span));
486 }
487
488 new_body
489}
490
491fn make_assert_call(cond: &Form, span: &cljrs_types::span::Span) -> Form {
493 Form::new(
494 FormKind::List(vec![
495 Form::new(FormKind::Symbol("assert".to_string()), span.clone()),
496 cond.clone(),
497 ]),
498 span.clone(),
499 )
500}
501
502fn peel_param_hint(p: &Form) -> (Option<TypeHint>, &Form) {
506 if let FormKind::Meta(meta, inner) = &p.kind {
507 let hint = tag_name_of_meta(meta).and_then(|n| TypeHint::from_tag(&n));
508 let (inner_hint, inner_form) = peel_param_hint(inner);
510 (hint.or(inner_hint), inner_form)
511 } else {
512 (None, p)
513 }
514}
515
516fn tag_name_of_meta(meta: &Form) -> Option<Arc<str>> {
519 match &meta.kind {
520 FormKind::Symbol(s) => Some(strip_tag_ns(s)),
522 FormKind::Map(entries) => entries.chunks(2).find_map(|kv| {
524 let is_tag = matches!(&kv[0].kind, FormKind::Keyword(k) if k == "tag");
525 if !is_tag {
526 return None;
527 }
528 match kv.get(1).map(|f| &f.kind) {
529 Some(FormKind::Symbol(s)) => Some(strip_tag_ns(s)),
530 Some(FormKind::Str(s)) => Some(strip_tag_ns(s)),
531 _ => None,
532 }
533 }),
534 _ => None,
535 }
536}
537
538fn strip_tag_ns(s: &str) -> Arc<str> {
540 match s.rfind('/') {
541 Some(pos) if pos + 1 < s.len() => Arc::from(&s[pos + 1..]),
542 _ => Arc::from(s),
543 }
544}
545
546fn eval_if(args: &[Form], env: &mut Env) -> EvalResult {
549 if args.is_empty() {
550 return Err(EvalError::Runtime("if requires a test".into()));
551 }
552 let test = eval(&args[0], env)?;
553 let truthy = !matches!(test, Value::Nil | Value::Bool(false));
554 if truthy {
555 if args.len() > 1 {
556 eval(&args[1], env)
557 } else {
558 Ok(Value::Nil)
559 }
560 } else if args.len() > 2 {
561 eval(&args[2], env)
562 } else {
563 Ok(Value::Nil)
564 }
565}
566
567fn eval_let(args: &[Form], env: &mut Env) -> EvalResult {
570 let bindings = match args.first().and_then(|f| f.as_vector()) {
571 Some(v) => expand_pairs(v)
572 .map_err(|_| EvalError::Runtime("let* binding vector must have even length".into()))?
573 .into_owned(),
574 None => return Err(EvalError::Runtime("let* requires a binding vector".into())),
575 };
576
577 let body = &args[1..];
578
579 let chains = crate::interp::virtualize::detect_let_chains(&bindings);
581 let virtualizable_chains = find_virtualizable_chains(&chains, &bindings, body);
582
583 env.push_frame();
584
585 let pairs: Vec<_> = bindings.chunks(2).collect();
586 let mut i = 0;
587 while i < pairs.len() {
588 if let Some(chain) = virtualizable_chains.iter().find(|c| c.start == i) {
590 match eval_virtualized_chain(chain, &pairs, env) {
591 Ok(()) => {
592 i += chain.len;
593 continue;
594 }
595 Err(e) => {
596 env.pop_frame();
597 return Err(e);
598 }
599 }
600 }
601
602 let pair = pairs[i];
604 let val = match eval(&pair[1], env) {
605 Ok(v) => v,
606 Err(e) => {
607 env.pop_frame();
608 return Err(e);
609 }
610 };
611 if let Err(e) = bind_pattern(&pair[0], val, env) {
612 env.pop_frame();
613 return Err(e);
614 }
615 i += 1;
616 }
617
618 let result = eval_body(body, env);
619 env.pop_frame();
620 result
621}
622
623fn find_virtualizable_chains<'a>(
628 chains: &'a [crate::interp::virtualize::LetChain],
629 bindings: &[Form],
630 body: &[Form],
631) -> Vec<&'a crate::interp::virtualize::LetChain> {
632 chains
633 .iter()
634 .filter(|chain| {
635 for j in chain.start..(chain.start + chain.len - 1) {
638 let name = match &bindings[j * 2].kind {
639 FormKind::Symbol(s) => s.as_str(),
640 _ => return false,
641 };
642 if crate::interp::virtualize::binding_used_in_body(name, body) {
643 return false;
644 }
645 if crate::interp::virtualize::binding_used_in_other_bindings(
646 name,
647 bindings,
648 chain.start,
649 chain.len,
650 ) {
651 return false;
652 }
653 }
654 true
655 })
656 .collect()
657}
658
659fn eval_virtualized_chain(
669 chain: &crate::interp::virtualize::LetChain,
670 pairs: &[&[Form]],
671 env: &mut Env,
672) -> Result<(), EvalError> {
673 use crate::builtins::transients::{
674 builtin_assoc_bang, builtin_conj_bang, builtin_persistent_bang, builtin_transient,
675 };
676
677 let first_pair = pairs[chain.start];
679 let first_expr_forms = match &first_pair[1].kind {
680 FormKind::List(forms) => forms,
681 _ => unreachable!("chain detection ensures this is a list"),
682 };
683 let root_collection = eval(&first_expr_forms[1], env)?;
684
685 let mut transient = match builtin_transient(std::slice::from_ref(&root_collection)) {
687 Ok(t) => t,
688 Err(_) => {
689 return eval_chain_normally(chain, pairs, env);
692 }
693 };
694
695 for j in 0..chain.len {
697 let pair_idx = chain.start + j;
698 let pair = pairs[pair_idx];
699 let expr_forms = match &pair[1].kind {
700 FormKind::List(forms) => forms,
701 _ => unreachable!(),
702 };
703
704 let mut args = vec![transient.clone()];
706 for arg_form in expr_forms.iter().skip(2) {
707 args.push(eval(arg_form, env)?);
708 }
709
710 transient = match chain.ops[j] {
712 crate::interp::virtualize::ChainOpKind::Assoc => {
713 builtin_assoc_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
714 }
715 crate::interp::virtualize::ChainOpKind::Conj => {
716 builtin_conj_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
717 }
718 };
719
720 if j < chain.len - 1 {
724 let name = match &pair[0].kind {
725 FormKind::Symbol(s) => s.clone(),
726 _ => unreachable!(),
727 };
728 env.bind(Arc::from(name.as_str()), Value::Nil);
730 }
731 }
732
733 let persistent =
735 builtin_persistent_bang(&[transient]).map_err(|e| EvalError::Runtime(e.to_string()))?;
736
737 let last_pair = pairs[chain.start + chain.len - 1];
739 bind_pattern(&last_pair[0], persistent, env)?;
740
741 Ok(())
742}
743
744fn eval_chain_normally(
746 chain: &crate::interp::virtualize::LetChain,
747 pairs: &[&[Form]],
748 env: &mut Env,
749) -> Result<(), EvalError> {
750 for j in 0..chain.len {
751 let pair_idx = chain.start + j;
752 let pair = pairs[pair_idx];
753 let val = eval(&pair[1], env)?;
754 bind_pattern(&pair[0], val, env)?;
755 }
756 Ok(())
757}
758
759pub fn eval_loop(args: &[Form], env: &mut Env) -> EvalResult {
762 let bindings = match args.first().and_then(|f| f.as_vector()) {
763 Some(v) => expand_pairs(v)
764 .map_err(|_| EvalError::Runtime("loop* binding vector must have even length".into()))?
765 .into_owned(),
766 None => return Err(EvalError::Runtime("loop* requires a binding vector".into())),
767 };
768
769 let body = &args[1..];
770
771 let patterns: Vec<Form> = bindings.iter().step_by(2).cloned().collect();
773 let mut current_vals: Vec<Value> = Vec::new();
774
775 for i in (1..bindings.len()).step_by(2) {
777 current_vals.push(eval(&bindings[i], env)?);
778 }
779
780 loop {
781 let _vals_root = crate::env::gc_roots::root_values(¤t_vals);
783
784 crate::env::gc_roots::gc_safepoint(env);
787
788 #[cfg(feature = "no-gc")]
792 let mut scratch = cljrs_gc::alloc_ctx::ScratchGuard::new();
793
794 #[cfg(not(feature = "no-gc"))]
805 let _iter_frame = cljrs_gc::push_alloc_frame();
806
807 env.push_frame();
808 for (pat, val) in patterns.iter().zip(current_vals.iter()) {
809 if let Err(e) = bind_pattern(pat, val.clone(), env) {
810 env.pop_frame();
811 return Err(e);
812 }
813 }
814
815 #[cfg(not(feature = "no-gc"))]
818 let result = eval_body_recur(body, env);
819 #[cfg(feature = "no-gc")]
820 let result = eval_body_with_scratch_loop(body, &mut scratch, env);
821
822 env.pop_frame();
823 match result {
827 Ok(v) => return Ok(v),
828 Err(EvalError::Recur(new_vals)) => {
829 if new_vals.len() != patterns.len() {
830 return Err(EvalError::Arity {
831 name: "recur".into(),
832 expected: patterns.len().to_string(),
833 got: new_vals.len(),
834 });
835 }
836 current_vals = new_vals;
839 }
840 Err(e) => return Err(e),
841 }
842 }
843}
844
845fn eval_recur(args: &[Form], env: &mut Env) -> EvalResult {
846 let vals: Vec<Value> = args
847 .iter()
848 .map(|f| eval(f, env))
849 .collect::<EvalResult<_>>()?;
850 Err(EvalError::Recur(vals))
851}
852
853pub fn eval_body_recur(body: &[Form], env: &mut Env) -> EvalResult {
855 let mut result = Value::Nil;
856 for form in body {
857 result = eval(form, env)?;
858 }
859 Ok(result)
860}
861
862#[cfg(feature = "no-gc")]
868fn eval_body_with_scratch_loop(
869 body: &[Form],
870 scratch: &mut cljrs_gc::alloc_ctx::ScratchGuard,
871 env: &mut Env,
872) -> EvalResult {
873 if body.is_empty() {
874 scratch.pop_for_return();
875 return Ok(Value::Nil);
876 }
877 for form in &body[..body.len() - 1] {
878 eval(form, env)?;
879 }
880 scratch.pop_for_return();
881 eval(&body[body.len() - 1], env)
882}
883
884fn eval_quote(args: &[Form], env: &Env) -> EvalResult {
887 match args.first() {
888 Some(f) => form_to_value(&resolve_auto_forms(f, env)?),
892 None => Err(EvalError::Runtime("quote requires an argument".into())),
893 }
894}
895
896fn eval_var(args: &[Form], env: &mut Env) -> EvalResult {
899 let sym = match args.first().map(|f| &f.kind) {
900 Some(FormKind::Symbol(s)) => s.clone(),
901 _ => return Err(EvalError::Runtime("var requires a symbol".into())),
902 };
903 let parsed = cljrs_value::Symbol::parse(&sym);
904 let ns: Arc<str> = env.resolve_ns_or_current(parsed.namespace.as_deref());
905 let name = parsed.name.as_ref();
906 env.globals
907 .lookup_var_in_ns(&ns, name)
908 .map(Value::Var)
909 .ok_or_else(|| EvalError::UnboundSymbol(sym))
910}
911
912fn eval_set_bang(args: &[Form], env: &mut Env) -> EvalResult {
915 let target = args
916 .first()
917 .ok_or_else(|| EvalError::Runtime("set! requires a target".into()))?;
918 let val = if args.len() > 1 {
919 eval(&args[1], env)?
920 } else {
921 Value::Nil
922 };
923 match &target.kind {
924 FormKind::Symbol(sym) => set_bang_symbol(sym, val, env),
925 _ => match set_bang_field_target(target) {
926 Some((field, inst_form)) => {
927 let inst = eval(inst_form, env)?;
928 set_type_instance_field(&inst, field, val)
929 }
930 None => Err(set_bang_target_error()),
931 },
932 }
933}
934
935pub fn set_bang_symbol(sym: &str, val: Value, env: &mut Env) -> EvalResult {
938 if !sym.contains('/')
941 && let Some(v) = try_set_mutable_field(env, sym, &val)?
942 {
943 return Ok(v);
944 }
945 let parsed = cljrs_value::Symbol::parse(sym);
946 let ns = parsed.namespace.as_deref().unwrap_or(&env.current_ns);
947 let var = env
948 .globals
949 .lookup_var_in_ns(ns, &parsed.name)
950 .ok_or_else(|| EvalError::UnboundSymbol(sym.to_string()))?;
951 if !crate::env::dynamics::set_thread_local(&var, val.clone()) {
953 var.get().bind(val.clone());
954 }
955 Ok(val)
956}
957
958pub fn set_bang_field_target(target: &Form) -> Option<(&str, &Form)> {
961 match &target.kind {
962 FormKind::List(parts) if parts.len() == 2 => match &parts[0].kind {
963 FormKind::Symbol(op) if op.starts_with(".-") => Some((&op[2..], &parts[1])),
964 _ => None,
965 },
966 _ => None,
967 }
968}
969
970pub fn set_bang_target_error() -> EvalError {
972 EvalError::Runtime("set! requires a symbol or (.-field inst) target".into())
973}
974
975fn try_set_mutable_field(env: &mut Env, sym: &str, val: &Value) -> EvalResult<Option<Value>> {
980 let Some(Value::TypeInstance(ti)) = env.lookup_local_frames(DEFTYPE_SELF) else {
981 return Ok(None);
982 };
983 let Some(atom) = ti.get().mutable.clone() else {
984 return Ok(None);
985 };
986 let key = Value::keyword(cljrs_value::Keyword::simple(sym));
987 let Value::Map(map) = atom.get().deref() else {
988 return Ok(None);
989 };
990 if map.get(&key).is_none() {
991 return Ok(None);
992 }
993 atom.get().reset(Value::Map(map.assoc(key, val.clone())));
994 env.bind(Arc::from(sym), val.clone());
996 Ok(Some(val.clone()))
997}
998
999pub fn set_type_instance_field(inst: &Value, field: &str, val: Value) -> EvalResult {
1001 let Value::TypeInstance(ti) = inst else {
1002 return Err(EvalError::Runtime(format!(
1003 "set! (.-{field} …): target is not a type instance"
1004 )));
1005 };
1006 let atom = ti.get().mutable.clone().ok_or_else(|| {
1007 EvalError::Runtime(format!("set! (.-{field} …): type has no mutable fields"))
1008 })?;
1009 let key = Value::keyword(cljrs_value::Keyword::simple(field));
1010 let map = match atom.get().deref() {
1011 Value::Map(m) => m,
1012 _ => MapValue::empty(),
1013 };
1014 if map.get(&key).is_none() {
1015 return Err(EvalError::Runtime(format!(
1016 "set!: {field} is not a mutable field"
1017 )));
1018 }
1019 atom.get().reset(Value::Map(map.assoc(key, val.clone())));
1020 Ok(val)
1021}
1022
1023fn eval_throw(args: &[Form], env: &mut Env) -> EvalResult {
1026 let val = match args.first() {
1027 Some(f) => eval(f, env)?,
1028 None => Value::Nil,
1029 };
1030 Err(throw_value(val))
1031}
1032
1033pub fn throw_value(val: Value) -> EvalError {
1038 let val = match val {
1039 Value::Error(_) => val,
1040 other => {
1041 let msg = format!("{}", other);
1042 Value::Error(GcPtr::new(ExceptionInfo::new(
1043 ValueError::Other(msg.clone()),
1044 msg,
1045 None,
1046 None,
1047 )))
1048 }
1049 };
1050 EvalError::Thrown(val)
1051}
1052
1053pub struct CatchClause<'a> {
1060 pub type_sym: &'a str,
1061 pub binding: &'a str,
1062 pub body: &'a [Form],
1063}
1064
1065pub fn eval_error_to_value(err: &EvalError) -> Value {
1070 let msg = err.to_string();
1071 Value::Error(GcPtr::new(ExceptionInfo::new(
1072 ValueError::Other(msg.clone()),
1073 msg,
1074 None,
1075 None,
1076 )))
1077}
1078
1079pub fn catch_type_matches(type_name: &str, val: &Value) -> bool {
1083 let short = type_name.rsplit('.').next().unwrap_or(type_name);
1084 match short {
1085 "Object" | "Exception" | "Throwable" | "Error" | "default" => true,
1089 "ExceptionInfo" => matches!(val, Value::Error(_)),
1091 _ => false,
1092 }
1093}
1094
1095fn eval_try(args: &[Form], env: &mut Env) -> EvalResult {
1096 let (body, catches, fin_body) = parse_try_args(args);
1097
1098 let mut result = eval_body(body, env);
1099
1100 let err_opt = match std::mem::replace(&mut result, Ok(Value::Nil)) {
1102 Ok(v) => {
1103 result = Ok(v);
1104 None
1105 }
1106 Err(EvalError::Recur(args)) => {
1107 result = Err(EvalError::Recur(args));
1108 None
1109 }
1110 Err(EvalError::GasExhausted) => {
1111 result = Err(EvalError::GasExhausted);
1112 None
1113 }
1114 Err(other) => Some(other),
1115 };
1116
1117 if let Some(err) = err_opt {
1118 let thrown_val = match err {
1119 EvalError::Thrown(v) => v,
1120 ref other => eval_error_to_value(other),
1121 };
1122 let mut handled = false;
1123 for c in &catches {
1124 if catch_type_matches(c.type_sym, &thrown_val) {
1125 env.push_frame();
1126 env.bind(Arc::from(c.binding), thrown_val.clone());
1127 result = eval_body(c.body, env);
1128 env.pop_frame();
1129 handled = true;
1130 break;
1131 }
1132 }
1133 if !handled {
1134 result = Err(EvalError::Thrown(thrown_val));
1136 }
1137 }
1138
1139 if !fin_body.is_empty() {
1143 eval_body(fin_body, env)?;
1144 }
1145
1146 result
1147}
1148
1149fn catch_target(f: &Form) -> Option<&str> {
1151 f.as_symbol().or_else(|| f.as_keyword())
1152}
1153
1154pub fn parse_try_args(args: &[Form]) -> (&[Form], Vec<CatchClause<'_>>, &[Form]) {
1158 let mut body_end = args.len();
1159 let mut catches: Vec<CatchClause<'_>> = Vec::new();
1160 let mut fin_body: &[Form] = &[];
1161
1162 for (i, form) in args.iter().enumerate() {
1163 if let Some(parts) = form.as_list()
1164 && let Some(s) = parts.first().and_then(|f| f.as_symbol())
1165 {
1166 if s == "catch" {
1167 if i < body_end {
1168 body_end = i;
1169 }
1170 let type_sym = match parts.get(1) {
1175 Some(f) => match catch_target(f) {
1176 Some(name) => name,
1177 None => match &f.unmeta().kind {
1178 FormKind::ReaderCond {
1179 splicing: false,
1180 clauses,
1181 } => match select_reader_cond(clauses).and_then(catch_target) {
1182 Some(name) => name,
1183 None => continue,
1184 },
1185 _ => continue,
1186 },
1187 },
1188 None => continue,
1189 };
1190 let binding = match parts.get(2).and_then(|f| f.as_symbol()) {
1191 Some(s) => s,
1192 None => continue,
1193 };
1194 catches.push(CatchClause {
1195 type_sym,
1196 binding,
1197 body: &parts[3..],
1198 });
1199 continue;
1200 }
1201 if s == "finally" {
1202 if i < body_end {
1203 body_end = i;
1204 }
1205 fin_body = &parts[1..];
1206 continue;
1207 }
1208 }
1209 }
1210
1211 (&args[..body_end], catches, fin_body)
1212}
1213
1214pub fn eval_defn(args: &[Form], env: &mut Env, private: bool) -> EvalResult {
1217 let name_form = args
1219 .first()
1220 .ok_or_else(|| EvalError::Runtime("defn requires a symbol name".into()))?;
1221 let (name_metas, name_sym) = name_form.peel_meta();
1222 let (name, mut is_async) = match &name_sym.kind {
1223 FormKind::Symbol(s) => (s.clone(), name_metas.iter().any(|m| meta_form_is_async(m))),
1224 _ => return Err(EvalError::Runtime("defn name must be a symbol".into())),
1225 };
1226 let mut rest_start = 1;
1230 let mut docstring: Option<String> = None;
1231 if rest_start < args.len()
1232 && let Some(s) = args[rest_start].as_string()
1233 {
1234 docstring = Some(s.to_string());
1235 rest_start += 1;
1236 }
1237 let mut attr_meta: Option<Value> = None;
1238 if rest_start < args.len() && args[rest_start].as_map().is_some() {
1239 is_async |= meta_form_is_async(&args[rest_start]);
1241 attr_meta = Some(eval(&args[rest_start], env)?);
1242 rest_start += 1;
1243 }
1244 let mut fn_args = vec![Form::new(
1246 FormKind::Symbol(name.to_string()),
1247 args[0].span.clone(),
1248 )];
1249 fn_args.extend_from_slice(&args[rest_start..]);
1250 #[cfg(feature = "no-gc")]
1253 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1254 let mut fn_val = eval_fn(&fn_args, env)?;
1255 if is_async && let Value::Fn(ref mut f) = fn_val {
1256 f.get_mut().is_async = true;
1257 }
1258 let var = env
1259 .globals
1260 .intern(&env.current_ns, Arc::from(name.as_str()), fn_val.clone());
1261 let mut meta = attr_meta;
1262 if let Some(doc) = &docstring {
1263 meta = merge_meta(meta, Some(doc_meta(doc)));
1264 }
1265 meta = merge_meta(meta, arglists_meta(&fn_val, 0));
1266 if private {
1267 meta = merge_meta(meta, Some(private_meta()));
1268 }
1269 if let Some(meta_val) = meta {
1270 var.get().set_meta(meta_val);
1271 }
1272 Ok(Value::Var(var))
1273}
1274
1275fn prepend_macro_params(form: &Form) -> Form {
1283 let span = form.span.clone();
1284 match &form.unmeta().kind {
1285 FormKind::Vector(params) => {
1286 let mut new_params = vec![
1287 Form::new(FormKind::Symbol("&form".to_string()), span.clone()),
1288 Form::new(FormKind::Symbol("&env".to_string()), span.clone()),
1289 ];
1290 new_params.extend_from_slice(params);
1291 Form::new(FormKind::Vector(new_params), span)
1292 }
1293 FormKind::List(forms) => {
1294 if let Some(first) = forms.first() {
1296 let new_params_form = prepend_macro_params(first);
1297 let mut new_forms = vec![new_params_form];
1298 new_forms.extend_from_slice(&forms[1..]);
1299 Form::new(FormKind::List(new_forms), span)
1300 } else {
1301 form.clone()
1302 }
1303 }
1304 _ => form.clone(),
1305 }
1306}
1307
1308fn eval_defmacro(args: &[Form], env: &mut Env) -> EvalResult {
1309 let mut current = args
1312 .first()
1313 .ok_or_else(|| EvalError::Runtime("defmacro requires a symbol at position 0".into()))?
1314 .clone();
1315 let mut name_meta: Option<Value> = None;
1316 while let FormKind::Meta(meta_form, inner) = current.kind {
1317 let meta_val = compile_meta_form(&meta_form, env)?;
1318 name_meta = merge_meta(name_meta, Some(meta_val));
1319 current = *inner;
1320 }
1321 let name = match ¤t.kind {
1322 FormKind::Symbol(s) => s.clone(),
1323 _ => {
1324 return Err(EvalError::Runtime(
1325 "defmacro requires a symbol at position 0".into(),
1326 ));
1327 }
1328 };
1329
1330 let mut rest_start = 1;
1331 let mut docstring: Option<String> = None;
1332 if rest_start < args.len()
1333 && let FormKind::Str(s) = &args[rest_start].kind
1334 {
1335 docstring = Some(s.clone());
1336 rest_start += 1;
1337 }
1338 let mut attr_meta = None;
1339 if rest_start < args.len() && matches!(args[rest_start].kind, FormKind::Map(_)) {
1340 attr_meta = Some(eval(&args[rest_start], env)?);
1341 rest_start += 1;
1342 }
1343 let mut fn_args = vec![Form::new(
1345 FormKind::Symbol(name.to_string()),
1346 args[0].span.clone(),
1347 )];
1348 for form in &args[rest_start..] {
1349 fn_args.push(prepend_macro_params(form));
1350 }
1351 #[cfg(feature = "no-gc")]
1354 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1355 let fn_val = eval_fn(&fn_args, env)?;
1356
1357 let macro_val = match fn_val {
1359 Value::Fn(f) => {
1360 let mut mfn = f.get().clone();
1361 mfn.is_macro = true;
1362 Value::Macro(GcPtr::new(mfn))
1363 }
1364 other => other,
1365 };
1366
1367 let var = env
1368 .globals
1369 .intern(&env.current_ns, Arc::from(name.as_str()), macro_val.clone());
1370 let mut meta = merge_meta(name_meta, attr_meta);
1371 if let Some(doc) = &docstring {
1372 meta = merge_meta(meta, Some(doc_meta(doc)));
1373 }
1374 meta = merge_meta(meta, arglists_meta(¯o_val, 2));
1376 if let Some(m) = meta {
1377 var.get().set_meta(m);
1378 }
1379 Ok(Value::Var(var))
1380}
1381
1382fn eval_defonce(args: &[Form], env: &mut Env) -> EvalResult {
1385 if args.is_empty() {
1386 return Err(EvalError::Runtime("defonce requires a name".into()));
1387 }
1388 let (name, _meta) = extract_def_name(&args[0], env)?;
1391 if let Some(var) = defonce_existing(&name, env) {
1393 return Ok(var);
1394 }
1395 eval_def(args, env)
1396}
1397
1398fn eval_and(args: &[Form], env: &mut Env) -> EvalResult {
1401 let mut result = Value::Bool(true);
1402 for form in args {
1403 result = eval(form, env)?;
1404 if matches!(result, Value::Nil | Value::Bool(false)) {
1405 return Ok(result);
1406 }
1407 }
1408 Ok(result)
1409}
1410
1411fn eval_or(args: &[Form], env: &mut Env) -> EvalResult {
1412 let mut last = Value::Nil;
1413 for form in args {
1414 last = eval(form, env)?;
1415 if !matches!(last, Value::Nil | Value::Bool(false)) {
1416 return Ok(last);
1417 }
1418 }
1419 Ok(last)
1420}
1421
1422fn eval_require(args: &[Form], env: &mut Env) -> EvalResult {
1425 for arg in args {
1426 let val = eval(arg, env)?;
1427 let spec = parse_require_spec_val(val).map_err(EvalError::Runtime)?;
1428 load_ns(env.globals.clone(), &spec, &env.current_ns)?;
1429 }
1430 Ok(Value::Nil)
1431}
1432
1433fn parse_require_spec_val(val: Value) -> Result<RequireSpec, String> {
1438 match val {
1439 Value::Symbol(s) => {
1440 let sym = s.get();
1441 Ok(RequireSpec {
1442 ns: sym.name.clone(),
1443 version: sym.version.clone(),
1444 alias: None,
1445 refer: RequireRefer::None,
1446 })
1447 }
1448 Value::Vector(v) => {
1449 let items: Vec<Value> = v.get().iter().cloned().collect();
1450 if items.is_empty() {
1451 return Err("require spec vector must not be empty".into());
1452 }
1453 let (ns, version) = match &items[0] {
1454 Value::Symbol(s) => {
1455 let sym = s.get();
1456 (sym.name.clone(), sym.version.clone())
1457 }
1458 other => {
1459 return Err(format!(
1460 "require spec: first element must be a symbol, got {}",
1461 other.type_name()
1462 ));
1463 }
1464 };
1465 let mut alias = None;
1466 let mut refer = RequireRefer::None;
1467 let mut i = 1;
1468 while i < items.len() {
1469 match &items[i] {
1470 Value::Keyword(k) if k.get().name.as_ref() == "as" => {
1471 i += 1;
1472 alias = Some(match items.get(i) {
1473 Some(Value::Symbol(s)) => s.get().name.clone(),
1474 _ => return Err("require :as expects a symbol".into()),
1475 });
1476 }
1477 Value::Keyword(k) if k.get().name.as_ref() == "refer" => {
1478 i += 1;
1479 refer = match items.get(i) {
1480 Some(Value::Keyword(k2)) if k2.get().name.as_ref() == "all" => {
1481 RequireRefer::All
1482 }
1483 Some(Value::Vector(rv)) => {
1484 let names: Vec<Arc<str>> = rv
1485 .get()
1486 .iter()
1487 .map(|v| match v {
1488 Value::Symbol(s) => Ok(s.get().name.clone()),
1489 other => Err(format!(
1490 "require :refer expects symbols, got {}",
1491 other.type_name()
1492 )),
1493 })
1494 .collect::<Result<_, _>>()?;
1495 RequireRefer::Named(names)
1496 }
1497 _ => {
1498 return Err(
1499 "require :refer expects :all or a vector of symbols".into()
1500 );
1501 }
1502 };
1503 }
1504 other => {
1505 return Err(format!(
1506 "require spec: unexpected option {}",
1507 other.type_name()
1508 ));
1509 }
1510 }
1511 i += 1;
1512 }
1513 Ok(RequireSpec {
1514 ns,
1515 version,
1516 alias,
1517 refer,
1518 })
1519 }
1520 other => Err(format!(
1521 "require expects a symbol or vector, got {}",
1522 other.type_name()
1523 )),
1524 }
1525}
1526
1527fn spec_element(form: &Form) -> Option<&Form> {
1531 match &form.kind {
1532 FormKind::ReaderCond { clauses, .. } => select_reader_cond(clauses),
1533 _ => Some(form),
1534 }
1535}
1536
1537pub fn parse_require_spec_form(form: &Form) -> Result<RequireSpec, String> {
1544 match &form.kind {
1545 FormKind::Symbol(s) => {
1546 let sym = cljrs_value::Symbol::parse(s);
1547 Ok(RequireSpec {
1548 ns: sym.name.clone(),
1549 version: sym.version.clone(),
1550 alias: None,
1551 refer: RequireRefer::None,
1552 })
1553 }
1554 FormKind::Vector(items) => {
1555 if items.is_empty() {
1556 return Err("require spec vector must not be empty".into());
1557 }
1558 let head = spec_element(&items[0]).ok_or_else(|| {
1559 "require spec: no reader-conditional branch matched for the namespace".to_string()
1560 })?;
1561 let (ns, version) = match &head.kind {
1562 FormKind::Symbol(s) => {
1563 let sym = cljrs_value::Symbol::parse(s);
1564 (sym.name.clone(), sym.version.clone())
1565 }
1566 _ => return Err("require spec: first element must be a symbol".into()),
1567 };
1568 let mut alias = None;
1569 let mut refer = RequireRefer::None;
1570 let mut i = 1;
1571 while i < items.len() {
1572 let Some(item) = spec_element(&items[i]) else {
1575 i += 1;
1576 continue;
1577 };
1578 match &item.kind {
1579 FormKind::Keyword(k) if k == "as" => {
1580 i += 1;
1581 alias = Some(match items.get(i).map(|f| &f.kind) {
1582 Some(FormKind::Symbol(s)) => Arc::from(s.as_str()),
1583 _ => return Err("require :as expects a symbol".into()),
1584 });
1585 }
1586 FormKind::Keyword(k) if k == "refer" => {
1587 i += 1;
1588 refer = match items.get(i).map(|f| &f.kind) {
1589 Some(FormKind::Keyword(k2)) if k2 == "all" => RequireRefer::All,
1590 Some(FormKind::Vector(rv)) => {
1591 let names: Vec<Arc<str>> = rv
1592 .iter()
1593 .map(|f| match &f.kind {
1594 FormKind::Symbol(s) => Ok(Arc::from(s.as_str())),
1595 _ => Err("require :refer expects symbols".to_string()),
1596 })
1597 .collect::<Result<_, _>>()?;
1598 RequireRefer::Named(names)
1599 }
1600 _ => return Err("require :refer expects :all or a vector".into()),
1601 };
1602 }
1603 _ => return Err(format!("require spec: unexpected form at position {i}")),
1604 }
1605 i += 1;
1606 }
1607 Ok(RequireSpec {
1608 ns,
1609 version,
1610 alias,
1611 refer,
1612 })
1613 }
1614 _ => Err("require spec must be a symbol or vector".into()),
1615 }
1616}
1617
1618fn extract_ns_name_form(form: Option<&Form>, env: &mut Env) -> EvalResult<(String, Option<Value>)> {
1624 let mut current = form
1625 .ok_or_else(|| EvalError::Runtime("ns requires a symbol at position 0".into()))?
1626 .clone();
1627 let mut meta_acc: Option<Value> = None;
1628 while let FormKind::Meta(meta_form, inner) = current.kind {
1629 let meta_val = compile_meta_form(&meta_form, env)?;
1630 meta_acc = merge_meta(meta_acc, Some(meta_val));
1631 current = *inner;
1632 }
1633 match ¤t.kind {
1634 FormKind::Symbol(s) => Ok((s.clone(), meta_acc)),
1635 _ => Err(EvalError::Runtime(
1636 "ns requires a symbol at position 0".into(),
1637 )),
1638 }
1639}
1640
1641fn merge_meta(base: Option<Value>, overlay: Option<Value>) -> Option<Value> {
1644 match (base, overlay) {
1645 (None, None) => None,
1646 (Some(b), None) => Some(b),
1647 (None, Some(o)) => Some(o),
1648 (Some(Value::Map(b)), Some(Value::Map(o))) => {
1649 let mut merged = b;
1650 for (k, v) in o.iter() {
1651 merged = merged.assoc(k.clone(), v.clone());
1652 }
1653 Some(Value::Map(merged))
1654 }
1655 (_, Some(o)) => Some(o),
1656 }
1657}
1658
1659fn parse_refer_clojure_clause(items: &[Form]) -> Result<ReferClojureFilter, String> {
1663 let mut filter = ReferClojureFilter::default();
1664 let items = expand_reader_conds(items);
1665 let mut i = 0;
1666 while i < items.len() {
1667 let FormKind::Keyword(k) = &items[i].kind else {
1668 return Err(":refer-clojure expects keyword options (:exclude, :only, :rename)".into());
1669 };
1670 let arg = items
1671 .get(i + 1)
1672 .ok_or_else(|| format!(":refer-clojure :{k} expects a value"))?;
1673 match k.as_str() {
1674 "exclude" => filter.exclude = symbol_name_set(arg, "exclude")?,
1675 "only" => filter.only = Some(symbol_name_set(arg, "only")?),
1676 "rename" => {
1677 let FormKind::Map(entries) = &arg.kind else {
1678 return Err(":refer-clojure :rename expects a map".into());
1679 };
1680 if entries.len() % 2 != 0 {
1681 return Err(":refer-clojure :rename expects an even-sized map".into());
1682 }
1683 for pair in entries.chunks(2) {
1684 match (&pair[0].kind, &pair[1].kind) {
1685 (FormKind::Symbol(from), FormKind::Symbol(to)) => {
1686 filter
1687 .rename
1688 .insert(Arc::from(from.as_str()), Arc::from(to.as_str()));
1689 }
1690 _ => {
1691 return Err(
1692 ":refer-clojure :rename expects symbol keys and values".into()
1693 );
1694 }
1695 }
1696 }
1697 }
1698 other => return Err(format!(":refer-clojure does not support :{other}")),
1699 }
1700 i += 2;
1701 }
1702 Ok(filter)
1703}
1704
1705fn symbol_name_set(form: &Form, opt: &str) -> Result<HashSet<Arc<str>>, String> {
1707 let FormKind::Vector(items) = &form.kind else {
1708 return Err(format!(":refer-clojure :{opt} expects a vector of symbols"));
1709 };
1710 expand_reader_conds(items)
1711 .iter()
1712 .map(|f| match &f.kind {
1713 FormKind::Symbol(sym) => Ok(Arc::from(sym.as_str())),
1714 _ => Err(format!(":refer-clojure :{opt} expects symbols")),
1715 })
1716 .collect()
1717}
1718
1719fn eval_ns(args: &[Form], env: &mut Env) -> EvalResult {
1720 let (name, name_meta) = extract_ns_name_form(args.first(), env)?;
1721 env.globals.get_or_create_ns(&name);
1722 env.current_ns = Arc::from(name.as_str());
1723 if name != "clojure.core" {
1725 env.globals.refer_core(&name);
1726 }
1727 sync_star_ns(env);
1728
1729 let mut rest = &args[1..];
1731 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Str(_))) {
1732 rest = &rest[1..];
1733 }
1734 let mut attr_meta = None;
1735 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Map(_))) {
1736 attr_meta = Some(eval(&rest[0], env)?);
1737 rest = &rest[1..];
1738 }
1739
1740 if let Some(m) = merge_meta(name_meta, attr_meta) {
1741 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1742 ns_ptr.get().set_meta(m);
1743 }
1744
1745 let mut refer_clojure = None;
1756 for clause in rest {
1757 if let FormKind::List(items) = &clause.kind
1758 && matches!(items.first().map(|f| &f.kind), Some(FormKind::Keyword(k)) if k == "refer-clojure")
1759 {
1760 refer_clojure =
1761 Some(parse_refer_clojure_clause(&items[1..]).map_err(EvalError::Runtime)?);
1762 }
1763 }
1764 if name != "clojure.core" {
1765 env.globals
1766 .set_refer_clojure_filter(&name, refer_clojure)
1767 .map_err(EvalError::Runtime)?;
1768 }
1769
1770 for clause in rest {
1771 if let FormKind::List(items) = &clause.kind {
1772 match items.first().map(|f| &f.kind) {
1773 Some(FormKind::Keyword(k)) if k == "require" => {
1774 let expanded = expand_reader_conds(&items[1..]);
1776 for spec_form in &expanded {
1777 let spec =
1778 parse_require_spec_form(spec_form).map_err(EvalError::Runtime)?;
1779 load_ns(env.globals.clone(), &spec, &name)?;
1780 }
1781 }
1782 _ => {}
1785 }
1786 }
1787 }
1788
1789 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1790 Ok(Value::Namespace(ns_ptr))
1791}
1792
1793fn eval_load_file(args: &[Form], env: &mut Env) -> EvalResult {
1796 if args.is_empty() {
1797 return Err(EvalError::Runtime(
1798 "load-file requires a path argument".into(),
1799 ));
1800 }
1801 let path_val = eval(&args[0], env)?;
1802 let path = match &path_val {
1803 Value::Str(s) => s.get().clone(),
1804 v => {
1805 return Err(EvalError::Runtime(format!(
1806 "load-file: expected string, got {}",
1807 v.type_name()
1808 )));
1809 }
1810 };
1811 let src = std::fs::read_to_string(&path)
1812 .map_err(|e| EvalError::Runtime(format!("load-file: {e}")))?;
1813 let mut parser = cljrs_reader::Parser::new(src, path.clone());
1814 let forms = parser
1815 .parse_all()
1816 .map_err(|e| EvalError::Runtime(format!("load-file parse error: {e}")))?;
1817 let mut result = Value::Nil;
1818 for form in forms {
1819 let _alloc_frame = cljrs_gc::push_alloc_frame();
1820 result = eval(&form, env)?;
1821 }
1822 Ok(result)
1823}
1824
1825fn eval_letfn(args: &[Form], env: &mut Env) -> EvalResult {
1828 push_letfn_frame(args, env)?;
1829 let result = eval_body(&args[1..], env);
1830 env.pop_frame();
1831 result
1832}
1833
1834pub fn push_letfn_frame(args: &[Form], env: &mut Env) -> EvalResult<()> {
1840 let bindings = match args.first().and_then(|f| f.as_vector()) {
1849 Some(v) => expand_reader_conds_cow(v).into_owned(),
1850 None => return Err(EvalError::Runtime("letfn requires a binding vector".into())),
1851 };
1852
1853 env.push_frame();
1854
1855 for binding in &bindings {
1858 if let Some(parts) = binding.as_list() {
1859 if parts.is_empty() {
1860 continue;
1861 }
1862 let Some(name) = parts[0].as_symbol() else {
1863 env.pop_frame();
1864 return Err(EvalError::Runtime(
1865 "letfn binding name must be a symbol".into(),
1866 ));
1867 };
1868 env.bind(Arc::from(name), Value::Nil);
1869 }
1870 }
1871
1872 let mut built: Vec<(Arc<str>, Value)> = Vec::new();
1875 for binding in &bindings {
1876 if let Some(parts) = binding.as_list() {
1877 if parts.is_empty() {
1878 continue;
1879 }
1880 let fn_val = match eval_fn(parts, env) {
1883 Ok(v) => v,
1884 Err(e) => {
1885 env.pop_frame();
1886 return Err(e);
1887 }
1888 };
1889 let name: Arc<str> = match parts[0].as_symbol() {
1890 Some(s) => Arc::from(s),
1891 None => unreachable!("pass 1 rejected every non-symbol name"),
1892 };
1893 env.bind(Arc::clone(&name), fn_val.clone());
1894 built.push((name, fn_val));
1895 }
1896 }
1897
1898 for (_, fn_val) in &built {
1903 if let Value::Fn(ptr) = fn_val {
1904 let mut ptr = ptr.clone();
1905 let f = ptr.get_mut();
1906 for i in 0..f.closed_over_names.len() {
1907 let captured = f.closed_over_names[i].clone();
1908 if let Some((_, real)) = built.iter().find(|(n, _)| *n == captured) {
1909 f.closed_over_vals[i] = real.clone();
1910 }
1911 }
1912 }
1913 }
1914
1915 Ok(())
1916}
1917
1918fn eval_in_ns(args: &[Form], env: &mut Env) -> EvalResult {
1921 if args.is_empty() {
1923 return Err(EvalError::Runtime("in-ns requires a namespace name".into()));
1924 }
1925 let ns_val = eval(&args[0], env)?;
1926 let ns_name = extract_ns_name(&ns_val)?;
1927 env.globals.get_or_create_ns(&ns_name);
1928 env.globals.refer_core(&ns_name);
1929 env.current_ns = Arc::from(ns_name.as_str());
1930 sync_star_ns(env);
1931 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1932 Ok(Value::Namespace(ns_ptr))
1933}
1934
1935fn eval_alias(args: &[Form], env: &mut Env) -> EvalResult {
1938 if args.len() < 2 {
1940 return Err(EvalError::Runtime(
1941 "alias requires alias-sym and namespace-sym".into(),
1942 ));
1943 }
1944 let alias_val = eval(&args[0], env)?;
1945 let ns_val = eval(&args[1], env)?;
1946
1947 let alias_name = extract_ns_name(&alias_val)?;
1948 let full_ns = extract_ns_name(&ns_val)?;
1949
1950 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1951 let mut aliases = ns_ptr.get().aliases.lock().unwrap();
1952 aliases.insert(Arc::from(alias_name.as_str()), Arc::from(full_ns.as_str()));
1953 Ok(Value::Nil)
1954}
1955
1956fn extract_ns_name(v: &Value) -> EvalResult<String> {
1958 match v {
1959 Value::Symbol(s) => {
1960 Ok(s.get().name.as_ref().to_string())
1962 }
1963 Value::Str(s) => Ok(s.get().clone()),
1964 Value::Keyword(k) => Ok(k.get().name.as_ref().to_string()),
1965 other => Err(EvalError::Runtime(format!(
1966 "expected a symbol or string for namespace name, got {}",
1967 other.type_name()
1968 ))),
1969 }
1970}
1971
1972fn protocol_method_of(spec: &Value) -> EvalResult<ProtocolMethod> {
1976 let Value::Map(m) = spec.unwrap_meta() else {
1977 return Err(EvalError::Runtime(format!(
1978 "protocol* method spec must be a map, got {}",
1979 spec.type_name()
1980 )));
1981 };
1982 let field = |k: &str| m.get(&Value::keyword(Keyword::simple(k)));
1983 let name: Arc<str> = match field("name") {
1984 Some(Value::Str(s)) => Arc::from(s.get().as_str()),
1985 Some(Value::Symbol(s)) => Arc::from(s.get().name.as_ref()),
1986 Some(Value::Keyword(k)) => Arc::from(k.get().name.as_ref()),
1987 _ => {
1988 return Err(EvalError::Runtime(
1989 "protocol* method spec needs a :name".into(),
1990 ));
1991 }
1992 };
1993 let min_arity = match field("min-arity") {
1994 Some(Value::Long(n)) if n >= 0 => n as usize,
1995 _ => 1,
1996 };
1997 let variadic = !matches!(
1998 field("variadic"),
1999 None | Some(Value::Nil) | Some(Value::Bool(false))
2000 );
2001 Ok(ProtocolMethod {
2002 name,
2003 min_arity,
2004 variadic,
2005 })
2006}
2007
2008fn eval_protocol_star(args: &[Form], env: &mut Env) -> EvalResult {
2017 if args.len() < 2 {
2018 return Err(EvalError::Runtime(
2019 "protocol* requires a name and method specs".into(),
2020 ));
2021 }
2022 let (name, _) = require_sym_meta(args, 0, "protocol*", env)?;
2024 let specs = crate::interp::eval::eval(&args[1], env)?;
2025 let specs: Vec<Value> = match specs.unwrap_meta() {
2026 Value::Vector(v) => v.get().iter().cloned().collect(),
2027 Value::Nil => Vec::new(),
2028 v => {
2029 return Err(EvalError::Runtime(format!(
2030 "protocol* method specs must be a vector, got {}",
2031 v.type_name()
2032 )));
2033 }
2034 };
2035 let methods = specs
2036 .iter()
2037 .map(protocol_method_of)
2038 .collect::<EvalResult<Vec<_>>>()?;
2039 let extend_via_metadata = match args.get(2) {
2040 Some(f) => !matches!(
2041 crate::interp::eval::eval(f, env)?,
2042 Value::Nil | Value::Bool(false)
2043 ),
2044 None => false,
2045 };
2046 let proto = Protocol::new(
2047 Arc::from(name.as_str()),
2048 env.current_ns.clone(),
2049 methods,
2050 extend_via_metadata,
2051 );
2052 Ok(Value::Protocol(GcPtr::new(proto)))
2053}
2054
2055fn synth_field_scope(
2073 params_form: &Form,
2074 fields: &[Arc<str>],
2075 mutable_fields: &[Arc<str>],
2076 body: &[Form],
2077) -> Option<Vec<Form>> {
2078 let param_forms = match ¶ms_form.kind {
2079 FormKind::Vector(v) => v,
2080 _ => return None,
2081 };
2082 let this_name = match param_forms.first().map(|f| &f.kind) {
2083 Some(FormKind::Symbol(s)) => s.clone(),
2084 _ => return None,
2085 };
2086 let param_names: Vec<&str> = param_forms
2087 .iter()
2088 .filter_map(|f| match &f.kind {
2089 FormKind::Symbol(s) => Some(s.as_str()),
2090 _ => None,
2091 })
2092 .collect();
2093
2094 let span = params_form.span.clone();
2095 let is_mut = |name: &str| mutable_fields.iter().any(|m| m.as_ref() == name);
2096 let mut bindings: Vec<Form> = Vec::new();
2097 for field in fields {
2098 if param_names.contains(&field.as_ref()) {
2099 continue;
2100 }
2101 bindings.push(Form::new(FormKind::Symbol(field.to_string()), span.clone()));
2102 let accessor = if is_mut(field) {
2106 FormKind::List(vec![
2107 Form::new(FormKind::Symbol(format!(".-{field}")), span.clone()),
2108 Form::new(FormKind::Symbol(this_name.clone()), span.clone()),
2109 ])
2110 } else {
2111 FormKind::List(vec![
2112 Form::new(FormKind::Keyword(field.to_string()), span.clone()),
2113 Form::new(FormKind::Symbol(this_name.clone()), span.clone()),
2114 ])
2115 };
2116 bindings.push(Form::new(accessor, span.clone()));
2117 }
2118 if !mutable_fields.is_empty() {
2121 bindings.push(Form::new(
2122 FormKind::Symbol(DEFTYPE_SELF.to_string()),
2123 span.clone(),
2124 ));
2125 bindings.push(Form::new(FormKind::Symbol(this_name.clone()), span.clone()));
2126 }
2127 if bindings.is_empty() {
2128 return None;
2129 }
2130
2131 let mut let_forms = vec![
2132 Form::new(FormKind::Symbol("let*".to_string()), span.clone()),
2133 Form::new(FormKind::Vector(bindings), span.clone()),
2134 ];
2135 let_forms.extend_from_slice(body);
2136 Some(vec![Form::new(FormKind::List(let_forms), span)])
2137}
2138
2139fn build_impl_fn(
2140 parts: &[Form],
2141 fields: &[Arc<str>],
2142 mutable_fields: &[Arc<str>],
2143 env: &mut Env,
2144) -> EvalResult<Value> {
2145 if parts.len() < 2 {
2146 return Err(EvalError::Runtime(
2147 "protocol method impl requires params and body".into(),
2148 ));
2149 }
2150 let params_form = &parts[1];
2152 let body = &parts[2..];
2153 let scoped;
2154 let body: &[Form] = if fields.is_empty() {
2155 body
2156 } else {
2157 match synth_field_scope(params_form, fields, mutable_fields, body) {
2158 Some(v) => {
2159 scoped = v;
2160 &scoped
2161 }
2162 None => body,
2163 }
2164 };
2165 let arity = parse_arity(params_form, body)?;
2166 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
2167 let fn_name: Option<Arc<str>> = parts[0].as_symbol().map(Arc::from);
2168 let cljrs_fn = CljxFn::new(
2169 fn_name,
2170 vec![arity],
2171 closed_over_names,
2172 closed_over_vals,
2173 false,
2174 Arc::clone(&env.current_ns),
2175 );
2176 Ok(Value::Fn(GcPtr::new(cljrs_fn)))
2177}
2178
2179fn eval_binding(args: &[Form], env: &mut Env) -> EvalResult {
2182 let pairs = match args.first().and_then(|f| f.as_vector()) {
2183 Some(v) => expand_pairs(v)
2184 .map_err(|_| EvalError::Runtime("binding vector must have even count".into()))?
2185 .into_owned(),
2186 None => return Err(EvalError::Runtime("binding requires a vector".into())),
2187 };
2188
2189 let mut frame: HashMap<usize, Value> = HashMap::new();
2190 for pair in pairs.chunks(2) {
2191 let Some(sym_str) = pair[0].as_symbol() else {
2192 return Err(EvalError::Runtime("binding targets must be symbols".into()));
2193 };
2194 let parsed = cljrs_value::Symbol::parse(sym_str);
2195 let ns_part: Arc<str> = env.resolve_ns_or_current(parsed.namespace.as_deref());
2196 let var_ptr = env
2197 .globals
2198 .lookup_var_in_ns(&ns_part, &parsed.name)
2199 .ok_or_else(|| EvalError::UnboundSymbol(sym_str.to_string()))?;
2200 let val = eval(&pair[1], env)?;
2201 frame.insert(crate::env::dynamics::var_key_of(&var_ptr), val);
2202 }
2203
2204 let _guard = crate::env::dynamics::push_frame(frame);
2205 eval_body(&args[1..], env)
2206 }
2208
2209const DEFTYPE_SELF: &str = "__deftype_self__";
2215
2216fn meta_form_is_mutable(meta: &Form) -> bool {
2220 let is_mut_kw = |k: &str| k == "unsynchronized-mutable" || k == "volatile-mutable";
2221 match &meta.kind {
2222 FormKind::Keyword(k) => is_mut_kw(k),
2223 FormKind::Map(entries) => entries.chunks(2).any(|kv| {
2224 matches!(&kv[0].kind, FormKind::Keyword(k) if is_mut_kw(k))
2225 && !matches!(
2226 kv.get(1).map(|f| &f.kind),
2227 None | Some(FormKind::Bool(false)) | Some(FormKind::Nil)
2228 )
2229 }),
2230 FormKind::Quote(inner) => meta_form_is_mutable(inner),
2236 _ => false,
2237 }
2238}
2239
2240fn field_spec_of(form: &Form) -> Option<(Arc<str>, bool)> {
2242 match &form.kind {
2243 FormKind::Symbol(s) => Some((Arc::from(s.as_str()), false)),
2244 FormKind::Meta(meta, inner) => {
2245 let here = meta_form_is_mutable(meta);
2246 field_spec_of(inner).map(|(name, inner_mut)| (name, inner_mut || here))
2247 }
2248 _ => None,
2249 }
2250}
2251
2252fn parse_field_specs(form: &Form, ctx: &str) -> EvalResult<Vec<(Arc<str>, bool)>> {
2254 let Some(fields) = form.as_vector() else {
2257 return Err(EvalError::Runtime(format!(
2258 "{ctx} requires a field vector as second arg"
2259 )));
2260 };
2261 fields
2262 .iter()
2263 .map(|f| {
2264 field_spec_of(f)
2265 .ok_or_else(|| EvalError::Runtime(format!("{ctx} field names must be symbols")))
2266 })
2267 .collect()
2268}
2269
2270fn eval_deftype_star(args: &[Form], env: &mut Env) -> EvalResult {
2278 if args.len() < 2 {
2280 return Err(EvalError::Runtime(
2281 "deftype* requires a name and field vector".into(),
2282 ));
2283 }
2284 let (type_name, _) = require_sym_meta(args, 0, "deftype*", env)?;
2287 let type_tag: Arc<str> = Arc::from(type_name.as_str());
2288
2289 let specs = parse_field_specs(&args[1], "deftype*")?;
2290 let field_names: Vec<Arc<str>> = specs.iter().map(|(n, _)| n.clone()).collect();
2291 let mutable_names: Vec<Arc<str>> = specs
2292 .iter()
2293 .filter(|(_, m)| *m)
2294 .map(|(n, _)| n.clone())
2295 .collect();
2296
2297 register_impls_for_tag(&type_tag, &args[2..], &field_names, &mutable_names, env)?;
2301 Ok(Value::string(type_name))
2305}
2306
2307fn resolve_protocol_sym(env: &Env, s: &str) -> Option<GcPtr<Protocol>> {
2320 let parsed = cljrs_value::Symbol::parse(s);
2321 let val = match parsed.namespace.as_deref() {
2322 Some(ns_part) => {
2323 let ns = env.resolve_ns_part(ns_part);
2324 env.globals.lookup_in_ns(&ns, &parsed.name)
2325 }
2326 None => env.globals.lookup_in_ns(&env.current_ns, s),
2327 };
2328 match val {
2329 Some(Value::Protocol(p)) => Some(p),
2330 _ => None,
2331 }
2332}
2333
2334fn register_impls_for_tag(
2337 type_tag: &Arc<str>,
2338 forms: &[Form],
2339 fields: &[Arc<str>],
2340 mutable_fields: &[Arc<str>],
2341 env: &mut Env,
2342) -> EvalResult<()> {
2343 let mut current_proto: Option<GcPtr<cljrs_value::Protocol>> = None;
2344
2345 for form in forms {
2346 match &form.unmeta().kind {
2347 FormKind::Symbol(s) => match resolve_protocol_sym(env, s) {
2348 Some(p) => current_proto = Some(p),
2349 None => {
2350 return Err(EvalError::Runtime(format!(
2351 "reify/defrecord: {} is not a protocol",
2352 s
2353 )));
2354 }
2355 },
2356 FormKind::List(parts) => {
2357 let proto = current_proto.as_ref().ok_or_else(|| {
2358 EvalError::Runtime("reify/defrecord: method impl before protocol name".into())
2359 })?;
2360 if parts.is_empty() {
2361 continue;
2362 }
2363 let method_name: Arc<str> = match parts[0].as_symbol() {
2364 Some(s) => Arc::from(s),
2365 None => continue,
2366 };
2367 let fn_val = build_impl_fn(parts, fields, mutable_fields, env)?;
2368 let mut impls = proto.get().impls.lock().unwrap();
2369 impls
2370 .entry(type_tag.clone())
2371 .or_default()
2372 .insert(method_name, fn_val);
2373 drop(impls);
2374 cljrs_value::bump_protocol_generation();
2375 }
2376 _ => {}
2377 }
2378 }
2379 Ok(())
2380}
2381
2382pub fn sync_star_ns(env: &mut Env) {
2387 if let Some(star_ns_var) = env.globals.lookup_var("clojure.core", "*ns*") {
2388 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
2389 star_ns_var.get().bind(Value::Namespace(ns_ptr));
2390 }
2391}
2392
2393fn require_sym_meta(
2405 args: &[Form],
2406 idx: usize,
2407 form_name: &str,
2408 env: &mut Env,
2409) -> EvalResult<(String, Option<Value>)> {
2410 fn peel(form: &Form, env: &mut Env) -> EvalResult<Option<(String, Option<Value>)>> {
2411 match &form.kind {
2412 FormKind::Symbol(s) => Ok(Some((s.clone(), None))),
2413 FormKind::Meta(meta_form, inner) => {
2415 let meta_val = compile_meta_form(meta_form, env)?;
2416 match peel(inner, env)? {
2417 Some((name, inner_meta)) => {
2418 Ok(Some((name, merge_meta(inner_meta, Some(meta_val)))))
2419 }
2420 None => Ok(None),
2421 }
2422 }
2423 _ => Ok(None),
2424 }
2425 }
2426 let err = || EvalError::Runtime(format!("{form_name} requires a symbol at position {idx}"));
2427 match args.get(idx) {
2428 Some(form) => peel(form, env)?.ok_or_else(err),
2429 None => Err(err()),
2430 }
2431}
2432
2433fn eval_with_out_str(body: &[Form], env: &mut Env) -> EvalResult {
2436 crate::builtins::builtins::push_output_capture();
2437 let result = eval_body(body, env);
2438 let captured = crate::builtins::builtins::pop_output_capture().unwrap_or_default();
2439 result?;
2441 Ok(Value::string(captured))
2442}
2443
2444fn eval_await(args: &[Form], env: &mut Env) -> EvalResult {
2453 if args.is_empty() {
2454 return Err(EvalError::Runtime("await requires one argument".into()));
2455 }
2456 let val = eval(&args[0], env)?;
2457 match val {
2458 Value::Future(f) => {
2459 let mut guard = f.get().state.lock().unwrap();
2460 loop {
2461 match &*guard {
2462 FutureState::Done(v) => {
2463 f.get().mark_observed();
2464 return Ok(v.clone());
2465 }
2466 FutureState::Failed(v) => {
2467 f.get().mark_observed();
2468 return Err(EvalError::Thrown(v.clone()));
2469 }
2470 FutureState::GasExhausted => {
2471 f.get().mark_observed();
2472 return Err(EvalError::GasExhausted);
2473 }
2474 FutureState::Cancelled => {
2475 return Err(EvalError::Thrown(CljxFuture::cancelled_error()));
2476 }
2477 FutureState::Running => {
2478 guard = f.get().cond.wait(guard).unwrap();
2479 }
2480 }
2481 }
2482 }
2483 Value::Promise(p) => Ok(p.get().deref_blocking()),
2484 other => Ok(other),
2485 }
2486}