mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 05:54:33 +00:00
Fix match crashes
This commit is contained in:
parent
85370fb051
commit
48f91f969b
5 changed files with 137 additions and 20 deletions
|
@ -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);
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)) = ¶ms[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(),
|
||||
|
|
|
@ -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<_>>()
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue