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#[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(®istry, 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(®istry, namespace));
114 }
115 }
116 force_lazy_alias(®istry, 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(®istry, namespace));
324 }
325 }
326 force_lazy_alias(®istry, 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}