aboutsummaryrefslogtreecommitdiff
path: root/src/type
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-21 12:35:37 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-21 12:35:37 +0300
commitd1c97e405230b6616ef834cf38be351e566a228e (patch)
tree7c75d9353b0b3cc9f08400c5d09e0b7552afc9c8 /src/type
parenta70dcaa949f41c585f9aea5e79f2550053d8e857 (diff)
downloadmyslip-d1c97e405230b6616ef834cf38be351e566a228e.tar.gz
myslip-d1c97e405230b6616ef834cf38be351e566a228e.zip
feat: implemented coproducts according to tests
Diffstat (limited to 'src/type')
-rw-r--r--src/type/case.rs97
-rw-r--r--src/type/check.rs25
-rw-r--r--src/type/display.rs13
-rw-r--r--src/type/mod.rs2
4 files changed, 40 insertions, 97 deletions
diff --git a/src/type/case.rs b/src/type/case.rs
index d8871af..ae4eb77 100644
--- a/src/type/case.rs
+++ b/src/type/case.rs
@@ -120,99 +120,20 @@ impl SExp {
_ => Err(OtherError)
},
- _ => 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()),
+ (se, SumType(l, r)) => match (&(se.parts())[..], (*l, *r)) {
+ ([op, exp], (l, _)) if *op == Atom(Inl) =>
+ exp.clone().matches_type_ctx(l, ctx.clone()),
+ ([op, exp], (_, r)) if *op == Atom(Inr) =>
+ exp.clone().matches_type_ctx(r, ctx.clone()),
+ _ => Err(OtherError),
+ },
- // (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
- // }))
- // },
+ _ => Err(OtherError), // maybe add nicer error?
- // }
+ }
}
}
diff --git a/src/type/check.rs b/src/type/check.rs
index 96a4408..5ccd0e7 100644
--- a/src/type/check.rs
+++ b/src/type/check.rs
@@ -193,8 +193,9 @@ impl SExp {
/// let exp = parse_to_ast(
/// "(let mysum (coprod Bool 7)) \
/// (case mysum \
- /// ((inl b) (if b 0 1)) \
- /// ((inr x) x))"
+ /// ((inl b) (case b (true 0) (_ 1))) \
+ /// ((inr x) x) \
+ /// (_ 0))"
/// ).unwrap();
/// assert_eq!(
/// exp.type_check(),
@@ -300,9 +301,9 @@ impl SExp {
vecof(vt("T")),
List(vec![VecType, vecof(vt("T"))])
)),
- Atom(Coprod) => todo!(),
- Atom(Inl) => todo!(),
- Atom(Inr) => todo!(),
+ Atom(Coprod) => Err(OtherError), // TODO
+ Atom(Inl) => Err(OtherError), // TODO
+ Atom(Inr) => Err(OtherError), // TODO
Atom(Let) => Ok(LetType),
Atom(Print) => Ok(arr(vt("_"), NilType)),
Atom(Ty(_)) => Ok(TypeLit),
@@ -379,6 +380,20 @@ impl SExp {
}
}
+ // Coproducts
+ if **op == Atom(Coprod) {
+ let mut parts = (**l).clone().parts().into_iter();
+ return match (parts.next(), parts.next(), parts.next()) {
+ (Some(Atom(Ty(ty))), Some(r), None)
+ => Ok(sumtype(ty, r.infer_type(ctx)?)),
+ (Some(l), Some(Atom(Ty(ty))), None)
+ => Ok(sumtype(l.infer_type(ctx)?, ty)),
+ (Some(l), Some(r), None)
+ => Err(SumDefNoTypeLiteral(scons(l, r))),
+ _ => Err(OtherError)
+ };
+ }
+
// Normal operation
let opertype = (*op).infer_type(ctx.clone())?;
let argstype = (*l).infer_list_type(ctx)?;
diff --git a/src/type/display.rs b/src/type/display.rs
index 99394df..586483c 100644
--- a/src/type/display.rs
+++ b/src/type/display.rs
@@ -119,12 +119,17 @@ impl fmt::Display for TypeError {
letexp
)
},
- DifferentTypeCaseArms(ty1, ty2) => write!(f, "arms of match have different types, '{ty1}' and '{ty2}'"),
- FunAsAtom => write!(f, "'fn' used as atom doesn't make sense"),
+ DifferentTypeCaseArms(ty1, ty2)
+ => write!(f, "arms of match have different types, '{ty1}' and '{ty2}'"),
+ FunAsAtom => write!(f, "'fn' used as atom doesn't make sense"),
CaseAsAtom => write!(f, "'case' used as atom doesn't make sense"),
RestAsAtom => write!(f, "'..[name]' used as atom doesn't make sense"),
- InvalidFunDef(exp, err) => write!(f, "invalid function definition '{exp}': {err}"),
- NoWildcardInCase(exp) => write!(f, "no wildcard in cases: '{exp}'"),
+ InvalidFunDef(exp, err)
+ => write!(f, "invalid function definition '{exp}': {err}"),
+ NoWildcardInCase(exp)
+ => write!(f, "no wildcard in cases: '{exp}'"),
+ SumDefNoTypeLiteral(exp)
+ => write!(f, "other arm of coproduct should've been a type in {exp}"),
OtherError => write!(f, "uncategorized error"),
}
}
diff --git a/src/type/mod.rs b/src/type/mod.rs
index c726001..e1ca798 100644
--- a/src/type/mod.rs
+++ b/src/type/mod.rs
@@ -83,6 +83,8 @@ pub enum TypeError {
DifferentTypeCaseArms(Type, Type),
+ SumDefNoTypeLiteral(SExp),
+
OtherError
}