diff options
Diffstat (limited to 'src/type/display.rs')
-rw-r--r-- | src/type/display.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/type/display.rs b/src/type/display.rs new file mode 100644 index 0000000..781d614 --- /dev/null +++ b/src/type/display.rs @@ -0,0 +1,85 @@ + +use std::fmt; +use crate::r#type::{Type, TypeError, Type::*, TypeError::*}; + + +impl fmt::Display for Type { + /// Formats the type for display to the programmer + /// using this programming language. + /// + /// Examples: + /// ```rust + /// use melisp::r#type::{Type::*, util::*}; + /// assert_eq!(Integer.to_string(), "Int".to_string()); + /// assert_eq!(arr(Integer, Integer).to_string(), "Int -> Int".to_string()); + /// assert_eq!(List(vec![Integer, Integer, Integer]).to_string(), "(Int Int Int)".to_string()); + /// ``` + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Integer => write!(f, "{}", "Int"), + Arrow(a, b) => write!(f, "{} -> {}", a, b), + List(types) => write!( + f, + "({})", + types.into_iter() + .map(|t| t.to_string()) + .collect::<Vec<String>>() + .join(" ") + ), + UndefinedType => write!(f, "?"), + } + } +} + + +impl fmt::Display for TypeError { + /// Formats this type error for display to humans. + /// + /// Examples: + /// ```rust + /// use melisp::r#type::{TypeError::*, Type::*, util::*}; + /// use melisp::sexp::{SExp, SExp::*, SLeaf::*, util::*}; + /// + /// assert_eq!( + /// UndefinedVariable(String::from("x")).to_string(), + /// "undefined variable: 'x'".to_string() + /// ); + /// assert_eq!( + /// InvalidOperator { + /// operator: Atom(Int(1)), + /// expected: arr(UndefinedType, UndefinedType), + /// found: Integer + /// }.to_string(), + /// "invalid operator: '1'\nexpected: '? -> ?'\nfound: 'Int'".to_string() + /// ); + /// assert_eq!( + /// InvalidArgList { + /// arglist: scons(1, scons(2, scons(3, Nil))), + /// expected: List(vec![Integer, Integer]), + /// found: List(vec![Integer, Integer, Integer]), + /// }.to_string(), + /// "invalid argument list: '(1 2 3)'\nexpected: '(Int Int)'\nfound: '(Int Int Int)'".to_string() + /// ); + /// ``` + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + UndefinedVariable(name) => write!(f, "undefined variable: '{}'", name), + InvalidOperator { operator, expected, found } => { + write!( + f, + "invalid operator: '{}'\nexpected: '{}'\nfound: '{}'", + operator, expected, found + ) + }, + InvalidArgList { arglist, expected, found } => { + write!( + f, + "invalid argument list: '{}'\nexpected: '{}'\nfound: '{}'", + arglist, expected, found + ) + }, + OtherError => write!(f, "uncategorized error"), + } + } +} + |