1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
use std::{fmt, error::Error};

pub type ParsingError = lalrpop_util::ParseError<usize, String, String>;
pub type ParsingResult<T> = Result<T, ParsingError>;

#[derive(Clone, Debug)]
pub enum AscesisError {
    ParsingError(ParsingError),
    ParsingRecovery,
    AxiomUnknown(String),
    RootUnset,
    RootMissing(String),
    RootRedefined(String),
    RootBlockMismatch,
    RootBlockMissing,
    RootUnresolvable,
    ScriptUncompiled,
    UnexpectedDependency(String),
    InvalidAST,
    FatLeak,
    MissingPropSelector,
    InvalidPropSelector,
    InvalidSATProp(String, String),
    SizeLiteralOverflow,
    ExpectedSizeLiteral,
    ExpectedNameLiteral,
}

impl Error for AscesisError {
    fn description(&self) -> &str {
        use AscesisError::*;

        match self {
            ParsingError(_) => "ascesis parsing error",
            ParsingRecovery => "recovering from ascesis parsing error",
            AxiomUnknown(_) => "unknown axiom",
            RootUnset => "unset root structure",
            RootMissing(_) => "missing root structure",
            RootRedefined(_) => "redefined root structure",
            RootBlockMismatch => "root block mismatch",
            RootBlockMissing => "root block missing",
            RootUnresolvable => "root contains instances without known definitions",
            ScriptUncompiled => "script uncompiled",
            UnexpectedDependency(_) => "unexpected uncompiled dependency",
            InvalidAST => "invalid AST",
            FatLeak => "fat arrow rule leaked through FIT transformation",
            MissingPropSelector => "property block without selector",
            InvalidPropSelector => "invalid block selector",
            InvalidSATProp(..) => "invalid SAT property",
            SizeLiteralOverflow => "size literal overflow",
            ExpectedSizeLiteral => "bad literal, not a size",
            ExpectedNameLiteral => "bad literal, not a name",
        }
    }
}

impl fmt::Display for AscesisError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use AscesisError::*;

        match self {
            ParsingError(err) => {
                let message = format!("{}", err);
                let mut lines = message.lines();

                if let Some(line) = lines.next() {
                    writeln!(f, "{}", line)?;
                }

                for line in lines {
                    writeln!(f, "\t{}", line)?;
                }

                Ok(())
            }
            ParsingRecovery => write!(f, "Recovering from ascesis parsing error"),
            AxiomUnknown(symbol) => write!(f, "Unknown axiom '{}'", symbol),
            RootUnset => write!(f, "Undeclared root structure"),
            RootMissing(name) => write!(f, "Missing root structure '{}'", name),
            RootRedefined(name) => write!(f, "Redefined root structure '{}'", name),
            RootBlockMismatch => write!(f, "Root block mismatch"),
            RootBlockMissing => write!(f, "Root block missing"),
            RootUnresolvable => write!(f, "Root contains instances without known definitions"),
            ScriptUncompiled => write!(f, "Script uncompiled"),
            UnexpectedDependency(name) => write!(f, "Unexpected uncompiled dependency '{}'", name),
            InvalidAST => write!(f, "Invalid AST"),
            FatLeak => write!(f, "Fat arrow rule leaked through FIT transformation"),
            MissingPropSelector => write!(f, "Property block without selector"),
            InvalidPropSelector => write!(f, "Invalid block selector"),
            InvalidSATProp(prop, value) => write!(f, "Invalid SAT {} '{}'", prop, value),
            SizeLiteralOverflow => write!(f, "Size literal overflow"),
            ExpectedSizeLiteral => write!(f, "Bad literal, not a size"),
            ExpectedNameLiteral => write!(f, "Bad literal, not a name"),
        }
    }
}

impl<L: Into<usize>, T: fmt::Display, E: Into<String>> From<lalrpop_util::ParseError<L, T, E>>
    for AscesisError
{
    fn from(err: lalrpop_util::ParseError<L, T, E>) -> Self {
        let err =
            err.map_location(|l| l.into()).map_token(|t| t.to_string()).map_error(|e| e.into());

        AscesisError::ParsingError(err)
    }
}