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, FutureState, Keyword, MapValue, MultiFn, Protocol, ProtocolFn,
21 ProtocolMethod, ReferClojureFilter, TypeHint, TypeInstance, 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" | "defn-" => eval_defn(args, env),
41 "defmacro" => eval_defmacro(args, env),
42 "defonce" => eval_defonce(args, env),
43 "and" => eval_and(args, env),
44 "or" => eval_or(args, env),
45 "." => Err(EvalError::Runtime("interop not yet implemented".into())),
46 "ns" => eval_ns(args, env),
47 "require" => eval_require(args, env),
48 "letfn" => eval_letfn(args, env),
49 "in-ns" => eval_in_ns(args, env),
50 "alias" => eval_alias(args, env),
51 "defprotocol" => eval_defprotocol(args, env),
52 "extend-type" => eval_extend_type(args, env),
53 "extend-protocol" => eval_extend_protocol(args, env),
54 "defmulti" => eval_defmulti(args, env),
55 "defmethod" => eval_defmethod(args, env),
56 "defrecord" => eval_defrecord(args, env),
57 "reify" => eval_reify(args, env),
58 "load-file" => eval_load_file(args, env),
59 "binding" => eval_binding(args, env),
60 "with-out-str" => eval_with_out_str(args, env),
61 "await" => eval_await(args, env),
62 _ => unreachable!("unknown special form: {head}"),
63 }
64}
65
66fn eval_def(args: &[Form], env: &mut Env) -> EvalResult {
69 if args.is_empty() {
70 return Err(EvalError::Runtime("def requires a name".into()));
71 }
72 let (name, meta_opt) = extract_def_name(&args[0], env)?;
73 let (docstring, val_idx) = if args.len() > 2
75 && let FormKind::Str(s) = &args[1].kind
76 {
77 (Some(s.clone()), 2)
78 } else {
79 (None, 1)
80 };
81 let val = if args.len() > val_idx {
82 #[cfg(feature = "no-gc")]
85 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
86 eval(&args[val_idx], env)?
87 } else {
88 Value::Nil
89 };
90 let var = env
91 .globals
92 .intern(&env.current_ns, Arc::from(name.as_str()), val.clone());
93 let meta = merge_meta(meta_opt, docstring.as_deref().map(doc_meta));
94 if let Some(meta_val) = meta {
95 var.get().set_meta(meta_val);
96 }
97 Ok(Value::Var(var))
98}
99
100fn doc_meta(doc: &str) -> Value {
102 Value::Map(MapValue::empty().assoc(
103 Value::keyword(Keyword::parse("doc")),
104 Value::string(doc.to_string()),
105 ))
106}
107
108fn arglists_meta(fn_val: &Value, skip: usize) -> Option<Value> {
113 let arities = match fn_val {
114 Value::Fn(f) => &f.get().arities,
115 Value::Macro(f) => &f.get().arities,
116 _ => return None,
117 };
118 let lists: Vec<Value> = arities
119 .iter()
120 .map(|a| {
121 let mut syms: Vec<Value> = a
122 .params
123 .iter()
124 .skip(skip)
125 .map(|p| Value::symbol(cljrs_value::Symbol::simple(p.as_ref())))
126 .collect();
127 if let Some(rest) = &a.rest_param {
128 syms.push(Value::symbol(cljrs_value::Symbol::simple("&")));
129 syms.push(Value::symbol(cljrs_value::Symbol::simple(rest.as_ref())));
130 }
131 Value::Vector(GcPtr::new(cljrs_value::PersistentVector::from_iter(syms)))
132 })
133 .collect();
134 Some(Value::Map(MapValue::empty().assoc(
135 Value::keyword(Keyword::parse("arglists")),
136 Value::Vector(GcPtr::new(cljrs_value::PersistentVector::from_iter(lists))),
137 )))
138}
139
140fn extract_def_name(form: &Form, env: &mut Env) -> EvalResult<(String, Option<Value>)> {
142 match &form.kind {
143 FormKind::Symbol(s) => Ok((s.clone(), None)),
144 FormKind::Meta(meta_form, inner) => {
146 let meta_val = compile_meta_form(meta_form, env)?;
147 let (name, inner_meta) = extract_def_name(inner, env)?;
148 Ok((name, merge_meta(inner_meta, Some(meta_val))))
149 }
150 _ => Err(EvalError::Runtime("def name must be a symbol".into())),
151 }
152}
153
154fn compile_meta_form(meta: &Form, env: &mut Env) -> EvalResult<Value> {
156 match &meta.kind {
157 FormKind::Keyword(k) => {
158 let m = MapValue::empty().assoc(Value::keyword(Keyword::parse(k)), Value::Bool(true));
160 Ok(Value::Map(m))
161 }
162 FormKind::Symbol(s) => {
163 let m = MapValue::empty().assoc(
165 Value::keyword(Keyword::parse("tag")),
166 Value::string(s.clone()),
167 );
168 Ok(Value::Map(m))
169 }
170 _ => eval(meta, env), }
172}
173
174pub fn meta_form_is_async(meta: &Form) -> bool {
181 match &meta.kind {
182 FormKind::Keyword(k) => k == "async",
183 FormKind::Map(entries) => entries.chunks(2).any(|kv| {
184 matches!(&kv[0].kind, FormKind::Keyword(k) if k == "async")
185 && !matches!(
186 kv.get(1).map(|f| &f.kind),
187 None | Some(FormKind::Bool(false)) | Some(FormKind::Nil)
188 )
189 }),
190 _ => false,
191 }
192}
193
194fn eval_fn(args: &[Form], env: &mut Env) -> EvalResult {
195 let mut is_async = false;
198 let peeled: Vec<Form>;
199 let args: &[Form] = if matches!(args.first().map(|f| &f.kind), Some(FormKind::Meta(..))) {
200 let (metas, head) = args[0].peel_meta();
201 is_async |= metas.iter().any(|m| meta_form_is_async(m));
202 peeled = std::iter::once(head.clone())
203 .chain(args[1..].iter().cloned())
204 .collect();
205 &peeled
206 } else {
207 args
208 };
209
210 let mut idx = 0;
211 let mut name: Option<Arc<str>> = None;
212
213 if let Some(FormKind::Symbol(s)) = args.first().map(|f| &f.kind)
215 && !is_special_form(s)
216 {
217 name = Some(Arc::from(s.as_str()));
218 idx = 1;
219 }
220
221 let rest = &args[idx..];
222 if rest.is_empty() {
223 return Err(EvalError::Runtime("fn* requires params and body".into()));
224 }
225
226 let arities = match &rest[0].unmeta().kind {
229 FormKind::Vector(_) => {
230 vec![parse_arity(&rest[0], &rest[1..])?]
232 }
233 FormKind::List(_) => {
234 rest.iter()
236 .map(|arity_form| {
237 if let Some(forms) = arity_form.as_list() {
238 if forms.is_empty() {
239 return Err(EvalError::Runtime("arity clause requires params".into()));
240 }
241 parse_arity(&forms[0], &forms[1..])
242 } else {
243 Err(EvalError::Runtime("expected arity clause (list)".into()))
244 }
245 })
246 .collect::<EvalResult<Vec<_>>>()?
247 }
248 _ => {
249 return Err(EvalError::Runtime(
250 "fn* expects vector or arity clauses".into(),
251 ));
252 }
253 };
254
255 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
257
258 let mut cljrs_fn = CljxFn::new(
259 name.clone(),
260 arities,
261 closed_over_names,
262 closed_over_vals,
263 false,
264 Arc::clone(&env.current_ns),
265 );
266 cljrs_fn.is_async = is_async;
267
268 env.on_fn_defined(&cljrs_fn);
269
270 let mut ptr = GcPtr::new(cljrs_fn);
274 if ptr.get().name.is_some() {
278 let self_clone = ptr.clone();
279 ptr.get_mut().self_ptr = Some(self_clone);
280 }
281 Ok(Value::Fn(ptr))
282}
283
284pub fn parse_arity(params_form: &Form, body: &[Form]) -> EvalResult<CljxFnArity> {
286 let Some(param_forms) = params_form.as_vector() else {
287 return Err(EvalError::Runtime(
288 "fn arity params must be a vector".into(),
289 ));
290 };
291
292 let mut params: Vec<Arc<str>> = Vec::new();
293 let mut param_hints: Vec<Option<TypeHint>> = Vec::new();
294 let mut rest_param: Option<Arc<str>> = None;
295 let mut rest_hint: Option<TypeHint> = None;
296 let mut destructure_params: Vec<(usize, Form)> = Vec::new();
297 let mut destructure_rest: Option<Form> = None;
298 let mut saw_amp = false;
299
300 for p in param_forms {
301 let (hint, p) = peel_param_hint(p);
307 match &p.kind {
308 FormKind::Symbol(s) if s == "&" => {
309 saw_amp = true;
310 }
311 FormKind::Symbol(s) => {
312 if saw_amp {
313 rest_param = Some(Arc::from(s.as_str()));
314 rest_hint = hint;
315 break;
316 } else {
317 params.push(Arc::from(s.as_str()));
318 param_hints.push(hint);
319 }
320 }
321 FormKind::Vector(_) | FormKind::Map(_) => {
323 if saw_amp {
324 let gensym = format!("__destructure_rest_{}", params.len());
325 rest_param = Some(Arc::from(gensym.as_str()));
326 destructure_rest = Some(p.clone());
327 break;
328 } else {
329 let idx = params.len();
330 let gensym = format!("__destructure_{idx}");
331 params.push(Arc::from(gensym.as_str()));
332 param_hints.push(None);
334 destructure_params.push((idx, p.clone()));
335 }
336 }
337 _ => {
338 return Err(EvalError::Runtime(
339 "fn params must be symbols, vectors, or maps".into(),
340 ));
341 }
342 }
343 }
344
345 let body = desugar_pre_post_conditions(body);
346
347 Ok(CljxFnArity {
348 params,
349 rest_param,
350 body,
351 destructure_params,
352 destructure_rest,
353 ir_arity_id: crate::interp::arity::fresh_arity_id(),
354 param_hints,
355 rest_hint,
356 })
357}
358
359fn desugar_pre_post_conditions(body: &[Form]) -> Vec<Form> {
377 let first = match body.first() {
378 Some(f) => f,
379 None => return body.to_vec(),
380 };
381
382 let entries = match first.as_map() {
383 Some(entries) => entries,
384 None => return body.to_vec(),
385 };
386
387 let mut pre_conds: Vec<Form> = Vec::new();
388 let mut post_conds: Vec<Form> = Vec::new();
389 let mut has_conditions = false;
390
391 for chunk in entries.chunks(2) {
392 if chunk.len() < 2 {
393 break;
394 }
395 let (key, val) = (&chunk[0], &chunk[1]);
396 match &key.kind {
397 FormKind::Keyword(k) if k == "pre" => {
398 if let FormKind::Vector(conds) = &val.kind {
399 pre_conds.extend_from_slice(conds);
400 has_conditions = true;
401 }
402 }
403 FormKind::Keyword(k) if k == "post" => {
404 if let FormKind::Vector(conds) = &val.kind {
405 post_conds.extend_from_slice(conds);
406 has_conditions = true;
407 }
408 }
409 _ => {}
410 }
411 }
412
413 if !has_conditions {
414 return body.to_vec();
415 }
416
417 let real_body = &body[1..]; let span = first.span.clone();
419 let mut new_body: Vec<Form> = Vec::new();
420
421 for cond in &pre_conds {
423 new_body.push(make_assert_call(cond, &span));
424 }
425
426 if post_conds.is_empty() {
427 new_body.extend_from_slice(real_body);
428 } else {
429 let percent = Form::new(FormKind::Symbol("%".to_string()), span.clone());
432
433 let body_expr = if real_body.len() == 1 {
434 real_body[0].clone()
435 } else {
436 let mut do_forms = vec![Form::new(FormKind::Symbol("do".to_string()), span.clone())];
437 do_forms.extend_from_slice(real_body);
438 Form::new(FormKind::List(do_forms), span.clone())
439 };
440
441 let binding_vec = Form::new(
442 FormKind::Vector(vec![percent.clone(), body_expr]),
443 span.clone(),
444 );
445
446 let mut let_forms = vec![
447 Form::new(FormKind::Symbol("let*".to_string()), span.clone()),
448 binding_vec,
449 ];
450 for cond in &post_conds {
451 let_forms.push(make_assert_call(cond, &span));
452 }
453 let_forms.push(percent);
454
455 new_body.push(Form::new(FormKind::List(let_forms), span));
456 }
457
458 new_body
459}
460
461fn make_assert_call(cond: &Form, span: &cljrs_types::span::Span) -> Form {
463 Form::new(
464 FormKind::List(vec![
465 Form::new(FormKind::Symbol("assert".to_string()), span.clone()),
466 cond.clone(),
467 ]),
468 span.clone(),
469 )
470}
471
472fn peel_param_hint(p: &Form) -> (Option<TypeHint>, &Form) {
476 if let FormKind::Meta(meta, inner) = &p.kind {
477 let hint = tag_name_of_meta(meta).and_then(|n| TypeHint::from_tag(&n));
478 let (inner_hint, inner_form) = peel_param_hint(inner);
480 (hint.or(inner_hint), inner_form)
481 } else {
482 (None, p)
483 }
484}
485
486fn tag_name_of_meta(meta: &Form) -> Option<Arc<str>> {
489 match &meta.kind {
490 FormKind::Symbol(s) => Some(strip_tag_ns(s)),
492 FormKind::Map(entries) => entries.chunks(2).find_map(|kv| {
494 let is_tag = matches!(&kv[0].kind, FormKind::Keyword(k) if k == "tag");
495 if !is_tag {
496 return None;
497 }
498 match kv.get(1).map(|f| &f.kind) {
499 Some(FormKind::Symbol(s)) => Some(strip_tag_ns(s)),
500 Some(FormKind::Str(s)) => Some(strip_tag_ns(s)),
501 _ => None,
502 }
503 }),
504 _ => None,
505 }
506}
507
508fn strip_tag_ns(s: &str) -> Arc<str> {
510 match s.rfind('/') {
511 Some(pos) if pos + 1 < s.len() => Arc::from(&s[pos + 1..]),
512 _ => Arc::from(s),
513 }
514}
515
516fn eval_if(args: &[Form], env: &mut Env) -> EvalResult {
519 if args.is_empty() {
520 return Err(EvalError::Runtime("if requires a test".into()));
521 }
522 let test = eval(&args[0], env)?;
523 let truthy = !matches!(test, Value::Nil | Value::Bool(false));
524 if truthy {
525 if args.len() > 1 {
526 eval(&args[1], env)
527 } else {
528 Ok(Value::Nil)
529 }
530 } else if args.len() > 2 {
531 eval(&args[2], env)
532 } else {
533 Ok(Value::Nil)
534 }
535}
536
537fn eval_let(args: &[Form], env: &mut Env) -> EvalResult {
540 let bindings = match args.first().and_then(|f| f.as_vector()) {
541 Some(v) => expand_pairs(v)
542 .map_err(|_| EvalError::Runtime("let* binding vector must have even length".into()))?
543 .into_owned(),
544 None => return Err(EvalError::Runtime("let* requires a binding vector".into())),
545 };
546
547 let body = &args[1..];
548
549 let chains = crate::interp::virtualize::detect_let_chains(&bindings);
551 let virtualizable_chains = find_virtualizable_chains(&chains, &bindings, body);
552
553 env.push_frame();
554
555 let pairs: Vec<_> = bindings.chunks(2).collect();
556 let mut i = 0;
557 while i < pairs.len() {
558 if let Some(chain) = virtualizable_chains.iter().find(|c| c.start == i) {
560 match eval_virtualized_chain(chain, &pairs, env) {
561 Ok(()) => {
562 i += chain.len;
563 continue;
564 }
565 Err(e) => {
566 env.pop_frame();
567 return Err(e);
568 }
569 }
570 }
571
572 let pair = pairs[i];
574 let val = match eval(&pair[1], env) {
575 Ok(v) => v,
576 Err(e) => {
577 env.pop_frame();
578 return Err(e);
579 }
580 };
581 if let Err(e) = bind_pattern(&pair[0], val, env) {
582 env.pop_frame();
583 return Err(e);
584 }
585 i += 1;
586 }
587
588 let result = eval_body(body, env);
589 env.pop_frame();
590 result
591}
592
593fn find_virtualizable_chains<'a>(
598 chains: &'a [crate::interp::virtualize::LetChain],
599 bindings: &[Form],
600 body: &[Form],
601) -> Vec<&'a crate::interp::virtualize::LetChain> {
602 chains
603 .iter()
604 .filter(|chain| {
605 for j in chain.start..(chain.start + chain.len - 1) {
608 let name = match &bindings[j * 2].kind {
609 FormKind::Symbol(s) => s.as_str(),
610 _ => return false,
611 };
612 if crate::interp::virtualize::binding_used_in_body(name, body) {
613 return false;
614 }
615 if crate::interp::virtualize::binding_used_in_other_bindings(
616 name,
617 bindings,
618 chain.start,
619 chain.len,
620 ) {
621 return false;
622 }
623 }
624 true
625 })
626 .collect()
627}
628
629fn eval_virtualized_chain(
639 chain: &crate::interp::virtualize::LetChain,
640 pairs: &[&[Form]],
641 env: &mut Env,
642) -> Result<(), EvalError> {
643 use crate::builtins::transients::{
644 builtin_assoc_bang, builtin_conj_bang, builtin_persistent_bang, builtin_transient,
645 };
646
647 let first_pair = pairs[chain.start];
649 let first_expr_forms = match &first_pair[1].kind {
650 FormKind::List(forms) => forms,
651 _ => unreachable!("chain detection ensures this is a list"),
652 };
653 let root_collection = eval(&first_expr_forms[1], env)?;
654
655 let mut transient = match builtin_transient(std::slice::from_ref(&root_collection)) {
657 Ok(t) => t,
658 Err(_) => {
659 return eval_chain_normally(chain, pairs, env);
662 }
663 };
664
665 for j in 0..chain.len {
667 let pair_idx = chain.start + j;
668 let pair = pairs[pair_idx];
669 let expr_forms = match &pair[1].kind {
670 FormKind::List(forms) => forms,
671 _ => unreachable!(),
672 };
673
674 let mut args = vec![transient.clone()];
676 for arg_form in expr_forms.iter().skip(2) {
677 args.push(eval(arg_form, env)?);
678 }
679
680 transient = match chain.ops[j] {
682 crate::interp::virtualize::ChainOpKind::Assoc => {
683 builtin_assoc_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
684 }
685 crate::interp::virtualize::ChainOpKind::Conj => {
686 builtin_conj_bang(&args).map_err(|e| EvalError::Runtime(e.to_string()))?
687 }
688 };
689
690 if j < chain.len - 1 {
694 let name = match &pair[0].kind {
695 FormKind::Symbol(s) => s.clone(),
696 _ => unreachable!(),
697 };
698 env.bind(Arc::from(name.as_str()), Value::Nil);
700 }
701 }
702
703 let persistent =
705 builtin_persistent_bang(&[transient]).map_err(|e| EvalError::Runtime(e.to_string()))?;
706
707 let last_pair = pairs[chain.start + chain.len - 1];
709 bind_pattern(&last_pair[0], persistent, env)?;
710
711 Ok(())
712}
713
714fn eval_chain_normally(
716 chain: &crate::interp::virtualize::LetChain,
717 pairs: &[&[Form]],
718 env: &mut Env,
719) -> Result<(), EvalError> {
720 for j in 0..chain.len {
721 let pair_idx = chain.start + j;
722 let pair = pairs[pair_idx];
723 let val = eval(&pair[1], env)?;
724 bind_pattern(&pair[0], val, env)?;
725 }
726 Ok(())
727}
728
729pub fn eval_loop(args: &[Form], env: &mut Env) -> EvalResult {
732 let bindings = match args.first().and_then(|f| f.as_vector()) {
733 Some(v) => expand_pairs(v)
734 .map_err(|_| EvalError::Runtime("loop* binding vector must have even length".into()))?
735 .into_owned(),
736 None => return Err(EvalError::Runtime("loop* requires a binding vector".into())),
737 };
738
739 let body = &args[1..];
740
741 let patterns: Vec<Form> = bindings.iter().step_by(2).cloned().collect();
743 let mut current_vals: Vec<Value> = Vec::new();
744
745 for i in (1..bindings.len()).step_by(2) {
747 current_vals.push(eval(&bindings[i], env)?);
748 }
749
750 loop {
751 let _vals_root = crate::env::gc_roots::root_values(¤t_vals);
753
754 crate::env::gc_roots::gc_safepoint(env);
757
758 #[cfg(feature = "no-gc")]
762 let mut scratch = cljrs_gc::alloc_ctx::ScratchGuard::new();
763
764 #[cfg(not(feature = "no-gc"))]
775 let _iter_frame = cljrs_gc::push_alloc_frame();
776
777 env.push_frame();
778 for (pat, val) in patterns.iter().zip(current_vals.iter()) {
779 if let Err(e) = bind_pattern(pat, val.clone(), env) {
780 env.pop_frame();
781 return Err(e);
782 }
783 }
784
785 #[cfg(not(feature = "no-gc"))]
788 let result = eval_body_recur(body, env);
789 #[cfg(feature = "no-gc")]
790 let result = eval_body_with_scratch_loop(body, &mut scratch, env);
791
792 env.pop_frame();
793 match result {
797 Ok(v) => return Ok(v),
798 Err(EvalError::Recur(new_vals)) => {
799 if new_vals.len() != patterns.len() {
800 return Err(EvalError::Arity {
801 name: "recur".into(),
802 expected: patterns.len().to_string(),
803 got: new_vals.len(),
804 });
805 }
806 current_vals = new_vals;
809 }
810 Err(e) => return Err(e),
811 }
812 }
813}
814
815fn eval_recur(args: &[Form], env: &mut Env) -> EvalResult {
816 let vals: Vec<Value> = args
817 .iter()
818 .map(|f| eval(f, env))
819 .collect::<EvalResult<_>>()?;
820 Err(EvalError::Recur(vals))
821}
822
823pub fn eval_body_recur(body: &[Form], env: &mut Env) -> EvalResult {
825 let mut result = Value::Nil;
826 for form in body {
827 result = eval(form, env)?;
828 }
829 Ok(result)
830}
831
832#[cfg(feature = "no-gc")]
838fn eval_body_with_scratch_loop(
839 body: &[Form],
840 scratch: &mut cljrs_gc::alloc_ctx::ScratchGuard,
841 env: &mut Env,
842) -> EvalResult {
843 if body.is_empty() {
844 scratch.pop_for_return();
845 return Ok(Value::Nil);
846 }
847 for form in &body[..body.len() - 1] {
848 eval(form, env)?;
849 }
850 scratch.pop_for_return();
851 eval(&body[body.len() - 1], env)
852}
853
854fn eval_quote(args: &[Form], env: &Env) -> EvalResult {
857 match args.first() {
858 Some(f) => form_to_value(&resolve_auto_forms(f, env)?),
862 None => Err(EvalError::Runtime("quote requires an argument".into())),
863 }
864}
865
866fn eval_var(args: &[Form], env: &mut Env) -> EvalResult {
869 let sym = match args.first().map(|f| &f.kind) {
870 Some(FormKind::Symbol(s)) => s.clone(),
871 _ => return Err(EvalError::Runtime("var requires a symbol".into())),
872 };
873 let parsed = cljrs_value::Symbol::parse(&sym);
874 let ns: Arc<str> = match parsed.namespace.as_deref() {
875 Some(ns_part) => env
876 .globals
877 .resolve_alias(&env.current_ns, ns_part)
878 .unwrap_or_else(|| Arc::from(ns_part)),
879 None => env.current_ns.clone(),
880 };
881 let name = parsed.name.as_ref();
882 env.globals
883 .lookup_var_in_ns(&ns, name)
884 .map(Value::Var)
885 .ok_or_else(|| EvalError::UnboundSymbol(sym))
886}
887
888fn eval_set_bang(args: &[Form], env: &mut Env) -> EvalResult {
891 let sym = match args.first().map(|f| &f.kind) {
892 Some(FormKind::Symbol(s)) => s.clone(),
893 _ => return Err(EvalError::Runtime("set! requires a symbol".into())),
894 };
895 let val = if args.len() > 1 {
896 eval(&args[1], env)?
897 } else {
898 Value::Nil
899 };
900 let parsed = cljrs_value::Symbol::parse(&sym);
901 let ns = parsed.namespace.as_deref().unwrap_or(&env.current_ns);
902 let var = env
903 .globals
904 .lookup_var_in_ns(ns, &parsed.name)
905 .ok_or_else(|| EvalError::UnboundSymbol(sym))?;
906 if !crate::env::dynamics::set_thread_local(&var, val.clone()) {
908 var.get().bind(val.clone());
909 }
910 Ok(val)
911}
912
913fn eval_throw(args: &[Form], env: &mut Env) -> EvalResult {
916 let val = match args.first() {
917 Some(f) => eval(f, env)?,
918 None => Value::Nil,
919 };
920 let val = match val {
923 Value::Error(_) => val,
924 other => {
925 let msg = format!("{}", other);
926 Value::Error(GcPtr::new(ExceptionInfo::new(
927 ValueError::Other(msg.clone()),
928 msg,
929 None,
930 None,
931 )))
932 }
933 };
934 Err(EvalError::Thrown(val))
935}
936
937pub struct CatchClause<'a> {
944 pub type_sym: &'a str,
945 pub binding: &'a str,
946 pub body: &'a [Form],
947}
948
949pub fn eval_error_to_value(err: &EvalError) -> Value {
954 let msg = err.to_string();
955 Value::Error(GcPtr::new(ExceptionInfo::new(
956 ValueError::Other(msg.clone()),
957 msg,
958 None,
959 None,
960 )))
961}
962
963pub fn catch_type_matches(type_name: &str, val: &Value) -> bool {
967 let short = type_name.rsplit('.').next().unwrap_or(type_name);
968 match short {
969 "Object" | "Exception" | "Throwable" | "Error" | "default" => true,
973 "ExceptionInfo" => matches!(val, Value::Error(_)),
975 _ => false,
976 }
977}
978
979fn eval_try(args: &[Form], env: &mut Env) -> EvalResult {
980 let (body, catches, fin_body) = parse_try_args(args);
981
982 let mut result = eval_body(body, env);
983
984 let err_opt = match std::mem::replace(&mut result, Ok(Value::Nil)) {
986 Ok(v) => {
987 result = Ok(v);
988 None
989 }
990 Err(EvalError::Recur(args)) => {
991 result = Err(EvalError::Recur(args));
992 None
993 }
994 Err(EvalError::GasExhausted) => {
995 result = Err(EvalError::GasExhausted);
996 None
997 }
998 Err(other) => Some(other),
999 };
1000
1001 if let Some(err) = err_opt {
1002 let thrown_val = match err {
1003 EvalError::Thrown(v) => v,
1004 ref other => eval_error_to_value(other),
1005 };
1006 let mut handled = false;
1007 for c in &catches {
1008 if catch_type_matches(c.type_sym, &thrown_val) {
1009 env.push_frame();
1010 env.bind(Arc::from(c.binding), thrown_val.clone());
1011 result = eval_body(c.body, env);
1012 env.pop_frame();
1013 handled = true;
1014 break;
1015 }
1016 }
1017 if !handled {
1018 result = Err(EvalError::Thrown(thrown_val));
1020 }
1021 }
1022
1023 if !fin_body.is_empty() {
1027 eval_body(fin_body, env)?;
1028 }
1029
1030 result
1031}
1032
1033fn catch_target(f: &Form) -> Option<&str> {
1035 f.as_symbol().or_else(|| f.as_keyword())
1036}
1037
1038pub fn parse_try_args(args: &[Form]) -> (&[Form], Vec<CatchClause<'_>>, &[Form]) {
1042 let mut body_end = args.len();
1043 let mut catches: Vec<CatchClause<'_>> = Vec::new();
1044 let mut fin_body: &[Form] = &[];
1045
1046 for (i, form) in args.iter().enumerate() {
1047 if let Some(parts) = form.as_list()
1048 && let Some(s) = parts.first().and_then(|f| f.as_symbol())
1049 {
1050 if s == "catch" {
1051 if i < body_end {
1052 body_end = i;
1053 }
1054 let type_sym = match parts.get(1) {
1059 Some(f) => match catch_target(f) {
1060 Some(name) => name,
1061 None => match &f.unmeta().kind {
1062 FormKind::ReaderCond {
1063 splicing: false,
1064 clauses,
1065 } => match select_reader_cond(clauses).and_then(catch_target) {
1066 Some(name) => name,
1067 None => continue,
1068 },
1069 _ => continue,
1070 },
1071 },
1072 None => continue,
1073 };
1074 let binding = match parts.get(2).and_then(|f| f.as_symbol()) {
1075 Some(s) => s,
1076 None => continue,
1077 };
1078 catches.push(CatchClause {
1079 type_sym,
1080 binding,
1081 body: &parts[3..],
1082 });
1083 continue;
1084 }
1085 if s == "finally" {
1086 if i < body_end {
1087 body_end = i;
1088 }
1089 fin_body = &parts[1..];
1090 continue;
1091 }
1092 }
1093 }
1094
1095 (&args[..body_end], catches, fin_body)
1096}
1097
1098pub fn eval_defn(args: &[Form], env: &mut Env) -> EvalResult {
1101 let name_form = args
1103 .first()
1104 .ok_or_else(|| EvalError::Runtime("defn requires a symbol name".into()))?;
1105 let (name_metas, name_sym) = name_form.peel_meta();
1106 let (name, mut is_async) = match &name_sym.kind {
1107 FormKind::Symbol(s) => (s.clone(), name_metas.iter().any(|m| meta_form_is_async(m))),
1108 _ => return Err(EvalError::Runtime("defn name must be a symbol".into())),
1109 };
1110 let mut rest_start = 1;
1114 let mut docstring: Option<String> = None;
1115 if rest_start < args.len()
1116 && let Some(s) = args[rest_start].as_string()
1117 {
1118 docstring = Some(s.to_string());
1119 rest_start += 1;
1120 }
1121 let mut attr_meta: Option<Value> = None;
1122 if rest_start < args.len() && args[rest_start].as_map().is_some() {
1123 is_async |= meta_form_is_async(&args[rest_start]);
1125 attr_meta = Some(eval(&args[rest_start], env)?);
1126 rest_start += 1;
1127 }
1128 let mut fn_args = vec![Form::new(
1130 FormKind::Symbol(name.to_string()),
1131 args[0].span.clone(),
1132 )];
1133 fn_args.extend_from_slice(&args[rest_start..]);
1134 #[cfg(feature = "no-gc")]
1137 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1138 let mut fn_val = eval_fn(&fn_args, env)?;
1139 if is_async && let Value::Fn(ref mut f) = fn_val {
1140 f.get_mut().is_async = true;
1141 }
1142 let var = env
1143 .globals
1144 .intern(&env.current_ns, Arc::from(name.as_str()), fn_val.clone());
1145 let mut meta = attr_meta;
1146 if let Some(doc) = &docstring {
1147 meta = merge_meta(meta, Some(doc_meta(doc)));
1148 }
1149 meta = merge_meta(meta, arglists_meta(&fn_val, 0));
1150 if let Some(meta_val) = meta {
1151 var.get().set_meta(meta_val);
1152 }
1153 Ok(Value::Var(var))
1154}
1155
1156fn prepend_macro_params(form: &Form) -> Form {
1164 let span = form.span.clone();
1165 match &form.unmeta().kind {
1166 FormKind::Vector(params) => {
1167 let mut new_params = vec![
1168 Form::new(FormKind::Symbol("&form".to_string()), span.clone()),
1169 Form::new(FormKind::Symbol("&env".to_string()), span.clone()),
1170 ];
1171 new_params.extend_from_slice(params);
1172 Form::new(FormKind::Vector(new_params), span)
1173 }
1174 FormKind::List(forms) => {
1175 if let Some(first) = forms.first() {
1177 let new_params_form = prepend_macro_params(first);
1178 let mut new_forms = vec![new_params_form];
1179 new_forms.extend_from_slice(&forms[1..]);
1180 Form::new(FormKind::List(new_forms), span)
1181 } else {
1182 form.clone()
1183 }
1184 }
1185 _ => form.clone(),
1186 }
1187}
1188
1189fn eval_defmacro(args: &[Form], env: &mut Env) -> EvalResult {
1190 let mut current = args
1193 .first()
1194 .ok_or_else(|| EvalError::Runtime("defmacro requires a symbol at position 0".into()))?
1195 .clone();
1196 let mut name_meta: Option<Value> = None;
1197 while let FormKind::Meta(meta_form, inner) = current.kind {
1198 let meta_val = compile_meta_form(&meta_form, env)?;
1199 name_meta = merge_meta(name_meta, Some(meta_val));
1200 current = *inner;
1201 }
1202 let name = match ¤t.kind {
1203 FormKind::Symbol(s) => s.clone(),
1204 _ => {
1205 return Err(EvalError::Runtime(
1206 "defmacro requires a symbol at position 0".into(),
1207 ));
1208 }
1209 };
1210
1211 let mut rest_start = 1;
1212 let mut docstring: Option<String> = None;
1213 if rest_start < args.len()
1214 && let FormKind::Str(s) = &args[rest_start].kind
1215 {
1216 docstring = Some(s.clone());
1217 rest_start += 1;
1218 }
1219 let mut attr_meta = None;
1220 if rest_start < args.len() && matches!(args[rest_start].kind, FormKind::Map(_)) {
1221 attr_meta = Some(eval(&args[rest_start], env)?);
1222 rest_start += 1;
1223 }
1224 let mut fn_args = vec![Form::new(
1226 FormKind::Symbol(name.to_string()),
1227 args[0].span.clone(),
1228 )];
1229 for form in &args[rest_start..] {
1230 fn_args.push(prepend_macro_params(form));
1231 }
1232 #[cfg(feature = "no-gc")]
1235 let _static_ctx = cljrs_gc::alloc_ctx::StaticCtxGuard::new();
1236 let fn_val = eval_fn(&fn_args, env)?;
1237
1238 let macro_val = match fn_val {
1240 Value::Fn(f) => {
1241 let mut mfn = f.get().clone();
1242 mfn.is_macro = true;
1243 Value::Macro(GcPtr::new(mfn))
1244 }
1245 other => other,
1246 };
1247
1248 let var = env
1249 .globals
1250 .intern(&env.current_ns, Arc::from(name.as_str()), macro_val.clone());
1251 let mut meta = merge_meta(name_meta, attr_meta);
1252 if let Some(doc) = &docstring {
1253 meta = merge_meta(meta, Some(doc_meta(doc)));
1254 }
1255 meta = merge_meta(meta, arglists_meta(¯o_val, 2));
1257 if let Some(m) = meta {
1258 var.get().set_meta(m);
1259 }
1260 Ok(Value::Var(var))
1261}
1262
1263fn eval_defonce(args: &[Form], env: &mut Env) -> EvalResult {
1266 if args.is_empty() {
1267 return Err(EvalError::Runtime("defonce requires a name".into()));
1268 }
1269 let (name, _meta) = extract_def_name(&args[0], env)?;
1272 if let Some(var) = env.globals.lookup_var(&env.current_ns, &name)
1274 && var.get().is_bound()
1275 {
1276 return Ok(Value::Var(var));
1277 }
1278 eval_def(args, env)
1279}
1280
1281fn eval_and(args: &[Form], env: &mut Env) -> EvalResult {
1284 let mut result = Value::Bool(true);
1285 for form in args {
1286 result = eval(form, env)?;
1287 if matches!(result, Value::Nil | Value::Bool(false)) {
1288 return Ok(result);
1289 }
1290 }
1291 Ok(result)
1292}
1293
1294fn eval_or(args: &[Form], env: &mut Env) -> EvalResult {
1295 let mut last = Value::Nil;
1296 for form in args {
1297 last = eval(form, env)?;
1298 if !matches!(last, Value::Nil | Value::Bool(false)) {
1299 return Ok(last);
1300 }
1301 }
1302 Ok(last)
1303}
1304
1305fn eval_require(args: &[Form], env: &mut Env) -> EvalResult {
1308 for arg in args {
1309 let val = eval(arg, env)?;
1310 let spec = parse_require_spec_val(val).map_err(EvalError::Runtime)?;
1311 load_ns(env.globals.clone(), &spec, &env.current_ns)?;
1312 }
1313 Ok(Value::Nil)
1314}
1315
1316fn parse_require_spec_val(val: Value) -> Result<RequireSpec, String> {
1321 match val {
1322 Value::Symbol(s) => {
1323 let sym = s.get();
1324 Ok(RequireSpec {
1325 ns: sym.name.clone(),
1326 version: sym.version.clone(),
1327 alias: None,
1328 refer: RequireRefer::None,
1329 })
1330 }
1331 Value::Vector(v) => {
1332 let items: Vec<Value> = v.get().iter().cloned().collect();
1333 if items.is_empty() {
1334 return Err("require spec vector must not be empty".into());
1335 }
1336 let (ns, version) = match &items[0] {
1337 Value::Symbol(s) => {
1338 let sym = s.get();
1339 (sym.name.clone(), sym.version.clone())
1340 }
1341 other => {
1342 return Err(format!(
1343 "require spec: first element must be a symbol, got {}",
1344 other.type_name()
1345 ));
1346 }
1347 };
1348 let mut alias = None;
1349 let mut refer = RequireRefer::None;
1350 let mut i = 1;
1351 while i < items.len() {
1352 match &items[i] {
1353 Value::Keyword(k) if k.get().name.as_ref() == "as" => {
1354 i += 1;
1355 alias = Some(match items.get(i) {
1356 Some(Value::Symbol(s)) => s.get().name.clone(),
1357 _ => return Err("require :as expects a symbol".into()),
1358 });
1359 }
1360 Value::Keyword(k) if k.get().name.as_ref() == "refer" => {
1361 i += 1;
1362 refer = match items.get(i) {
1363 Some(Value::Keyword(k2)) if k2.get().name.as_ref() == "all" => {
1364 RequireRefer::All
1365 }
1366 Some(Value::Vector(rv)) => {
1367 let names: Vec<Arc<str>> = rv
1368 .get()
1369 .iter()
1370 .map(|v| match v {
1371 Value::Symbol(s) => Ok(s.get().name.clone()),
1372 other => Err(format!(
1373 "require :refer expects symbols, got {}",
1374 other.type_name()
1375 )),
1376 })
1377 .collect::<Result<_, _>>()?;
1378 RequireRefer::Named(names)
1379 }
1380 _ => {
1381 return Err(
1382 "require :refer expects :all or a vector of symbols".into()
1383 );
1384 }
1385 };
1386 }
1387 other => {
1388 return Err(format!(
1389 "require spec: unexpected option {}",
1390 other.type_name()
1391 ));
1392 }
1393 }
1394 i += 1;
1395 }
1396 Ok(RequireSpec {
1397 ns,
1398 version,
1399 alias,
1400 refer,
1401 })
1402 }
1403 other => Err(format!(
1404 "require expects a symbol or vector, got {}",
1405 other.type_name()
1406 )),
1407 }
1408}
1409
1410fn spec_element(form: &Form) -> Option<&Form> {
1414 match &form.kind {
1415 FormKind::ReaderCond { clauses, .. } => select_reader_cond(clauses),
1416 _ => Some(form),
1417 }
1418}
1419
1420pub fn parse_require_spec_form(form: &Form) -> Result<RequireSpec, String> {
1427 match &form.kind {
1428 FormKind::Symbol(s) => {
1429 let sym = cljrs_value::Symbol::parse(s);
1430 Ok(RequireSpec {
1431 ns: sym.name.clone(),
1432 version: sym.version.clone(),
1433 alias: None,
1434 refer: RequireRefer::None,
1435 })
1436 }
1437 FormKind::Vector(items) => {
1438 if items.is_empty() {
1439 return Err("require spec vector must not be empty".into());
1440 }
1441 let head = spec_element(&items[0]).ok_or_else(|| {
1442 "require spec: no reader-conditional branch matched for the namespace".to_string()
1443 })?;
1444 let (ns, version) = match &head.kind {
1445 FormKind::Symbol(s) => {
1446 let sym = cljrs_value::Symbol::parse(s);
1447 (sym.name.clone(), sym.version.clone())
1448 }
1449 _ => return Err("require spec: first element must be a symbol".into()),
1450 };
1451 let mut alias = None;
1452 let mut refer = RequireRefer::None;
1453 let mut i = 1;
1454 while i < items.len() {
1455 let Some(item) = spec_element(&items[i]) else {
1458 i += 1;
1459 continue;
1460 };
1461 match &item.kind {
1462 FormKind::Keyword(k) if k == "as" => {
1463 i += 1;
1464 alias = Some(match items.get(i).map(|f| &f.kind) {
1465 Some(FormKind::Symbol(s)) => Arc::from(s.as_str()),
1466 _ => return Err("require :as expects a symbol".into()),
1467 });
1468 }
1469 FormKind::Keyword(k) if k == "refer" => {
1470 i += 1;
1471 refer = match items.get(i).map(|f| &f.kind) {
1472 Some(FormKind::Keyword(k2)) if k2 == "all" => RequireRefer::All,
1473 Some(FormKind::Vector(rv)) => {
1474 let names: Vec<Arc<str>> = rv
1475 .iter()
1476 .map(|f| match &f.kind {
1477 FormKind::Symbol(s) => Ok(Arc::from(s.as_str())),
1478 _ => Err("require :refer expects symbols".to_string()),
1479 })
1480 .collect::<Result<_, _>>()?;
1481 RequireRefer::Named(names)
1482 }
1483 _ => return Err("require :refer expects :all or a vector".into()),
1484 };
1485 }
1486 _ => return Err(format!("require spec: unexpected form at position {i}")),
1487 }
1488 i += 1;
1489 }
1490 Ok(RequireSpec {
1491 ns,
1492 version,
1493 alias,
1494 refer,
1495 })
1496 }
1497 _ => Err("require spec must be a symbol or vector".into()),
1498 }
1499}
1500
1501fn extract_ns_name_form(form: Option<&Form>, env: &mut Env) -> EvalResult<(String, Option<Value>)> {
1507 let mut current = form
1508 .ok_or_else(|| EvalError::Runtime("ns requires a symbol at position 0".into()))?
1509 .clone();
1510 let mut meta_acc: Option<Value> = None;
1511 while let FormKind::Meta(meta_form, inner) = current.kind {
1512 let meta_val = compile_meta_form(&meta_form, env)?;
1513 meta_acc = merge_meta(meta_acc, Some(meta_val));
1514 current = *inner;
1515 }
1516 match ¤t.kind {
1517 FormKind::Symbol(s) => Ok((s.clone(), meta_acc)),
1518 _ => Err(EvalError::Runtime(
1519 "ns requires a symbol at position 0".into(),
1520 )),
1521 }
1522}
1523
1524fn merge_meta(base: Option<Value>, overlay: Option<Value>) -> Option<Value> {
1527 match (base, overlay) {
1528 (None, None) => None,
1529 (Some(b), None) => Some(b),
1530 (None, Some(o)) => Some(o),
1531 (Some(Value::Map(b)), Some(Value::Map(o))) => {
1532 let mut merged = b;
1533 for (k, v) in o.iter() {
1534 merged = merged.assoc(k.clone(), v.clone());
1535 }
1536 Some(Value::Map(merged))
1537 }
1538 (_, Some(o)) => Some(o),
1539 }
1540}
1541
1542fn parse_refer_clojure_clause(items: &[Form]) -> Result<ReferClojureFilter, String> {
1546 let mut filter = ReferClojureFilter::default();
1547 let items = expand_reader_conds(items);
1548 let mut i = 0;
1549 while i < items.len() {
1550 let FormKind::Keyword(k) = &items[i].kind else {
1551 return Err(":refer-clojure expects keyword options (:exclude, :only, :rename)".into());
1552 };
1553 let arg = items
1554 .get(i + 1)
1555 .ok_or_else(|| format!(":refer-clojure :{k} expects a value"))?;
1556 match k.as_str() {
1557 "exclude" => filter.exclude = symbol_name_set(arg, "exclude")?,
1558 "only" => filter.only = Some(symbol_name_set(arg, "only")?),
1559 "rename" => {
1560 let FormKind::Map(entries) = &arg.kind else {
1561 return Err(":refer-clojure :rename expects a map".into());
1562 };
1563 if entries.len() % 2 != 0 {
1564 return Err(":refer-clojure :rename expects an even-sized map".into());
1565 }
1566 for pair in entries.chunks(2) {
1567 match (&pair[0].kind, &pair[1].kind) {
1568 (FormKind::Symbol(from), FormKind::Symbol(to)) => {
1569 filter
1570 .rename
1571 .insert(Arc::from(from.as_str()), Arc::from(to.as_str()));
1572 }
1573 _ => {
1574 return Err(
1575 ":refer-clojure :rename expects symbol keys and values".into()
1576 );
1577 }
1578 }
1579 }
1580 }
1581 other => return Err(format!(":refer-clojure does not support :{other}")),
1582 }
1583 i += 2;
1584 }
1585 Ok(filter)
1586}
1587
1588fn symbol_name_set(form: &Form, opt: &str) -> Result<HashSet<Arc<str>>, String> {
1590 let FormKind::Vector(items) = &form.kind else {
1591 return Err(format!(":refer-clojure :{opt} expects a vector of symbols"));
1592 };
1593 expand_reader_conds(items)
1594 .iter()
1595 .map(|f| match &f.kind {
1596 FormKind::Symbol(sym) => Ok(Arc::from(sym.as_str())),
1597 _ => Err(format!(":refer-clojure :{opt} expects symbols")),
1598 })
1599 .collect()
1600}
1601
1602fn eval_ns(args: &[Form], env: &mut Env) -> EvalResult {
1603 let (name, name_meta) = extract_ns_name_form(args.first(), env)?;
1604 env.globals.get_or_create_ns(&name);
1605 env.current_ns = Arc::from(name.as_str());
1606 if name != "clojure.core" {
1608 env.globals.refer_core(&name);
1609 }
1610 sync_star_ns(env);
1611
1612 let mut rest = &args[1..];
1614 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Str(_))) {
1615 rest = &rest[1..];
1616 }
1617 let mut attr_meta = None;
1618 if matches!(rest.first().map(|f| &f.kind), Some(FormKind::Map(_))) {
1619 attr_meta = Some(eval(&rest[0], env)?);
1620 rest = &rest[1..];
1621 }
1622
1623 if let Some(m) = merge_meta(name_meta, attr_meta) {
1624 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1625 ns_ptr.get().set_meta(m);
1626 }
1627
1628 let mut refer_clojure = None;
1639 for clause in rest {
1640 if let FormKind::List(items) = &clause.kind
1641 && matches!(items.first().map(|f| &f.kind), Some(FormKind::Keyword(k)) if k == "refer-clojure")
1642 {
1643 refer_clojure =
1644 Some(parse_refer_clojure_clause(&items[1..]).map_err(EvalError::Runtime)?);
1645 }
1646 }
1647 if name != "clojure.core" {
1648 env.globals
1649 .set_refer_clojure_filter(&name, refer_clojure)
1650 .map_err(EvalError::Runtime)?;
1651 }
1652
1653 for clause in rest {
1654 if let FormKind::List(items) = &clause.kind {
1655 match items.first().map(|f| &f.kind) {
1656 Some(FormKind::Keyword(k)) if k == "require" => {
1657 let expanded = expand_reader_conds(&items[1..]);
1659 for spec_form in &expanded {
1660 let spec =
1661 parse_require_spec_form(spec_form).map_err(EvalError::Runtime)?;
1662 load_ns(env.globals.clone(), &spec, &name)?;
1663 }
1664 }
1665 _ => {}
1668 }
1669 }
1670 }
1671
1672 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1673 Ok(Value::Namespace(ns_ptr))
1674}
1675
1676fn eval_load_file(args: &[Form], env: &mut Env) -> EvalResult {
1679 if args.is_empty() {
1680 return Err(EvalError::Runtime(
1681 "load-file requires a path argument".into(),
1682 ));
1683 }
1684 let path_val = eval(&args[0], env)?;
1685 let path = match &path_val {
1686 Value::Str(s) => s.get().clone(),
1687 v => {
1688 return Err(EvalError::Runtime(format!(
1689 "load-file: expected string, got {}",
1690 v.type_name()
1691 )));
1692 }
1693 };
1694 let src = std::fs::read_to_string(&path)
1695 .map_err(|e| EvalError::Runtime(format!("load-file: {e}")))?;
1696 let mut parser = cljrs_reader::Parser::new(src, path.clone());
1697 let forms = parser
1698 .parse_all()
1699 .map_err(|e| EvalError::Runtime(format!("load-file parse error: {e}")))?;
1700 let mut result = Value::Nil;
1701 for form in forms {
1702 let _alloc_frame = cljrs_gc::push_alloc_frame();
1703 result = eval(&form, env)?;
1704 }
1705 Ok(result)
1706}
1707
1708fn eval_letfn(args: &[Form], env: &mut Env) -> EvalResult {
1711 let bindings = match args.first().and_then(|f| f.as_vector()) {
1713 Some(v) => expand_reader_conds_cow(v).into_owned(),
1714 None => return Err(EvalError::Runtime("letfn requires a binding vector".into())),
1715 };
1716
1717 env.push_frame();
1718
1719 for binding in &bindings {
1720 if let Some(parts) = binding.as_list() {
1721 if parts.is_empty() {
1722 continue;
1723 }
1724 let fn_val = match eval_fn(parts, env) {
1728 Ok(v) => v,
1729 Err(e) => {
1730 env.pop_frame();
1731 return Err(e);
1732 }
1733 };
1734 let Some(name) = parts[0].as_symbol() else {
1735 env.pop_frame();
1736 return Err(EvalError::Runtime(
1737 "letfn binding name must be a symbol".into(),
1738 ));
1739 };
1740 env.bind(Arc::from(name), fn_val);
1741 }
1742 }
1743
1744 let body = &args[1..];
1745 let result = eval_body(body, env);
1746 env.pop_frame();
1747 result
1748}
1749
1750fn eval_in_ns(args: &[Form], env: &mut Env) -> EvalResult {
1753 if args.is_empty() {
1755 return Err(EvalError::Runtime("in-ns requires a namespace name".into()));
1756 }
1757 let ns_val = eval(&args[0], env)?;
1758 let ns_name = extract_ns_name(&ns_val)?;
1759 env.globals.get_or_create_ns(&ns_name);
1760 env.globals.refer_core(&ns_name);
1761 env.current_ns = Arc::from(ns_name.as_str());
1762 sync_star_ns(env);
1763 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1764 Ok(Value::Namespace(ns_ptr))
1765}
1766
1767fn eval_alias(args: &[Form], env: &mut Env) -> EvalResult {
1770 if args.len() < 2 {
1772 return Err(EvalError::Runtime(
1773 "alias requires alias-sym and namespace-sym".into(),
1774 ));
1775 }
1776 let alias_val = eval(&args[0], env)?;
1777 let ns_val = eval(&args[1], env)?;
1778
1779 let alias_name = extract_ns_name(&alias_val)?;
1780 let full_ns = extract_ns_name(&ns_val)?;
1781
1782 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
1783 let mut aliases = ns_ptr.get().aliases.lock().unwrap();
1784 aliases.insert(Arc::from(alias_name.as_str()), Arc::from(full_ns.as_str()));
1785 Ok(Value::Nil)
1786}
1787
1788fn extract_ns_name(v: &Value) -> EvalResult<String> {
1790 match v {
1791 Value::Symbol(s) => {
1792 Ok(s.get().name.as_ref().to_string())
1794 }
1795 Value::Str(s) => Ok(s.get().clone()),
1796 Value::Keyword(k) => Ok(k.get().name.as_ref().to_string()),
1797 other => Err(EvalError::Runtime(format!(
1798 "expected a symbol or string for namespace name, got {}",
1799 other.type_name()
1800 ))),
1801 }
1802}
1803
1804fn eval_defprotocol(args: &[Form], env: &mut Env) -> EvalResult {
1807 let name = require_sym(args, 0, "defprotocol")?;
1809 let proto_name: Arc<str> = Arc::from(name);
1810
1811 let methods_start = if args.len() > 1 && args[1].as_string().is_some() {
1813 2
1814 } else {
1815 1
1816 };
1817
1818 let mut methods: Vec<ProtocolMethod> = Vec::new();
1819 let mut extend_via_metadata = false;
1820
1821 let rest = &args[methods_start..];
1822 let mut i = 0;
1823 while i < rest.len() {
1824 if let Some(kw) = rest[i].as_keyword() {
1827 if kw == "extend-via-metadata" {
1828 extend_via_metadata = matches!(
1829 rest.get(i + 1).map(|f| &f.unmeta().kind),
1830 Some(FormKind::Bool(true))
1831 );
1832 }
1833 i += 2;
1834 continue;
1835 }
1836 let form = &rest[i];
1837 i += 1;
1838 let parts = match form.as_list() {
1840 Some(parts) => parts,
1841 None => continue, };
1843 if parts.is_empty() {
1844 continue;
1845 }
1846 let method_name: Arc<str> = match parts[0].as_symbol() {
1847 Some(s) => Arc::from(s),
1848 None => continue,
1849 };
1850 let (min_arity, variadic) = match parts.iter().find_map(|f| f.as_vector()) {
1852 Some(param_forms) => {
1853 let is_amp = |p: &Form| p.as_symbol() == Some("&");
1854 let variadic = param_forms.iter().any(is_amp);
1855 let fixed = param_forms.iter().filter(|p| !is_amp(p)).count();
1856 (fixed, variadic)
1857 }
1858 None => (1, false),
1859 };
1860 methods.push(ProtocolMethod {
1861 name: method_name,
1862 min_arity,
1863 variadic,
1864 });
1865 }
1866
1867 let ns: Arc<str> = env.current_ns.clone();
1868 let proto = Protocol::new(proto_name.clone(), ns, methods.clone(), extend_via_metadata);
1869 let proto_ptr = GcPtr::new(proto);
1870
1871 let proto_var = env.globals.intern(
1873 &env.current_ns,
1874 proto_name.clone(),
1875 Value::Protocol(proto_ptr.clone()),
1876 );
1877
1878 for method in &methods {
1880 let pf = ProtocolFn {
1881 protocol: proto_ptr.clone(),
1882 method_name: method.name.clone(),
1883 min_arity: method.min_arity,
1884 variadic: method.variadic,
1885 };
1886 env.globals.intern(
1887 &env.current_ns,
1888 method.name.clone(),
1889 Value::ProtocolFn(GcPtr::new(pf)),
1890 );
1891 }
1892
1893 Ok(Value::Var(proto_var))
1894}
1895
1896fn eval_extend_type(args: &[Form], env: &mut Env) -> EvalResult {
1899 if args.is_empty() {
1901 return Err(EvalError::Runtime(
1902 "extend-type requires a type symbol".into(),
1903 ));
1904 }
1905 let Some(type_sym) = args[0].as_symbol() else {
1906 return Err(EvalError::Runtime(
1907 "extend-type: first arg must be a type symbol".into(),
1908 ));
1909 };
1910 let type_tag = crate::interp::apply::resolve_type_tag(type_sym);
1911
1912 let mut current_proto: Option<GcPtr<Protocol>> = None;
1913
1914 for form in &args[1..] {
1915 match &form.unmeta().kind {
1916 FormKind::Symbol(s) => {
1917 let val = env.globals.lookup_in_ns(&env.current_ns, s);
1919 match val {
1920 Some(Value::Protocol(p)) => {
1921 current_proto = Some(p);
1922 }
1923 _ => {
1924 return Err(EvalError::Runtime(format!(
1925 "extend-type: {} is not a protocol",
1926 s
1927 )));
1928 }
1929 }
1930 }
1931 FormKind::List(parts) => {
1932 let proto = current_proto.as_ref().ok_or_else(|| {
1934 EvalError::Runtime("extend-type: method before protocol name".into())
1935 })?;
1936 if parts.is_empty() {
1937 continue;
1938 }
1939 let method_name: Arc<str> = match parts[0].as_symbol() {
1940 Some(s) => Arc::from(s),
1941 None => continue,
1942 };
1943 let fn_val = build_impl_fn(parts, env)?;
1944 let mut impls = proto.get().impls.lock().unwrap();
1945 impls
1946 .entry(type_tag.clone())
1947 .or_default()
1948 .insert(method_name, fn_val);
1949 drop(impls);
1950 cljrs_value::bump_protocol_generation();
1951 }
1952 _ => {}
1953 }
1954 }
1955
1956 Ok(Value::Nil)
1957}
1958
1959fn eval_extend_protocol(args: &[Form], env: &mut Env) -> EvalResult {
1962 if args.is_empty() {
1964 return Err(EvalError::Runtime(
1965 "extend-protocol requires a protocol".into(),
1966 ));
1967 }
1968 let Some(proto_sym) = args[0].as_symbol() else {
1969 return Err(EvalError::Runtime(
1970 "extend-protocol: first arg must be a protocol symbol".into(),
1971 ));
1972 };
1973 let proto_val = env.globals.lookup_in_ns(&env.current_ns, proto_sym);
1974 let proto_ptr = match proto_val {
1975 Some(Value::Protocol(p)) => p,
1976 _ => {
1977 return Err(EvalError::Runtime(format!(
1978 "extend-protocol: {} is not a protocol",
1979 proto_sym
1980 )));
1981 }
1982 };
1983
1984 let mut current_type: Option<Arc<str>> = None;
1985
1986 for form in &args[1..] {
1987 match &form.unmeta().kind {
1988 FormKind::Symbol(s) => {
1989 current_type = Some(crate::interp::apply::resolve_type_tag(s));
1990 }
1991 FormKind::List(parts) => {
1992 let type_tag = current_type.as_ref().ok_or_else(|| {
1993 EvalError::Runtime("extend-protocol: method before type name".into())
1994 })?;
1995 if parts.is_empty() {
1996 continue;
1997 }
1998 let method_name: Arc<str> = match parts[0].as_symbol() {
1999 Some(s) => Arc::from(s),
2000 None => continue,
2001 };
2002 let fn_val = build_impl_fn(parts, env)?;
2003 let mut impls = proto_ptr.get().impls.lock().unwrap();
2004 impls
2005 .entry(type_tag.clone())
2006 .or_default()
2007 .insert(method_name, fn_val);
2008 drop(impls);
2009 cljrs_value::bump_protocol_generation();
2010 }
2011 _ => {}
2012 }
2013 }
2014
2015 Ok(Value::Nil)
2016}
2017
2018fn build_impl_fn(parts: &[Form], env: &mut Env) -> EvalResult<Value> {
2023 if parts.len() < 2 {
2024 return Err(EvalError::Runtime(
2025 "protocol method impl requires params and body".into(),
2026 ));
2027 }
2028 let params_form = &parts[1];
2030 let body = &parts[2..];
2031 let arity = parse_arity(params_form, body)?;
2032 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
2033 let fn_name: Option<Arc<str>> = parts[0].as_symbol().map(Arc::from);
2034 let cljrs_fn = CljxFn::new(
2035 fn_name,
2036 vec![arity],
2037 closed_over_names,
2038 closed_over_vals,
2039 false,
2040 Arc::clone(&env.current_ns),
2041 );
2042 Ok(Value::Fn(GcPtr::new(cljrs_fn)))
2043}
2044
2045fn eval_defmulti(args: &[Form], env: &mut Env) -> EvalResult {
2048 let name = require_sym(args, 0, "defmulti")?;
2050 let name_arc: Arc<str> = Arc::from(name);
2051
2052 let rest_start = if args.len() > 2 && args[1].as_string().is_some() {
2053 2
2054 } else {
2055 1
2056 };
2057
2058 if args.len() <= rest_start {
2059 return Err(EvalError::Runtime(
2060 "defmulti requires a dispatch function".into(),
2061 ));
2062 }
2063
2064 let dispatch_fn = eval(&args[rest_start], env)?;
2065
2066 let mut default_dispatch = ":default".to_string();
2068 let mut i = rest_start + 1;
2069 while i + 1 < args.len() {
2070 if let FormKind::Keyword(k) = &args[i].kind
2071 && k == "default"
2072 {
2073 let dv = eval(&args[i + 1], env)?;
2074 default_dispatch = format!("{}", dv);
2075 }
2076 i += 2;
2077 }
2078
2079 let mfn = MultiFn::new(name_arc.clone(), dispatch_fn, default_dispatch);
2080 let var = env
2081 .globals
2082 .intern(&env.current_ns, name_arc, Value::MultiFn(GcPtr::new(mfn)));
2083 Ok(Value::Var(var))
2084}
2085
2086fn eval_defmethod(args: &[Form], env: &mut Env) -> EvalResult {
2089 if args.len() < 3 {
2091 return Err(EvalError::Runtime(
2092 "defmethod requires name, dispatch-val, params, and body".into(),
2093 ));
2094 }
2095 let multi_name = require_sym(args, 0, "defmethod")?;
2096
2097 let mf_ptr = match env.globals.lookup_in_ns(&env.current_ns, multi_name) {
2098 Some(Value::MultiFn(mf)) => mf,
2099 _ => {
2100 return Err(EvalError::Runtime(format!(
2101 "defmethod: {} is not a multimethod",
2102 multi_name
2103 )));
2104 }
2105 };
2106
2107 let dispatch_val = eval(&args[1], env)?;
2108 let key = format!("{}", dispatch_val);
2109
2110 let params_form = &args[2];
2112 let body = &args[3..];
2113 let arity = parse_arity(params_form, body)?;
2114 let (closed_over_names, closed_over_vals) = env.all_local_bindings();
2115 let fn_name = Some(Arc::from(multi_name));
2116 let cljrs_fn = CljxFn::new(
2117 fn_name,
2118 vec![arity],
2119 closed_over_names,
2120 closed_over_vals,
2121 false,
2122 Arc::clone(&env.current_ns),
2123 );
2124 let fn_val = Value::Fn(GcPtr::new(cljrs_fn));
2125
2126 mf_ptr.get().methods.lock().unwrap().insert(key, fn_val);
2127
2128 Ok(Value::MultiFn(mf_ptr))
2129}
2130
2131fn eval_binding(args: &[Form], env: &mut Env) -> EvalResult {
2134 let pairs = match args.first().and_then(|f| f.as_vector()) {
2135 Some(v) => expand_pairs(v)
2136 .map_err(|_| EvalError::Runtime("binding vector must have even count".into()))?
2137 .into_owned(),
2138 None => return Err(EvalError::Runtime("binding requires a vector".into())),
2139 };
2140
2141 let mut frame: HashMap<usize, Value> = HashMap::new();
2142 for pair in pairs.chunks(2) {
2143 let Some(sym_str) = pair[0].as_symbol() else {
2144 return Err(EvalError::Runtime("binding targets must be symbols".into()));
2145 };
2146 let parsed = cljrs_value::Symbol::parse(sym_str);
2147 let ns_part: Arc<str> = match parsed.namespace.as_deref() {
2148 Some(ns_part) => env
2152 .globals
2153 .resolve_alias(&env.current_ns, ns_part)
2154 .unwrap_or_else(|| Arc::from(ns_part)),
2155 None => env.current_ns.clone(),
2156 };
2157 let var_ptr = env
2158 .globals
2159 .lookup_var_in_ns(&ns_part, &parsed.name)
2160 .ok_or_else(|| EvalError::UnboundSymbol(sym_str.to_string()))?;
2161 let val = eval(&pair[1], env)?;
2162 frame.insert(crate::env::dynamics::var_key_of(&var_ptr), val);
2163 }
2164
2165 let _guard = crate::env::dynamics::push_frame(frame);
2166 eval_body(&args[1..], env)
2167 }
2169
2170fn eval_defrecord(args: &[Form], env: &mut Env) -> EvalResult {
2173 if args.len() < 2 {
2175 return Err(EvalError::Runtime(
2176 "defrecord requires a name and field vector".into(),
2177 ));
2178 }
2179 let type_name = require_sym(args, 0, "defrecord")?;
2180 let type_tag: Arc<str> = Arc::from(type_name);
2181
2182 let Some(fields) = args[1].as_vector() else {
2184 return Err(EvalError::Runtime(
2185 "defrecord requires a field vector as second arg".into(),
2186 ));
2187 };
2188 let field_names: Vec<Arc<str>> = fields
2189 .iter()
2190 .map(|f| {
2191 f.as_symbol()
2192 .map(Arc::from)
2193 .ok_or_else(|| EvalError::Runtime("defrecord field names must be symbols".into()))
2194 })
2195 .collect::<EvalResult<_>>()?;
2196
2197 register_impls_for_tag(&type_tag, &args[2..], env)?;
2199
2200 let ns = env.current_ns.clone();
2204 let globals = env.globals.clone();
2205 let type_tag2 = type_tag.clone();
2206
2207 {
2209 let params: Vec<Arc<str>> = field_names.clone();
2210 let rest_param = None;
2211 use cljrs_reader::form::FormKind as FK;
2213 let dummy_span =
2214 cljrs_types::span::Span::new(std::sync::Arc::new("<defrecord>".into()), 0, 0, 1, 1);
2215 let make_form = |kind: FK| Form {
2216 kind,
2217 span: dummy_span.clone(),
2218 };
2219 let mut kv_forms: Vec<Form> = Vec::new();
2220 for f in &field_names {
2221 kv_forms.push(make_form(FK::Keyword(f.as_ref().to_string())));
2222 kv_forms.push(make_form(FK::Symbol(f.as_ref().to_string())));
2223 }
2224 let map_form = make_form(FK::Map(kv_forms));
2225 let body = vec![make_form(FK::List(vec![
2226 make_form(FK::Symbol("make-type-instance".into())),
2227 make_form(FK::Str(type_tag.as_ref().to_string())),
2228 map_form,
2229 ]))];
2230 let arity = CljxFnArity {
2231 params,
2232 rest_param,
2233 body,
2234 destructure_params: vec![],
2235 destructure_rest: None,
2236 ir_arity_id: crate::interp::arity::fresh_arity_id(),
2237 param_hints: vec![],
2238 rest_hint: None,
2239 };
2240 let fn_name: Arc<str> = Arc::from(format!("->{}", type_name));
2241 let ctor = CljxFn::new(
2242 Some(fn_name.clone()),
2243 vec![arity],
2244 vec![],
2245 vec![],
2246 false,
2247 Arc::clone(&ns),
2248 );
2249 globals.intern(&ns, fn_name, Value::Fn(GcPtr::new(ctor)));
2250 }
2251
2252 {
2254 use cljrs_reader::form::FormKind as FK;
2255 let dummy_span =
2256 cljrs_types::span::Span::new(std::sync::Arc::new("<defrecord>".into()), 0, 0, 1, 1);
2257 let make_form = |kind: FK| Form {
2258 kind,
2259 span: dummy_span.clone(),
2260 };
2261 let m_sym: Arc<str> = Arc::from("m__");
2262 let body = vec![make_form(FK::List(vec![
2263 make_form(FK::Symbol("make-type-instance".into())),
2264 make_form(FK::Str(type_tag2.as_ref().to_string())),
2265 make_form(FK::Symbol(m_sym.as_ref().to_string())),
2266 ]))];
2267 let arity = CljxFnArity {
2268 params: vec![m_sym],
2269 rest_param: None,
2270 body,
2271 destructure_params: vec![],
2272 destructure_rest: None,
2273 ir_arity_id: crate::interp::arity::fresh_arity_id(),
2274 param_hints: vec![],
2275 rest_hint: None,
2276 };
2277 let fn_name: Arc<str> = Arc::from(format!("map->{}", type_name));
2278 let ctor = CljxFn::new(
2279 Some(fn_name.clone()),
2280 vec![arity],
2281 vec![],
2282 vec![],
2283 false,
2284 Arc::clone(&ns),
2285 );
2286 globals.intern(&ns, fn_name, Value::Fn(GcPtr::new(ctor)));
2287 }
2288
2289 let type_sym = cljrs_value::Symbol::simple(type_name);
2291 globals.intern(
2292 &ns,
2293 Arc::from(type_name),
2294 Value::Symbol(GcPtr::new(type_sym)),
2295 );
2296 Ok(Value::Nil)
2297}
2298
2299fn eval_reify(args: &[Form], env: &mut Env) -> EvalResult {
2302 let n = crate::builtins::builtins::GENSYM_COUNTER
2305 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
2306 let type_tag: Arc<str> = Arc::from(format!("reify__{}", n));
2307
2308 register_impls_for_tag(&type_tag, args, env)?;
2310
2311 Ok(Value::TypeInstance(GcPtr::new(TypeInstance {
2313 type_tag,
2314 fields: MapValue::empty(),
2315 })))
2316}
2317
2318fn register_impls_for_tag(type_tag: &Arc<str>, forms: &[Form], env: &mut Env) -> EvalResult<()> {
2323 let mut current_proto: Option<GcPtr<cljrs_value::Protocol>> = None;
2324
2325 for form in forms {
2326 match &form.unmeta().kind {
2327 FormKind::Symbol(s) => {
2328 let val = env.globals.lookup_in_ns(&env.current_ns, s);
2329 match val {
2330 Some(Value::Protocol(p)) => {
2331 current_proto = Some(p);
2332 }
2333 _ => {
2334 return Err(EvalError::Runtime(format!(
2335 "reify/defrecord: {} is not a protocol",
2336 s
2337 )));
2338 }
2339 }
2340 }
2341 FormKind::List(parts) => {
2342 let proto = current_proto.as_ref().ok_or_else(|| {
2343 EvalError::Runtime("reify/defrecord: method impl before protocol name".into())
2344 })?;
2345 if parts.is_empty() {
2346 continue;
2347 }
2348 let method_name: Arc<str> = match parts[0].as_symbol() {
2349 Some(s) => Arc::from(s),
2350 None => continue,
2351 };
2352 let fn_val = build_impl_fn(parts, env)?;
2353 let mut impls = proto.get().impls.lock().unwrap();
2354 impls
2355 .entry(type_tag.clone())
2356 .or_default()
2357 .insert(method_name, fn_val);
2358 drop(impls);
2359 cljrs_value::bump_protocol_generation();
2360 }
2361 _ => {}
2362 }
2363 }
2364 Ok(())
2365}
2366
2367pub fn sync_star_ns(env: &mut Env) {
2372 if let Some(star_ns_var) = env.globals.lookup_var("clojure.core", "*ns*") {
2373 let ns_ptr = env.globals.get_or_create_ns(&env.current_ns);
2374 star_ns_var.get().bind(Value::Namespace(ns_ptr));
2375 }
2376}
2377
2378fn require_sym<'a>(args: &'a [Form], idx: usize, form_name: &str) -> EvalResult<&'a str> {
2379 args.get(idx).and_then(|f| f.as_symbol()).ok_or_else(|| {
2380 EvalError::Runtime(format!("{form_name} requires a symbol at position {idx}"))
2381 })
2382}
2383
2384fn eval_with_out_str(body: &[Form], env: &mut Env) -> EvalResult {
2387 crate::builtins::builtins::push_output_capture();
2388 let result = eval_body(body, env);
2389 let captured = crate::builtins::builtins::pop_output_capture().unwrap_or_default();
2390 result?;
2392 Ok(Value::string(captured))
2393}
2394
2395fn eval_await(args: &[Form], env: &mut Env) -> EvalResult {
2404 if args.is_empty() {
2405 return Err(EvalError::Runtime("await requires one argument".into()));
2406 }
2407 let val = eval(&args[0], env)?;
2408 match val {
2409 Value::Future(f) => {
2410 let mut guard = f.get().state.lock().unwrap();
2411 loop {
2412 match &*guard {
2413 FutureState::Done(v) => {
2414 f.get().mark_observed();
2415 return Ok(v.clone());
2416 }
2417 FutureState::Failed(v) => {
2418 f.get().mark_observed();
2419 return Err(EvalError::Thrown(v.clone()));
2420 }
2421 FutureState::GasExhausted => {
2422 f.get().mark_observed();
2423 return Err(EvalError::GasExhausted);
2424 }
2425 FutureState::Cancelled => {
2426 return Err(EvalError::Runtime("future was cancelled".into()));
2427 }
2428 FutureState::Running => {
2429 guard = f.get().cond.wait(guard).unwrap();
2430 }
2431 }
2432 }
2433 }
2434 Value::Promise(p) => Ok(p.get().deref_blocking()),
2435 other => Ok(other),
2436 }
2437}