narju/error/mod.rs
1//! The crate-wide error type.
2
3use thiserror::Error;
4
5/// Any error the evaluator or its entry points can produce.
6///
7/// Errors abort the current top-level evaluation and unwind the CK
8/// machine's continuation stack. Two forms survive in-language: a
9/// [`NarjuError::Throw`] raised inside a `catch` arrives at the catch
10/// site with its payload intact, and any *other* error inside a `catch`
11/// arrives stringified via `Display`. The `#[error]` strings here are
12/// therefore user-visible surface, both at the REPL and through
13/// `catch`.
14#[derive(Debug, Error)]
15pub enum NarjuError {
16 /// Malformed source, from the reader or from lowering (which
17 /// reports unbound names at parse time with their surface names).
18 #[error("parse error: {0}")]
19 Parse(String),
20
21 /// A `Var` index past the end of the runtime environment. Lowering
22 /// makes this unreachable from surface source; it can only arise
23 /// from hand-built or mis-translated `Exp` trees, so the message
24 /// reports raw indices — there is no name to report.
25 #[error("unbound variable at level {level} (env len {env_len})")]
26 UnboundVar {
27 /// The out-of-range `Var` index.
28 level: usize,
29 /// Environment length at the point of lookup.
30 env_len: usize,
31 },
32
33 /// A primitive applied to a value of the wrong shape.
34 #[error("type error in {op}: expected {expected}, got {actual}")]
35 TypeError {
36 /// Surface name of the offending operation (e.g. `"car"`).
37 op: &'static str,
38 /// What the operation accepts.
39 expected: &'static str,
40 /// Compact description of what it got — `Val::short_desc`
41 /// output, which never dumps a full code tree.
42 actual: String,
43 },
44
45 /// A staging-discipline violation: lifting the unliftable,
46 /// running at the wrong level, a malformed `trans`/`evalms`
47 /// argument, and the like.
48 #[error("staging error: {0}")]
49 Stage(String),
50
51 /// A failure from the underlying I/O implementation
52 /// (`read`, `read-file`, `print`).
53 #[error("i/o error: {0}")]
54 Io(#[from] std::io::Error),
55
56 /// `(throw v)`: a user-raised error carrying a first-class `Val`
57 /// payload. `unwind_to_catch` unpacks the payload structurally into
58 /// `(error <payload> ())` instead of stringifying it, so structured
59 /// signals like `(unbound . name)` survive to the catch site.
60 #[error("uncaught throw: {}", crate::eval::display(.0))]
61 Throw(crate::core::Val),
62}