mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 14:04: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],
|
kw_args: &[hir::KwArg],
|
||||||
) -> TyCheckResult<VarInfo> {
|
) -> TyCheckResult<VarInfo> {
|
||||||
if !kw_args.is_empty() {
|
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) {
|
for pos_arg in pos_args.iter().skip(1) {
|
||||||
let t = pos_arg.expr.ref_t();
|
let t = pos_arg.expr.ref_t();
|
||||||
|
@ -266,22 +273,22 @@ impl Context {
|
||||||
for (i, pos_arg) in pos_args.iter().skip(1).enumerate() {
|
for (i, pos_arg) in pos_args.iter().skip(1).enumerate() {
|
||||||
let lambda = erg_common::enum_unwrap!(&pos_arg.expr, hir::Expr::Lambda);
|
let lambda = erg_common::enum_unwrap!(&pos_arg.expr, hir::Expr::Lambda);
|
||||||
if !lambda.params.defaults.is_empty() {
|
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 {
|
if lambda.params.len() != 1 {
|
||||||
return Err(TyCheckErrors::from(TyCheckError::argument_error(
|
return Err(TyCheckErrors::from(TyCheckError::param_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
pos_args[i + 1].loc(),
|
pos_args[i + 1].loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
1,
|
1,
|
||||||
pos_args[i + 1]
|
lambda.params.len(),
|
||||||
.expr
|
|
||||||
.signature_t()
|
|
||||||
.unwrap()
|
|
||||||
.typarams_len()
|
|
||||||
.unwrap_or(0),
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
|
|
|
@ -1553,14 +1553,27 @@ impl Context {
|
||||||
}
|
}
|
||||||
(Type::Proj { .. }, _) => todo!(),
|
(Type::Proj { .. }, _) => todo!(),
|
||||||
(_, Type::Proj { .. }) => todo!(),
|
(_, Type::Proj { .. }) => todo!(),
|
||||||
(Refinement(l), Refinement(r)) => {
|
(Refinement(sub), Refinement(sup)) => {
|
||||||
if l.preds.len() == 1 && r.preds.len() == 1 {
|
if sub.preds.len() == 1 && sup.preds.len() == 1 {
|
||||||
let l_first = l.preds.iter().next().unwrap();
|
let sub_first = sub.preds.iter().next().unwrap();
|
||||||
let r_first = r.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)?;
|
self.sub_unify_pred(l_first, r_first, loc)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
todo!("{l}, {r}")
|
todo!("{sub}, {sup}")
|
||||||
},
|
},
|
||||||
(Type::Subr(_) | Type::Record(_), Type) => Ok(()),
|
(Type::Subr(_) | Type::Record(_), Type) => Ok(()),
|
||||||
// REVIEW: correct?
|
// 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(
|
pub fn match_error(
|
||||||
input: Input,
|
input: Input,
|
||||||
errno: usize,
|
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> {
|
pub fn typarams(&self) -> Vec<TyParam> {
|
||||||
match self {
|
match self {
|
||||||
Self::FreeVar(f) if f.is_linked() => f.crack().typarams(),
|
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> {
|
pub fn vec_from_const_args(args: ConstArgs) -> Vec<Self> {
|
||||||
args.deconstruct()
|
args.deconstruct()
|
||||||
.0
|
.0
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|elem| {
|
.map(|elem| Self::from_const_expr(elem.expr))
|
||||||
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()
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue