open_pql/error/
mod.rs

1use std::num::ParseIntError;
2
3use derive_more::derive::{Display, From};
4
5use crate::{Loc, LocInfo, PQLType, pql_parser, range_parser};
6
7mod parse_error;
8
9pub use parse_error::ParseError;
10
11type SelectorName = String;
12type OpSymbol = String;
13
14type NumGiven = usize;
15type NumExpected = NumGiven;
16
17type GotType = PQLType;
18type ExpectedType = GotType;
19
20#[derive(Debug, Clone, PartialEq, Eq, From, Display)]
21pub enum PQLError {
22    TooManyVariables,
23    #[display("UnknownIdent")]
24    UnknownIdent(LocInfo),
25    #[display("UnrecognizedGame")]
26    UnrecognizedGame(LocInfo),
27    #[display("UnrecognizedFunction")]
28    UnrecognizedFunction(LocInfo),
29    #[display("WrongNumberOfArguments. expected {_2} got {_1}")]
30    WrongNumberOfArguments(LocInfo, NumGiven, NumExpected),
31    #[display("ParseIntError {_1}")]
32    ParseIntError(LocInfo, ParseIntError),
33    #[from]
34    #[display("TypeError {_1}")]
35    TypeError(LocInfo, TypeError),
36    #[from]
37    #[display("RuntimeError {_0}")]
38    RuntimeError(RuntimeError),
39    #[from]
40    #[display("InvalidPQL {_0:?}")]
41    InvalidPQL(pql_parser::Error),
42    #[from]
43    #[display("InvalidRange")]
44    InvalidRange(Loc, range_parser::Error),
45    #[from]
46    Internal(InternalError),
47}
48
49// Error for
50// * calling evaluate::to_rank as API
51// * Vm at runtime
52#[derive(Debug, Clone, PartialEq, Eq, Display)]
53pub enum RuntimeError {
54    ToRankParseFailed(String),
55    ToCardParseFailed(String),
56    RateHiHandExpectedFiveCards(String),
57    RateHiHandParseFailed(String),
58    AddFailed,
59    CmpFailed,
60    MinMaxNotDefined,
61    DefaultNotDefined,
62}
63
64// Vm Compile-time Error
65#[derive(Debug, Clone, PartialEq, Eq, Display)]
66pub enum TypeError {
67    #[display("BinOpError {_1} {_0} {_2}")]
68    BinOpError(OpSymbol, PQLType, PQLType),
69    #[display("InvalidIdent")]
70    InvalidIdent(PQLType),
71    #[display("SelectorDoesNotSupport {_0} {_1}")]
72    SelectorDoesNotSupport(SelectorName, GotType),
73    #[display("expected {_0}")]
74    TypeMismatch(ExpectedType),
75}
76
77// Error that should not happen
78#[derive(Debug, Clone, PartialEq, Eq, Display)]
79pub enum InternalError {
80    BrokenStack,
81    CannotAddValue,
82    ThreadJoinFailed,
83    InvalidVmValue,
84}
85
86impl From<&PQLError> for Option<LocInfo> {
87    fn from(e: &PQLError) -> Self {
88        match e {
89            PQLError::Internal(_)
90            | PQLError::TooManyVariables
91            | PQLError::RuntimeError(_) => None,
92
93            PQLError::UnknownIdent(loc)
94            | PQLError::ParseIntError(loc, _)
95            | PQLError::UnrecognizedGame(loc)
96            | PQLError::WrongNumberOfArguments(loc, _, _)
97            | PQLError::UnrecognizedFunction(loc)
98            | PQLError::TypeError(loc, _) => Some(*loc),
99
100            PQLError::InvalidPQL(e) => Some(e.into()),
101
102            PQLError::InvalidRange(offset, e) => {
103                let (a, b): LocInfo = e.into();
104
105                Some((a + offset + 1, b + offset + 1))
106            }
107        }
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn test_loc() {
117        let opt: Option<LocInfo> =
118            (&PQLError::Internal(InternalError::BrokenStack)).into();
119        assert!(opt.is_none());
120
121        let opt: Option<LocInfo> = (&PQLError::TooManyVariables).into();
122        assert!(opt.is_none());
123    }
124}