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 myslip::r#type::{Type::*, util::*}; /// assert_eq!(Integer.to_string(), "Int".to_string()); /// assert_eq!(Boolean.to_string(), "Bool".to_string()); /// assert_eq!(arr(Integer, Boolean).to_string(), "(Int -> Bool)".to_string()); /// assert_eq!(List(vec![Integer, Boolean, Integer]).to_string(), "(Int Bool Int)".to_string()); /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Integer => write!(f, "{}", "Int"), Boolean => write!(f, "{}", "Bool"), QuoteTy => write!(f, "{}", "Quote"), VecType => write!(f, "{}", "Vector"), VecOf(ty) => write!(f, "({} ... {})", *ty, *ty), Arrow(a, b) => write!(f, "({} -> {})", a, b), List(types) => write!( f, "({})", types.into_iter() .map(|t| t.to_string()) .collect::>() .join(" ") ), VarType(name) => write!(f, "{}", name), } } } impl fmt::Display for TypeError { /// Formats this type error for display to humans. /// /// Examples: /// ```rust /// use myslip::r#type::{TypeError::*, Type::*, util::*}; /// use myslip::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(VarType("?".to_string()), VarType("?".to_string())), /// 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() /// ); /// assert_eq!( /// UnboundGeneric(String::from("?")).to_string(), /// "unbound generic type: '?'".to_string() /// ); /// assert_eq!( /// ArgumentsDontMatchGeneric { /// argtype: Integer, /// generictype: arr(VarType("T".to_string()), Integer) /// }.to_string(), /// "incompatible argument type 'Int' and generic operator type '(T -> Int)'".to_string() /// ); /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { UndefinedVariable(name) => write!(f, "undefined variable: '{}'", name), UnboundGeneric(name) => write!(f, "unbound generic type: '{}'", 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 ) }, ArgumentsDontMatchGeneric { argtype, generictype } => { write!( f, "incompatible argument type '{}' and generic operator type '{}'", argtype, generictype ) }, OtherError => write!(f, "uncategorized error"), } } }