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 is_async = Form::fn_args_request_async(args);
211 let peeled: Vec<Form>;
213 let args: &[Form] = if matches!(args.first().map(|f| &f.kind), Some(FormKind::Meta(..))) {
214 let (_, head) = args[0].peel_meta();
215 peeled = std::iter::once(head.clone())
216 .chain(args[1..].iter().cloned())
217 .collect();
218 &peeled
219 } else {
220 args
221 };
222
223 let mut idx = 0;
224 let mut name: Option<Arc<str>> = None;
225
226 if let Some(FormKind::Symbol(s)) = args.first().map(|f| &f.kind)
228 && !is_special_form(s)
229 {
230 name = Some(Arc::from(s.as_str()));
231 idx = 1;
232 }
233
234 let rest = &args[idx..];
235 if rest.is_empty() {
236 return Err(EvalError::Runtime("fn* requires params and body".into()));
237 }
238
239 let arities = match &rest[0].unmeta().kind {
242 FormKind::Vector(_) => {
243 vec![parse_arity(&rest[0], &rest[1..])?]
245 }
246 FormKind::List(_) => {
247 rest.iter()
249 .map(|arity_form| {
250 if let Some(forms) = arity_form.as_list() {
251 if forms.is_empty() {
252 return Err(EvalError::Runtime("arity clause requires params".into()));
253 }
254 parse_arity(&forms[0], &forms[1..])
255 } else {
256 Err(EvalError::Runtime("expected arity clause (list)".into()))
257 }
258 })
259 .collect::<EvalResult<Vec<_>>>()?
260 }
261 _ => {
262 return Err(EvalError::Runtime(
263 "fn* expects vector or arity clauses".into(),
264 ));
265 }
266 };
267
268 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
270
271 let mut cljrs_fn = CljxFn::new(
272 name.clone(),
273 arities,
274 closed_over_names,
275 closed_over_vals,
276 false,
277 Arc::clone(&env.current_ns),
278 );
279 cljrs_fn.is_async = is_async;
280
281 env.on_fn_defined(&cljrs_fn);
282
283 let mut ptr = GcPtr::new(cljrs_fn);
287 if ptr.get().name.is_some() {
291 let self_clone = ptr.clone();
292 ptr.get_mut().self_ptr = Some(self_clone);
293 }
294 Ok(Value::Fn(ptr))
295}
296
297pub fn parse_arity(params_form: &Form, body: &[Form]) -> EvalResult<CljxFnArity> {
299 let Some(param_forms) = params_form.as_vector() else {
300 return Err(EvalError::Runtime(
301 "fn arity params must be a vector".into(),
302 ));
303 };
304
305 let mut params: Vec<Arc<str>> = Vec::new();
306 let mut param_hints: Vec<Option<TypeHint>> = Vec::new();
307 let mut rest_param: Option<Arc<str>> = None;
308 let mut rest_hint: Option<TypeHint> = None;
309 let mut destructure_params: Vec<(usize, Form)> = Vec::new();
310 let mut destructure_rest: Option<Form> = None;
311 let mut saw_amp = false;
312
313 for p in param_forms {
314 let (hint, p) = peel_param_hint(p);
320 match &p.kind {
321 FormKind::Symbol(s) if s == "&" => {
322 saw_amp = true;
323 }
324 FormKind::Symbol(s) => {
325 if saw_amp {
326 rest_param = Some(Arc::from(s.as_str()));
327 rest_hint = hint;
328 break;
329 } else {
330 params.push(Arc::from(s.as_str()));
331 param_hints.push(hint);
332 }
333 }
334 FormKind::Vector(_) | FormKind::Map(_) => {
336 if saw_amp {
337 let gensym = format!("__destructure_rest_{}", params.len());
338 rest_param = Some(Arc::from(gensym.as_str()));
339 destructure_rest = Some(p.clone());
340 break;
341 } else {
342 let idx = params.len();
343 let gensym = format!("__destructure_{idx}");
344 params.push(Arc::from(gensym.as_str()));
345 param_hints.push(None);
347 destructure_params.push((idx, p.clone()));
348 }
349 }
350 _ => {
351 return Err(EvalError::Runtime(
352 "fn params must be symbols, vectors, or maps".into(),
353 ));
354 }
355 }
356 }
357
358 let body = desugar_pre_post_conditions(body);
359
360 Ok(CljxFnArity {
361 params,
362 rest_param,
363 body,
364 destructure_params,
365 destructure_rest,
366 ir_arity_id: crate::interp::arity::fresh_arity_id(),
367 param_hints,
368 rest_hint,
369 })
370}
371
372fn desugar_pre_post_conditions(body: &[Form]) -> Vec<Form> {
390 let first = match body.first() {
391 Some(f) => f,
392 None => return body.to_vec(),
393 };
394
395 let entries = match first.as_map() {
396 Some(entries) => entries,
397 None => return body.to_vec(),
398 };
399
400 let mut pre_conds: Vec<Form> = Vec::new();
401 let mut post_conds: Vec<Form> = Vec::new();
402 let mut has_conditions = false;
403
404 for chunk in entries.chunks(2) {
405 if chunk.len() < 2 {
406 break;
407 }
408 let (key, val) = (&chunk[0], &chunk[1]);
409 match &key.kind {
410 FormKind::Keyword(k) if k == "pre" => {
411 if let FormKind::Vector(conds) = &val.kind {
412 pre_conds.extend_from_slice(conds);
413 has_conditions = true;
414 }
415 }
416 FormKind::Keyword(k) if k == "post" => {
417 if let FormKind::Vector(conds) = &val.kind {
418 post_conds.extend_from_slice(conds);
419 has_conditions = true;
420 }
421 }
422 _ => {}
423 }
424 }
425
426 if !has_conditions {
427 return body.to_vec();
428 }
429
430 let real_body = &body[1..]; let span = first.span.clone();
432 let mut new_body: Vec<Form> = Vec::new();
433
434 for cond in &pre_conds {
436 new_body.push(make_assert_call(cond, &span));
437 }
438
439 if post_conds.is_empty() {
440 new_body.extend_from_slice(real_body);
441 } else {
442 let percent = Form::new(FormKind::Symbol("%".to_string()), span.clone());
445
446 let body_expr = if real_body.len() == 1 {
447 real_body[0].clone()
448 } else {
449 let mut do_forms = vec![Form::new(FormKind::Symbol("do".to_string()), span.clone())];
450 do_forms.extend_from_slice(real_body);
451 Form::new(FormKind::List(do_forms), span.clone())
452 };
453
454 let binding_vec = Form::new(
455 FormKind::Vector(vec![percent.clone(), body_expr]),
456 span.clone(),
457 );
458
459 let mut let_forms = vec![
460 Form::new(FormKind::Symbol("let*".to_string()), span.clone()),
461 binding_vec,
462 ];
463 for cond in &post_conds {
464 let_forms.push(make_assert_call(cond, &span));
465 }
466 let_forms.push(percent);
467
468 new_body.push(Form::new(FormKind::List(let_forms), span));
469 }
470
471 new_body
472}
473
474fn make_assert_call(cond: &Form, span: &cljrs_types::span::Span) -> Form {
476 Form::new(
477 FormKind::List(vec![
478 Form::new(FormKind::Symbol("assert".to_string()), span.clone()),
479 cond.clone(),
480 ]),
481 span.clone(),
482 )
483}
484
485fn peel_param_hint(p: &Form) -> (Option<TypeHint>, &Form) {
489 if let FormKind::Meta(meta, inner) = &p.kind {
490 let hint = tag_name_of_meta(meta).and_then(|n| TypeHint::from_tag(&n));
491 let (inner_hint, inner_form) = peel_param_hint(inner);
493 (hint.or(inner_hint), inner_form)
494 } else {
495 (None, p)
496 }
497}
498
499fn tag_name_of_meta(meta: &Form) -> Option<Arc<str>> {
502 match &meta.kind {
503 FormKind::Symbol(s) => Some(strip_tag_ns(s)),
505 FormKind::Map(entries) => entries.chunks(2).find_map(|kv| {
507 let is_tag = matches!(&kv[0].kind, FormKind::Keyword(k) if k == "tag");
508 if !is_tag {
509 return None;
510 }
511 match kv.get(1).map(|f| &f.kind) {
512 Some(FormKind::Symbol(s)) => Some(strip_tag_ns(s)),
513 Some(FormKind::Str(s)) => Some(strip_tag_ns(s)),
514 _ => None,
515 }
516 }),
517 _ => None,
518 }
519}
520
521fn strip_tag_ns(s: &str) -> Arc<str> {
523 match s.rfind('/') {
524 Some(pos) if pos + 1 < s.len() => Arc::from(&s[pos + 1..]),
525 _ => Arc::from(s),
526 }
527}
528
529fn eval_if(args: &[Form], env: &mut Env) -> EvalResult {
532 if args.is_empty() {
533 return Err(EvalError::Runtime("if requires a test".into()));
534 }
535 let test = eval(&args[0], env)?;
536 let truthy = !matches!(test, Value::Nil | Value::Bool(false));
537 if truthy {
538 if args.len() > 1 {
539 eval(&args[1], env)
540 } else {
541 Ok(Value::Nil)
542 }
543 } else if args.len() > 2 {
544 eval(&args[2], env)
545 } else {
546 Ok(Value::Nil)
547 }
548}
549
550fn eval_let(args: &[Form], env: &mut Env) -> EvalResult {
553 let bindings = match args.first().and_then(|f| f.as_vector()) {
554 Some(v) => expand_pairs(v)
555 .map_err(|_| EvalError::Runtime("let* binding vector must have even length".into()))?
556 .into_owned(),
557 None => return Err(EvalError::Runtime("let* requires a binding vector".into())),
558 };
559
560 let body = &args[1..];
561
562 let chains = crate::interp::virtualize::detect_let_chains(&bindings);
564 let virtualizable_chains = find_virtualizable_chains(&chains, &bindings, body);
565
566 env.push_frame();
567
568 let pairs: Vec<_> = bindings.chunks(2).collect();
569 let mut i = 0;
570 while i < pairs.len() {
571 if let Some(chain) = virtualizable_chains.iter().find(|c| c.start == i) {
573 match eval_virtualized_chain(chain, &pairs, env) {
574 Ok(()) => {
575 i += chain.len;
576 continue;
577 }
578 Err(e) => {
579 env.pop_frame();
580 return Err(e);
581 }
582 }
583 }
584
585 let pair = pairs[i];
587 let val = match eval(&pair[1], env) {
588 Ok(v) => v,
589 Err(e) => {
590 env.pop_frame();
591 return Err(e);
592 }
593 };
594 if let Err(e) = bind_pattern(&pair[0], val, env) {
595 env.pop_frame();
596 return Err(e);
597 }
598 i += 1;
599 }
600
601 let result = eval_body(body, env);
602 env.pop_frame();
603 result
604}
605
606fn find_virtualizable_chains<'a>(
611 chains: &'a [crate::interp::virtualize::LetChain],
612 bindings: &[Form],
613 body: &[Form],
614) -> Vec<&'a crate::interp::virtualize::LetChain> {
615 chains
616 .iter()
617 .filter(|chain| {
618 for j in chain.start..(chain.start + chain.len - 1) {
621 let name = match &bindings[j * 2].kind {
622 FormKind::Symbol(s) => s.as_str(),
623 _ => return false,
624 };
625 if crate::interp::virtualize::binding_used_in_body(name, body) {
626 return false;
627 }
628 if crate::interp::virtualize::binding_used_in_other_bindings(
629 name,
630 bindings,
631 chain.start,
632 chain.len,
633 ) {
634 return false;
635 }
636 }
637 true
638 })
639 .collect()
640}
641
642fn eval_virtualized_chain(
652 chain: &crate::interp::virtualize::LetChain,
653 pairs: &[&[Form]],
654 env: &mut Env,
655) -> Result<(), EvalError> {
656 use crate::builtins::transients::{
657 builtin_assoc_bang, builtin_conj_bang, builtin_persistent_bang, builtin_transient,
658 };
659
660 let first_pair = pairs[chain.start];
662 let first_expr_forms = match &first_pair[1].kind {
663 FormKind::List(forms) => forms,
664 _ => unreachable!("chain detection ensures this is a list"),
665 };
666 let root_collection = eval(&first_expr_forms[1], env)?;
667
668 let mut transient = match builtin_transient(std::slice::from_ref(&root_collection)) {
670 Ok(t) => t,
671 Err(_) => {
672 return eval_chain_normally(chain, pairs, env);
675 }
676 };
677
678 for j in 0..chain.len {
680 let pair_idx = chain.start + j;
681 let pair = pairs[pair_idx];
682 let expr_forms = match &pair[1].kind {
683 FormKind::List(forms) => forms,
684 _ => unreachable!(),
685 };
686
687 let mut args = vec![transient.clone()];
689 for arg_form in expr_forms.iter().skip(2) {
690 args.push(eval(arg_form, env)?);
691 }
692
693 transient = match chain.ops[j] {
695 crate::interp::virtualize::ChainOpKind::Assoc => {
696 builtin_assoc_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
697 }
698 crate::interp::virtualize::ChainOpKind::Conj => {
699 builtin_conj_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
700 }
701 };
702
703 if j < chain.len - 1 {
707 let name = match &pair[0].kind {
708 FormKind::Symbol(s) => s.clone(),
709 _ => unreachable!(),
710 };
711 env.bind(Arc::from(name.as_str()), Value::Nil);
713 }
714 }
715
716 let persistent =
718 builtin_persistent_bang(&[transient]).map_err(|e| EvalError::Runtime(e.to_string()))?;
719
720 let last_pair = pairs[chain.start + chain.len - 1];
722 bind_pattern(&last_pair[0], persistent, env)?;
723
724 Ok(())
725}
726
727fn eval_chain_normally(
729 chain: &crate::interp::virtualize::LetChain,
730 pairs: &[&[Form]],
731 env: &mut Env,
732) -> Result<(), EvalError> {
733 for j in 0..chain.len {
734 let pair_idx = chain.start + j;
735 let pair = pairs[pair_idx];
736 let val = eval(&pair[1], env)?;
737 bind_pattern(&pair[0], val, env)?;
738 }
739 Ok(())
740}
741
742pub fn eval_loop(args: &[Form], env: &mut Env) -> EvalResult {
745 let bindings = match args.first().and_then(|f| f.as_vector()) {
746 Some(v) => expand_pairs(v)
747 .map_err(|_| EvalError::Runtime("loop* binding vector must have even length".into()))?
748 .into_owned(),
749 None => return Err(EvalError::Runtime("loop* requires a binding vector".into())),
750 };
751
752 let body = &args[1..];
753
754 let patterns: Vec<Form> = bindings.iter().step_by(2).cloned().collect();
756 let mut current_vals: Vec<Value> = Vec::new();
757
758 for i in (1..bindings.len()).step_by(2) {
760 current_vals.push(eval(&bindings[i], env)?);
761 }
762
763 loop {
764 let _vals_root = crate::env::gc_roots::root_values(¤t_vals);
766
767 crate::env::gc_roots::gc_safepoint(env)?;
770
771 #[cfg(feature = "no-gc")]
775 let mut scratch = cljrs_gc::alloc_ctx::ScratchGuard::new();
776
777 #[cfg(not(feature = "no-gc"))]
788 let _iter_frame = cljrs_gc::push_alloc_frame();
789
790 env.push_frame();
791 for (pat, val) in patterns.iter().zip(current_vals.iter()) {
792 if let Err(e) = bind_pattern(pat, val.clone(), env) {
793 env.pop_frame();
794 return Err(e);
795 }
796 }
797
798 #[cfg(not(feature = "no-gc"))]
801 let result = eval_body_recur(body, env);
802 #[cfg(feature = "no-gc")]
803 let result = eval_body_with_scratch_loop(body, &mut scratch, env);
804
805 env.pop_frame();
806 match result {
810 Ok(v) => return Ok(v),
811 Err(EvalError::Recur(new_vals)) => {
812 if new_vals.len() != patterns.len() {
813 return Err(EvalError::Arity {
814 name: "recur".into(),
815 expected: patterns.len().to_string(),
816 got: new_vals.len(),
817 });
818 }
819 current_vals = new_vals;
822 }
823 Err(e) => return Err(e),
824 }
825 }
826}
827
828fn eval_recur(args: &[Form], env: &mut Env) -> EvalResult {
829 let vals: Vec<Value> = args
830 .iter()
831 .map(|f| eval(f, env))
832 .collect::<EvalResult<_>>()?;
833 Err(EvalError::Recur(vals))
834}
835
836pub fn eval_body_recur(body: &[Form], env: &mut Env) -> EvalResult {
838 let mut result = Value::Nil;
839 for form in body {
840 result = eval(form, env)?;
841 }
842 Ok(result)
843}
844
845#[cfg(feature = "no-gc")]
851fn eval_body_with_scratch_loop(
852 body: &[Form],
853 scratch: &mut cljrs_gc::alloc_ctx::ScratchGuard,
854 env: &mut Env,
855) -> EvalResult {
856 if body.is_empty() {
857 scratch.pop_for_return();
858 return Ok(Value::Nil);
859 }
860 for form in &body[..body.len() - 1] {
861 eval(form, env)?;
862 }
863 scratch.pop_for_return();
864 eval(&body[body.len() - 1], env)
865}
866
867fn eval_quote(args: &[Form], env: &Env) -> EvalResult {
870 match args.first() {
871 Some(f) => form_to_value(&resolve_auto_forms(f, env)?),
875 None => Err(EvalError::Runtime("quote requires an argument".into())),
876 }
877}
878
879fn eval_var(args: &[Form], env: &mut Env) -> EvalResult {
882 let sym = match args.first().map(|f| &f.kind) {
883 Some(FormKind::Symbol(s)) => s.clone(),
884 _ => return Err(EvalError::Runtime("var requires a symbol".into())),
885 };
886 let parsed = cljrs_value::Symbol::parse(&sym);
887 let ns: Arc<str> = env.resolve_ns_or_current(parsed.namespace.as_deref());
888 let name = parsed.name.as_ref();
889 env.globals
890 .lookup_var_in_ns(&ns, name)
891 .map(Value::Var)
892 .ok_or_else(|| EvalError::UnboundSymbol(sym))
893}
894
895fn eval_set_bang(args: &[Form], env: &mut Env) -> EvalResult {
898 let target = args
899 .first()
900 .ok_or_else(|| EvalError::Runtime("set! requires a target".into()))?;
901 let val = if args.len() > 1 {
902 eval(&args[1], env)?
903 } else {
904 Value::Nil
905 };
906 match &target.kind {
907 FormKind::Symbol(sym) => set_bang_symbol(sym, val, env),
908 _ => match set_bang_field_target(target) {
909 Some((field, inst_form)) => {
910 let inst = eval(inst_form, env)?;
911 set_type_instance_field(&inst, field, val)
912 }
913 None => Err(set_bang_target_error()),
914 },
915 }
916}
917
918pub fn set_bang_symbol(sym: &str, val: Value, env: &mut Env) -> EvalResult {
921 if !sym.contains('/')
924 && let Some(v) = try_set_mutable_field(env, sym, &val)?
925 {
926 return Ok(v);
927 }
928 let parsed = cljrs_value::Symbol::parse(sym);
929 let ns = parsed.namespace.as_deref().unwrap_or(&env.current_ns);
930 let var = env
931 .globals
932 .lookup_var_in_ns(ns, &parsed.name)
933 .ok_or_else(|| EvalError::UnboundSymbol(sym.to_string()))?;
934 if !crate::env::dynamics::set_thread_local(&var, val.clone()) {
936 var.get().bind(val.clone());
937 }
938 Ok(val)
939}
940
941pub fn set_bang_field_target(target: &Form) -> Option<(&str, &Form)> {
944 match &target.kind {
945 FormKind::List(parts) if parts.len() == 2 => match &parts[0].kind {
946 FormKind::Symbol(op) if op.starts_with(".-") => Some((&op[2..], &parts[1])),
947 _ => None,
948 },
949 _ => None,
950 }
951}
952
953pub fn set_bang_target_error() -> EvalError {
955 EvalError::Runtime("set! requires a symbol or (.-field inst) target".into())
956}
957
958fn try_set_mutable_field(env: &mut Env, sym: &str, val: &Value) -> EvalResult<Option<Value>> {
963 let Some(Value::TypeInstance(ti)) = env.lookup_local_frames(DEFTYPE_SELF) else {
964 return Ok(None);
965 };
966 let Some(atom) = ti.get().mutable.clone() else {
967 return Ok(None);
968 };
969 let key = Value::keyword(cljrs_value::Keyword::simple(sym));
970 let Value::Map(map) = atom.get().deref() else {
971 return Ok(None);
972 };
973 if map.get(&key).is_none() {
974 return Ok(None);
975 }
976 atom.get().reset(Value::Map(map.assoc(key, val.clone())));
977 env.bind(Arc::from(sym), val.clone());
979 Ok(Some(val.clone()))
980}
981
982pub fn set_type_instance_field(inst: &Value, field: &str, val: Value) -> EvalResult {
984 let Value::TypeInstance(ti) = inst else {
985 return Err(EvalError::Runtime(format!(
986 "set! (.-{field} …): target is not a type instance"
987 )));
988 };
989 let atom = ti.get().mutable.clone().ok_or_else(|| {
990 EvalError::Runtime(format!("set! (.-{field} …): type has no mutable fields"))
991 })?;
992 let key = Value::keyword(cljrs_value::Keyword::simple(field));
993 let map = match atom.get().deref() {
994 Value::Map(m) => m,
995 _ => MapValue::empty(),
996 };
997 if map.get(&key).is_none() {
998 return Err(EvalError::Runtime(format!(
999 "set!: {field} is not a mutable field"
1000 )));
1001 }
1002 atom.get().reset(Value::Map(map.assoc(key, val.clone())));
1003 Ok(val)
1004}
1005
1006fn eval_throw(args: &[Form], env: &mut Env) -> EvalResult {
1009 let val = match args.first() {
1010 Some(f) => eval(f, env)?,
1011 None => Value::Nil,
1012 };
1013 Err(throw_value(val))
1014}
1015
1016pub fn throw_value(val: Value) -> EvalError {
1021 let val = match val {
1022 Value::Error(_) => val,
1023 other => {
1024 let msg = format!("{}", other);
1025 Value::Error(GcPtr::new(ExceptionInfo::new(
1026 ValueError::Other(msg.clone()),
1027 msg,
1028 None,
1029 None,
1030 )))
1031 }
1032 };
1033 EvalError::Thrown(val)
1034}
1035
1036pub struct CatchClause<'a> {
1043 pub type_sym: &'a str,
1044 pub binding: &'a str,
1045 pub body: &'a [Form],
1046}
1047
1048pub fn eval_error_to_value(err: &EvalError) -> Value {
1053 let msg = err.to_string();
1054 Value::Error(GcPtr::new(ExceptionInfo::new(
1055 ValueError::Other(msg.clone()),
1056 msg,
1057 None,
1058 None,
1059 )))
1060}
1061
1062pub fn catch_type_matches(type_name: &str, val: &Value) -> bool {
1066 let short = type_name.rsplit('.').next().unwrap_or(type_name);
1067 match short {
1068 "Object" | "Exception" | "Throwable" | "Error" | "default" => true,
1072 "ExceptionInfo" => matches!(val, Value::Error(_)),
1074 _ => false,
1075 }
1076}
1077
1078fn eval_try(args: &[Form], env: &mut Env) -> EvalResult {
1079 let (body, catches, fin_body) = parse_try_args(args);
1080
1081 let mut result = eval_body(body, env);
1082
1083 let err_opt = match std::mem::replace(&mut result, Ok(Value::Nil)) {
1085 Ok(v) => {
1086 result = Ok(v);
1087 None
1088 }
1089 Err(EvalError::Recur(args)) => {
1090 result = Err(EvalError::Recur(args));
1091 None
1092 }
1093 Err(EvalError::GasExhausted) => {
1094 result = Err(EvalError::GasExhausted);
1095 None
1096 }
1097 Err(EvalError::MemoryLimitExceeded(fault)) => {
1098 result = Err(EvalError::MemoryLimitExceeded(fault));
1099 None
1100 }
1101 Err(other) => Some(other),
1102 };
1103
1104 if let Some(err) = err_opt {
1105 let thrown_val = match err {
1106 EvalError::Thrown(v) => v,
1107 ref other => eval_error_to_value(other),
1108 };
1109 let mut handled = false;
1110 for c in &catches {
1111 if catch_type_matches(c.type_sym, &thrown_val) {
1112 env.push_frame();
1113 env.bind(Arc::from(c.binding), thrown_val.clone());
1114 result = eval_body(c.body, env);
1115 env.pop_frame();
1116 handled = true;
1117 break;
1118 }
1119 }
1120 if !handled {
1121 result = Err(EvalError::Thrown(thrown_val));
1123 }
1124 }
1125
1126 if !fin_body.is_empty() {
1130 eval_body(fin_body, env)?;
1131 }
1132
1133 result
1134}
1135
1136fn catch_target(f: &Form) -> Option<&str> {
1138 f.as_symbol().or_else(|| f.as_keyword())
1139}
1140
1141pub fn parse_try_args(args: &[Form]) -> (&[Form], Vec<CatchClause<'_>>, &[Form]) {
1145 let mut body_end = args.len();
1146 let mut catches: Vec<CatchClause<'_>> = Vec::new();
1147 let mut fin_body: &[Form] = &[];
1148
1149 for (i, form) in args.iter().enumerate() {
1150 if let Some(parts) = form.as_list()
1151 && let Some(s) = parts.first().and_then(|f| f.as_symbol())
1152 {
1153 if s == "catch" {
1154 if i < body_end {
1155 body_end = i;
1156 }
1157 let type_sym = match parts.get(1) {
1162 Some(f) => match catch_target(f) {
1163 Some(name) => name,
1164 None => match &f.unmeta().kind {
1165 FormKind::ReaderCond {
1166 splicing: false,
1167 clauses,
1168 } => match select_reader_cond(clauses).and_then(catch_target) {
1169 Some(name) => name,
1170 None => continue,
1171 },
1172 _ => continue,
1173 },
1174 },
1175 None => continue,
1176 };
1177 let binding = match parts.get(2).and_then(|f| f.as_symbol()) {
1178 Some(s) => s,
1179 None => continue,
1180 };
1181 catches.push(CatchClause {
1182 type_sym,
1183 binding,
1184 body: &parts[3..],
1185 });
1186 continue;
1187 }
1188 if s == "finally" {
1189 if i < body_end {
1190 body_end = i;
1191 }
1192 fin_body = &parts[1..];
1193 continue;
1194 }
1195 }
1196 }
1197
1198 (&args[..body_end], catches, fin_body)
1199}
1200
1201pub fn eval_defn(args: &[Form], env: &mut Env, private: bool) -> EvalResult {
1204 let name_form = args
1206 .first()
1207 .ok_or_else(|| EvalError::Runtime("defn requires a symbol name".into()))?;
1208 let (name_metas, name_sym) = name_form.peel_meta();
1209 let (name, mut is_async) = match &name_sym.kind {
1210 FormKind::Symbol(s) => (s.clone(), name_metas.iter().any(|m| m.requests_async())),
1211 _ => return Err(EvalError::Runtime("defn name must be a symbol".into())),
1212 };
1213 let mut rest_start = 1;
1217 let mut docstring: Option<String> = None;
1218 if rest_start < args.len()
1219 && let Some(s) = args[rest_start].as_string()
1220 {
1221 docstring = Some(s.to_string());
1222 rest_start += 1;
1223 }
1224 let mut attr_meta: Option<Value> = None;
1225 if rest_start < args.len() && args[rest_start].as_map().is_some() {
1226 is_async |= args[rest_start].requests_async();
1228 attr_meta = Some(eval(&args[rest_start], env)?);
1229 rest_start += 1;
1230 }
1231 let mut fn_args = vec![Form::new(
1233 FormKind::Symbol(name.to_string()),
1234 args[0].span.clone(),
1235 )];
1236 fn_args.extend_from_slice(&args[rest_start..]);
1237 #[cfg(feature = "no-gc")]
1240 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1241 let mut fn_val = eval_fn(&fn_args, env)?;
1242 if is_async && let Value::Fn(ref mut f) = fn_val {
1243 f.get_mut().is_async = true;
1244 }
1245 let var = env
1246 .globals
1247 .intern(&env.current_ns, Arc::from(name.as_str()), fn_val.clone());
1248 let mut meta = attr_meta;
1249 if let Some(doc) = &docstring {
1250 meta = merge_meta(meta, Some(doc_meta(doc)));
1251 }
1252 meta = merge_meta(meta, arglists_meta(&fn_val, 0));
1253 if private {
1254 meta = merge_meta(meta, Some(private_meta()));
1255 }
1256 if let Some(meta_val) = meta {
1257 var.get().set_meta(meta_val);
1258 }
1259 Ok(Value::Var(var))
1260}
1261
1262fn prepend_macro_params(form: &Form) -> Form {
1270 let span = form.span.clone();
1271 match &form.unmeta().kind {
1272 FormKind::Vector(params) => {
1273 let mut new_params = vec![
1274 Form::new(FormKind::Symbol("&form".to_string()), span.clone()),
1275 Form::new(FormKind::Symbol("&env".to_string()), span.clone()),
1276 ];
1277 new_params.extend_from_slice(params);
1278 Form::new(FormKind::Vector(new_params), span)
1279 }
1280 FormKind::List(forms) => {
1281 if let Some(first) = forms.first() {
1283 let new_params_form = prepend_macro_params(first);
1284 let mut new_forms = vec![new_params_form];
1285 new_forms.extend_from_slice(&forms[1..]);
1286 Form::new(FormKind::List(new_forms), span)
1287 } else {
1288 form.clone()
1289 }
1290 }
1291 _ => form.clone(),
1292 }
1293}
1294
1295fn eval_defmacro(args: &[Form], env: &mut Env) -> EvalResult {
1296 let mut current = args
1299 .first()
1300 .ok_or_else(|| EvalError::Runtime("defmacro requires a symbol at position 0".into()))?
1301 .clone();
1302 let mut name_meta: Option<Value> = None;
1303 while let FormKind::Meta(meta_form, inner) = current.kind {
1304 let meta_val = compile_meta_form(&meta_form, env)?;
1305 name_meta = merge_meta(name_meta, Some(meta_val));
1306 current = *inner;
1307 }
1308 let name = match ¤t.kind {
1309 FormKind::Symbol(s) => s.clone(),
1310 _ => {
1311 return Err(EvalError::Runtime(
1312 "defmacro requires a symbol at position 0".into(),
1313 ));
1314 }
1315 };
1316
1317 let mut rest_start = 1;
1318 let mut docstring: Option<String> = None;
1319 if rest_start < args.len()
1320 && let FormKind::Str(s) = &args[rest_start].kind
1321 {
1322 docstring = Some(s.clone());
1323 rest_start += 1;
1324 }
1325 let mut attr_meta = None;
1326 if rest_start < args.len() && matches!(args[rest_start].kind, FormKind::Map(_)) {
1327 attr_meta = Some(eval(&args[rest_start], env)?);
1328 rest_start += 1;
1329 }
1330 let mut fn_args = vec![Form::new(
1332 FormKind::Symbol(name.to_string()),
1333 args[0].span.clone(),
1334 )];
1335 for form in &args[rest_start..] {
1336 fn_args.push(prepend_macro_params(form));
1337 }
1338 #[cfg(feature = "no-gc")]
1341 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1342 let fn_val = eval_fn(&fn_args, env)?;
1343
1344 let macro_val = match fn_val {
1346 Value::Fn(f) => {
1347 let mut mfn = f.get().clone();
1348 mfn.is_macro = true;
1349 Value::Macro(GcPtr::new(mfn))
1350 }
1351 other => other,
1352 };
1353
1354 let var = env
1355 .globals
1356 .intern(&env.current_ns, Arc::from(name.as_str()), macro_val.clone());
1357 let mut meta = merge_meta(name_meta, attr_meta);
1358 if let Some(doc) = &docstring {
1359 meta = merge_meta(meta, Some(doc_meta(doc)));
1360 }
1361 meta = merge_meta(meta, arglists_meta(¯o_val, 2));
1363 if let Some(m) = meta {
1364 var.get().set_meta(m);
1365 }
1366 Ok(Value::Var(var))
1367}
1368
1369fn eval_defonce(args: &[Form], env: &mut Env) -> EvalResult {
1372 if args.is_empty() {
1373 return Err(EvalError::Runtime("defonce requires a name".into()));
1374 }
1375 let (name, _meta) = extract_def_name(&args[0], env)?;
1378 if let Some(var) = defonce_existing(&name, env) {
1380 return Ok(var);
1381 }
1382 eval_def(args, env)
1383}
1384
1385fn eval_and(args: &[Form], env: &mut Env) -> EvalResult {
1388 let mut result = Value::Bool(true);
1389 for form in args {
1390 result = eval(form, env)?;
1391 if matches!(result, Value::Nil | Value::Bool(false)) {
1392 return Ok(result);
1393 }
1394 }
1395 Ok(result)
1396}
1397
1398fn eval_or(args: &[Form], env: &mut Env) -> EvalResult {
1399 let mut last = Value::Nil;
1400 for form in args {
1401 last = eval(form, env)?;
1402 if !matches!(last, Value::Nil | Value::Bool(false)) {
1403 return Ok(last);
1404 }
1405 }
1406 Ok(last)
1407}
1408
1409fn eval_require(args: &[Form], env: &mut Env) -> EvalResult {
1412 for arg in args {
1413 let val = eval(arg, env)?;
1414 let spec = parse_require_spec_val(val).map_err(EvalError::Runtime)?;
1415 load_ns(env.globals.clone(), &spec, &env.current_ns)?;
1416 }
1417 Ok(Value::Nil)
1418}
1419
1420fn parse_require_spec_val(val: Value) -> Result<RequireSpec, String> {
1425 match val {
1426 Value::Symbol(s) => {
1427 let sym = s.get();
1428 Ok(RequireSpec {
1429 ns: sym.name.clone(),
1430 version: sym.version.clone(),
1431 alias: None,
1432 refer: RequireRefer::None,
1433 })
1434 }
1435 Value::Vector(v) => {
1436 let items: Vec<Value> = v.get().iter().cloned().collect();
1437 if items.is_empty() {
1438 return Err("require spec vector must not be empty".into());
1439 }
1440 let (ns, version) = match &items[0] {
1441 Value::Symbol(s) => {
1442 let sym = s.get();
1443 (sym.name.clone(), sym.version.clone())
1444 }
1445 other => {
1446 return Err(format!(
1447 "require spec: first element must be a symbol, got {}",
1448 other.type_name()
1449 ));
1450 }
1451 };
1452 let mut alias = None;
1453 let mut refer = RequireRefer::None;
1454 let mut i = 1;
1455 while i < items.len() {
1456 match &items[i] {
1457 Value::Keyword(k) if k.get().name.as_ref() == "as" => {
1458 i += 1;
1459 alias = Some(match items.get(i) {
1460 Some(Value::Symbol(s)) => s.get().name.clone(),
1461 _ => return Err("require :as expects a symbol".into()),
1462 });
1463 }
1464 Value::Keyword(k) if k.get().name.as_ref() == "refer" => {
1465 i += 1;
1466 refer = match items.get(i) {
1467 Some(Value::Keyword(k2)) if k2.get().name.as_ref() == "all" => {
1468 RequireRefer::All
1469 }
1470 Some(Value::Vector(rv)) => {
1471 let names: Vec<Arc<str>> = rv
1472 .get()
1473 .iter()
1474 .map(|v| match v {
1475 Value::Symbol(s) => Ok(s.get().name.clone()),
1476 other => Err(format!(
1477 "require :refer expects symbols, got {}",
1478 other.type_name()
1479 )),
1480 })
1481 .collect::<Result<_, _>>()?;
1482 RequireRefer::Named(names)
1483 }
1484 _ => {
1485 return Err(
1486 "require :refer expects :all or a vector of symbols".into()
1487 );
1488 }
1489 };
1490 }
1491 other => {
1492 return Err(format!(
1493 "require spec: unexpected option {}",
1494 other.type_name()
1495 ));
1496 }
1497 }
1498 i += 1;
1499 }
1500 Ok(RequireSpec {
1501 ns,
1502 version,
1503 alias,
1504 refer,
1505 })
1506 }
1507 other => Err(format!(
1508 "require expects a symbol or vector, got {}",
1509 other.type_name()
1510 )),
1511 }
1512}
1513
1514fn spec_element(form: &Form) -> Option<&Form> {
1518 match &form.kind {
1519 FormKind::ReaderCond { clauses, .. } => select_reader_cond(clauses),
1520 _ => Some(form),
1521 }
1522}
1523
1524pub fn parse_require_spec_form(form: &Form) -> Result<RequireSpec, String> {
1531 match &form.kind {
1532 FormKind::Symbol(s) => {
1533 let sym = cljrs_value::Symbol::parse(s);
1534 Ok(RequireSpec {
1535 ns: sym.name.clone(),
1536 version: sym.version.clone(),
1537 alias: None,
1538 refer: RequireRefer::None,
1539 })
1540 }
1541 FormKind::Vector(items) => {
1542 if items.is_empty() {
1543 return Err("require spec vector must not be empty".into());
1544 }
1545 let head = spec_element(&items[0]).ok_or_else(|| {
1546 "require spec: no reader-conditional branch matched for the namespace".to_string()
1547 })?;
1548 let (ns, version) = match &head.kind {
1549 FormKind::Symbol(s) => {
1550 let sym = cljrs_value::Symbol::parse(s);
1551 (sym.name.clone(), sym.version.clone())
1552 }
1553 _ => return Err("require spec: first element must be a symbol".into()),
1554 };
1555 let mut alias = None;
1556 let mut refer = RequireRefer::None;
1557 let mut i = 1;
1558 while i < items.len() {
1559 let Some(item) = spec_element(&items[i]) else {
1562 i += 1;
1563 continue;
1564 };
1565 match &item.kind {
1566 FormKind::Keyword(k) if k == "as" => {
1567 i += 1;
1568 alias = Some(match items.get(i).map(|f| &f.kind) {
1569 Some(FormKind::Symbol(s)) => Arc::from(s.as_str()),
1570 _ => return Err("require :as expects a symbol".into()),
1571 });
1572 }
1573 FormKind::Keyword(k) if k == "refer" => {
1574 i += 1;
1575 refer = match items.get(i).map(|f| &f.kind) {
1576 Some(FormKind::Keyword(k2)) if k2 == "all" => RequireRefer::All,
1577 Some(FormKind::Vector(rv)) => {
1578 let names: Vec<Arc<str>> = rv
1579 .iter()
1580 .map(|f| match &f.kind {
1581 FormKind::Symbol(s) => Ok(Arc::from(s.as_str())),
1582 _ => Err("require :refer expects symbols".to_string()),
1583 })
1584 .collect::<Result<_, _>>()?;
1585 RequireRefer::Named(names)
1586 }
1587 _ => return Err("require :refer expects :all or a vector".into()),
1588 };
1589 }
1590 _ => return Err(format!("require spec: unexpected form at position {i}")),
1591 }
1592 i += 1;
1593 }
1594 Ok(RequireSpec {
1595 ns,
1596 version,
1597 alias,
1598 refer,
1599 })
1600 }
1601 _ => Err("require spec must be a symbol or vector".into()),
1602 }
1603}
1604
1605fn extract_ns_name_form(form: Option<&Form>, env: &mut Env) -> EvalResult<(String, Option<Value>)> {
1611 let mut current = form
1612 .ok_or_else(|| EvalError::Runtime("ns requires a symbol at position 0".into()))?
1613 .clone();
1614 let mut meta_acc: Option<Value> = None;
1615 while let FormKind::Meta(meta_form, inner) = current.kind {
1616 let meta_val = compile_meta_form(&meta_form, env)?;
1617 meta_acc = merge_meta(meta_acc, Some(meta_val));
1618 current = *inner;
1619 }
1620 match ¤t.kind {
1621 FormKind::Symbol(s) => Ok((s.clone(), meta_acc)),
1622 _ => Err(EvalError::Runtime(
1623 "ns requires a symbol at position 0".into(),
1624 )),
1625 }
1626}
1627
1628fn merge_meta(base: Option<Value>, overlay: Option<Value>) -> Option<Value> {
1631 match (base, overlay) {
1632 (None, None) => None,
1633 (Some(b), None) => Some(b),
1634 (None, Some(o)) => Some(o),
1635 (Some(Value::Map(b)), Some(Value::Map(o))) => {
1636 let mut merged = b;
1637 for (k, v) in o.iter() {
1638 merged = merged.assoc(k.clone(), v.clone());
1639 }
1640 Some(Value::Map(merged))
1641 }
1642 (_, Some(o)) => Some(o),
1643 }
1644}
1645
1646fn parse_refer_clojure_clause(items: &[Form]) -> Result<ReferClojureFilter, String> {
1650 let mut filter = ReferClojureFilter::default();
1651 let items = expand_reader_conds(items);
1652 let mut i = 0;
1653 while i < items.len() {
1654 let FormKind::Keyword(k) = &items[i].kind else {
1655 return Err(":refer-clojure expects keyword options (:exclude, :only, :rename)".into());
1656 };
1657 let arg = items
1658 .get(i + 1)
1659 .ok_or_else(|| format!(":refer-clojure :{k} expects a value"))?;
1660 match k.as_str() {
1661 "exclude" => filter.exclude = symbol_name_set(arg, "exclude")?,
1662 "only" => filter.only = Some(symbol_name_set(arg, "only")?),
1663 "rename" => {
1664 let FormKind::Map(entries) = &arg.kind else {
1665 return Err(":refer-clojure :rename expects a map".into());
1666 };
1667 if entries.len() % 2 != 0 {
1668 return Err(":refer-clojure :rename expects an even-sized map".into());
1669 }
1670 for pair in entries.chunks(2) {
1671 match (&pair[0].kind, &pair[1].kind) {
1672 (FormKind::Symbol(from), FormKind::Symbol(to)) => {
1673 filter
1674 .rename
1675 .insert(Arc::from(from.as_str()), Arc::from(to.as_str()));
1676 }
1677 _ => {
1678 return Err(
1679 ":refer-clojure :rename expects symbol keys and values".into()
1680 );
1681 }
1682 }
1683 }
1684 }
1685 other => return Err(format!(":refer-clojure does not support :{other}")),
1686 }
1687 i += 2;
1688 }
1689 Ok(filter)
1690}
1691
1692fn symbol_name_set(form: &Form, opt: &str) -> Result<HashSet<Arc<str>>, String> {
1694 let FormKind::Vector(items) = &form.kind else {
1695 return Err(format!(":refer-clojure :{opt} expects a vector of symbols"));
1696 };
1697 expand_reader_conds(items)
1698 .iter()
1699 .map(|f| match &f.kind {
1700 FormKind::Symbol(sym) => Ok(Arc::from(sym.as_str())),
1701 _ => Err(format!(":refer-clojure :{opt} expects symbols")),
1702 })
1703 .collect()
1704}
1705
1706fn eval_ns(args: &[Form], env: &mut Env) -> EvalResult {
1707 let (name, name_meta) = extract_ns_name_form(args.first(), env)?;
1708 env.globals.get_or_create_ns(&name);
1709 env.current_ns = Arc::from(name.as_str());
1710 if name != "clojure.core" {
1712 env.globals.refer_core(&name);
1713 }
1714 sync_star_ns(env);
1715
1716 let mut rest = &args[1..];
1718 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Str(_))) {
1719 rest = &rest[1..];
1720 }
1721 let mut attr_meta = None;
1722 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Map(_))) {
1723 attr_meta = Some(eval(&rest[0], env)?);
1724 rest = &rest[1..];
1725 }
1726
1727 if let Some(m) = merge_meta(name_meta, attr_meta) {
1728 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1729 ns_ptr.get().set_meta(m);
1730 }
1731
1732 let mut refer_clojure = None;
1743 for clause in rest {
1744 if let FormKind::List(items) = &clause.kind
1745 && matches!(items.first().map(|f| &f.kind), Some(FormKind::Keyword(k)) if k == "refer-clojure")
1746 {
1747 refer_clojure =
1748 Some(parse_refer_clojure_clause(&items[1..]).map_err(EvalError::Runtime)?);
1749 }
1750 }
1751 if name != "clojure.core" {
1752 env.globals
1753 .set_refer_clojure_filter(&name, refer_clojure)
1754 .map_err(EvalError::Runtime)?;
1755 }
1756
1757 for clause in rest {
1758 if let FormKind::List(items) = &clause.kind {
1759 match items.first().map(|f| &f.kind) {
1760 Some(FormKind::Keyword(k)) if k == "require" => {
1761 let expanded = expand_reader_conds(&items[1..]);
1763 for spec_form in &expanded {
1764 let spec =
1765 parse_require_spec_form(spec_form).map_err(EvalError::Runtime)?;
1766 load_ns(env.globals.clone(), &spec, &name)?;
1767 }
1768 }
1769 Some(FormKind::Keyword(k)) if k == "import" => {
1770 for spec in &expand_reader_conds(&items[1..]) {
1771 import_types(env, &name, spec);
1772 }
1773 }
1774 _ => {}
1777 }
1778 }
1779 }
1780
1781 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1782 Ok(Value::Namespace(ns_ptr))
1783}
1784
1785fn import_types(env: &Env, dst_ns: &str, spec: &Form) {
1793 match &spec.unmeta().kind {
1794 FormKind::Vector(items) | FormKind::List(items) => {
1795 let mut syms = items.iter().filter_map(Form::as_symbol);
1796 if let Some(pkg) = syms.next() {
1797 for name in syms {
1798 import_type(env, dst_ns, pkg, name);
1799 }
1800 }
1801 }
1802 FormKind::Symbol(s) => {
1803 if let Some((pkg, name)) = s.rsplit_once('.') {
1804 import_type(env, dst_ns, pkg, name);
1805 }
1806 }
1807 _ => {}
1808 }
1809}
1810
1811fn import_type(env: &Env, dst_ns: &str, pkg: &str, name: &str) {
1816 let demunged = pkg.replace('_', "-");
1817 for ns in [pkg, demunged.as_str()] {
1818 let tag = format!("{ns}.{name}");
1819 let names_type = matches!(
1820 env.globals.lookup_in_ns(ns, name),
1821 Some(Value::Symbol(s)) if s.get().to_string() == tag
1822 );
1823 if names_type {
1824 env.globals.refer_named(dst_ns, ns, &[Arc::from(name)]);
1825 return;
1826 }
1827 }
1828}
1829
1830fn eval_load_file(args: &[Form], env: &mut Env) -> EvalResult {
1833 if args.is_empty() {
1834 return Err(EvalError::Runtime(
1835 "load-file requires a path argument".into(),
1836 ));
1837 }
1838 let path_val = eval(&args[0], env)?;
1839 let path = match &path_val {
1840 Value::Str(s) => s.get().clone(),
1841 v => {
1842 return Err(EvalError::Runtime(format!(
1843 "load-file: expected string, got {}",
1844 v.type_name()
1845 )));
1846 }
1847 };
1848 let src = std::fs::read_to_string(&path)
1849 .map_err(|e| EvalError::Runtime(format!("load-file: {e}")))?;
1850 let mut parser = cljrs_reader::Parser::new(src, path.clone());
1851 let forms = parser
1852 .parse_all()
1853 .map_err(|e| EvalError::Runtime(format!("load-file parse error: {e}")))?;
1854 let mut result = Value::Nil;
1855 for form in forms {
1856 let _alloc_frame = cljrs_gc::push_alloc_frame();
1857 result = eval(&form, env)?;
1858 }
1859 Ok(result)
1860}
1861
1862fn eval_letfn(args: &[Form], env: &mut Env) -> EvalResult {
1865 push_letfn_frame(args, env)?;
1866 let result = eval_body(&args[1..], env);
1867 env.pop_frame();
1868 result
1869}
1870
1871pub fn push_letfn_frame(args: &[Form], env: &mut Env) -> EvalResult<()> {
1877 let bindings = match args.first().and_then(|f| f.as_vector()) {
1886 Some(v) => expand_reader_conds_cow(v).into_owned(),
1887 None => return Err(EvalError::Runtime("letfn requires a binding vector".into())),
1888 };
1889
1890 env.push_frame();
1891
1892 for binding in &bindings {
1895 if let Some(parts) = binding.as_list() {
1896 if parts.is_empty() {
1897 continue;
1898 }
1899 let Some(name) = parts[0].as_symbol() else {
1900 env.pop_frame();
1901 return Err(EvalError::Runtime(
1902 "letfn binding name must be a symbol".into(),
1903 ));
1904 };
1905 env.bind(Arc::from(name), Value::Nil);
1906 }
1907 }
1908
1909 let mut built: Vec<(Arc<str>, Value)> = Vec::new();
1912 for binding in &bindings {
1913 if let Some(parts) = binding.as_list() {
1914 if parts.is_empty() {
1915 continue;
1916 }
1917 let fn_val = match eval_fn(parts, env) {
1920 Ok(v) => v,
1921 Err(e) => {
1922 env.pop_frame();
1923 return Err(e);
1924 }
1925 };
1926 let name: Arc<str> = match parts[0].as_symbol() {
1927 Some(s) => Arc::from(s),
1928 None => unreachable!("pass 1 rejected every non-symbol name"),
1929 };
1930 env.bind(Arc::clone(&name), fn_val.clone());
1931 built.push((name, fn_val));
1932 }
1933 }
1934
1935 for (_, fn_val) in &built {
1940 if let Value::Fn(ptr) = fn_val {
1941 let mut ptr = ptr.clone();
1942 let f = ptr.get_mut();
1943 for i in 0..f.closed_over_names.len() {
1944 let captured = f.closed_over_names[i].clone();
1945 if let Some((_, real)) = built.iter().find(|(n, _)| *n == captured) {
1946 f.closed_over_vals[i] = real.clone();
1947 }
1948 }
1949 }
1950 }
1951
1952 Ok(())
1953}
1954
1955fn eval_in_ns(args: &[Form], env: &mut Env) -> EvalResult {
1958 if args.is_empty() {
1960 return Err(EvalError::Runtime("in-ns requires a namespace name".into()));
1961 }
1962 let ns_val = eval(&args[0], env)?;
1963 let ns_name = extract_ns_name(&ns_val)?;
1964 env.globals.get_or_create_ns(&ns_name);
1965 env.globals.refer_core(&ns_name);
1966 env.current_ns = Arc::from(ns_name.as_str());
1967 sync_star_ns(env);
1968 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1969 Ok(Value::Namespace(ns_ptr))
1970}
1971
1972fn eval_alias(args: &[Form], env: &mut Env) -> EvalResult {
1975 if args.len() < 2 {
1977 return Err(EvalError::Runtime(
1978 "alias requires alias-sym and namespace-sym".into(),
1979 ));
1980 }
1981 let alias_val = eval(&args[0], env)?;
1982 let ns_val = eval(&args[1], env)?;
1983
1984 let alias_name = extract_ns_name(&alias_val)?;
1985 let full_ns = extract_ns_name(&ns_val)?;
1986
1987 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1988 let mut aliases = ns_ptr.get().aliases.lock().unwrap();
1989 aliases.insert(Arc::from(alias_name.as_str()), Arc::from(full_ns.as_str()));
1990 Ok(Value::Nil)
1991}
1992
1993fn extract_ns_name(v: &Value) -> EvalResult<String> {
1995 match v {
1996 Value::Symbol(s) => {
1997 Ok(s.get().name.as_ref().to_string())
1999 }
2000 Value::Str(s) => Ok(s.get().clone()),
2001 Value::Keyword(k) => Ok(k.get().name.as_ref().to_string()),
2002 other => Err(EvalError::Runtime(format!(
2003 "expected a symbol or string for namespace name, got {}",
2004 other.type_name()
2005 ))),
2006 }
2007}
2008
2009fn protocol_method_of(spec: &Value) -> EvalResult<ProtocolMethod> {
2013 let Value::Map(m) = spec.unwrap_meta() else {
2014 return Err(EvalError::Runtime(format!(
2015 "protocol* method spec must be a map, got {}",
2016 spec.type_name()
2017 )));
2018 };
2019 let field = |k: &str| m.get(&Value::keyword(Keyword::simple(k)));
2020 let name: Arc<str> = match field("name") {
2021 Some(Value::Str(s)) => Arc::from(s.get().as_str()),
2022 Some(Value::Symbol(s)) => Arc::from(s.get().name.as_ref()),
2023 Some(Value::Keyword(k)) => Arc::from(k.get().name.as_ref()),
2024 _ => {
2025 return Err(EvalError::Runtime(
2026 "protocol* method spec needs a :name".into(),
2027 ));
2028 }
2029 };
2030 let min_arity = match field("min-arity") {
2031 Some(Value::Long(n)) if n >= 0 => n as usize,
2032 _ => 1,
2033 };
2034 let variadic = !matches!(
2035 field("variadic"),
2036 None | Some(Value::Nil) | Some(Value::Bool(false))
2037 );
2038 Ok(ProtocolMethod {
2039 name,
2040 min_arity,
2041 variadic,
2042 })
2043}
2044
2045fn eval_protocol_star(args: &[Form], env: &mut Env) -> EvalResult {
2054 if args.len() < 2 {
2055 return Err(EvalError::Runtime(
2056 "protocol* requires a name and method specs".into(),
2057 ));
2058 }
2059 let (name, _) = require_sym_meta(args, 0, "protocol*", env)?;
2061 let specs = crate::interp::eval::eval(&args[1], env)?;
2062 let specs: Vec<Value> = match specs.unwrap_meta() {
2063 Value::Vector(v) => v.get().iter().cloned().collect(),
2064 Value::Nil => Vec::new(),
2065 v => {
2066 return Err(EvalError::Runtime(format!(
2067 "protocol* method specs must be a vector, got {}",
2068 v.type_name()
2069 )));
2070 }
2071 };
2072 let methods = specs
2073 .iter()
2074 .map(protocol_method_of)
2075 .collect::<EvalResult<Vec<_>>>()?;
2076 let extend_via_metadata = match args.get(2) {
2077 Some(f) => !matches!(
2078 crate::interp::eval::eval(f, env)?,
2079 Value::Nil | Value::Bool(false)
2080 ),
2081 None => false,
2082 };
2083 let proto = Protocol::new(
2084 Arc::from(name.as_str()),
2085 env.current_ns.clone(),
2086 methods,
2087 extend_via_metadata,
2088 );
2089 Ok(Value::Protocol(GcPtr::new(proto)))
2090}
2091
2092fn synth_field_scope(
2110 params_form: &Form,
2111 fields: &[Arc<str>],
2112 mutable_fields: &[Arc<str>],
2113 body: &[Form],
2114) -> Option<Vec<Form>> {
2115 let param_forms = match ¶ms_form.kind {
2116 FormKind::Vector(v) => v,
2117 _ => return None,
2118 };
2119 let this_name = match param_forms.first().map(|f| &f.kind) {
2120 Some(FormKind::Symbol(s)) => s.clone(),
2121 _ => return None,
2122 };
2123 let param_names: Vec<&str> = param_forms
2124 .iter()
2125 .filter_map(|f| match &f.kind {
2126 FormKind::Symbol(s) => Some(s.as_str()),
2127 _ => None,
2128 })
2129 .collect();
2130
2131 let span = params_form.span.clone();
2132 let is_mut = |name: &str| mutable_fields.iter().any(|m| m.as_ref() == name);
2133 let mut bindings: Vec<Form> = Vec::new();
2134 for field in fields {
2135 if param_names.contains(&field.as_ref()) {
2136 continue;
2137 }
2138 bindings.push(Form::new(FormKind::Symbol(field.to_string()), span.clone()));
2139 let accessor = if is_mut(field) {
2143 FormKind::List(vec![
2144 Form::new(FormKind::Symbol(format!(".-{field}")), span.clone()),
2145 Form::new(FormKind::Symbol(this_name.clone()), span.clone()),
2146 ])
2147 } else {
2148 FormKind::List(vec![
2149 Form::new(FormKind::Keyword(field.to_string()), span.clone()),
2150 Form::new(FormKind::Symbol(this_name.clone()), span.clone()),
2151 ])
2152 };
2153 bindings.push(Form::new(accessor, span.clone()));
2154 }
2155 if !mutable_fields.is_empty() {
2158 bindings.push(Form::new(
2159 FormKind::Symbol(DEFTYPE_SELF.to_string()),
2160 span.clone(),
2161 ));
2162 bindings.push(Form::new(FormKind::Symbol(this_name.clone()), span.clone()));
2163 }
2164 if bindings.is_empty() {
2165 return None;
2166 }
2167
2168 let mut let_forms = vec![
2169 Form::new(FormKind::Symbol("let*".to_string()), span.clone()),
2170 Form::new(FormKind::Vector(bindings), span.clone()),
2171 ];
2172 let_forms.extend_from_slice(body);
2173 Some(vec![Form::new(FormKind::List(let_forms), span)])
2174}
2175
2176fn build_impl_fn(
2177 parts: &[Form],
2178 fields: &[Arc<str>],
2179 mutable_fields: &[Arc<str>],
2180 env: &mut Env,
2181) -> EvalResult<Value> {
2182 if parts.len() < 2 {
2183 return Err(EvalError::Runtime(
2184 "protocol method impl requires params and body".into(),
2185 ));
2186 }
2187 let params_form = &parts[1];
2189 let body = &parts[2..];
2190 let scoped;
2191 let body: &[Form] = if fields.is_empty() {
2192 body
2193 } else {
2194 match synth_field_scope(params_form, fields, mutable_fields, body) {
2195 Some(v) => {
2196 scoped = v;
2197 &scoped
2198 }
2199 None => body,
2200 }
2201 };
2202 let arity = parse_arity(params_form, body)?;
2203 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
2204 let fn_name: Option<Arc<str>> = parts[0].as_symbol().map(Arc::from);
2205 let cljrs_fn = CljxFn::new(
2206 fn_name,
2207 vec![arity],
2208 closed_over_names,
2209 closed_over_vals,
2210 false,
2211 Arc::clone(&env.current_ns),
2212 );
2213 Ok(Value::Fn(GcPtr::new(cljrs_fn)))
2214}
2215
2216fn eval_binding(args: &[Form], env: &mut Env) -> EvalResult {
2219 let pairs = match args.first().and_then(|f| f.as_vector()) {
2220 Some(v) => expand_pairs(v)
2221 .map_err(|_| EvalError::Runtime("binding vector must have even count".into()))?
2222 .into_owned(),
2223 None => return Err(EvalError::Runtime("binding requires a vector".into())),
2224 };
2225
2226 let mut frame: HashMap<usize, Value> = HashMap::new();
2227 for pair in pairs.chunks(2) {
2228 let Some(sym_str) = pair[0].as_symbol() else {
2229 return Err(EvalError::Runtime("binding targets must be symbols".into()));
2230 };
2231 let parsed = cljrs_value::Symbol::parse(sym_str);
2232 let ns_part: Arc<str> = env.resolve_ns_or_current(parsed.namespace.as_deref());
2233 let var_ptr = env
2234 .globals
2235 .lookup_var_in_ns(&ns_part, &parsed.name)
2236 .ok_or_else(|| EvalError::UnboundSymbol(sym_str.to_string()))?;
2237 let val = eval(&pair[1], env)?;
2238 frame.insert(crate::env::dynamics::var_key_of(&var_ptr), val);
2239 }
2240
2241 let _guard = crate::env::dynamics::push_frame(frame);
2242 eval_body(&args[1..], env)
2243 }
2245
2246const DEFTYPE_SELF: &str = "__deftype_self__";
2252
2253fn meta_form_is_mutable(meta: &Form) -> bool {
2257 let is_mut_kw = |k: &str| k == "unsynchronized-mutable" || k == "volatile-mutable";
2258 match &meta.kind {
2259 FormKind::Keyword(k) => is_mut_kw(k),
2260 FormKind::Map(entries) => entries.chunks(2).any(|kv| {
2261 matches!(&kv[0].kind, FormKind::Keyword(k) if is_mut_kw(k))
2262 && !matches!(
2263 kv.get(1).map(|f| &f.kind),
2264 None | Some(FormKind::Bool(false)) | Some(FormKind::Nil)
2265 )
2266 }),
2267 FormKind::Quote(inner) => meta_form_is_mutable(inner),
2273 _ => false,
2274 }
2275}
2276
2277fn field_spec_of(form: &Form) -> Option<(Arc<str>, bool)> {
2279 match &form.kind {
2280 FormKind::Symbol(s) => Some((Arc::from(s.as_str()), false)),
2281 FormKind::Meta(meta, inner) => {
2282 let here = meta_form_is_mutable(meta);
2283 field_spec_of(inner).map(|(name, inner_mut)| (name, inner_mut || here))
2284 }
2285 _ => None,
2286 }
2287}
2288
2289fn parse_field_specs(form: &Form, ctx: &str) -> EvalResult<Vec<(Arc<str>, bool)>> {
2291 let Some(fields) = form.as_vector() else {
2294 return Err(EvalError::Runtime(format!(
2295 "{ctx} requires a field vector as second arg"
2296 )));
2297 };
2298 fields
2299 .iter()
2300 .map(|f| {
2301 field_spec_of(f)
2302 .ok_or_else(|| EvalError::Runtime(format!("{ctx} field names must be symbols")))
2303 })
2304 .collect()
2305}
2306
2307fn eval_deftype_star(args: &[Form], env: &mut Env) -> EvalResult {
2315 if args.len() < 2 {
2317 return Err(EvalError::Runtime(
2318 "deftype* requires a name and field vector".into(),
2319 ));
2320 }
2321 let (type_name, _) = require_sym_meta(args, 0, "deftype*", env)?;
2324 let type_tag = qualified_type_tag(&type_name, env);
2325
2326 let specs = parse_field_specs(&args[1], "deftype*")?;
2327 let field_names: Vec<Arc<str>> = specs.iter().map(|(n, _)| n.clone()).collect();
2328 let mutable_names: Vec<Arc<str>> = specs
2329 .iter()
2330 .filter(|(_, m)| *m)
2331 .map(|(n, _)| n.clone())
2332 .collect();
2333
2334 register_impls_for_tag(&type_tag, &args[2..], &field_names, &mutable_names, env)?;
2338 Ok(Value::string(type_tag.to_string()))
2342}
2343
2344fn qualified_type_tag(type_name: &str, env: &Env) -> Arc<str> {
2350 Arc::from(format!("{}.{}", env.current_ns, type_name))
2351}
2352
2353fn resolve_protocol_sym(env: &Env, s: &str) -> Option<GcPtr<Protocol>> {
2366 let parsed = cljrs_value::Symbol::parse(s);
2367 let val = match parsed.namespace.as_deref() {
2368 Some(ns_part) => {
2369 let ns = env.resolve_ns_part(ns_part);
2370 env.globals.lookup_in_ns(&ns, &parsed.name)
2371 }
2372 None => env.globals.lookup_in_ns(&env.current_ns, s),
2373 };
2374 match val {
2375 Some(Value::Protocol(p)) => Some(p),
2376 _ => None,
2377 }
2378}
2379
2380fn register_impls_for_tag(
2383 type_tag: &Arc<str>,
2384 forms: &[Form],
2385 fields: &[Arc<str>],
2386 mutable_fields: &[Arc<str>],
2387 env: &mut Env,
2388) -> EvalResult<()> {
2389 let mut current_proto: Option<GcPtr<cljrs_value::Protocol>> = None;
2390
2391 for form in forms {
2392 match &form.unmeta().kind {
2393 FormKind::Symbol(s) => match resolve_protocol_sym(env, s) {
2394 Some(p) => current_proto = Some(p),
2395 None => {
2396 return Err(EvalError::Runtime(format!(
2397 "reify/defrecord: {} is not a protocol",
2398 s
2399 )));
2400 }
2401 },
2402 FormKind::List(parts) => {
2403 let proto = current_proto.as_ref().ok_or_else(|| {
2404 EvalError::Runtime("reify/defrecord: method impl before protocol name".into())
2405 })?;
2406 if parts.is_empty() {
2407 continue;
2408 }
2409 let method_name: Arc<str> = match parts[0].as_symbol() {
2410 Some(s) => Arc::from(s),
2411 None => continue,
2412 };
2413 let fn_val = build_impl_fn(parts, fields, mutable_fields, env)?;
2414 let mut impls = proto.get().impls.lock().unwrap();
2415 impls
2416 .entry(type_tag.clone())
2417 .or_default()
2418 .insert(method_name, fn_val);
2419 drop(impls);
2420 cljrs_value::bump_protocol_generation();
2421 }
2422 _ => {}
2423 }
2424 }
2425 Ok(())
2426}
2427
2428pub fn sync_star_ns(env: &mut Env) {
2433 if let Some(star_ns_var) = env.globals.lookup_var("clojure.core", "*ns*") {
2434 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
2435 star_ns_var.get().bind(Value::Namespace(ns_ptr));
2436 }
2437}
2438
2439fn require_sym_meta(
2451 args: &[Form],
2452 idx: usize,
2453 form_name: &str,
2454 env: &mut Env,
2455) -> EvalResult<(String, Option<Value>)> {
2456 fn peel(form: &Form, env: &mut Env) -> EvalResult<Option<(String, Option<Value>)>> {
2457 match &form.kind {
2458 FormKind::Symbol(s) => Ok(Some((s.clone(), None))),
2459 FormKind::Meta(meta_form, inner) => {
2461 let meta_val = compile_meta_form(meta_form, env)?;
2462 match peel(inner, env)? {
2463 Some((name, inner_meta)) => {
2464 Ok(Some((name, merge_meta(inner_meta, Some(meta_val)))))
2465 }
2466 None => Ok(None),
2467 }
2468 }
2469 _ => Ok(None),
2470 }
2471 }
2472 let err = || EvalError::Runtime(format!("{form_name} requires a symbol at position {idx}"));
2473 match args.get(idx) {
2474 Some(form) => peel(form, env)?.ok_or_else(err),
2475 None => Err(err()),
2476 }
2477}
2478
2479fn eval_with_out_str(body: &[Form], env: &mut Env) -> EvalResult {
2482 crate::builtins::builtins::push_output_capture();
2483 let result = eval_body(body, env);
2484 let captured = crate::builtins::builtins::pop_output_capture().unwrap_or_default();
2485 result?;
2487 Ok(Value::string(captured))
2488}
2489
2490fn eval_await(args: &[Form], env: &mut Env) -> EvalResult {
2499 if args.is_empty() {
2500 return Err(EvalError::Runtime("await requires one argument".into()));
2501 }
2502 let val = eval(&args[0], env)?;
2503 match val {
2504 Value::Future(f) => {
2505 let mut guard = f.get().state.lock().unwrap();
2506 loop {
2507 match &*guard {
2508 FutureState::Done(v) => {
2509 f.get().mark_observed();
2510 return Ok(v.clone());
2511 }
2512 FutureState::Failed(v) => {
2513 f.get().mark_observed();
2514 return Err(EvalError::Thrown(v.clone()));
2515 }
2516 FutureState::GasExhausted => {
2517 f.get().mark_observed();
2518 return Err(EvalError::GasExhausted);
2519 }
2520 FutureState::MemoryLimitExceeded(fault) => {
2521 f.get().mark_observed();
2522 return Err(EvalError::MemoryLimitExceeded(*fault));
2523 }
2524 FutureState::Cancelled => {
2525 return Err(EvalError::Thrown(CljxFuture::cancelled_error()));
2526 }
2527 FutureState::Running => {
2528 guard = f.get().cond.wait(guard).unwrap();
2529 }
2530 }
2531 }
2532 }
2533 Value::Promise(p) => Ok(p.get().deref_blocking()),
2534 other => Ok(other),
2535 }
2536}