From fdae943090463526423f5e43e72cd2f0e8147a1b Mon Sep 17 00:00:00 2001 From: Joel Kronqvist Date: Mon, 4 Aug 2025 23:50:46 +0300 Subject: Added repl and some documentation. Improved error messages. Removed dead code. * Removed same_variant in parse::parsetree * Added SExp::multistep (for use of the repl) Improved error messages: * Added parenthesis around types * Changed how errors propagate inferring generics: added the error variant ArgumentsDontMatchGeneric, implemented the displaying of it, added tests for it. * Had to change some tests to match for the new changes --- src/type/check.rs | 17 ++++++++++------- src/type/display.rs | 20 +++++++++++++++++--- src/type/mod.rs | 5 +++++ 3 files changed, 32 insertions(+), 10 deletions(-) (limited to 'src/type') diff --git a/src/type/check.rs b/src/type/check.rs index 647ec4d..80cc974 100644 --- a/src/type/check.rs +++ b/src/type/check.rs @@ -192,7 +192,14 @@ impl Type { match self { Arrow(from, to) => { - let generics = (*from).infer_generics_ctx(argtype, Vec::new())?; + let generics = match (*from).infer_generics_ctx(argtype, Vec::new()) { + Ok(x) => Ok(x), + Err(None) => Err(ArgumentsDontMatchGeneric { + argtype: argtype.clone(), + generictype: self.clone(), + }), + Err(Some(e)) => Err(e), + }?; let mut restype = (**to).clone(); for (name, ty) in generics { restype = restype.subst(&name, &ty); @@ -211,7 +218,7 @@ impl Type { &self, argtype: &Type, ctx: Vec<(String, Type)> - ) -> Result, TypeError> { + ) -> Result, Option> { match (self, argtype) { (a, b) if a == b => Ok(ctx), @@ -239,11 +246,7 @@ impl Type { Ok(res) }, - (_a, _b) => Err(InvalidArgList { - arglist: Atom(Var("undefined".to_string())), // TODO: hacky as heck - expected: self.clone(), - found: argtype.clone(), - }), + (_a, _b) => Err(None), } } diff --git a/src/type/display.rs b/src/type/display.rs index be51858..68d7fec 100644 --- a/src/type/display.rs +++ b/src/type/display.rs @@ -11,13 +11,13 @@ impl fmt::Display for Type { /// ```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!(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), + Arrow(a, b) => write!(f, "({} -> {})", a, b), List(types) => write!( f, "({})", @@ -50,7 +50,7 @@ impl fmt::Display for TypeError { /// expected: arr(VarType("?".to_string()), VarType("?".to_string())), /// found: Integer /// }.to_string(), - /// "invalid operator: '1'\nexpected: '? -> ?'\nfound: 'Int'".to_string() + /// "invalid operator: '1'\nexpected: '(? -> ?)'\nfound: 'Int'".to_string() /// ); /// assert_eq!( /// InvalidArgList { @@ -64,6 +64,13 @@ impl fmt::Display for TypeError { /// 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 { @@ -83,6 +90,13 @@ impl fmt::Display for TypeError { arglist, expected, found ) }, + ArgumentsDontMatchGeneric { argtype, generictype } => { + write!( + f, + "incompatible argument type '{}' and generic operator type '{}'", + argtype, generictype + ) + }, OtherError => write!(f, "uncategorized error"), } } diff --git a/src/type/mod.rs b/src/type/mod.rs index aeeff93..2454f31 100644 --- a/src/type/mod.rs +++ b/src/type/mod.rs @@ -45,6 +45,11 @@ pub enum TypeError { found: Type, }, + ArgumentsDontMatchGeneric { + argtype: Type, + generictype: Type, + }, + OtherError } -- cgit v1.2.3