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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use std::error;
use std::fmt;

/// Represents a general error.
#[derive(Debug, Clone)]
pub enum Error {
    ParseError(ParseError),
    TranspileError(TranspileError),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::ParseError(e) => write!(f, "{}", e),
            Error::TranspileError(e) => write!(f, "{}", e),
        }
    }
}

impl error::Error for Error {}

impl From<ParseError> for Error {
    fn from(error: ParseError) -> Self {
        Error::ParseError(error)
    }
}

impl From<TranspileError> for Error {
    fn from(error: TranspileError) -> Self {
        Error::TranspileError(error)
    }
}

/// Represents an error during parsing.
#[derive(Debug, Clone)]
pub enum ParseError {
    BadSyntax(String),
    BadYololNumber(String),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ParseError::BadSyntax(s) => write!(f, "syntax error: {}", s),
            ParseError::BadYololNumber(s) => write!(f, "failed to parse number: {}", s),
        }
    }
}

/// Represents an error during transpilation.
#[derive(Debug, Clone)]
pub enum TranspileError {
    // Import errors
    ImportExisting(String),
    ImportKeyword(String),
    ImportTwice(String),

    // Define errors
    DefineKeyword(String),
    RedefineFunction(String),

    // Assign errors
    AssignSameLowercase(String),
    AssignToKeyword(String),
    ReassignVariable(String),

    // Export errors
    ExportTwice(String),
    ExportUndefined(String),

    // Access errors
    GetUndefinedFunction(String),
    GetUndefinedLocal(String),
    GetUndefinedVariable(String),

    // TODO: separate error type?
    DuplicateParams,
    RecursiveCall,
    WrongNumberOfArgs(String),

    // Type errors
    // TODO: separate error type?
    MismatchedArrays,
    NestedArrays,
}

impl fmt::Display for TranspileError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TranspileError::ImportExisting(variable) => {
                write!(f, "cannot import existing variable: {}", variable)
            }
            TranspileError::ImportKeyword(keyword) => {
                write!(f, "cannot import reserved keyword: {}", keyword)
            }
            TranspileError::ImportTwice(variable) => write!(f, "duplicate import: {}", variable),
            TranspileError::DefineKeyword(keyword) => {
                write!(f, "cannot define reserved keyword: {}", keyword)
            }
            TranspileError::RedefineFunction(function) => {
                write!(f, "cannot redefine function: {}", function)
            }
            TranspileError::AssignSameLowercase(variable) => write!(
                f,
                "multiple variable must not have the same lowercase representation: {}",
                variable
            ),
            TranspileError::AssignToKeyword(keyword) => {
                write!(f, "cannot assign to keyword: {}", keyword)
            }
            TranspileError::ReassignVariable(variable) => {
                write!(f, "cannot reassign variable: {}", variable)
            }
            TranspileError::ExportTwice(variable) => write!(f, "duplicate export: {}", variable),
            TranspileError::ExportUndefined(variable) => {
                write!(f, "cannot export undefined variable: {}", variable)
            }
            TranspileError::GetUndefinedFunction(function) => {
                write!(f, "undefined function: {}", function)
            }
            TranspileError::GetUndefinedLocal(local) => {
                write!(f, "undefined local variable: {}", local)
            }
            TranspileError::GetUndefinedVariable(variable) => {
                write!(f, "undefined variable: {}", variable)
            }
            TranspileError::DuplicateParams => write!(f, "duplicate function parameters"),
            TranspileError::RecursiveCall => write!(f, "cannot define function recursively"),
            TranspileError::WrongNumberOfArgs(function) => {
                write!(f, "wrong number of args for function: {}", function)
            }
            TranspileError::MismatchedArrays => write!(f, "cannot operate on mismatched arrays"),
            TranspileError::NestedArrays => write!(f, "cannot create nested arrays"),
        }
    }
}