aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parse/parsetree.rs6
-rw-r--r--src/sexp/display.rs2
-rw-r--r--src/sexp/mod.rs19
-rw-r--r--src/sexp/step.rs24
-rw-r--r--src/type/check.rs22
-rw-r--r--src/type/display.rs19
-rw-r--r--src/type/mod.rs3
-rw-r--r--src/type/subst.rs1
8 files changed, 71 insertions, 25 deletions
diff --git a/src/parse/parsetree.rs b/src/parse/parsetree.rs
index 28e5044..6dd4e01 100644
--- a/src/parse/parsetree.rs
+++ b/src/parse/parsetree.rs
@@ -10,6 +10,7 @@ use nom::{
};
use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*};
+use crate::r#type::{Type::*};
#[derive(Debug,PartialEq,Clone)]
@@ -113,8 +114,11 @@ 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 == "print" => Ok(Atom(Print)),
Some(Sym(s)) if s == "let" => Ok(Atom(Let)),
+ Some(Sym(s)) if s == "->" => Ok(Atom(Arr)),
+ Some(Sym(s)) if s == "int" => Ok(Atom(Ty(Integer))),
+ Some(Sym(s)) if s == "bool" => Ok(Atom(Ty(Boolean))),
Some(Sym(s)) => Ok(Atom(Var(s))),
Some(ParClose) => break,
Some(ParOpen) => {
diff --git a/src/sexp/display.rs b/src/sexp/display.rs
index a978f61..5d78e93 100644
--- a/src/sexp/display.rs
+++ b/src/sexp/display.rs
@@ -29,6 +29,8 @@ impl fmt::Display for SLeaf {
Vector => "vector".to_string(),
Print => "print".to_string(),
Let => "let".to_string(),
+ Ty(t) => t.to_string(),
+ Arr => "->".to_string(),
Nil => "()".to_string(),
})
}
diff --git a/src/sexp/mod.rs b/src/sexp/mod.rs
index 296553f..11c185f 100644
--- a/src/sexp/mod.rs
+++ b/src/sexp/mod.rs
@@ -4,6 +4,8 @@ pub mod util;
pub mod subst;
pub mod display;
+use crate::r#type::Type;
+
/// A leaf node for S-Expressions.
///
/// May represent built-in operators,
@@ -33,6 +35,9 @@ pub enum SLeaf {
Let,
+ Ty(Type),
+ Arr,
+
Print,
Int(i32),
@@ -58,6 +63,7 @@ pub enum SExp {
use SExp::*;
use SLeaf::*;
+use crate::sexp::util::*;
impl SExp {
@@ -71,7 +77,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).is_type_lit())
&& b.consists_of_values()
),
Atom(Var(_)) => false,
@@ -85,4 +91,15 @@ impl SExp {
_ => false
}
}
+
+ pub fn is_type_lit(&self) -> bool {
+ match self {
+ Atom(Ty(_)) => true,
+ SCons(a, b) => scons(a.clone(), b.clone())
+ .parts()
+ .into_iter()
+ .all(|x| x.is_type_lit()),
+ _ => false
+ }
+ }
}
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index 11df257..c26dce9 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -1,5 +1,6 @@
use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*};
+use crate::r#type::{Type::*, util::*};
impl SExp {
@@ -521,6 +522,29 @@ impl SExp {
}
},
+ // Type arrow
+ SCons(op, l) if *op == Atom(Arr) => {
+ let ls = l.parts();
+ let t1 = ls.get(0).ok_or("wrong list length".to_string())?;
+ let t2 = ls.get(1).ok_or("wrong list length".to_string())?;
+ match (t1.clone().multistep()?, t2.clone().multistep()?) {
+ (Atom(Ty(a)), Atom(Ty(b))) => Ok(Atom(Ty(arr(a.clone(), b.clone())))),
+ _ => Err("invalid args".to_string()),
+ }
+ },
+
+ // Type list
+ SCons(op, l) if (*op).is_type_lit() => {
+ let mut res = vec![];
+ for exp in std::iter::once(*op).chain(l.parts()) {
+ res.push(match exp.multistep()? {
+ Atom(Ty(t)) => Ok(t),
+ e => Err(format!("not a type: {e}")),
+ }?);
+ }
+ Ok(Atom(Ty(List(res))))
+ },
+
// Print
SCons(op, l) if *op == Atom(Print) => {
println!("{}", *l);
diff --git a/src/type/check.rs b/src/type/check.rs
index 874db58..24c255d 100644
--- a/src/type/check.rs
+++ b/src/type/check.rs
@@ -67,8 +67,6 @@ impl SExp {
/// sexp::{SExp::*, SLeaf::*, util::*},
/// };
///
- /// assert_eq!(Atom(Add).type_check(), Ok(arr(List(vec![Integer, Integer]), Integer)));
- /// assert_eq!(Atom(Mul).type_check(), Ok(arr(List(vec![Integer, Integer]), Integer)));
/// assert_eq!(Atom(Sub).type_check(), Ok(arr(List(vec![Integer, Integer]), Integer)));
/// assert_eq!(Atom(Div).type_check(), Ok(arr(List(vec![Integer, Integer]), Integer)));
/// assert_eq!(Atom(Eq) .type_check(), Ok(arr(List(vec![Integer, Integer]), Boolean)));
@@ -112,15 +110,6 @@ impl SExp {
/// sexp::{SExp::*, SLeaf::*, util::*},
/// };
///
- /// let err = scons(Mul, scons(1, Nil)).type_check();
- /// match err {
- /// Err(InvalidArgList { .. }) => (),
- /// _ => panic!(
- /// "passing only 1 argument to '*' should result in InvalidArgList error, found '{:?}'",
- /// err
- /// ),
- /// };
- ///
/// match scons(Sub, scons(1, scons(2, scons(3, Nil)))).type_check() {
/// Err(InvalidArgList { .. }) => (),
/// _ => panic!(
@@ -178,8 +167,8 @@ impl SExp {
Atom(Var(name)) => ctx.get(name)
.ok_or(UndefinedVariable(name.to_string()))
.cloned(),
- Atom(Add) => Ok(arr(List(vec![Integer, Integer]), Integer)), // TODO varlen
- Atom(Mul) => Ok(arr(List(vec![Integer, Integer]), Integer)), // TODO varlen
+ Atom(Add) => Ok(arr(vecof(Integer), Integer)),
+ Atom(Mul) => Ok(arr(vecof(Integer), Integer)),
Atom(Sub) => Ok(arr(List(vec![Integer, Integer]), Integer)),
Atom(Div) => Ok(arr(List(vec![Integer, Integer]), Integer)),
Atom(Eq | Neq | Lt | Gt | Le | Ge) =>
@@ -197,7 +186,8 @@ impl SExp {
)),
Atom(Let) => Ok(LetType),
Atom(Print) => Ok(arr(vt("_"), List(vec![]))),
-
+ Atom(Ty(_)) => Ok(TypeLit),
+ Atom(Arr) => Ok(arr(List(vec![TypeLit, TypeLit]), TypeLit)),
SCons(op, l) => {
@@ -218,6 +208,10 @@ impl SExp {
let opertype = (*op).infer_type(ctx.clone())?;
let argstype = (*l).infer_list_type(ctx)?;
+ if opertype == TypeLit && argstype.aka(&vecof(TypeLit)) {
+ return Ok(TypeLit);
+ }
+
let conv_args = match (opertype.clone(), argstype.clone()) {
(Arrow(from, _), a) => match a.clone().into_type(&*from) {
Ok(s) => Ok(s),
diff --git a/src/type/display.rs b/src/type/display.rs
index 72e3693..cd60673 100644
--- a/src/type/display.rs
+++ b/src/type/display.rs
@@ -10,19 +10,20 @@ impl fmt::Display for Type {
/// 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());
+ /// 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"),
+ Integer => write!(f, "{}", "int"),
+ Boolean => write!(f, "{}", "bool"),
QuoteTy => write!(f, "{}", "Quote"),
VecType => write!(f, "{}", "Vector"),
LetType => write!(f, "{}", "Let"),
NilType => write!(f, "()"),
+ TypeLit => write!(f, "[type literal]"),
VecOf(ty) => write!(f, "({} ... {})", *ty, *ty),
Arrow(a, b) => write!(f, "({} -> {})", a, b),
List(types) => write!(
@@ -57,7 +58,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 {
@@ -65,7 +66,7 @@ impl fmt::Display for TypeError {
/// 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()
+ /// "invalid argument list: '(1 2 3)'\nexpected: '(int int)'\nfound: '(int int int)'".to_string()
/// );
/// assert_eq!(
/// UnboundGeneric(String::from("?")).to_string(),
@@ -76,7 +77,7 @@ impl fmt::Display for TypeError {
/// argtype: Integer,
/// generictype: arr(VarType("T".to_string()), Integer)
/// }.to_string(),
- /// "incompatible argument type 'Int' and generic operator type '(T -> Int)'".to_string()
+ /// "incompatible argument type 'int' and generic operator type '(T -> int)'".to_string()
/// );
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/src/type/mod.rs b/src/type/mod.rs
index 9c2f89c..c138bba 100644
--- a/src/type/mod.rs
+++ b/src/type/mod.rs
@@ -17,6 +17,8 @@ pub enum Type {
Boolean,
+ TypeLit,
+
QuoteTy, //constructor
Arrow(Box<Type>, Box<Type>),
@@ -111,6 +113,7 @@ impl Type {
VecType => Ok(()),
LetType => Ok(()),
NilType => Ok(()),
+ TypeLit => Ok(()),
Arrow(a, b) => b.is_concrete().and_then(|_ok| a.is_concrete()),
List(v) => {
let mut res = Ok(());
diff --git a/src/type/subst.rs b/src/type/subst.rs
index ab9d38a..18c9926 100644
--- a/src/type/subst.rs
+++ b/src/type/subst.rs
@@ -45,6 +45,7 @@ impl Type {
VecType => VecType,
LetType => LetType,
NilType => NilType,
+ TypeLit => TypeLit,
}
}