diff options
-rw-r--r-- | src/type/case.rs | 246 | ||||
-rw-r--r-- | src/type/check.rs | 8 | ||||
-rw-r--r-- | stdlib.slip | 4 |
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)) |