1use crate::val::{Val, ValT};
3use alloc::string::{String, ToString};
4use core::fmt;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
10#[non_exhaustive]
11pub enum Error<V = Val> {
12 Val(V),
14
15 Type(V, Type),
17 MathOp(V, jaq_syn::MathOp, V),
19 Index(V, V),
21
22 IndexOutOfBounds(isize),
24 PathExp,
26
27 TailCall(crate::filter::TailCall<V>),
32}
33
34#[derive(Clone, Debug, PartialEq, Eq)]
36#[non_exhaustive]
37pub enum Type {
38 Int,
40 Float,
42 Num,
44 Str,
46 Arr,
48 Iter,
50 Range,
52}
53
54impl<V: ValT> Error<V> {
55 pub fn as_val(self) -> V {
57 match self {
58 Self::Val(ev) => ev,
59 _ => V::from(self.to_string()),
60 }
61 }
62}
63
64impl<V: From<String>> Error<V> {
65 pub fn str(s: impl ToString) -> Self {
67 Self::Val(V::from(s.to_string()))
68 }
69}
70
71impl<V: ValT> fmt::Display for Error<V> {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 match self {
74 Self::Val(v) => {
75 if let Some(s) = v.as_str() {
76 write!(f, "{s}")
77 } else {
78 write!(f, "{v}")
79 }
80 }
81 Self::Type(v, ty) => write!(f, "cannot use {v} as {ty}"),
82 Self::MathOp(l, op, r) => write!(f, "cannot calculate {l} {op} {r}"),
83 Self::Index(v, i) => write!(f, "cannot index {v} with {i}"),
84 Self::IndexOutOfBounds(i) => write!(f, "index {i} is out of bounds"),
85 Self::PathExp => write!(f, "invalid path expression"),
86 Self::TailCall(_) => panic!(),
87 }
88 }
89}
90
91#[cfg(feature = "std")]
92impl std::error::Error for Error {}
93
94impl fmt::Display for Type {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 match self {
97 Self::Int => "integer".fmt(f),
98 Self::Float => "floating-point number".fmt(f),
99 Self::Num => "number".fmt(f),
100 Self::Str => "string".fmt(f),
101 Self::Arr => "array".fmt(f),
102 Self::Iter => "iterable (array or object)".fmt(f),
103 Self::Range => "rangeable (array or string)".fmt(f),
104 }
105 }
106}