Fix match crashes

This commit is contained in:
Shunsuke Shibayama 2022-12-04 11:43:39 +09:00
parent 85370fb051
commit 48f91f969b
5 changed files with 137 additions and 20 deletions

View file

@ -240,7 +240,14 @@ impl Context {
kw_args: &[hir::KwArg],
) -> TyCheckResult<VarInfo> {
if !kw_args.is_empty() {
todo!()
// TODO: this error desc is not good
return Err(TyCheckErrors::from(TyCheckError::default_param_error(
self.cfg.input.clone(),
line!() as usize,
kw_args[0].loc(),
self.caused_by(),
"match",
)));
}
for pos_arg in pos_args.iter().skip(1) {
let t = pos_arg.expr.ref_t();
@ -266,22 +273,22 @@ impl Context {
for (i, pos_arg) in pos_args.iter().skip(1).enumerate() {
let lambda = erg_common::enum_unwrap!(&pos_arg.expr, hir::Expr::Lambda);
if !lambda.params.defaults.is_empty() {
todo!()
return Err(TyCheckErrors::from(TyCheckError::default_param_error(
self.cfg.input.clone(),
line!() as usize,
pos_args[i + 1].loc(),
self.caused_by(),
"match",
)));
}
// TODO: If the first argument of the match is a tuple?
if lambda.params.len() != 1 {
return Err(TyCheckErrors::from(TyCheckError::argument_error(
return Err(TyCheckErrors::from(TyCheckError::param_error(
self.cfg.input.clone(),
line!() as usize,
pos_args[i + 1].loc(),
self.caused_by(),
1,
pos_args[i + 1]
.expr
.signature_t()
.unwrap()
.typarams_len()
.unwrap_or(0),
lambda.params.len(),
)));
}
let mut dummy_tv_cache = TyVarCache::new(self.level, self);

View file

@ -1553,14 +1553,27 @@ impl Context {
}
(Type::Proj { .. }, _) => todo!(),
(_, Type::Proj { .. }) => todo!(),
(Refinement(l), Refinement(r)) => {
if l.preds.len() == 1 && r.preds.len() == 1 {
let l_first = l.preds.iter().next().unwrap();
let r_first = r.preds.iter().next().unwrap();
(Refinement(sub), Refinement(sup)) => {
if sub.preds.len() == 1 && sup.preds.len() == 1 {
let sub_first = sub.preds.iter().next().unwrap();
let sup_first = sup.preds.iter().next().unwrap();
self.sub_unify_pred(sub_first, sup_first, loc)?;
return Ok(());
}
todo!("{sub}, {sup}")
},
// {I: Int | I >= 1} <: Nat == {I: Int | I >= 0}
(Type::Refinement(sub), sup) => {
let sup = self.into_refinement(sup.clone());
if sup.preds.is_empty() {
return self.sub_unify(&sub.t, maybe_sup, loc, param_name);
} else if sub.preds.len() == 1 && sup.preds.len() == 1 {
let l_first = sub.preds.iter().next().unwrap();
let r_first = sup.preds.iter().next().unwrap();
self.sub_unify_pred(l_first, r_first, loc)?;
return Ok(());
}
todo!("{l}, {r}")
todo!("{sub}, {sup}")
},
(Type::Subr(_) | Type::Record(_), Type) => Ok(()),
// REVIEW: correct?

View file

@ -554,6 +554,79 @@ impl TyCheckError {
)
}
pub fn param_error(
input: Input,
errno: usize,
loc: Location,
caused_by: String,
expect: usize,
found: usize,
) -> Self {
let mut expct = StyledStrings::default();
switch_lang!(
"japanese" => expct.push_str("予期した個数: "),
"simplified_chinese" =>expct.push_str("预期: "),
"traditional_chinese" => expct.push_str("預期: "),
"english" => expct.push_str("expected: "),
);
expct.push_str_with_color_and_attribute(format!("{}", expect), HINT, ATTR);
let mut fnd = StyledStrings::default();
switch_lang!(
"japanese" => fnd.push_str("与えられた個数: "),
"simplified_chinese" => fnd.push_str("但找到: "),
"traditional_chinese" => fnd.push_str("但找到: "),
"english" =>fnd.push_str("but found: "),
);
fnd.push_str_with_color_and_attribute(format!("{}", found), ERR, ATTR);
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(
loc,
vec![expct.to_string(), fnd.to_string()],
None,
)],
switch_lang!(
"japanese" => format!("引数の数が違います"),
"simplified_chinese" => format!("参数的数量不匹配"),
"traditional_chinese" => format!("參數的數量不匹配"),
"english" => format!("the number of parameters is mismatched"),
),
errno,
TypeError,
loc,
),
input,
caused_by,
)
}
pub fn default_param_error(
input: Input,
errno: usize,
loc: Location,
caused_by: String,
name: &str,
) -> Self {
Self::new(
ErrorCore::new(
vec![],
switch_lang!(
"japanese" => format!("{name}はデフォルト引数を受け取りません"),
"simplified_chinese" => format!("{name}不接受默认参数"),
"traditional_chinese" => format!("{name}不接受預設參數"),
"english" => format!("{name} does not accept default parameters"),
),
errno,
TypeError,
loc,
),
input,
caused_by,
)
}
pub fn match_error(
input: Input,
errno: usize,

View file

@ -2043,6 +2043,24 @@ impl Type {
}
}
pub fn container_len(&self) -> Option<usize> {
log!(err "{self}");
match self {
Self::Poly { name, params } => match &name[..] {
"Array" => {
if let TyParam::Value(ValueObj::Nat(n)) = &params[0] {
Some(*n as usize)
} else {
None
}
}
"Tuple" => Some(params.len()),
_ => None,
},
_ => None,
}
}
pub fn typarams(&self) -> Vec<TyParam> {
match self {
Self::FreeVar(f) if f.is_linked() => f.crack().typarams(),

View file

@ -736,15 +736,21 @@ impl ValueObj {
}
}
pub fn from_const_expr(expr: ConstExpr) -> Self {
let ConstExpr::Lit(lit) = expr else { todo!() };
let t = type_from_token_kind(lit.token.kind);
ValueObj::from_str(t, lit.token.content).unwrap()
}
pub fn tuple_from_const_args(args: ConstArgs) -> Self {
Self::Tuple(Rc::from(&Self::vec_from_const_args(args)[..]))
}
pub fn vec_from_const_args(args: ConstArgs) -> Vec<Self> {
args.deconstruct()
.0
.into_iter()
.map(|elem| {
let ConstExpr::Lit(lit) = elem.expr else { todo!() };
let t = type_from_token_kind(lit.token.kind);
ValueObj::from_str(t, lit.token.content).unwrap()
})
.map(|elem| Self::from_const_expr(elem.expr))
.collect::<Vec<_>>()
}