diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index dd3ba304..b8b09ce6 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -240,7 +240,14 @@ impl Context { kw_args: &[hir::KwArg], ) -> TyCheckResult { 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); diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index a1cfebff..8f0aa967 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -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? diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 471b6195..52f6f1c0 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -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, diff --git a/compiler/erg_compiler/ty/mod.rs b/compiler/erg_compiler/ty/mod.rs index 1ddf638a..4066dcba 100644 --- a/compiler/erg_compiler/ty/mod.rs +++ b/compiler/erg_compiler/ty/mod.rs @@ -2043,6 +2043,24 @@ impl Type { } } + pub fn container_len(&self) -> Option { + 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 { match self { Self::FreeVar(f) if f.is_linked() => f.crack().typarams(), diff --git a/compiler/erg_compiler/ty/value.rs b/compiler/erg_compiler/ty/value.rs index c3c10935..3e8f8c2b 100644 --- a/compiler/erg_compiler/ty/value.rs +++ b/compiler/erg_compiler/ty/value.rs @@ -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 { 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::>() }