1use crate::core::cons::{Cons, ConsError};
3use crate::core::env::{ArgSlice, CallFrame, Env, sym};
4use crate::core::error::{Type, TypeError};
5use crate::core::gc::{Rt, Rto};
6use crate::core::object::{
7 FnArgs, Function, LispString, NIL, ObjectType, Symbol, TagType, display_slice,
8};
9use crate::core::{
10 gc::Context,
11 object::{FunctionType, Gc, Object},
12};
13use crate::data::LispError;
14use crate::fns::{assq, eq};
15use crate::rooted_iter;
16use anyhow::{Result, anyhow, bail, ensure};
17use fallible_iterator::FallibleIterator;
18use fallible_streaming_iterator::FallibleStreamingIterator;
19use rune_core::macros::{bail_err, call, list, root};
20use rune_macros::defun;
21use std::fmt::{Display, Formatter};
22
23#[derive(Debug)]
24pub(crate) struct EvalError {
25 backtrace: Vec<Box<str>>,
26 pub(crate) error: ErrorType,
27}
28
29#[derive(Debug)]
30pub(crate) enum ErrorType {
31 Throw(u32),
32 Signal(u32),
33 Err(anyhow::Error),
34}
35
36impl std::error::Error for EvalError {}
37
38impl Display for EvalError {
39 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40 match &self.error {
41 ErrorType::Err(e) => writeln!(f, "{e}")?,
42 ErrorType::Throw(_) => writeln!(f, "No catch for throw")?,
43 ErrorType::Signal(_) => writeln!(f, "Signal")?,
44 }
45 Ok(())
46 }
47}
48
49impl EvalError {
50 pub(crate) fn new_error(error: anyhow::Error) -> Self {
51 Self { backtrace: Vec::new(), error: ErrorType::Err(error) }
52 }
53
54 pub(crate) fn signal(error_symbol: Object, data: Object, env: &mut Rt<Env>) -> Self {
55 Self {
56 backtrace: Vec::new(),
57 error: ErrorType::Signal(env.set_exception(error_symbol, data)),
58 }
59 }
60
61 pub(crate) fn throw(tag: Object, data: Object, env: &mut Rt<Env>) -> Self {
62 Self { backtrace: Vec::new(), error: ErrorType::Throw(env.set_exception(tag, data)) }
63 }
64
65 pub(crate) fn new(error: impl Into<Self>) -> Self {
66 error.into()
67 }
68
69 pub(crate) fn with_trace(error: anyhow::Error, name: &str, args: &[Rto<Object>]) -> Self {
70 let display = display_slice(args);
71 let trace = format!("{name} {display}").into_boxed_str();
72 Self { backtrace: vec![trace], error: ErrorType::Err(error) }
73 }
74
75 pub(crate) fn add_trace(mut self, name: &str, args: &[Rto<Object>]) -> Self {
76 let display = display_slice(args);
77 self.backtrace.push(format!("{name} {display}").into_boxed_str());
78 self
79 }
80
81 pub(crate) fn print_backtrace(&self) {
82 println!("BEGIN_BACKTRACE");
83 for (i, x) in self.backtrace.iter().enumerate() {
84 println!("{i}: {x}");
85 }
86 println!("END_BACKTRACE");
87 }
88}
89
90impl From<anyhow::Error> for EvalError {
91 fn from(e: anyhow::Error) -> Self {
92 Self::new_error(e)
93 }
94}
95
96impl From<ConsError> for EvalError {
97 fn from(e: ConsError) -> Self {
98 Self::new_error(anyhow::anyhow!(e))
99 }
100}
101
102impl From<String> for EvalError {
103 fn from(e: String) -> Self {
104 Self::new_error(anyhow::anyhow!(e))
105 }
106}
107
108impl From<&'static str> for EvalError {
109 fn from(e: &'static str) -> Self {
110 Self::new_error(anyhow::anyhow!(e))
111 }
112}
113
114impl From<TypeError> for EvalError {
115 fn from(e: TypeError) -> Self {
116 Self::new_error(e.into())
117 }
118}
119
120impl From<LispError> for EvalError {
121 fn from(e: LispError) -> Self {
122 Self::new_error(e.into())
123 }
124}
125
126impl From<std::convert::Infallible> for EvalError {
127 fn from(e: std::convert::Infallible) -> Self {
128 Self::new_error(e.into())
129 }
130}
131
132pub(crate) type EvalResult<'ob> = Result<Object<'ob>, EvalError>;
133
134#[defun]
135pub(crate) fn apply<'ob>(
136 function: &Rto<Function>,
137 arguments: ArgSlice,
138 env: &mut Rt<Env>,
139 cx: &'ob mut Context,
140) -> Result<Object<'ob>> {
141 let arg_slice = env.stack.arg_slice(arguments);
142 if !arg_slice.is_empty() {
143 let last = arg_slice.last().unwrap().bind(cx);
144 let len = env.stack.len();
145 let beg = len - arg_slice.len();
146 let end = len - 1;
147 env.stack.extend_as_vec_from_within(beg..end);
148 for element in last.as_list()? {
149 let e = cx.bind(element?);
150 env.stack.push(e);
151 }
152 let args = env.stack.len() - len;
153 let frame = &mut CallFrame::new_with_args(env, args);
154 function.call(frame, None, cx).map_err(Into::into)
155 } else {
156 function.call(&mut CallFrame::new(env), None, cx).map_err(Into::into)
157 }
158}
159
160#[defun]
161pub(crate) fn funcall<'ob>(
162 function: &Rto<Function>,
163 arguments: ArgSlice,
164 env: &mut Rt<Env>,
165 cx: &'ob mut Context,
166) -> Result<Object<'ob>> {
167 let beg = env.stack.len() - arguments.len();
168 env.stack.extend_as_vec_from_within(beg..);
169 let frame = &mut CallFrame::new_with_args(env, arguments.len());
170 function.call(frame, None, cx).map_err(Into::into)
171}
172
173#[defun]
174fn run_hooks<'ob>(hooks: ArgSlice, env: &mut Rt<Env>, cx: &'ob mut Context) -> Result<Object<'ob>> {
175 let hook_count = hooks.len();
176 for i in 0..hook_count {
177 let hook = env.stack[hook_count - i - 1].bind(cx);
178 match hook.untag() {
179 ObjectType::Symbol(sym) => {
180 if let Some(val) = env.vars.get(sym) {
181 let val = val.bind(cx);
182 match val.untag() {
183 ObjectType::Cons(hook_list) => {
184 rooted_iter!(hooks, hook_list, cx);
185 while let Some(hook) = hooks.next()? {
186 let func = hook.try_as()?;
187 call!(func; env, cx)?;
188 }
189 }
190 ObjectType::NIL => {}
191 _ => {
192 let func: Function = val.try_into()?;
193 root!(func, cx);
194 call!(func; env, cx)?;
195 }
196 }
197 }
198 }
199 x => bail!(TypeError::new(Type::Symbol, x)),
200 }
201 }
202 Ok(NIL)
203}
204
205#[defun]
206fn run_hook_with_args<'ob>(
207 hook: &Rto<Object>,
208 args: ArgSlice,
209 env: &mut Rt<Env>,
210 cx: &'ob mut Context,
211) -> Result<Object<'ob>> {
212 match hook.untag(cx) {
213 ObjectType::Symbol(sym) => {
214 if let Some(val) = env.vars.get(sym) {
215 let val = val.bind(cx);
216 match val.untag() {
217 ObjectType::Cons(hook_list) => {
218 rooted_iter!(hooks, hook_list, cx);
219 while let Some(hook) = hooks.next()? {
220 let func: &Rto<Function> = hook.try_as()?;
221 let beg = env.stack.len() - args.len();
222 env.stack.extend_as_vec_from_within(beg..);
223 let frame = &mut CallFrame::new_with_args(env, args.len());
224 func.call(frame, None, cx)?;
225 }
226 }
227 ObjectType::NIL => {}
228 _ => {
229 let func: Function = val.try_into()?;
230 root!(func, cx);
231 call!(func; env, cx)?;
232 }
233 }
234 }
235 }
236 x => bail!(TypeError::new(Type::Symbol, x)),
237 }
238 Ok(NIL)
239}
240
241#[defun]
242pub(crate) fn autoload_do_load<'ob>(
243 fundef: &Rto<Object>,
244 funname: Option<&Rto<Gc<Symbol>>>,
245 macro_only: Option<&Rto<Object>>,
246 env: &mut Rt<Env>,
247 cx: &'ob mut Context,
248) -> Result<Object<'ob>> {
249 let Ok((sym::AUTOLOAD, ObjectType::Cons(body))) = fundef.bind(cx).as_cons_pair() else {
251 return Ok(fundef.bind(cx));
252 };
253 ensure!(macro_only.is_none(), "autoload-do-load macro-only is not yet implemented");
254 let mut iter = body.elements();
255 let file: Gc<&LispString> = match iter.next() {
256 Some(x) => x?.try_into()?,
257 None => bail!("Malformed autoload"),
258 };
259 ensure!(
260 iter.fallible().all(|x| Ok(x.is_nil()))?,
261 "autoload arguments are not yet implemented"
262 );
263 root!(file, cx);
264 crate::lread::load(file, None, None, cx, env)?;
265 match funname {
266 Some(func) => match func.untag(cx).func(cx) {
267 Some(x) => Ok(x.into()),
268 None => Err(anyhow!("autoload of {func} did not provide a definition")),
269 },
270 _ => Ok(NIL),
271 }
272}
273
274#[defun]
275fn autoload<'ob>(
276 function: Symbol<'ob>,
277 file: &str,
278 docstring: Option<Object>,
279 interactive: Option<Object>,
280 load_type: Option<Object>,
281 cx: &'ob Context,
282) -> Result<Symbol<'ob>> {
283 if function.has_func() {
284 Ok(sym::NIL)
285 } else {
286 let autoload = list![sym::AUTOLOAD, file, docstring, interactive, load_type; cx];
287 crate::data::fset(function, autoload)
288 }
289}
290
291#[defun]
292pub(crate) fn macroexpand<'ob>(
293 form: &Rto<Object>,
294 environment: Option<&Rto<Object>>,
295 cx: &'ob mut Context,
296 env: &mut Rt<Env>,
297) -> Result<Object<'ob>> {
298 let ObjectType::Cons(cons) = form.untag(cx) else { return Ok(form.bind(cx)) };
299 let ObjectType::Symbol(sym) = cons.car().untag() else { return Ok(form.bind(cx)) };
300 let func = match environment {
302 Some(env) => match assq(sym.into(), env.bind(cx).try_into()?)?.untag() {
303 ObjectType::Cons(cons) => Some(cons.cdr().try_into()?),
304 _ => get_macro_func(sym, cx),
305 },
306 _ => get_macro_func(sym, cx),
307 };
308 let Some(macro_func) = func else { return Ok(form.bind(cx)) };
309 let mut iter = cons.cdr().as_list()?.fallible();
310 let mut frame = CallFrame::new(env);
311 while let Some(arg) = iter.next()? {
312 frame.push_arg(arg);
313 }
314 root!(macro_func, cx);
315 let name = sym.name().to_owned();
316 let new_form = macro_func.call(&mut frame, Some(&name), cx)?;
317 drop(frame);
318 root!(new_form, cx); if eq(new_form.bind(cx), form.bind(cx)) {
320 Ok(form.bind(cx))
321 } else {
322 macroexpand(new_form, environment, cx, env)
324 }
325}
326
327fn get_macro_func<'ob>(name: Symbol, cx: &'ob Context) -> Option<Function<'ob>> {
328 if let Some(callable) = name.follow_indirect(cx)
329 && let Ok((sym::MACRO, cdr)) = callable.as_cons_pair()
330 {
331 return Some(cdr.tag());
332 }
333 None
334}
335
336#[defun]
337fn func_arity<'ob>(function: Function, cx: &'ob Context) -> Result<&'ob Cons> {
338 let from_args = |args: FnArgs| {
339 let min = args.required;
340 if args.rest {
341 Cons::new(min, sym::MANY, cx)
343 } else {
344 Cons::new(min, args.optional + min, cx)
345 }
346 };
347 match function.untag() {
348 FunctionType::ByteFn(func) => Ok(from_args(func.args)),
349 FunctionType::SubrFn(func) => Ok(from_args(func.args)),
350 FunctionType::Cons(func) => {
351 let arg_pos = match func.car().untag() {
352 ObjectType::Symbol(sym::CLOSURE) => 2,
353 ObjectType::Symbol(sym::LAMBDA) => 1,
354 other => bail!(TypeError::new(Type::Func, other)),
355 };
356 let Some(args) = func.elements().fallible().nth(arg_pos)? else {
357 bail!("Invalid function: {func}")
358 };
359 let (req, opt, rest) = crate::interpreter::parse_arg_list(args)?;
360 let args = FnArgs {
361 required: req.len() as u16,
362 optional: opt.len() as u16,
363 rest: rest.is_some(),
364 ..FnArgs::default()
365 };
366 Ok(from_args(args))
367 }
368 FunctionType::Symbol(sym) => {
369 let Some(func) = sym.follow_indirect(cx) else { bail!("Void Function: {sym}") };
370 func_arity(func, cx)
371 }
372 }
373}
374
375#[defun]
376#[expect(non_snake_case)]
377fn internal__define_uninitialized_variable<'ob>(
378 _symbol: Symbol<'ob>,
379 _doc: Option<Object>,
380) -> Object<'ob> {
381 NIL
383}
384
385#[defun]
386fn signal(mut error_symbol: Object, data: Object, env: &mut Rt<Env>) -> Result<bool> {
387 if error_symbol.is_nil() && data.is_nil() {
388 error_symbol = sym::ERROR.into();
389 }
390 Err(EvalError::signal(error_symbol, data, env).into())
391}
392
393#[defun]
394fn special_variable_p(symbol: Symbol) -> bool {
395 symbol.is_special()
396}
397
398#[defun]
399fn set_default_toplevel_value<'ob>(
400 symbol: Symbol,
401 value: Object,
402 env: &'ob mut Rt<Env>,
403) -> Result<Object<'ob>> {
404 env.set_var(symbol, value)?;
405 Ok(NIL)
406}
407
408#[defun]
409fn set_default<'ob>(
410 symbol: Symbol,
411 value: Object<'ob>,
412 env: &'ob mut Rt<Env>,
413) -> Result<Object<'ob>> {
414 env.set_var(symbol, value)?;
416 Ok(value)
417}
418
419impl Rto<Function<'_>> {
420 pub(crate) fn call<'ob>(
421 &self,
422 frame: &mut CallFrame<'_, '_>,
423 name: Option<&str>,
424 cx: &'ob mut Context,
425 ) -> EvalResult<'ob> {
426 debug!("calling: {self}");
427 let name = name.unwrap_or("lambda");
428 frame.finalize_arguments();
429 let arg_cnt = frame.arg_count();
430 cx.garbage_collect(false);
431 match self.untag(cx) {
432 FunctionType::ByteFn(f) => {
433 root!(f, cx);
434 crate::bytecode::call(f, arg_cnt, name, frame, cx)
435 .map_err(|e| e.add_trace(name, frame.arg_slice()))
436 }
437 FunctionType::SubrFn(f) => {
438 (*f).call(arg_cnt, frame, cx).map_err(|e| add_trace(e, name, frame.arg_slice()))
439 }
440 FunctionType::Cons(_) => {
441 crate::interpreter::call_closure(self.try_as().unwrap(), arg_cnt, name, frame, cx)
442 .map_err(|e| e.add_trace(name, frame.arg_slice()))
443 }
444 FunctionType::Symbol(sym) => {
445 let Some(func) = sym.follow_indirect(cx) else { bail_err!("Void Function: {sym}") };
446 if let Ok((sym::AUTOLOAD, _)) = func.as_cons_pair() {
447 root!(sym, cx);
449 crate::eval::autoload_do_load(self.cast(), None, None, frame, cx)
450 .map_err(|e| add_trace(e, name, frame.arg_slice()))?;
451 let Some(func) = sym.bind(cx).follow_indirect(cx) else {
452 bail_err!("autoload for {sym} failed to define function")
453 };
454 root!(func, cx);
455 let name = sym.bind(cx).name().to_owned();
456 func.call(frame, Some(&name), cx)
457 } else {
458 root!(func, cx);
459 let name = sym.name().to_owned();
460 func.call(frame, Some(&name), cx)
461 }
462 }
463 }
464 }
465}
466
467pub(crate) fn add_trace(err: anyhow::Error, name: &str, args: &[Rto<Object>]) -> EvalError {
468 match err.downcast::<EvalError>() {
469 Ok(err) => err.add_trace(name, args),
470 Err(e) => EvalError::with_trace(e, name, args),
471 }
472}
473
474defsym!(FUNCTION);
475defsym!(QUOTE);
476defsym!(MACRO);
477defsym!(UNQUOTE, ",");
478defsym!(SPLICE, ",@");
479defsym!(BACKQUOTE, "`");
480defsym!(AND_OPTIONAL, "&optional");
481defsym!(AND_REST, "&rest");
482defsym!(LAMBDA);
483defsym!(CLOSURE);
484defsym!(CONDITION_CASE);
485defsym!(UNWIND_PROTECT);
486defsym!(SAVE_EXCURSION);
487defsym!(SAVE_CURRENT_BUFFER);
488defsym!(WHILE);
489defsym!(INLINE);
490defsym!(PROGN);
491defsym!(PROG1);
492defsym!(PROG2);
493defsym!(SETQ);
494defsym!(DEFCONST);
495defsym!(COND);
496defsym!(LET);
497defsym!(LET_STAR, "let*");
498defsym!(IF);
499defsym!(AND);
500defsym!(OR);
501defsym!(INTERACTIVE);
502defsym!(CATCH);
503defsym!(THROW);
504defsym!(ERROR);
505defsym!(DEBUG);
506defsym!(VOID_VARIABLE);
507
508defvar!(DEBUG_ON_ERROR, false);
509defvar!(INTERNAL_MAKE_INTERPRETED_CLOSURE_FUNCTION);