aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parse/parsetree.rs39
-rw-r--r--src/sexp/display.rs1
-rw-r--r--src/sexp/mod.rs2
-rw-r--r--src/sexp/step.rs17
-rw-r--r--src/type/check.rs17
-rw-r--r--src/type/display.rs1
-rw-r--r--src/type/mod.rs6
-rw-r--r--src/type/subst.rs2
-rw-r--r--src/type/util.rs3
9 files changed, 69 insertions, 19 deletions
diff --git a/src/parse/parsetree.rs b/src/parse/parsetree.rs
index 3cdc6fe..13d73ea 100644
--- a/src/parse/parsetree.rs
+++ b/src/parse/parsetree.rs
@@ -94,25 +94,26 @@ fn tokens_to_ast_inner(
loop {
elements.push(match current_token {
- Some(Num(x)) => Ok(Atom(Int(x))),
- Some(Sym(s)) if s == "+" => Ok(Atom(Add)),
- Some(Sym(s)) if s == "*" => Ok(Atom(Mul)),
- Some(Sym(s)) if s == "/" => Ok(Atom(Div)),
- Some(Sym(s)) if s == "-" => Ok(Atom(Sub)),
- Some(Sym(s)) if s == ">" => Ok(Atom(Gt)),
- Some(Sym(s)) if s == "<" => Ok(Atom(Lt)),
- Some(Sym(s)) if s == ">=" => Ok(Atom(Ge)),
- Some(Sym(s)) if s == "<=" => Ok(Atom(Le)),
- Some(Sym(s)) if s == "=" => Ok(Atom(Eq)),
- Some(Sym(s)) if s == "!=" => Ok(Atom(Neq)),
- Some(Sym(s)) if s == "and" => Ok(Atom(And)),
- Some(Sym(s)) if s == "or" => Ok(Atom(Or)),
- Some(Sym(s)) if s == "not" => Ok(Atom(Not)),
- Some(Sym(s)) if s == "xor" => Ok(Atom(Xor)),
- Some(Sym(s)) if s == "true" => Ok(Atom(True)),
- Some(Sym(s)) if s == "false" => Ok(Atom(False)),
- Some(Sym(s)) if s == "quote" => Ok(Atom(Quote)),
- Some(Sym(s)) => Ok(Atom(Var(s))),
+ Some(Num(x)) => Ok(Atom(Int(x))),
+ Some(Sym(s)) if s == "+" => Ok(Atom(Add)),
+ Some(Sym(s)) if s == "*" => Ok(Atom(Mul)),
+ Some(Sym(s)) if s == "/" => Ok(Atom(Div)),
+ Some(Sym(s)) if s == "-" => Ok(Atom(Sub)),
+ Some(Sym(s)) if s == ">" => Ok(Atom(Gt)),
+ Some(Sym(s)) if s == "<" => Ok(Atom(Lt)),
+ Some(Sym(s)) if s == ">=" => Ok(Atom(Ge)),
+ Some(Sym(s)) if s == "<=" => Ok(Atom(Le)),
+ Some(Sym(s)) if s == "=" => Ok(Atom(Eq)),
+ Some(Sym(s)) if s == "!=" => Ok(Atom(Neq)),
+ Some(Sym(s)) if s == "and" => Ok(Atom(And)),
+ Some(Sym(s)) if s == "or" => Ok(Atom(Or)),
+ Some(Sym(s)) if s == "not" => Ok(Atom(Not)),
+ Some(Sym(s)) if s == "xor" => Ok(Atom(Xor)),
+ Some(Sym(s)) if s == "true" => Ok(Atom(True)),
+ 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)) => Ok(Atom(Var(s))),
Some(ParClose) => break,
Some(ParOpen) => {
let subexp = tokens_to_ast_inner(
diff --git a/src/sexp/display.rs b/src/sexp/display.rs
index 96ce435..57d1b50 100644
--- a/src/sexp/display.rs
+++ b/src/sexp/display.rs
@@ -26,6 +26,7 @@ impl fmt::Display for SLeaf {
Int(x) => x.to_string(),
Var(s) => s.to_string(),
Quote => "quote".to_string(),
+ Vector => "vector".to_string(),
Nil => "()".to_string(),
})
}
diff --git a/src/sexp/mod.rs b/src/sexp/mod.rs
index 60dd3b0..3f17b79 100644
--- a/src/sexp/mod.rs
+++ b/src/sexp/mod.rs
@@ -27,7 +27,9 @@ pub enum SLeaf {
Or,
Not,
Xor,
+
Quote,
+ Vector,
Int(i32),
True,
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index d66b1bd..535b183 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -220,6 +220,23 @@ impl SExp {
/// Ok(scons(Quote, scons(1, scons(2, Nil))))
/// );
/// ```
+ ///
+ /// **Vectors**
+ ///
+ /// The same as quotes functionally, but they require
+ /// the elements to be of the same type.
+ /// ```rust
+ /// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
+ /// assert_eq!(
+ /// scons(Vector, scons(1, scons(2, Nil))).step(),
+ /// Ok(scons(Vector, scons(1, scons(2, Nil))))
+ /// );
+ /// assert_eq!(
+ /// scons(Vector, scons(
+ /// scons(Sub, scons(2, scons(1, Nil))),
+ /// scons(2, Nil))).step(),
+ /// Ok(scons(Vector, scons(1, scons(2, Nil))))
+ /// );
pub fn step(self) -> Result<Self, String> {
match self {
diff --git a/src/type/check.rs b/src/type/check.rs
index c3bdcb4..10ef8b4 100644
--- a/src/type/check.rs
+++ b/src/type/check.rs
@@ -44,6 +44,20 @@ impl SExp {
/// );
/// ```
///
+ /// Vectors are kind of special...
+ /// ```rust
+ /// use myslip::{
+ /// r#type::{*, Type::*, TypeError::*, util::*},
+ /// sexp::{SExp::*, SLeaf::*, util::*},
+ /// };
+ ///
+ /// assert_eq!(
+ /// scons(Vector, scons(1, scons(3, Nil))).type_check(),
+ /// Ok(vecof(Integer))
+ /// );
+ /// ```
+ /// ...so please don't ask what their type is.
+ ///
/// Some common operators get arrow types:
/// ```rust
/// use myslip::{
@@ -109,6 +123,8 @@ impl SExp {
/// assert!(scons(And, scons(1, scons(Atom(True), Nil))).type_check().is_err());
/// assert!(scons(Mul, scons(1, scons(Atom(True), Nil))).type_check().is_err());
/// assert!(scons(Not, scons(1, Nil)).type_check().is_err());
+ ///
+ /// assert!(scons(Vector, scons(1, scons(True, Nil))).type_check().is_err());
/// ```
///
/// Also, free variables should result in an error
@@ -153,6 +169,7 @@ impl SExp {
vt("T"),
List(vec![QuoteTy, vt("T")])
)),
+ Atom(Vector) => todo!(),
SCons(op, l) => {
let opertype = (*op).infer_type(ctx.clone())?;
diff --git a/src/type/display.rs b/src/type/display.rs
index 8eb0647..6c3177a 100644
--- a/src/type/display.rs
+++ b/src/type/display.rs
@@ -20,6 +20,7 @@ impl fmt::Display for Type {
Integer => write!(f, "{}", "Int"),
Boolean => write!(f, "{}", "Bool"),
QuoteTy => write!(f, "{}", "Quote"),
+ VecOf(ty) => write!(f, "({} ... {})", *ty, *ty),
Arrow(a, b) => write!(f, "({} -> {})", a, b),
List(types) => write!(
f,
diff --git a/src/type/mod.rs b/src/type/mod.rs
index e29e069..01aed40 100644
--- a/src/type/mod.rs
+++ b/src/type/mod.rs
@@ -22,6 +22,8 @@ pub enum Type {
List(Vec<Type>),
+ VecOf(Box<Type>),
+
/// Type for generics
/// and also error messages
/// with unknown types
@@ -89,6 +91,9 @@ impl Type {
/// .is_concrete(),
/// Err("a".to_string())
/// );
+ ///
+ /// assert_eq!(vecof(vt("a")).is_concrete(), Err("a".to_string()));
+ /// assert_eq!(vecof(Integer).is_concrete(), Ok(()));
/// ```
pub fn is_concrete(&self) -> Result<(), String> {
match self {
@@ -103,6 +108,7 @@ impl Type {
}
res
},
+ VecOf(ty) => (*ty).is_concrete(),
VarType(s) => Err(s.clone()),
}
}
diff --git a/src/type/subst.rs b/src/type/subst.rs
index d63f71b..12a9f15 100644
--- a/src/type/subst.rs
+++ b/src/type/subst.rs
@@ -33,6 +33,8 @@ impl Type {
.collect()
),
+ VecOf(ty) => vecof((*ty).subst(name, value)),
+
VarType(s) if s == name => value.clone(),
VarType(s) => VarType(s),
diff --git a/src/type/util.rs b/src/type/util.rs
index 9be8c6e..85e64f1 100644
--- a/src/type/util.rs
+++ b/src/type/util.rs
@@ -9,3 +9,6 @@ pub fn vt(name: &str) -> Type {
VarType(name.to_string())
}
+pub fn vecof(ty: impl Into<Box<Type>>) -> Type {
+ VecOf(ty.into())
+}