aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-06 17:05:55 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-06 17:05:55 +0300
commit3e1bf7f9946efe70d452c71494ac77ed39110804 (patch)
treef7682f538db9d8b77890e8c0e9c54eb2968d4388 /src
parent313c044b4a878a425aaca6554576f5154ace8ff9 (diff)
downloadmyslip-3e1bf7f9946efe70d452c71494ac77ed39110804.tar.gz
myslip-3e1bf7f9946efe70d452c71494ac77ed39110804.zip
Added print, raised level on which UnboundGeneric error is returned
Diffstat (limited to 'src')
-rw-r--r--src/parse/parsetree.rs1
-rw-r--r--src/sexp/display.rs1
-rw-r--r--src/sexp/mod.rs4
-rw-r--r--src/sexp/step.rs15
-rw-r--r--src/sexp/util.rs7
-rw-r--r--src/type/check.rs24
-rw-r--r--src/type/display.rs8
-rw-r--r--src/type/mod.rs2
8 files changed, 43 insertions, 19 deletions
diff --git a/src/parse/parsetree.rs b/src/parse/parsetree.rs
index 75758dc..8e2b856 100644
--- a/src/parse/parsetree.rs
+++ b/src/parse/parsetree.rs
@@ -113,6 +113,7 @@ fn tokens_to_ast_inner(
Some(Sym(s)) if s == "false" => Ok(Atom(False)),
Some(Sym(s)) if s == "quote" => Ok(Atom(Quote)),
Some(Sym(s)) if s == "vector" => Ok(Atom(Vector)),
+ Some(Sym(s)) if s == "print" => Ok(Atom(Print)),
Some(Sym(s)) if s == "let" => Ok(Atom(Let)),
Some(Sym(s)) => Ok(Atom(Var(s))),
Some(ParClose) => break,
diff --git a/src/sexp/display.rs b/src/sexp/display.rs
index c3db144..dc5d6cb 100644
--- a/src/sexp/display.rs
+++ b/src/sexp/display.rs
@@ -27,6 +27,7 @@ impl fmt::Display for SLeaf {
Var(s) => s.to_string(),
Quote => "quote".to_string(),
Vector => "vector".to_string(),
+ Print => "print".to_string(),
Let => "let".to_string(),
Nil => "()".to_string(),
})
diff --git a/src/sexp/mod.rs b/src/sexp/mod.rs
index 7aa517b..c674ee9 100644
--- a/src/sexp/mod.rs
+++ b/src/sexp/mod.rs
@@ -33,6 +33,8 @@ pub enum SLeaf {
Let,
+ Print,
+
Int(i32),
True,
False,
@@ -69,7 +71,7 @@ impl SExp {
SCons(a, b) =>
SCons(a.clone(), b.clone()).check_let().is_some() ||
(
- (**a == Atom(Quote) || **a == Atom(Vector))
+ (**a == Atom(Quote) || **a == Atom(Vector) || **a == Atom(Print))
&& b.consists_of_values()
),
Atom(Var(_)) => false,
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index 816582c..94f6381 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -309,6 +309,21 @@ impl SExp {
None => panic!("unreachable as per match guard arm"),
},
+ // prints
+ SCons(op, l) if op.clone().is_print() => match *op {
+ SCons(_, b) => {
+ println!("{}", match *b {
+ SCons(a, b) if *b == Atom(Nil) => *a,
+ t => t,
+ });
+ Ok(match *l {
+ SCons(a, b) if *b == Atom(Nil) => *a,
+ t => t
+ })
+ },
+ Atom(_) => panic!("unreachable as per match arm guard"),
+ },
+
// op value and a1 .. an values, and b0, b1 .. bn not values
// ---------------------------------------------------------
diff --git a/src/sexp/util.rs b/src/sexp/util.rs
index a28aaad..507455f 100644
--- a/src/sexp/util.rs
+++ b/src/sexp/util.rs
@@ -86,4 +86,11 @@ impl SExp {
_ => None
}
}
+
+ pub fn is_print(&self) -> bool {
+ match self {
+ SCons(op, _) if **op == Atom(Print) => true,
+ _ => false
+ }
+ }
}
diff --git a/src/type/check.rs b/src/type/check.rs
index e536ce7..91ca422 100644
--- a/src/type/check.rs
+++ b/src/type/check.rs
@@ -163,7 +163,11 @@ impl SExp {
/// };
/// ```
pub fn type_check(&self) -> Result<Type, TypeError> {
- self.infer_type(HashMap::new())
+ let ty = self.infer_type(HashMap::new())?;
+ match ty.is_concrete() {
+ Ok(()) => Ok(ty),
+ Err(s) => Err(UnboundGeneric(ty, s)),
+ }
}
@@ -194,6 +198,7 @@ impl SExp {
List(vec![VecType, vecof(vt("T"))])
)),
Atom(Let) => Ok(LetType),
+ Atom(Print) => Ok(arr(vt("_"), arr(vt("T"), vt("T")))),
SCons(op, l) => {
@@ -298,10 +303,11 @@ impl Type {
restype = restype.subst(&name, &ty);
}
- match restype.is_concrete() {
- Ok(()) => Ok(arr(argtype.clone(), restype)),
- Err(unbound) => Err(UnboundGeneric(unbound)),
- }
+ //match restype.is_concrete() {
+ // Ok(()) => Ok(arr(argtype.clone(), restype)),
+ // Err(unbound) => Err(UnboundGeneric(unbound)),
+ //}
+ Ok(arr(argtype.clone(), restype))
},
_ => Err(OtherError)
}
@@ -379,14 +385,6 @@ mod tests {
use super::{*, TypeError};
#[test]
- fn test_failing_infer_generics() {
- assert_eq!(
- arr(Integer, VarType("X".to_string())).infer_generics(&Integer),
- Err(TypeError::UnboundGeneric(String::from("X")))
- );
- }
-
- #[test]
fn test_infer_generics() {
// Simple identity function, really all we
diff --git a/src/type/display.rs b/src/type/display.rs
index 4a9b54a..f859dc3 100644
--- a/src/type/display.rs
+++ b/src/type/display.rs
@@ -67,8 +67,8 @@ impl fmt::Display for TypeError {
/// "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()
+ /// UnboundGeneric(arr(Integer, vt("?")), String::from("?")).to_string(),
+ /// "unbound generic type in '(Int -> ?)': '?'".to_string()
/// );
/// assert_eq!(
/// ArgumentsDontMatchGeneric {
@@ -80,8 +80,8 @@ impl fmt::Display for TypeError {
/// ```
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),
+ UndefinedVariable(name) => write!(f, "undefined variable: '{}'", name),
+ UnboundGeneric(ty, name) => write!(f, "unbound generic type in '{}': '{}'", ty, name),
InvalidOperator { operator, expected, found } => {
write!(
f,
diff --git a/src/type/mod.rs b/src/type/mod.rs
index afb5a0b..6f5c6dc 100644
--- a/src/type/mod.rs
+++ b/src/type/mod.rs
@@ -40,7 +40,7 @@ pub enum TypeError {
UndefinedVariable(String),
- UnboundGeneric(String),
+ UnboundGeneric(Type, String),
InvalidOperator {
operator: SExp,