aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/type/case.rs246
-rw-r--r--src/type/check.rs8
-rw-r--r--stdlib.slip4
3 files changed, 168 insertions, 90 deletions
diff --git a/src/type/case.rs b/src/type/case.rs
index 5669e74..c53bbd0 100644
--- a/src/type/case.rs
+++ b/src/type/case.rs
@@ -1,15 +1,13 @@
use crate::r#type::{Type, TypeError, Type::*, TypeError::*, PatFail::*, util::*};
-use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*};
+use crate::sexp::{SExp, SExp::*, SLeaf::*};
use std::collections::{HashMap, HashSet};
use std::iter;
impl SExp {
- /// Checks if this expression matches the given type,
+ /// Checks if this pattern sexp can match the given type,
/// returns all variable names bound by a respective case.
- ///
- /// TODO? Nil / empty list
pub fn matches_type(
&self,
ty: &Type
@@ -36,98 +34,186 @@ impl SExp {
ctx: HashMap<String, Type>
) -> Result<Vec<(String, Type)>, TypeError> {
- println!("checking if {} matches pattern {}", &ty, &self);
-
match (self, ty) {
- (a, b) if a.infer_list_type(ctx.clone()) == Ok(b.clone()) =>
- Ok(ctx.into_iter().collect()),
-
- (a, b) if a.infer_type(ctx.clone()) == Ok(b.clone()) =>
+ (Atom(Var(name)), ty) =>
+ Ok(ctx.into_iter().chain(iter::once((name, ty))).collect()),
+ (s, ty) if s.infer_type(ctx.clone()) == Ok(ty.clone()) =>
Ok(ctx.into_iter().collect()),
- (Atom(Var(name)), t) =>
- Ok(ctx.into_iter()
- .chain(iter::once((name, t)))
- .collect()),
-
- (exp, VecOf(ty)) => {
- let mut res: Vec<(String, Type)> =
- ctx.clone().into_iter().collect();
- let mut exps = exp.clone().parts();
- // TODO: Nil or empty exp
- let restpat = exps.remove(exps.len() - 1);
- for exp in exps {
- for et in exp.matches_type_ctx(*ty.clone(), ctx.clone())? {
- res.push(et);
- }
- }
- match restpat {
- Atom(RestPat(name)) => {
- res.push((name, vecof(ty)));
- Ok(res)
- },
- t => {
- for et in t.matches_type_ctx(*ty.clone(), ctx.clone())? {
- res.push(et);
+ (se, List(v)) if v.get(0) == Some(&VecType) => match (&se, v.get(1)) {
+ (_, None) => Err(OtherError),
+ (SCons(_, _), Some(VecOf(ty))) => {
+ let mut res: Vec<(String, Type)> =
+ ctx.clone().into_iter().collect();
+ let mut exps = se.parts();
+ let restpat = exps.remove(exps.len() - 1);
+ for exp in exps {
+ match exp {
+ Atom(Var(name)) => res.push((name, *ty.clone())),
+ lit => { lit.matches_type_ctx(*ty.clone(), ctx.clone())?; }
}
- Ok(res)
}
- }
+ match restpat {
+ Atom(Var(name)) => res.push((name, *ty.clone())),
+ Atom(RestPat(name)) => res.push(
+ (name, List(vec![VecType, vecof(*ty.clone())]))
+ ),
+ lit => { lit.matches_type_ctx(*ty.clone(), ctx)?; }
+ }
+ Ok(res)
+ },
+ (Atom(Nil), Some(VecOf(_))) => Ok(ctx.into_iter().collect()),
+ _ => Err(OtherError),
},
- (SCons(e1, e2), List(typelist)) => {
- let explist = scons(e1.clone(), e2.clone()).parts();
- let mut res: Vec<(String, Type)> =
- ctx.clone().into_iter().collect();
- if explist.len() == typelist.len() {
- for (exp, ty) in explist.into_iter().zip(typelist) {
- for (e, t) in exp.matches_type_ctx(ty, ctx.clone())? {
- res.push((e, t));
+ (se, List(v)) if v.get(0) == Some(&QuoteTy) => match (&se, v.get(1)) {
+ (_, None) => Err(OtherError),
+ (SCons(_, _), Some(List(types))) => {
+ let mut res = vec![];
+
+ let exps = //if types.len() == 1 {
+ //vec![se.clone()]
+ //} else {
+ se.clone().parts()
+ /*}*/;
+
+ if exps.len() == types.len() {
+ for (exp, ty) in exps.into_iter().zip(types) {
+ for et in exp.matches_type_ctx(ty.clone(), ctx.clone() )? {
+ res.push(et);
+ }
}
- }
- Ok(res)
- } else {
- match explist.last().cloned() {
- Some(Atom(RestPat(name))) => {
- for (exp, ty) in explist.clone()
- .into_iter()
- .rev().skip(1).rev()
- .zip(typelist.clone())
- {
- for (e, t) in exp.matches_type_ctx(ty, ctx.clone())? {
- res.push((e, t));
+ Ok(res)
+ } else {
+ match exps.last().cloned() {
+ Some(Atom(RestPat(name))) => {
+ for (exp, ty) in exps.clone()
+ .into_iter()
+ .rev().skip(1).rev()
+ .zip(types.clone())
+ {
+ for (e, t) in exp.matches_type_ctx(ty, ctx.clone())? {
+ res.push((e, t));
+ }
}
- }
- res.push((
- name,
- List(typelist
- .into_iter()
- .skip(explist.len() - 1)
- .collect())
- ));
- Ok(res)
- },
- _ => Err(InvalidPattern(TypeMismatch {
- pattern: scons(e1.clone(), e2.clone()),
- expected: List(typelist),
- found: scons(e1, e2).infer_list_type(ctx)?,
- })),
+ res.push((
+ name,
+ List(vec![QuoteTy, List(types
+ .clone()
+ .into_iter()
+ .skip(exps.len() - 1)
+ .collect())])
+ ));
+ Ok(res)
+ },
+ _ => Err(InvalidPattern(TypeMismatch {
+ pattern: se.clone(),
+ expected: List(vec![QuoteTy, List(types.to_vec())]),
+ found: List(vec![QuoteTy, se.infer_list_type(ctx)?]),
+ })),
+ }
}
- }
+ },
+ (Atom(Nil), Some(List(v))) if v.len() == 0 =>
+ Ok(ctx.into_iter().collect()),
+ _ => Err(OtherError)
},
- (e, t) => {
- let found_ty = e.infer_list_type(ctx)?;
- Err(InvalidPattern(TypeMismatch {
- pattern: e,
- expected: t,
- found: found_ty
- }))
- },
+ _ => Err(OtherError), // maybe add nicer error?
}
+ // match (self, ty) {
+
+ // (a, b) if a.infer_list_type(ctx.clone()) == Ok(b.clone()) =>
+ // Ok(ctx.into_iter().collect()),
+
+ // (a, b) if a.infer_type(ctx.clone()) == Ok(b.clone()) =>
+ // Ok(ctx.into_iter().collect()),
+
+ // (Atom(Var(name)), t) =>
+ // Ok(ctx.into_iter()
+ // .chain(iter::once((name, t)))
+ // .collect()),
+
+ // (exp, VecOf(ty)) => {
+ // let mut res: Vec<(String, Type)> =
+ // ctx.clone().into_iter().collect();
+ // let mut exps = exp.clone().parts();
+ // // TODO: Nil or empty exp
+ // let restpat = exps.remove(exps.len() - 1);
+ // for exp in exps {
+ // for et in exp.matches_type_ctx(*ty.clone(), ctx.clone())? {
+ // res.push(et);
+ // }
+ // }
+ // match restpat {
+ // Atom(RestPat(name)) => {
+ // res.push((name, vecof(ty)));
+ // Ok(res)
+ // },
+ // t => {
+ // for et in t.matches_type_ctx(*ty.clone(), ctx.clone())? {
+ // res.push(et);
+ // }
+ // Ok(res)
+ // }
+ // }
+ // },
+
+ // (SCons(e1, e2), List(typelist)) => {
+ // let explist = scons(e1.clone(), e2.clone()).parts();
+ // let mut res: Vec<(String, Type)> =
+ // ctx.clone().into_iter().collect();
+ // if explist.len() == typelist.len() {
+ // for (exp, ty) in explist.into_iter().zip(typelist) {
+ // for (e, t) in exp.matches_type_ctx(ty, ctx.clone())? {
+ // res.push((e, t));
+ // }
+ // }
+ // Ok(res)
+ // } else {
+ // match explist.last().cloned() {
+ // Some(Atom(RestPat(name))) => {
+ // for (exp, ty) in explist.clone()
+ // .into_iter()
+ // .rev().skip(1).rev()
+ // .zip(typelist.clone())
+ // {
+ // for (e, t) in exp.matches_type_ctx(ty, ctx.clone())? {
+ // res.push((e, t));
+ // }
+ // }
+ // res.push((
+ // name,
+ // List(typelist
+ // .into_iter()
+ // .skip(explist.len() - 1)
+ // .collect())
+ // ));
+ // Ok(res)
+ // },
+ // _ => Err(InvalidPattern(TypeMismatch {
+ // pattern: scons(e1.clone(), e2.clone()),
+ // expected: List(typelist),
+ // found: scons(e1, e2).infer_list_type(ctx)?,
+ // })),
+ // }
+ // }
+ // },
+
+ // (e, t) => {
+ // let found_ty = e.infer_list_type(ctx)?;
+ // Err(InvalidPattern(TypeMismatch {
+ // pattern: e,
+ // expected: t,
+ // found: found_ty
+ // }))
+ // },
+
+ // }
+
}
}
diff --git a/src/type/check.rs b/src/type/check.rs
index b0311d1..6d54570 100644
--- a/src/type/check.rs
+++ b/src/type/check.rs
@@ -302,14 +302,6 @@ impl SExp {
// Case expressions
if let Some((scrutinee, patarms)) = scons(op.clone(), l.clone()).check_case() {
let scruty = scrutinee.infer_type(ctx.clone())?;
- let scruty = match scruty {
- List(v) if (
- v.get(0) == Some(&QuoteTy)
- || v.get(0) == Some(&VecType)
- ) && v.get(1).is_some() =>
- v[1].clone(),
- t => t,
- };
let mut ty: Option<Type> = None;
let mut has_wildcard = false;
for patandarm in patarms {
diff --git a/stdlib.slip b/stdlib.slip
index e73674e..107bb1f 100644
--- a/stdlib.slip
+++ b/stdlib.slip
@@ -22,8 +22,8 @@
(let sum (fix
- (fn sum' ((Int ...) -> Int) ((Int ...) -> Int)
- (fn vec (Int ...) Int
+ (fn sum' ((Vector (Int ...)) -> Int) ((Vector (Int ...)) -> Int)
+ (fn vec (Vector (Int ...)) Int
(case vec
((h ..t) (+ h (sum' t)))
(_ 0))