use std::fmt;
use error::{ Location, Error };
#[derive(Clone, Debug)]
pub enum TraceEntry {
SourceFile { target: String },
Operator { target: String, extension: String },
Position { from: Location },
}
#[derive(Debug, Clone)]
pub enum CastTarget {
Int,
Float,
Number,
}
#[derive(Clone, Debug)]
pub enum CastError {
FloatIsInfinite(f64),
FloatNotANumber(f64),
FloatRange(f64),
Null,
Array,
Hash,
Object,
Function,
StringEmpty,
StringNotNumerical(String),
}
impl fmt::Display for CastError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CastError::FloatIsInfinite(v) => write!(f, "Infinite float {:?}", v),
CastError::FloatNotANumber(v) => write!(f, "Nonnumerical float {:?}", v),
CastError::FloatRange(v) => write!(f, "Out-of-range float {:?}", v),
CastError::Null => "Null".fmt(f),
CastError::Array => "Array".fmt(f),
CastError::Hash => "Associative array".fmt(f),
CastError::Object => "Object".fmt(f),
CastError::Function => "Function".fmt(f),
CastError::StringEmpty => "Empty string".fmt(f),
CastError::StringNotNumerical(ref v) => write!(f, "Nonnumerical string {:?}", v),
}
}
}
#[derive(Clone, Debug)]
pub enum RuntimeError {
InvalidArgumentCount { defined: usize, given: usize },
ObjectHasNoProperty(String),
ObjectHasNoMethod(String),
ObjectPropertyIsNotMethod(String),
ObjectMethodIsNotProperty(String),
ObjectMethodArgumentMismatch { name: String, defined: u16, given: u16 },
ImpossibleCast { target: CastTarget, reason: CastError },
}
impl RuntimeError {
pub fn at(self, stack_trace: Vec<TraceEntry>) -> TracedRuntimeError {
TracedRuntimeError {
message: self,
stack_trace: stack_trace
}
}
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
RuntimeError::InvalidArgumentCount { ref defined, ref given } => {
write!(f, "Target requires {} arguments, called with {}", defined, given)
},
RuntimeError::ObjectHasNoProperty(ref name) => {
write!(f, "Object has no property {:?}", name)
},
RuntimeError::ObjectHasNoMethod(ref name) => {
write!(f, "Object has no method {:?}", name)
},
RuntimeError::ObjectPropertyIsNotMethod(ref name) => {
write!(f, "Property is not a method {:?}", name)
},
RuntimeError::ObjectMethodIsNotProperty(ref name) => {
write!(f, "Method is not a property {:?}", name)
},
RuntimeError::ObjectMethodArgumentMismatch { ref name, ref defined, ref given } => {
write!(f, "Method {:?} requires {} arguments, called with {}", name, defined, given)
},
RuntimeError::ImpossibleCast { ref target, ref reason } => {
write!(f, "{} is not {}", reason, match *target {
CastTarget::Float => "a float",
CastTarget::Int => "an integer",
CastTarget::Number => "a number",
})
}
}
}
}
#[derive(Clone, Debug)]
pub struct TracedRuntimeError {
pub message: RuntimeError,
pub stack_trace: Vec<TraceEntry>,
}
impl TracedRuntimeError {
pub fn new(message: RuntimeError) -> TracedRuntimeError {
TracedRuntimeError {
message: message,
stack_trace: Vec::new(),
}
}
}
impl fmt::Display for TracedRuntimeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.message)
}
}
impl From<TracedRuntimeError> for Error {
fn from(inner: TracedRuntimeError) -> Error {
Error::Runtime(inner)
}
}