Skip to main content

hara_native/core/
special_forms.rs

1thread_local! {
2    static PRINTER_CAPTURES: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };
3}
4
5fn printer_write(text: &str) -> Result<(), String> {
6    use std::io::Write;
7    if PRINTER_CAPTURES.with(|captures| {
8        let mut captures = captures.borrow_mut();
9        captures
10            .last_mut()
11            .map(|output| output.push_str(text))
12            .is_some()
13    }) {
14        return Ok(());
15    }
16    print!("{text}");
17    std::io::stdout()
18        .flush()
19        .map_err(|error| format!("Printer output failed: {error}"))
20}
21
22// This compatibility evaluator is also used while loading source-backed
23// namespaces. Keeping its large dispatch match out of line prevents the
24// recursive namespace/evaluator path from multiplying that frame until a
25// normal test or Wasm stack overflows. The fiber evaluator remains the
26// stack-safe execution path for ordinary evaluation.
27#[inline(never)]
28pub fn eval(form: &Form, env: &mut HashMap<String, Value>) -> Result<Value, String> {
29    check_evaluation_interrupt()?;
30    #[cfg(all(feature = "direct-native", not(target_arch = "wasm32")))]
31    if direct_native_execution() {
32        let location = current_exception_site().map_or_else(String::new, |site| {
33            format!(
34                " at {}:{}:{}",
35                site.namespace.as_deref().unwrap_or("<source>"),
36                site.line,
37                site.column
38            )
39        });
40        return Err(format!(
41            "direct-native cannot enter the tree evaluator{location}"
42        ));
43    }
44    match form {
45        Form::Number(v) => Ok(Value::Number(*v)),
46        Form::String(v) => Ok(Value::String(v.clone())),
47        Form::Keyword(v) => Ok(Value::Keyword(v.clone().into())),
48        Form::Nil => Ok(Value::Nil),
49        Form::Bool(value) => Ok(Value::Bool(*value)),
50        Form::Character(value) => Ok(Value::Character(*value)),
51        Form::Float(value) => Ok(Value::Float(crate::numeric::finite_float(*value)?)),
52        Form::BigInteger(value) => Ok(crate::numeric::compact_integer(value.clone())),
53        Form::Regex(value) => Ok(Value::Regex(value.clone())),
54        Form::Tagged(tag, value) if tag == "ptr" => pointer_from_descriptor(literal_value(value)?),
55        Form::Tagged(tag, value) => Ok(Value::Tagged(Box::new(PTaggedLiteral::new(
56            Symbol::parse(tag),
57            literal_value(value)?,
58        )))),
59        Form::Metadata(metadata, value) => {
60            if let Some((line, column)) = exception_location_from_metadata(metadata) {
61                with_exception_site(
62                    exception_site_at(line, column).expect("exception site always exists"),
63                    || eval(value, env),
64                )
65            } else {
66                eval(value, env)
67            }
68        }
69        Form::List(fs)
70            if fs.len() == 2 && matches!(&fs[0], Form::Symbol(name) if name == "syntax-quote") =>
71        {
72            syntax_quote_value(&fs[1], env)
73        }
74        Form::List(fs)
75            if fs.len() == 2 && matches!(&fs[0], Form::Symbol(name) if name == "quote") =>
76        {
77            literal_value(&fs[1])
78        }
79        Form::List(fs) if matches!(fs.first(), Some(Form::Symbol(name)) if name == "comment") => {
80            Ok(Value::Nil)
81        }
82        Form::Map(values) => Ok(Value::Map(
83            values
84                .iter()
85                .map(|(key, value)| Ok((eval(key, env)?, eval(value, env)?)))
86                .collect::<Result<_, String>>()?,
87        )),
88        Form::Set(values) => Ok(Value::OrderedSet(Box::new(
89            unique_values(
90                values
91                    .iter()
92                    .map(|value| eval(value, env))
93                    .collect::<Result<_, _>>()?,
94            )
95            .into_iter()
96            .collect(),
97        ))),
98        Form::Vector(values) => vector_literal(
99            values
100                .iter()
101                .map(|value| eval(value, env))
102                .collect::<Result<_, _>>()?,
103        ),
104        Form::Symbol(n) if n == "nil" => Ok(Value::Nil),
105        Form::Symbol(n) if n == "true" => Ok(Value::Bool(true)),
106        Form::Symbol(n) if n == "false" => Ok(Value::Bool(false)),
107        Form::Symbol(n) => {
108            if n.contains('/') {
109                if let Ok(registry) = namespace_registry() {
110                    ensure_foundation_namespace_for_symbol(&registry, env, n)?;
111                    if let Some((namespace, _)) = n.split_once('/') {
112                        if registry.load_state(namespace) == Some(NamespaceLoadState::Failed) {
113                            return Err(previously_failed_error(&registry, namespace));
114                        }
115                    }
116                    force_lazy_alias(&registry, env, n)?;
117                }
118            }
119            if let Some(value) = binding_value(env, n) {
120                return Ok(value);
121            }
122            if !n.contains('/') {
123                if let Ok(registry) = namespace_registry() {
124                    if let Some((_, namespace)) = registry
125                        .current()
126                        .aliases()
127                        .into_iter()
128                        .find(|(alias, _)| alias.as_str() == n)
129                    {
130                        return Ok(Value::Namespace(Rc::new(namespace)));
131                    }
132                    if let Some(namespace) = registry.find(n) {
133                        return Ok(Value::Namespace(Rc::new(namespace)));
134                    }
135                }
136            }
137            Err(format!("unbound symbol: {n}"))
138        }
139        Form::List(fs) if fs.is_empty() => Ok(Value::List(PList::new())),
140        Form::List(fs) => {
141            let operator = &fs[0];
142            if let Form::Symbol(name) = operator {
143                if foundation_fallback_omitted(env, name) {
144                    return Err(format!("unbound symbol: {name}"));
145                }
146            }
147            match operator {
148                Form::Symbol(n) if n == "fn" => {
149                    if fs.len() < 3 {
150                        return Err("fn expects parameters and a body".into());
151                    }
152                    if !matches!(form_without_metadata(&fs[1]), Form::Vector(_)) {
153                        return multi_arity_function("<anonymous>", &fs[1..], env, false);
154                    }
155                    let (params, variadic, patterns, variadic_pattern) = function_parts(&fs[1])?;
156                    let body = fs[2..].to_vec();
157                    Ok(Value::Function(Rc::new(Function {
158                        params,
159                        variadic,
160                        patterns,
161                        variadic_pattern,
162                        captured: Rc::new(RefCell::new(capture_environment(&body, env))),
163                        body,
164                        name: None,
165                        namespace: function_definition_namespace(),
166                        native: None,
167                        fiber_native: None,
168                        clauses: Vec::new(),
169                        metadata: None,
170                        is_macro: false,
171                    })))
172                }
173                Form::Symbol(n) if n == "letfn" => {
174                    if fs.len() < 3 {
175                        return Err("letfn expects a function binding vector and a body".into());
176                    }
177                    let definitions = match &fs[1] {
178                        Form::Vector(values) => values,
179                        _ => {
180                            return Err("letfn expects a function binding vector and a body".into())
181                        }
182                    };
183                    let mut capture_forms = fs[2..].to_vec();
184                    capture_forms.extend(definitions.iter().cloned());
185                    let captured = Rc::new(RefCell::new(capture_environment(&capture_forms, env)));
186                    let mut functions = Vec::with_capacity(definitions.len());
187                    let mut names = std::collections::HashSet::new();
188                    for definition in definitions {
189                        let Form::List(parts) = definition else {
190                            return Err(
191                                "letfn definitions must be (name [arguments] body...)".into()
192                            );
193                        };
194                        if parts.len() < 3 {
195                            return Err(
196                                "letfn definitions must be (name [arguments] body...)".into()
197                            );
198                        }
199                        let Form::Symbol(name) = &parts[0] else {
200                            return Err("letfn names must be unqualified symbols".into());
201                        };
202                        if name.contains('/') {
203                            return Err("letfn names must be unqualified symbols".into());
204                        }
205                        if !names.insert(name.clone()) {
206                            return Err(format!("Duplicate letfn name: {name}"));
207                        }
208                        let (params, variadic, patterns, variadic_pattern) =
209                            function_parts(&parts[1])
210                                .map_err(|_| "letfn parameters must be a binding vector")?;
211                        functions.push((
212                            name.clone(),
213                            Value::Function(Rc::new(Function {
214                                params,
215                                variadic,
216                                patterns,
217                                variadic_pattern,
218                                body: parts[2..].to_vec(),
219                                captured: captured.clone(),
220                                name: Some(name.clone()),
221                                namespace: function_definition_namespace(),
222                                native: None,
223                                fiber_native: None,
224                                clauses: Vec::new(),
225                                metadata: None,
226                                is_macro: false,
227                            })),
228                        ));
229                    }
230                    for (name, function) in &functions {
231                        captured.borrow_mut().insert(name.clone(), function.clone());
232                    }
233                    let mut previous = Vec::with_capacity(functions.len());
234                    for (name, function) in functions {
235                        previous.push((name.clone(), env.insert(name, function)));
236                    }
237                    let mut result = Ok(Value::Nil);
238                    for body in &fs[2..] {
239                        result = eval(body, env);
240                        if result.is_err() {
241                            break;
242                        }
243                    }
244                    for (name, old) in previous.into_iter().rev() {
245                        if let Some(old) = old {
246                            env.insert(name, old);
247                        } else {
248                            env.remove(&name);
249                        }
250                    }
251                    result
252                }
253                Form::Symbol(n) if n == "read-forms" => {
254                    if fs.len() != 2 {
255                        return Err("read-forms expects a path string".into());
256                    }
257                    let path = match eval(&fs[1], env)? {
258                        Value::String(path) => path,
259                        _ => return Err("read-forms expects a path string".into()),
260                    };
261                    if !(path.ends_with(".hal") || path.ends_with(".hrl")) {
262                        return Err("read-forms expects a .hal or .hrl path".into());
263                    }
264                    let promise = file_provider("read-forms")?
265                        .read(&path)
266                        .map_err(|error| file_error("read-forms", error))?;
267                    let bytes = match promise.wait_state() {
268                        PromiseState::Fulfilled(Value::Bytes(bytes)) => bytes,
269                        PromiseState::Fulfilled(Value::ByteBuffer(bytes)) => bytes.borrow().clone(),
270                        PromiseState::Fulfilled(value) => {
271                            return Err(format!(
272                                "read-forms expected file bytes, got {}",
273                                value.display()
274                            ))
275                        }
276                        PromiseState::Rejected(error) => {
277                            return Err(promise_rejection_error(error))
278                        }
279                        PromiseState::Pending => {
280                            return Err("read-forms file read is still pending".into())
281                        }
282                    };
283                    let source = String::from_utf8(bytes)
284                        .map_err(|_| format!("read-forms source is not UTF-8: {path}"))?;
285                    let forms = crate::kernel::parse_forms(&source)
286                        .map_err(|error| format!("read-forms failed: {error}"))?;
287                    let values = forms
288                        .iter()
289                        .map(form_to_value)
290                        .collect::<Result<Vec<_>, _>>()?;
291                    Ok(Value::Vector(PVector::from_iter(values)))
292                }
293                Form::Symbol(n) if n.ends_with("/var-sym") => {
294                    if fs.len() != 2 {
295                        return Err("var-sym expects one var".into());
296                    }
297                    let target = match &fs[1] {
298                        Form::Symbol(name) => match env.get(name) {
299                            Some(Value::Var(var)) => Value::Var(var.clone()),
300                            _ => eval(&fs[1], env)?,
301                        },
302                        _ => eval(&fs[1], env)?,
303                    };
304                    match target {
305                        Value::Var(var) => Ok(Value::Symbol(var.symbol().clone())),
306                        value => Err(format!("var-sym expects a var, got {}", value.display())),
307                    }
308                }
309                Form::Symbol(n) if n == "var" => {
310                    if fs.len() != 2 {
311                        return Err("var expects a symbol".into());
312                    }
313                    let name = match &fs[1] {
314                        Form::Symbol(name) => name,
315                        _ => return Err("var expects a symbol".into()),
316                    };
317                    if name.contains('/') {
318                        if let Ok(registry) = namespace_registry() {
319                            if let Some((namespace, _)) = name.split_once('/') {
320                                if registry.load_state(namespace)
321                                    == Some(NamespaceLoadState::Failed)
322                                {
323                                    return Err(previously_failed_error(&registry, namespace));
324                                }
325                            }
326                            force_lazy_alias(&registry, env, name)?;
327                        }
328                    }
329                    let cell =
330                        binding_var(env, name).ok_or_else(|| format!("unbound symbol: {name}"))?;
331                    Ok(Value::Var(cell))
332                }
333                Form::Symbol(n) if n == "set!" || n == "var/set" => {
334                    if fs.len() != 3 {
335                        return Err(format!("{n} expects a symbol and value"));
336                    }
337                    if n == "set!" {
338                        if let Form::List(place) = &fs[1] {
339                            if matches!(place.first(), Some(Form::Symbol(operation)) if operation == "field")
340                            {
341                                if place.len() != 3 {
342                                    return Err(
343                                        "set! field place expects a receiver and field".into()
344                                    );
345                                }
346                                let field = match &place[2] {
347                                    Form::Keyword(field) if !field.contains('/') => field.as_str(),
348                                    Form::Symbol(field) if !field.contains('/') => field.as_str(),
349                                    _ => {
350                                        return Err(
351                                            "set! field place expects an unqualified literal field"
352                                                .into(),
353                                        )
354                                    }
355                                };
356                                let receiver = eval(&place[1], env)?;
357                                let replacement = eval(&fs[2], env)?;
358                                return mutable_field_set(&receiver, field, replacement);
359                            }
360                        }
361                    }
362                    let name = match &fs[1] {
363                        Form::Symbol(name) => name,
364                        _ => return Err(format!("{n} expects a symbol")),
365                    };
366                    let value = eval(&fs[2], env)?;
367                    let cell =
368                        binding_var(env, name).ok_or_else(|| format!("unbound var: {name}"))?;
369                    if !binding_is_local(&cell) {
370                        return Err(format!(
371                            "Cannot replace referred Var without ns omission: {name}"
372                        ));
373                    }
374                    cell.reset_value(value.clone());
375                    Ok(value)
376                }
377                Form::Symbol(n) if n == "throw" => {
378                    if fs.len() != 2 {
379                        return Err("throw expects one value".into());
380                    }
381                    let value = eval(&fs[1], env)?;
382                    if !matches!(value, Value::ExceptionInfo(_)) {
383                        return Err("throw expects an Exception value created by ex".into());
384                    }
385                    Err(thrown_error(value))
386                }
387                Form::Symbol(n) if n == "try" => {
388                    if fs.len() < 2 {
389                        return Err("try expects a body".into());
390                    }
391                    let mut body = Vec::new();
392                    let mut catch_forms = Vec::new();
393                    let mut finally_forms = Vec::new();
394                    let mut clauses_started = false;
395                    for form in &fs[1..] {
396                        match form {
397                            Form::List(parts)
398                                if !parts.is_empty()
399                                    && matches!(&parts[0],Form::Symbol(name) if name=="catch") =>
400                            {
401                                clauses_started = true;
402                                catch_forms.push(parts)
403                            }
404                            Form::List(parts)
405                                if !parts.is_empty()
406                                    && matches!(&parts[0],Form::Symbol(name) if name=="finally") =>
407                            {
408                                clauses_started = true;
409                                finally_forms.extend_from_slice(&parts[1..])
410                            }
411                            _ if !clauses_started => body.push(form),
412                            _ => return Err("try clauses must follow the body".into()),
413                        }
414                    }
415                    let mut result = Ok(Value::Nil);
416                    for form in body {
417                        result = eval(form, env);
418                        if result.is_err() {
419                            break;
420                        }
421                    }
422                    if let Err(ref error) = result {
423                        for parts in catch_forms {
424                            if parts.len() < 3 {
425                                return Err("catch expects a selector, name, and body".into());
426                            }
427                            let (selector, binding_index, body_index) = match parts.as_slice() {
428                                [_, Form::Symbol(name), _]
429                                    if name != "Exception" && name != "Throwable" =>
430                                {
431                                    ("Exception".to_owned(), 1, 2)
432                                }
433                                [_, Form::Symbol(name), body, ..]
434                                    if name != "Exception"
435                                        && name != "Throwable"
436                                        && !matches!(body, Form::Symbol(_)) =>
437                                {
438                                    ("Exception".to_owned(), 1, 2)
439                                }
440                                [_, Form::Symbol(class), Form::Symbol(_), ..] => {
441                                    (class.clone(), 2, 3)
442                                }
443                                [_, Form::Keyword(code), Form::Symbol(_), ..]
444                                    if code.contains('/') =>
445                                {
446                                    (format!(":{code}"), 2, 3)
447                                }
448                                [_, Form::Vector(codes), Form::Symbol(_), ..]
449                                    if !codes.is_empty()
450                                        && codes.iter().all(|code| matches!(code, Form::Keyword(name) if name.contains('/'))) =>
451                                {
452                                    let selectors = codes
453                                        .iter()
454                                        .map(|code| match code {
455                                            Form::Keyword(name) => format!(":{name}"),
456                                            _ => unreachable!(),
457                                        })
458                                        .collect::<Vec<_>>()
459                                        .join(",");
460                                    (format!("[{selectors}]"), 2, 3)
461                                }
462                                _ => return Err("catch selector must be a namespaced keyword, a non-empty vector of namespaced keywords, or omitted".into()),
463                            };
464                            if !catch_matches(error, &selector) {
465                                continue;
466                            }
467                            let name = match &parts[binding_index] {
468                                Form::Symbol(name) => name.clone(),
469                                _ => return Err("catch name must be a symbol".into()),
470                            };
471                            let old = env.insert(name.clone(), caught_error(error));
472                            result = Ok(Value::Nil);
473                            for form in &parts[body_index..] {
474                                result = eval(form, env);
475                                if result.is_err() {
476                                    break;
477                                }
478                            }
479                            if let Some(old) = old {
480                                env.insert(name, old);
481                            } else {
482                                env.remove(&name);
483                            }
484                            break;
485                        }
486                    }
487                    for form in finally_forms {
488                        let final_result = eval(&form, env);
489                        if final_result.is_err() {
490                            result = final_result;
491                        }
492                    }
493                    result
494                }
495                Form::Symbol(n) if n == "def" => {
496                    if fs.len() != 3 {
497                        return Err("def expects a name and value".into());
498                    }
499                    let (name, metadata) = binding_symbol(&fs[1], "def name")?;
500                    prepare_owned_definition(env, &name)?;
501                    let value = eval(&fs[2], env)?;
502                    let var = if namespace_registry().is_ok() {
503                        let var = vm_def_global(&name, value, metadata)?;
504                        env.insert(name, Value::Var(var.clone()));
505                        var
506                    } else if let Some(Value::Var(var)) = env.get(&name) {
507                        if !binding_is_local(var) {
508                            let var = KernelVar::new(local_var_name(&name), value.clone());
509                            var.set_origin(definition_origin());
510                            var.set_hara_metadata(metadata);
511                            env.insert(name, Value::Var(var.clone()));
512                            var
513                        } else {
514                            var.reset_value(value);
515                            var.set_origin(definition_origin());
516                            if metadata.is_some() {
517                                var.set_hara_metadata(metadata);
518                            }
519                            var.clone()
520                        }
521                    } else {
522                        let var = KernelVar::new(local_var_name(&name), value);
523                        var.set_origin(definition_origin());
524                        var.set_hara_metadata(metadata);
525                        env.insert(name, Value::Var(var.clone()));
526                        var
527                    };
528                    refresh_schema_contract(&var)?;
529                    Ok(Value::Var(var))
530                }
531                Form::Symbol(n) if n == "declare" => {
532                    if fs.len() < 2 {
533                        return Err("declare expects at least one symbol".into());
534                    }
535                    for form in &fs[1..] {
536                        let name = match form {
537                            Form::Symbol(name) => name.clone(),
538                            _ => return Err("declare expects symbols".into()),
539                        };
540                        prepare_owned_definition(env, &name)?;
541                        let cell = match env.get(&name) {
542                            Some(Value::Var(cell)) if binding_is_local(cell) => cell.clone(),
543                            _ => KernelVar::new(local_var_name(&name), Value::Nil),
544                        };
545                        cell.set_origin(definition_origin());
546                        env.insert(name, Value::Var(cell));
547                    }
548                    Ok(Value::Nil)
549                }
550                Form::Symbol(n) if n == "field" => {
551                    if fs.len() != 3 {
552                        return Err("field expects a mutable value and field name".into());
553                    }
554                    let field = match &fs[2] {
555                        Form::Keyword(field) | Form::Symbol(field) if !field.contains('/') => field,
556                        _ => {
557                            return Err("field name must be an unqualified keyword or symbol".into())
558                        }
559                    };
560                    let value = eval(&fs[1], env)?;
561                    mutable_field_value(&value, field)
562                }
563                Form::Symbol(n) if n == "defmacro" => {
564                    if fs.len() < 3 {
565                        return Err("defmacro expects a name, parameters, and a body".into());
566                    }
567                    let (name, metadata) = binding_symbol(&fs[1], "defmacro name")?;
568                    let (metadata, rest) = definition_metadata(metadata, &fs[2..], false, true)?;
569                    if let Some(Value::Var(var)) = env.get(&name) {
570                        if var.symbol().get_namespace() == Some("std.foundation") {
571                            namespace_registry()?
572                                .current()
573                                .unmap(&crate::lang::data::Symbol::parse(&name));
574                            env.remove(&name);
575                        }
576                    }
577                    prepare_owned_definition(env, &name)?;
578                    let cell = match env.get(&name) {
579                        Some(Value::Var(cell)) if binding_is_local(cell) => cell.clone(),
580                        _ => KernelVar::new(local_var_name(&name), Value::Nil),
581                    };
582                    if metadata.is_some() {
583                        cell.set_hara_metadata(metadata);
584                    }
585                    env.insert(name.clone(), Value::Var(cell.clone()));
586                    if rest.is_empty() {
587                        return Err("defmacro expects a name, parameters, and a body".into());
588                    }
589                    let function = if matches!(
590                        rest.first().map(form_without_metadata),
591                        Some(Form::Vector(_))
592                    ) {
593                        let params = match form_without_metadata(&rest[0]) {
594                            Form::Vector(params) => params,
595                            _ => unreachable!(),
596                        };
597                        let mut macro_params =
598                            vec![Form::Symbol("&form".into()), Form::Symbol("&env".into())];
599                        macro_params.extend_from_slice(params);
600                        let (params, variadic, patterns, variadic_pattern) =
601                            function_parts(&Form::Vector(macro_params))?;
602                        let body = rest[1..].to_vec();
603                        Value::Function(Rc::new(Function {
604                            params,
605                            variadic,
606                            patterns,
607                            variadic_pattern,
608                            captured: Rc::new(RefCell::new(capture_environment(&body, env))),
609                            body,
610                            name: Some(name.clone()),
611                            namespace: function_definition_namespace(),
612                            native: None,
613                            fiber_native: None,
614                            clauses: Vec::new(),
615                            metadata: None,
616                            is_macro: true,
617                        }))
618                    } else {
619                        let clauses = rest
620                            .iter()
621                            .map(macro_clause_with_implicit_params)
622                            .collect::<Result<Vec<_>, _>>()?;
623                        multi_arity_function(&name, &clauses, env, true)?
624                    };
625                    if let Value::Function(ref function) = function {
626                        let namespace = namespace_registry()?.current().name().as_str().to_owned();
627                        register_macro(&namespace, &name, function.clone())?;
628                    }
629                    cell.reset_value(function.clone());
630                    cell.set_origin(definition_origin());
631                    refresh_schema_contract(&cell)?;
632                    Ok(function)
633                }
634                Form::Symbol(n) if n == "defn" => {
635                    if fs.len() < 4 {
636                        return Err("defn expects a name, parameters, and a body".into());
637                    }
638                    let (name, metadata) = binding_symbol(&fs[1], "defn name")?;
639                    let (metadata, rest) = definition_metadata(metadata, &fs[2..], false, false)
640                        .map_err(|error| format!("{name}: {error}"))?;
641                    if let Some(schema) = schema_var_reference(metadata.as_deref()) {
642                        if binding_var(env, schema.as_str()).is_none() {
643                            return Err(format!("schema Var does not exist: {schema}"));
644                        }
645                    }
646                    prepare_owned_definition(env, &name)?;
647                    let cell = match env.get(&name) {
648                        Some(Value::Var(cell)) if binding_is_local(cell) => cell.clone(),
649                        _ => KernelVar::new(local_var_name(&name), Value::Nil),
650                    };
651                    if metadata.is_some() {
652                        cell.set_hara_metadata(metadata);
653                    }
654                    env.insert(name.clone(), Value::Var(cell.clone()));
655                    if rest.is_empty() {
656                        return Err("defn expects a name, parameters, and a body".into());
657                    }
658                    let function = if matches!(
659                        rest.first().map(form_without_metadata),
660                        Some(Form::Vector(_))
661                    ) {
662                        let (params, variadic, patterns, variadic_pattern) =
663                            function_parts(&rest[0])?;
664                        let body = rest[1..].to_vec();
665                        Value::Function(Rc::new(Function {
666                            params,
667                            variadic,
668                            patterns,
669                            variadic_pattern,
670                            captured: Rc::new(RefCell::new(capture_environment(&body, env))),
671                            body,
672                            name: Some(name.clone()),
673                            namespace: function_definition_namespace(),
674                            native: None,
675                            fiber_native: None,
676                            clauses: Vec::new(),
677                            metadata: None,
678                            is_macro: false,
679                        }))
680                    } else {
681                        multi_arity_function(&name, rest, env, false)?
682                    };
683                    cell.reset_value(function.clone());
684                    cell.set_origin(definition_origin());
685                    refresh_schema_contract(&cell)?;
686                    Ok(Value::Var(cell))
687                }
688                Form::Symbol(n) if n == "do" => {
689                    let mut result = Value::Nil;
690                    for form in &fs[1..] {
691                        result = eval(form, env)?;
692                        if matches!(result, Value::Recur(_)) {
693                            return Ok(result);
694                        }
695                    }
696                    Ok(result)
697                }
698                Form::Symbol(n) if n == "declare" => {
699                    for form in &fs[1..] {
700                        if !matches!(form, Form::Symbol(_)) {
701                            return Err("declare expects symbols".into());
702                        }
703                    }
704                    Ok(Value::Nil)
705                }
706                Form::Symbol(n) if n == "ns" || n == "ns+" || n == "require" => {
707                    eval_namespace_form(fs, env)
708                }
709                Form::Symbol(n)
710                    if resolve_macro(n).is_none()
711                        && binding_value(env, n)
712                            .is_some_and(|value| matches!(value, Value::Function(_))) =>
713                {
714                    let function =
715                        binding_value(env, n).expect("namespace function binding was checked");
716                    let arguments = fs[1..]
717                        .iter()
718                        .map(|form| eval(form, env))
719                        .collect::<Result<Vec<_>, _>>()?;
720                    call_value(function, arguments)
721                }
722                Form::Symbol(n) if n == "." => {
723                    if fs.len() != 3 {
724                        return Err("dot expects a receiver and method".into());
725                    }
726                    let receiver = eval(&fs[1], env)?;
727                    dot_call(receiver, &fs[2], env)
728                }
729                Form::Symbol(n) if n == "recur" => {
730                    if fs.len() < 2 {
731                        return Err("recur expects values".into());
732                    }
733                    Ok(Value::Recur(
734                        fs[1..]
735                            .iter()
736                            .map(|form| eval(form, env))
737                            .collect::<Result<Vec<_>, _>>()?,
738                    ))
739                }
740                Form::Symbol(n) if n == "binding" => {
741                    if fs.len() < 3 {
742                        return Err("binding expects bindings and a body".into());
743                    }
744                    let pairs = match &fs[1] {
745                        Form::List(values) | Form::Vector(values) => values,
746                        _ => return Err("binding expects a binding list or vector".into()),
747                    };
748                    if pairs.len() % 2 != 0 {
749                        return Err("binding bindings require name/value pairs".into());
750                    }
751                    let mut pending = Vec::new();
752                    for pair in pairs.chunks(2) {
753                        let name = match &pair[0] {
754                            Form::Symbol(name) => name,
755                            _ => return Err("binding name must be a symbol".into()),
756                        };
757                        let var = binding_var(env, name)
758                            .ok_or_else(|| format!("binding expects a Var: {name}"))?;
759                        if !var.is_dynamic() {
760                            return Err(format!("binding expects a dynamic Var: {name}"));
761                        }
762                        let value = eval(&pair[1], env)?;
763                        pending.push((var, value));
764                    }
765                    for (var, value) in &pending {
766                        var.bind(value.clone());
767                    }
768                    let bound = pending.into_iter().map(|(var, _)| var).collect::<Vec<_>>();
769                    let mut result = Ok(Value::Nil);
770                    for form in &fs[2..] {
771                        result = eval(form, env);
772                        if result.is_err() {
773                            break;
774                        }
775                    }
776                    for var in bound.into_iter().rev() {
777                        if let Err(error) = var.unbind() {
778                            if result.is_ok() {
779                                result = Err(error);
780                            }
781                        }
782                    }
783                    result
784                }
785                Form::Symbol(n) if n == "loop" => {
786                    if fs.len() != 3 {
787                        return Err("loop expects bindings and a body".into());
788                    }
789                    let bindings = match &fs[1] {
790                        Form::List(values) | Form::Vector(values) => values,
791                        _ => return Err("loop expects a binding list or vector".into()),
792                    };
793                    if bindings.len() % 2 != 0 {
794                        return Err("loop bindings require name/value pairs".into());
795                    }
796                    let mut previous = Vec::new();
797                    let mut patterns = Vec::new();
798                    let mut pattern_names = Vec::new();
799                    for pair in bindings.chunks(2) {
800                        let value = eval(&pair[1], env)?;
801                        let before = env.clone();
802                        let mut names = Vec::new();
803                        bind_pattern(&pair[0], value, env, &mut names, None)
804                            .map_err(|error| format!("loop destructuring failed: {error}"))?;
805                        for name in &names {
806                            previous.push((name.clone(), before.get(name).cloned()));
807                        }
808                        patterns.push(pair[0].clone());
809                        pattern_names.push(names);
810                    }
811                    let result = loop {
812                        match eval(&fs[2], env)? {
813                            Value::Recur(values) => {
814                                if values.len() != patterns.len() {
815                                    break Err("loop recur arity mismatch".into());
816                                }
817                                for names in &pattern_names {
818                                    for name in names {
819                                        env.remove(name);
820                                    }
821                                }
822                                pattern_names.clear();
823                                for (pattern, value) in patterns.iter().zip(values) {
824                                    let mut names = Vec::new();
825                                    bind_pattern(pattern, value, env, &mut names, None)?;
826                                    pattern_names.push(names);
827                                }
828                            }
829                            result => break Ok(result),
830                        }
831                    };
832                    for (name, old) in previous.into_iter().rev() {
833                        if let Some(old) = old {
834                            env.insert(name, old);
835                        } else {
836                            env.remove(&name);
837                        }
838                    }
839                    result
840                }
841                Form::Symbol(n) if n == "if" => {
842                    if fs.len() != 3 && fs.len() != 4 {
843                        return Err("if expects 2 or 3 arguments".into());
844                    }
845                    if eval(&fs[1], env)?.truthy() {
846                        eval(&fs[2], env)
847                    } else if fs.len() == 4 {
848                        eval(&fs[3], env)
849                    } else {
850                        Ok(Value::Nil)
851                    }
852                }
853                Form::Symbol(n) if n == "and" => {
854                    let mut result = Value::Bool(true);
855                    for form in &fs[1..] {
856                        result = eval(form, env)?;
857                        if !result.truthy() {
858                            return Ok(result);
859                        }
860                    }
861                    Ok(result)
862                }
863                Form::Symbol(n) if n == "or" => {
864                    let mut result = Value::Nil;
865                    for form in &fs[1..] {
866                        result = eval(form, env)?;
867                        if result.truthy() {
868                            return Ok(result);
869                        }
870                    }
871                    Ok(result)
872                }
873                Form::Symbol(n) if n == "cond" => {
874                    if fs.len() % 2 == 0 {
875                        return Err("cond expects test/expression pairs".into());
876                    }
877                    let mut clauses = fs[1..].chunks_exact(2);
878                    for clause in &mut clauses {
879                        if eval(&clause[0], env)?.truthy() {
880                            return eval(&clause[1], env);
881                        }
882                    }
883                    Ok(Value::Nil)
884                }
885                Form::Symbol(n) if n == "let" => {
886                    if fs.len() < 3 {
887                        return Err("let expects bindings and a body".into());
888                    }
889                    let bindings = match &fs[1] {
890                        Form::List(values) | Form::Vector(values) => values,
891                        _ => return Err("let expects a binding list or vector".into()),
892                    };
893                    if bindings.len() % 2 != 0 {
894                        return Err("let bindings require name/value pairs".into());
895                    }
896                    let mut previous = Vec::new();
897                    for pair in bindings.chunks(2) {
898                        let value = eval(&pair[1], env)?;
899                        let before = env.clone();
900                        let mut names = Vec::new();
901                        bind_pattern(&pair[0], value, env, &mut names, None)
902                            .map_err(|error| format!("let destructuring failed: {error}"))?;
903                        for name in names {
904                            previous.push((name.clone(), before.get(&name).cloned()));
905                        }
906                    }
907                    let mut result = Ok(Value::Nil);
908                    for body in &fs[2..] {
909                        result = eval(body, env);
910                        if result.is_err() {
911                            break;
912                        }
913                    }
914                    for (name, old) in previous.into_iter().rev() {
915                        if let Some(old) = old {
916                            env.insert(name, old);
917                        } else {
918                            env.remove(&name);
919                        }
920                    }
921                    result
922                }
923                _ => {
924                    if let Form::Symbol(name) = &fs[0] {
925                        if let Some(expanded) = macroexpand_call(name, fs, env)? {
926                            return eval(&expanded, env);
927                        }
928                    }
929                    let function = eval(&fs[0], env)?;
930                    let arguments = fs[1..]
931                        .iter()
932                        .map(|form| eval(form, env))
933                        .collect::<Result<Vec<_>, _>>()?;
934                    call_value(function, arguments)
935                }
936            }
937        }
938    }
939}
940
941pub fn eval_traced(form: &Form, env: &mut HashMap<String, Value>) -> Result<Value, String> {
942    let _guard = StackTraceGuard::enable();
943    eval(form, env).map_err(append_trace)
944}
945
946pub fn eval_text(source: &str, env: &mut HashMap<String, Value>) -> Result<String, String> {
947    Ok(eval_value_text(source, env)?.display())
948}
949
950pub fn eval_text_traced(source: &str, env: &mut HashMap<String, Value>) -> Result<String, String> {
951    let _guard = StackTraceGuard::enable();
952    eval_text(source, env).map_err(append_trace)
953}
954
955pub fn eval_value_text_traced(
956    source: &str,
957    env: &mut HashMap<String, Value>,
958) -> Result<Value, String> {
959    let _guard = StackTraceGuard::enable();
960    eval_value_text(source, env).map_err(append_trace)
961}
962
963pub fn eval_value_text(source: &str, env: &mut HashMap<String, Value>) -> Result<Value, String> {
964    let forms = parse_forms(source)?;
965    let mut result = Value::Nil;
966    for form in forms {
967        result = eval(&form, env)?;
968        if matches!(result, Value::Recur(_)) {
969            return Err("recur must be inside loop".into());
970        }
971    }
972    Ok(result)
973}