use std::fmt; use crate::r#type::{ Type, TypeError, FunDefError, PatFail, Type::*, TypeError::*, FunDefError::*, PatFail::* }; 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"), LetType => write!(f, "{}", "Let"), NilType => write!(f, "Nil"), TypeLit => write!(f, "Type"), VecOf(ty) => write!(f, "({} ...)", *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!( /// 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, ty) => write!(f, "unbound generic type '{name}' in '{ty}'"), 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 ) }, InvalidPattern(ty) => write!(f, "invalid pattern: {ty}"), ArgumentsDontMatchGeneric { argtype, generictype } => { write!( f, "incompatible argument type '{}' and generic operator type '{}'", argtype, generictype ) }, LetAsOperator(letexp) => { write!( f, "let used as operator instead of generating an operator: maybe try '({} ...)' instead", letexp ) }, DifferentTypeCaseArms(ty1, ty2) => write!(f, "arms of match have different types, '{ty1}' and '{ty2}'"), FunAsAtom => write!(f, "'fn' used as atom doesn't make sense"), CaseAsAtom => write!(f, "'case' used as atom doesn't make sense"), RestAsAtom => write!(f, "'..[name]' used as atom doesn't make sense"), InvalidFunDef(exp, err) => write!(f, "invalid function definition '{exp}': {err}"), NoWildcardInCase(exp) => write!(f, "no wildcard in cases: '{exp}'"), OtherError => write!(f, "uncategorized error"), } } } impl fmt::Display for PatFail { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { RestNotAtEnd(exp) => write!(f, "rest pattern should be at end in '{exp}'"), NoArm(exp) => write!(f, "'{exp}' should consist of a pattern and a respective arm"), RepeatedVariable(name, exp_in) => write!(f, "repeated pattern variable '{name}' in '{exp_in}'"), TypeMismatch { pattern, expected, found } => write!( f, "type mismatch in '{}' — expected type '{}', found '{}'", pattern, expected, found, ), } } } impl fmt::Display for FunDefError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { NoFunToken => write!( f, "no '{}'-token at start of definition", crate::sexp::SLeaf::Fun ), NoArgumentList => write!( f, "no list of argument names" ), NoTypeList => write!( f, "no list of argument types" ), NoReturnType => write!( f, "no return type supplied" ), NoFunctionBody => write!( f, "function has no body" ), InvalidArgumentList => write!(f, "invalid argument list"), InvalidTypeList => write!(f, "invalid argument type list"), InvalidReturnType => write!(f, "invalid return type"), } } }