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